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 static org.apache.maven.model.building.Result.error;
23 import static org.apache.maven.model.building.Result.newResult;
24
25 import java.io.File;
26 import java.io.IOException;
27 import java.lang.reflect.Field;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.LinkedHashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Properties;
41 import java.util.Set;
42 import java.util.concurrent.ConcurrentHashMap;
43
44 import javax.inject.Inject;
45 import javax.inject.Named;
46 import javax.inject.Singleton;
47
48 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
49 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
50 import org.apache.maven.artifact.versioning.VersionRange;
51 import org.apache.maven.building.Source;
52 import org.apache.maven.feature.Features;
53 import org.apache.maven.model.Activation;
54 import org.apache.maven.model.ActivationFile;
55 import org.apache.maven.model.Build;
56 import org.apache.maven.model.Dependency;
57 import org.apache.maven.model.DependencyManagement;
58 import org.apache.maven.model.InputLocation;
59 import org.apache.maven.api.model.InputSource;
60 import org.apache.maven.model.Model;
61 import org.apache.maven.model.Parent;
62 import org.apache.maven.model.Plugin;
63 import org.apache.maven.model.PluginManagement;
64 import org.apache.maven.model.Profile;
65 import org.apache.maven.model.Repository;
66 import org.apache.maven.model.building.ModelProblem.Severity;
67 import org.apache.maven.model.building.ModelProblem.Version;
68 import org.apache.maven.model.composition.DependencyManagementImporter;
69 import org.apache.maven.model.inheritance.InheritanceAssembler;
70 import org.apache.maven.model.interpolation.ModelInterpolator;
71 import org.apache.maven.model.interpolation.ModelVersionProcessor;
72 import org.apache.maven.model.io.ModelParseException;
73 import org.apache.maven.model.io.ModelReader;
74 import org.apache.maven.model.management.DependencyManagementInjector;
75 import org.apache.maven.model.management.PluginManagementInjector;
76 import org.apache.maven.model.normalization.ModelNormalizer;
77 import org.apache.maven.model.path.ModelPathTranslator;
78 import org.apache.maven.model.path.ModelUrlNormalizer;
79 import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
80 import org.apache.maven.model.plugin.LifecycleBindingsInjector;
81 import org.apache.maven.model.plugin.PluginConfigurationExpander;
82 import org.apache.maven.model.plugin.ReportConfigurationExpander;
83 import org.apache.maven.model.plugin.ReportingConverter;
84 import org.apache.maven.model.profile.DefaultProfileActivationContext;
85 import org.apache.maven.model.profile.ProfileActivationContext;
86 import org.apache.maven.model.profile.ProfileInjector;
87 import org.apache.maven.model.profile.ProfileSelector;
88 import org.apache.maven.model.resolution.InvalidRepositoryException;
89 import org.apache.maven.model.resolution.ModelResolver;
90 import org.apache.maven.model.resolution.UnresolvableModelException;
91 import org.apache.maven.model.resolution.WorkspaceModelResolver;
92 import org.apache.maven.model.superpom.SuperPomProvider;
93 import org.apache.maven.model.v4.MavenMerger;
94 import org.apache.maven.model.validation.ModelValidator;
95 import org.codehaus.plexus.interpolation.InterpolationException;
96 import org.codehaus.plexus.interpolation.MapBasedValueSource;
97 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
98 import org.eclipse.sisu.Nullable;
99
100
101
102
103 @Named
104 @Singleton
105 public class DefaultModelBuilder
106 implements ModelBuilder
107 {
108 private final MavenMerger modelMerger = new FileToRawModelMerger();
109
110 private final ModelProcessor modelProcessor;
111 private final ModelValidator modelValidator;
112 private final ModelNormalizer modelNormalizer;
113 private final ModelInterpolator modelInterpolator;
114 private final ModelPathTranslator modelPathTranslator;
115 private final ModelUrlNormalizer modelUrlNormalizer;
116 private final SuperPomProvider superPomProvider;
117 private final InheritanceAssembler inheritanceAssembler;
118 private final ProfileSelector profileSelector;
119 private final ProfileInjector profileInjector;
120 private final PluginManagementInjector pluginManagementInjector;
121 private final DependencyManagementInjector dependencyManagementInjector;
122 private final DependencyManagementImporter dependencyManagementImporter;
123 private final LifecycleBindingsInjector lifecycleBindingsInjector;
124 private final PluginConfigurationExpander pluginConfigurationExpander;
125 private final ReportConfigurationExpander reportConfigurationExpander;
126 private final ReportingConverter reportingConverter;
127 private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
128 private final ModelVersionProcessor versionProcessor;
129
130 @SuppressWarnings( "checkstyle:ParameterNumber" )
131 @Inject
132 public DefaultModelBuilder(
133 ModelProcessor modelProcessor,
134 ModelValidator modelValidator,
135 ModelNormalizer modelNormalizer,
136 ModelInterpolator modelInterpolator,
137 ModelPathTranslator modelPathTranslator,
138 ModelUrlNormalizer modelUrlNormalizer,
139 SuperPomProvider superPomProvider,
140 InheritanceAssembler inheritanceAssembler,
141 ProfileSelector profileSelector,
142 ProfileInjector profileInjector,
143 PluginManagementInjector pluginManagementInjector,
144 DependencyManagementInjector dependencyManagementInjector,
145 DependencyManagementImporter dependencyManagementImporter,
146 @Nullable LifecycleBindingsInjector lifecycleBindingsInjector,
147 PluginConfigurationExpander pluginConfigurationExpander,
148 ReportConfigurationExpander reportConfigurationExpander,
149 ReportingConverter reportingConverter,
150 ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator,
151 ModelVersionProcessor versionProcessor )
152 {
153 this.modelProcessor = modelProcessor;
154 this.modelValidator = modelValidator;
155 this.modelNormalizer = modelNormalizer;
156 this.modelInterpolator = modelInterpolator;
157 this.modelPathTranslator = modelPathTranslator;
158 this.modelUrlNormalizer = modelUrlNormalizer;
159 this.superPomProvider = superPomProvider;
160 this.inheritanceAssembler = inheritanceAssembler;
161 this.profileSelector = profileSelector;
162 this.profileInjector = profileInjector;
163 this.pluginManagementInjector = pluginManagementInjector;
164 this.dependencyManagementInjector = dependencyManagementInjector;
165 this.dependencyManagementImporter = dependencyManagementImporter;
166 this.lifecycleBindingsInjector = lifecycleBindingsInjector;
167 this.pluginConfigurationExpander = pluginConfigurationExpander;
168 this.reportConfigurationExpander = reportConfigurationExpander;
169 this.reportingConverter = reportingConverter;
170 this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
171 this.versionProcessor = versionProcessor;
172 }
173
174
175
176
177
178 @Deprecated
179 public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
180 {
181 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
182 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
183 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
184 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
185 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
186 }
187
188
189
190
191
192 @Deprecated
193 public DefaultModelBuilder setModelValidator( ModelValidator modelValidator )
194 {
195 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
196 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
197 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
198 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
199 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
200 }
201
202
203
204
205
206 @Deprecated
207 public DefaultModelBuilder setModelNormalizer( ModelNormalizer modelNormalizer )
208 {
209 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
210 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
211 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
212 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
213 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
214 }
215
216
217
218
219
220 @Deprecated
221 public DefaultModelBuilder setModelInterpolator( ModelInterpolator modelInterpolator )
222 {
223 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
224 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
225 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
226 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
227 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
228 }
229
230
231
232
233
234 @Deprecated
235 public DefaultModelBuilder setModelPathTranslator( ModelPathTranslator modelPathTranslator )
236 {
237 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
238 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
239 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
240 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
241 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
242 }
243
244
245
246
247
248 @Deprecated
249 public DefaultModelBuilder setModelUrlNormalizer( ModelUrlNormalizer modelUrlNormalizer )
250 {
251 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
252 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
253 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
254 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
255 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
256 }
257
258
259
260
261
262 @Deprecated
263 public DefaultModelBuilder setSuperPomProvider( SuperPomProvider superPomProvider )
264 {
265 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
266 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
267 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
268 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
269 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
270 }
271
272
273
274
275
276 @Deprecated
277 public DefaultModelBuilder setInheritanceAssembler( InheritanceAssembler inheritanceAssembler )
278 {
279 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
280 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
281 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
282 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
283 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
284 }
285
286
287
288
289
290 @Deprecated
291 public DefaultModelBuilder setProfileSelector( ProfileSelector profileSelector )
292 {
293 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
294 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
295 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
296 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
297 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
298 }
299
300
301
302
303
304 @Deprecated
305 public DefaultModelBuilder setProfileInjector( ProfileInjector profileInjector )
306 {
307 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
308 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
309 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
310 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
311 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
312 }
313
314
315
316
317
318 @Deprecated
319 public DefaultModelBuilder setPluginManagementInjector( PluginManagementInjector pluginManagementInjector )
320 {
321 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
322 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
323 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
324 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
325 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
326 }
327
328
329
330
331
332 @Deprecated
333 public DefaultModelBuilder setDependencyManagementInjector(
334 DependencyManagementInjector dependencyManagementInjector )
335 {
336 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
337 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
338 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
339 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
340 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
341 }
342
343
344
345
346
347 @Deprecated
348 public DefaultModelBuilder setDependencyManagementImporter(
349 DependencyManagementImporter dependencyManagementImporter )
350 {
351 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
352 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
353 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
354 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
355 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
356 }
357
358
359
360
361
362 @Deprecated
363 public DefaultModelBuilder setLifecycleBindingsInjector( LifecycleBindingsInjector lifecycleBindingsInjector )
364 {
365 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
366 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
367 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
368 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
369 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
370 }
371
372
373
374
375
376 @Deprecated
377 public DefaultModelBuilder setPluginConfigurationExpander( PluginConfigurationExpander pluginConfigurationExpander )
378 {
379 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
380 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
381 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
382 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
383 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
384 }
385
386
387
388
389
390 @Deprecated
391 public DefaultModelBuilder setReportConfigurationExpander( ReportConfigurationExpander reportConfigurationExpander )
392 {
393 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
394 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
395 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
396 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
397 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
398 }
399
400
401
402
403
404 @Deprecated
405 public DefaultModelBuilder setReportingConverter( ReportingConverter reportingConverter )
406 {
407 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
408 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
409 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
410 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
411 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
412 }
413
414
415
416
417
418 @Deprecated
419 public DefaultModelBuilder setProfileActivationFilePathInterpolator(
420 ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator )
421 {
422 return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
423 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
424 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
425 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
426 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
427 }
428
429 @Override
430 public DefaultTransformerContextBuilder newTransformerContextBuilder()
431 {
432 return new DefaultTransformerContextBuilder();
433 }
434
435 @Override
436 public ModelBuildingResult build( ModelBuildingRequest request )
437 throws ModelBuildingException
438 {
439 return build( request, new LinkedHashSet<>() );
440 }
441
442 protected ModelBuildingResult build( ModelBuildingRequest request, Collection<String> importIds )
443 throws ModelBuildingException
444 {
445
446 DefaultModelBuildingResult result = new DefaultModelBuildingResult();
447
448 DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
449
450
451 Model fileModel = readFileModel( request, problems );
452
453 request.setFileModel( fileModel );
454 result.setFileModel( fileModel );
455
456 activateFileModel( request, result, problems );
457
458 if ( !request.isTwoPhaseBuilding() )
459 {
460 return build( request, result, importIds );
461 }
462 else if ( hasModelErrors( problems ) )
463 {
464 throw problems.newModelBuildingException();
465 }
466
467 return result;
468 }
469
470 private void activateFileModel( final ModelBuildingRequest request, final DefaultModelBuildingResult result,
471 DefaultModelProblemCollector problems )
472 throws ModelBuildingException
473 {
474 Model inputModel = request.getFileModel();
475 problems.setRootModel( inputModel );
476
477
478 DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
479
480 problems.setSource( "(external profiles)" );
481 List<Profile> activeExternalProfiles = profileSelector.getActiveProfiles( request.getProfiles(),
482 profileActivationContext, problems );
483
484 result.setActiveExternalProfiles( activeExternalProfiles );
485
486 if ( !activeExternalProfiles.isEmpty() )
487 {
488 Properties profileProps = new Properties();
489 for ( Profile profile : activeExternalProfiles )
490 {
491 profileProps.putAll( profile.getProperties() );
492 }
493 profileProps.putAll( profileActivationContext.getUserProperties() );
494 profileActivationContext.setUserProperties( profileProps );
495 }
496
497 profileActivationContext.setProjectProperties( inputModel.getProperties() );
498 problems.setSource( inputModel );
499 List<Profile> activePomProfiles = profileSelector.getActiveProfiles( inputModel.getProfiles(),
500 profileActivationContext, problems );
501
502
503 problems.setSource( inputModel );
504 inputModel.update( modelNormalizer.mergeDuplicates( inputModel.getDelegate(), request, problems ) );
505
506 Map<String, Activation> interpolatedActivations = getProfileActivations( inputModel, false );
507 injectProfileActivations( inputModel, interpolatedActivations );
508
509
510 for ( Profile activeProfile : activePomProfiles )
511 {
512 profileInjector.injectProfile( inputModel, activeProfile, request, problems );
513 }
514
515 for ( Profile activeProfile : activeExternalProfiles )
516 {
517 profileInjector.injectProfile( inputModel, activeProfile, request, problems );
518 }
519 }
520
521 @SuppressWarnings( "checkstyle:methodlength" )
522 private Model readEffectiveModel( final ModelBuildingRequest request, final DefaultModelBuildingResult result,
523 DefaultModelProblemCollector problems )
524 throws ModelBuildingException
525 {
526 Model inputModel =
527 readRawModel( request, problems );
528
529 problems.setRootModel( inputModel );
530
531 ModelData resultData = new ModelData( request.getModelSource(), inputModel );
532 ModelData superData = new ModelData( null, getSuperModel() );
533
534
535 DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
536
537 List<Profile> activeExternalProfiles = result.getActiveExternalProfiles();
538
539 if ( !activeExternalProfiles.isEmpty() )
540 {
541 Properties profileProps = new Properties();
542 for ( Profile profile : activeExternalProfiles )
543 {
544 profileProps.putAll( profile.getProperties() );
545 }
546 profileProps.putAll( profileActivationContext.getUserProperties() );
547 profileActivationContext.setUserProperties( profileProps );
548 }
549
550 Collection<String> parentIds = new LinkedHashSet<>();
551
552 List<Model> lineage = new ArrayList<>();
553
554 for ( ModelData currentData = resultData; ; )
555 {
556 String modelId = currentData.getId();
557 result.addModelId( modelId );
558
559 Model rawModel = currentData.getModel();
560 result.setRawModel( modelId, rawModel );
561
562 profileActivationContext.setProjectProperties( rawModel.getProperties() );
563 problems.setSource( rawModel );
564 List<Profile> activePomProfiles = profileSelector.getActiveProfiles( rawModel.getProfiles(),
565 profileActivationContext, problems );
566 result.setActivePomProfiles( modelId, activePomProfiles );
567
568 Model tmpModel = rawModel.clone();
569
570 problems.setSource( tmpModel );
571
572
573 tmpModel = new Model( modelNormalizer.mergeDuplicates( tmpModel.getDelegate(), request, problems ) );
574
575 profileActivationContext.setProjectProperties( tmpModel.getProperties() );
576
577 Map<String, Activation> interpolatedActivations = getInterpolatedActivations( rawModel,
578 profileActivationContext,
579 problems );
580 injectProfileActivations( tmpModel, interpolatedActivations );
581
582
583 for ( Profile activeProfile : result.getActivePomProfiles( modelId ) )
584 {
585 profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
586 }
587
588 if ( currentData == resultData )
589 {
590 for ( Profile activeProfile : activeExternalProfiles )
591 {
592 profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
593 }
594 result.setEffectiveModel( tmpModel );
595 }
596
597 lineage.add( tmpModel );
598
599 if ( currentData == superData )
600 {
601 break;
602 }
603
604 configureResolver( request.getModelResolver(), tmpModel, problems );
605
606 ModelData parentData =
607 readParent( currentData.getModel(), currentData.getSource(), request, result, problems );
608
609 if ( parentData == null )
610 {
611 currentData = superData;
612 }
613 else if ( !parentIds.add( parentData.getId() ) )
614 {
615 StringBuilder message = new StringBuilder( "The parents form a cycle: " );
616 for ( String parentId : parentIds )
617 {
618 message.append( parentId ).append( " -> " );
619 }
620 message.append( parentData.getId() );
621
622 problems.add( new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE )
623 .setMessage( message.toString() ) );
624
625 throw problems.newModelBuildingException();
626 }
627 else
628 {
629 currentData = parentData;
630 }
631 }
632
633 problems.setSource( result.getRawModel() );
634 checkPluginVersions( lineage, request, problems );
635
636
637 Model resultModel = assembleInheritance( lineage, request, problems );
638
639
640
641 problems.setSource( resultModel );
642 problems.setRootModel( resultModel );
643
644
645 resultModel = interpolateModel( resultModel, request, problems );
646
647
648 modelUrlNormalizer.normalize( resultModel, request );
649
650 result.setEffectiveModel( resultModel );
651
652
653 configureResolver( request.getModelResolver(), resultModel, problems, true );
654
655 return resultModel;
656 }
657
658 private Map<String, Activation> getInterpolatedActivations( Model rawModel,
659 DefaultProfileActivationContext context,
660 DefaultModelProblemCollector problems )
661 {
662 Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, true );
663 for ( Activation activation : interpolatedActivations.values() )
664 {
665 if ( activation.getFile() != null )
666 {
667 replaceWithInterpolatedValue( activation.getFile(), context, problems );
668 }
669 }
670 return interpolatedActivations;
671 }
672
673 private void replaceWithInterpolatedValue( ActivationFile activationFile, ProfileActivationContext context,
674 DefaultModelProblemCollector problems )
675 {
676 try
677 {
678 if ( isNotEmpty( activationFile.getExists() ) )
679 {
680 String path = activationFile.getExists();
681 String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
682 activationFile.setExists( absolutePath );
683 }
684 else if ( isNotEmpty( activationFile.getMissing() ) )
685 {
686 String path = activationFile.getMissing();
687 String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
688 activationFile.setMissing( absolutePath );
689 }
690 }
691 catch ( InterpolationException e )
692 {
693 String path = isNotEmpty(
694 activationFile.getExists() ) ? activationFile.getExists() : activationFile.getMissing();
695
696 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
697 "Failed to interpolate file location " + path + ": " + e.getMessage() ).setLocation(
698 activationFile.getLocation( isNotEmpty( activationFile.getExists() ) ? "exists" : "missing" ) )
699 .setException( e ) );
700 }
701 }
702
703 private static boolean isNotEmpty( String string )
704 {
705 return string != null && !string.isEmpty();
706 }
707
708 @Override
709 public ModelBuildingResult build( final ModelBuildingRequest request, final ModelBuildingResult result )
710 throws ModelBuildingException
711 {
712 return build( request, result, new LinkedHashSet<>() );
713 }
714
715 private ModelBuildingResult build( final ModelBuildingRequest request, final ModelBuildingResult phaseOneResult,
716 Collection<String> imports )
717 throws ModelBuildingException
718 {
719 DefaultModelBuildingResult result = asDefaultModelBuildingResult( phaseOneResult );
720
721 DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
722
723
724 Model resultModel = readEffectiveModel( request, result, problems );
725 problems.setSource( resultModel );
726 problems.setRootModel( resultModel );
727
728
729 modelPathTranslator.alignToBaseDirectory( resultModel, resultModel.getProjectDirectory(), request );
730
731
732 pluginManagementInjector.injectManagement( resultModel, request, problems );
733
734 fireEvent( resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED );
735
736 if ( request.isProcessPlugins() )
737 {
738 if ( lifecycleBindingsInjector == null )
739 {
740 throw new IllegalStateException( "lifecycle bindings injector is missing" );
741 }
742
743
744 lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems );
745 }
746
747
748 importDependencyManagement( resultModel, request, problems, imports );
749
750
751 dependencyManagementInjector.injectManagement( resultModel, request, problems );
752
753 resultModel.update( modelNormalizer.injectDefaultValues( resultModel.getDelegate(), request, problems ) );
754
755 if ( request.isProcessPlugins() )
756 {
757
758 reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
759
760
761 reportingConverter.convertReporting( resultModel, request, problems );
762
763
764 pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
765 }
766
767
768 modelValidator.validateEffectiveModel( resultModel, request, problems );
769
770 if ( hasModelErrors( problems ) )
771 {
772 throw problems.newModelBuildingException();
773 }
774
775 return result;
776 }
777
778 private DefaultModelBuildingResult asDefaultModelBuildingResult( ModelBuildingResult phaseOneResult )
779 {
780 if ( phaseOneResult instanceof DefaultModelBuildingResult )
781 {
782 return (DefaultModelBuildingResult) phaseOneResult;
783 }
784 else
785 {
786 return new DefaultModelBuildingResult( phaseOneResult );
787 }
788 }
789
790 @Override
791 public Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking )
792 {
793 final ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( validationLevel )
794 .setLocationTracking( locationTracking )
795 .setModelSource( new FileModelSource( pomFile ) );
796 final DefaultModelProblemCollector collector =
797 new DefaultModelProblemCollector( new DefaultModelBuildingResult() );
798 try
799 {
800 return newResult( readFileModel( request, collector ), collector.getProblems() );
801 }
802 catch ( ModelBuildingException e )
803 {
804 return error( collector.getProblems() );
805 }
806 }
807
808 private Model readFileModel( ModelBuildingRequest request,
809 DefaultModelProblemCollector problems )
810 throws ModelBuildingException
811 {
812 ModelSource modelSource = request.getModelSource();
813 org.apache.maven.api.model.Model model = fromCache( request.getModelCache(), modelSource, ModelCacheTag.FILE );
814 if ( model == null )
815 {
816 model = doReadFileModel( modelSource, request, problems );
817
818 intoCache( request.getModelCache(), modelSource, ModelCacheTag.FILE, model );
819 }
820
821 if ( modelSource instanceof FileModelSource )
822 {
823 if ( request.getTransformerContextBuilder() instanceof DefaultTransformerContextBuilder )
824 {
825 DefaultTransformerContextBuilder contextBuilder =
826 (DefaultTransformerContextBuilder) request.getTransformerContextBuilder();
827 contextBuilder.putSource( getGroupId( model ), model.getArtifactId(), modelSource );
828 }
829 }
830
831 return new Model( model );
832 }
833
834 @SuppressWarnings( "checkstyle:methodlength" )
835 private org.apache.maven.api.model.Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest request,
836 DefaultModelProblemCollector problems )
837 throws ModelBuildingException
838 {
839 org.apache.maven.api.model.Model model;
840 problems.setSource( modelSource.getLocation() );
841 try
842 {
843 boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
844
845 Map<String, Object> options = new HashMap<>( 3 );
846 options.put( ModelProcessor.IS_STRICT, strict );
847 options.put( ModelProcessor.SOURCE, modelSource );
848
849 InputSource source;
850 if ( request.isLocationTracking() )
851 {
852 source = new InputSource( null, modelSource.getLocation() );
853 options.put( ModelProcessor.INPUT_SOURCE, source );
854 }
855 else
856 {
857 source = null;
858 }
859
860 try
861 {
862 model = modelProcessor.read( modelSource.getInputStream(), options );
863 }
864 catch ( ModelParseException e )
865 {
866 if ( !strict )
867 {
868 throw e;
869 }
870
871 options.put( ModelProcessor.IS_STRICT, Boolean.FALSE );
872
873 try
874 {
875 model = modelProcessor.read( modelSource.getInputStream(), options );
876 }
877 catch ( ModelParseException ne )
878 {
879
880 throw e;
881 }
882
883 Severity severity = ( modelSource instanceof FileModelSource ) ? Severity.ERROR : Severity.WARNING;
884 problems.add( new ModelProblemCollectorRequest( severity, Version.V20 )
885 .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
886 .setException( e ) );
887 }
888
889 if ( source != null )
890 {
891 try
892 {
893 Field field = InputSource.class.getDeclaredField( "modelId" );
894 field.setAccessible( true );
895 field.set( source, ModelProblemUtils.toId( model ) );
896 }
897 catch ( Throwable t )
898 {
899
900 throw new IllegalStateException( "Unable to set modelId on InputSource", t );
901 }
902 }
903 }
904 catch ( ModelParseException e )
905 {
906 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
907 .setMessage( "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage() )
908 .setException( e ) );
909 throw problems.newModelBuildingException();
910 }
911 catch ( IOException e )
912 {
913 String msg = e.getMessage();
914 if ( msg == null || msg.length() <= 0 )
915 {
916
917 if ( e.getClass().getName().endsWith( "MalformedInputException" ) )
918 {
919 msg = "Some input bytes do not match the file encoding.";
920 }
921 else
922 {
923 msg = e.getClass().getSimpleName();
924 }
925 }
926 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
927 .setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg ).setException( e ) );
928 throw problems.newModelBuildingException();
929 }
930
931 if ( modelSource instanceof FileModelSource )
932 {
933 model = model.withPomFile( ( (FileModelSource) modelSource ).getFile().toPath() );
934 }
935
936 Model retModel = new Model( model );
937
938 problems.setSource( retModel );
939
940 modelValidator.validateFileModel( retModel, request, problems );
941
942 if ( hasFatalErrors( problems ) )
943 {
944 throw problems.newModelBuildingException();
945 }
946
947 return model;
948 }
949
950 private Model readRawModel( ModelBuildingRequest request, DefaultModelProblemCollector problems )
951 throws ModelBuildingException
952 {
953 ModelSource modelSource = request.getModelSource();
954
955 ModelData cachedData = fromCache( request.getModelCache(), modelSource, ModelCacheTag.RAW );
956 if ( cachedData != null )
957 {
958 return cachedData.getModel();
959 }
960
961 Model rawModel;
962 if ( Features.buildConsumer( request.getUserProperties() ).isActive()
963 && modelSource instanceof FileModelSource )
964 {
965 rawModel = readFileModel( request, problems );
966 File pomFile = ( (FileModelSource) modelSource ).getFile();
967
968 TransformerContext context = null;
969 if ( request.getTransformerContextBuilder() != null )
970 {
971 context = request.getTransformerContextBuilder().initialize( request, problems );
972 }
973
974 try
975 {
976
977 org.apache.maven.api.model.Model transformedFileModel = modelProcessor.read( pomFile,
978 Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) );
979
980
981
982
983 rawModel = new Model( modelMerger.merge( rawModel.getDelegate(),
984 transformedFileModel, false, null ) );
985 }
986 catch ( IOException e )
987 {
988 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V40 ).setException( e ) );
989 }
990 }
991 else if ( request.getFileModel() == null )
992 {
993 rawModel = readFileModel( request, problems );
994 }
995 else
996 {
997 rawModel = request.getFileModel().clone();
998 }
999
1000 modelValidator.validateRawModel( rawModel, request, problems );
1001
1002 if ( hasFatalErrors( problems ) )
1003 {
1004 throw problems.newModelBuildingException();
1005 }
1006
1007 String groupId = getGroupId( rawModel );
1008 String artifactId = rawModel.getArtifactId();
1009 String version = getVersion( rawModel );
1010
1011 ModelData modelData = new ModelData( modelSource, rawModel, groupId, artifactId, version );
1012 intoCache( request.getModelCache(), modelSource, ModelCacheTag.RAW, modelData );
1013
1014 return rawModel;
1015 }
1016
1017 private String getGroupId( Model model )
1018 {
1019 return getGroupId( model.getDelegate() );
1020 }
1021
1022 private String getGroupId( org.apache.maven.api.model.Model model )
1023 {
1024 String groupId = model.getGroupId();
1025 if ( groupId == null && model.getParent() != null )
1026 {
1027 groupId = model.getParent().getGroupId();
1028 }
1029 return groupId;
1030 }
1031
1032 private String getVersion( Model model )
1033 {
1034 String version = model.getVersion();
1035 if ( version == null && model.getParent() != null )
1036 {
1037 version = model.getParent().getVersion();
1038 }
1039 return version;
1040 }
1041
1042 private DefaultProfileActivationContext getProfileActivationContext( ModelBuildingRequest request )
1043 {
1044 DefaultProfileActivationContext context = new DefaultProfileActivationContext();
1045
1046 context.setActiveProfileIds( request.getActiveProfileIds() );
1047 context.setInactiveProfileIds( request.getInactiveProfileIds() );
1048 context.setSystemProperties( request.getSystemProperties() );
1049 context.setUserProperties( request.getUserProperties() );
1050 context.setProjectDirectory( ( request.getPomFile() != null ) ? request.getPomFile().getParentFile() : null );
1051
1052 return context;
1053 }
1054
1055 private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems )
1056 {
1057 configureResolver( modelResolver, model, problems, false );
1058 }
1059
1060 private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems,
1061 boolean replaceRepositories )
1062 {
1063 if ( modelResolver == null )
1064 {
1065 return;
1066 }
1067
1068 problems.setSource( model );
1069
1070 List<Repository> repositories = model.getRepositories();
1071
1072 for ( Repository repository : repositories )
1073 {
1074 try
1075 {
1076 modelResolver.addRepository( repository, replaceRepositories );
1077 }
1078 catch ( InvalidRepositoryException e )
1079 {
1080 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1081 .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
1082 .setLocation( repository.getLocation( "" ) ).setException( e ) );
1083 }
1084 }
1085 }
1086
1087 private void checkPluginVersions( List<Model> lineage, ModelBuildingRequest request,
1088 ModelProblemCollector problems )
1089 {
1090 if ( request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
1091 {
1092 return;
1093 }
1094
1095 Map<String, Plugin> plugins = new HashMap<>();
1096 Map<String, String> versions = new HashMap<>();
1097 Map<String, String> managedVersions = new HashMap<>();
1098
1099 for ( int i = lineage.size() - 1; i >= 0; i-- )
1100 {
1101 Model model = lineage.get( i );
1102 Build build = model.getBuild();
1103 if ( build != null )
1104 {
1105 for ( Plugin plugin : build.getPlugins() )
1106 {
1107 String key = plugin.getKey();
1108 if ( versions.get( key ) == null )
1109 {
1110 versions.put( key, plugin.getVersion() );
1111 plugins.put( key, plugin );
1112 }
1113 }
1114 PluginManagement mgmt = build.getPluginManagement();
1115 if ( mgmt != null )
1116 {
1117 for ( Plugin plugin : mgmt.getPlugins() )
1118 {
1119 String key = plugin.getKey();
1120 managedVersions.computeIfAbsent( key, k -> plugin.getVersion() );
1121 }
1122 }
1123 }
1124 }
1125
1126 for ( String key : versions.keySet() )
1127 {
1128 if ( versions.get( key ) == null && managedVersions.get( key ) == null )
1129 {
1130 InputLocation location = plugins.get( key ).getLocation( "" );
1131 problems
1132 .add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
1133 .setMessage( "'build.plugins.plugin.version' for " + key + " is missing." )
1134 .setLocation( location ) );
1135 }
1136 }
1137 }
1138
1139 private Model assembleInheritance( List<Model> lineage, ModelBuildingRequest request,
1140 ModelProblemCollector problems )
1141 {
1142 org.apache.maven.api.model.Model parent = lineage.get( lineage.size() - 1 ).getDelegate();
1143 for ( int i = lineage.size() - 2; i >= 0; i-- )
1144 {
1145 Model child = lineage.get( i );
1146 parent = inheritanceAssembler.assembleModelInheritance( child.getDelegate(), parent, request, problems );
1147 }
1148 return new Model( parent );
1149 }
1150
1151 private Map<String, Activation> getProfileActivations( Model model, boolean clone )
1152 {
1153 Map<String, Activation> activations = new HashMap<>();
1154 for ( Profile profile : model.getProfiles() )
1155 {
1156 Activation activation = profile.getActivation();
1157
1158 if ( activation == null )
1159 {
1160 continue;
1161 }
1162
1163 if ( clone )
1164 {
1165 activation = activation.clone();
1166 }
1167
1168 activations.put( profile.getId(), activation );
1169 }
1170
1171 return activations;
1172 }
1173
1174 private void injectProfileActivations( Model model, Map<String, Activation> activations )
1175 {
1176 for ( Profile profile : model.getProfiles() )
1177 {
1178 Activation activation = profile.getActivation();
1179
1180 if ( activation == null )
1181 {
1182 continue;
1183 }
1184
1185
1186 profile.setActivation( activations.get( profile.getId() ) );
1187 }
1188 }
1189
1190 private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
1191 {
1192
1193 Map<String, Activation> originalActivations = getProfileActivations( model, true );
1194
1195 Model interpolatedModel = new Model( modelInterpolator.interpolateModel(
1196 model.getDelegate(), model.getProjectDirectory(), request, problems ) );
1197 if ( interpolatedModel.getParent() != null )
1198 {
1199 StringSearchInterpolator ssi = new StringSearchInterpolator();
1200 ssi.addValueSource( new MapBasedValueSource( request.getUserProperties() ) );
1201
1202 ssi.addValueSource( new MapBasedValueSource( model.getProperties() ) );
1203
1204 ssi.addValueSource( new MapBasedValueSource( request.getSystemProperties() ) );
1205
1206 try
1207 {
1208 String interpolated = ssi.interpolate( interpolatedModel.getParent().getVersion() );
1209 interpolatedModel.getParent().setVersion( interpolated );
1210 }
1211 catch ( Exception e )
1212 {
1213 ModelProblemCollectorRequest mpcr =
1214 new ModelProblemCollectorRequest( Severity.ERROR,
1215 Version.BASE ).setMessage( "Failed to interpolate field: "
1216 + interpolatedModel.getParent().getVersion()
1217 + " on class: " ).setException( e );
1218 problems.add( mpcr );
1219 }
1220
1221
1222 }
1223 interpolatedModel.setPomFile( model.getPomFile() );
1224
1225
1226 injectProfileActivations( model, originalActivations );
1227
1228 return interpolatedModel;
1229 }
1230
1231 private ModelData readParent( Model childModel, Source childSource, ModelBuildingRequest request,
1232 ModelBuildingResult result, DefaultModelProblemCollector problems )
1233 throws ModelBuildingException
1234 {
1235 ModelData parentData = null;
1236
1237 Parent parent = childModel.getParent();
1238 if ( parent != null )
1239 {
1240 parentData = readParentLocally( childModel, childSource, request, result, problems );
1241 if ( parentData == null )
1242 {
1243 parentData = readParentExternally( childModel, request, result, problems );
1244 }
1245
1246 Model parentModel = parentData.getModel();
1247 if ( !"pom".equals( parentModel.getPackaging() ) )
1248 {
1249 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1250 .setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
1251 + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
1252 .setLocation( parentModel.getLocation( "packaging" ) ) );
1253 }
1254 }
1255
1256 return parentData;
1257 }
1258
1259 private ModelData readParentLocally( Model childModel, Source childSource, ModelBuildingRequest request,
1260 ModelBuildingResult result, DefaultModelProblemCollector problems )
1261 throws ModelBuildingException
1262 {
1263 final Parent parent = childModel.getParent();
1264 final ModelSource candidateSource;
1265 final Model candidateModel;
1266 final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
1267 if ( resolver == null )
1268 {
1269 candidateSource = getParentPomFile( childModel, childSource );
1270
1271 if ( candidateSource == null )
1272 {
1273 return null;
1274 }
1275
1276 ModelBuildingRequest candidateBuildRequest = new DefaultModelBuildingRequest( request )
1277 .setModelSource( candidateSource );
1278
1279 candidateModel = readRawModel( candidateBuildRequest, problems );
1280 }
1281 else
1282 {
1283 try
1284 {
1285 candidateModel =
1286 resolver.resolveRawModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
1287 }
1288 catch ( UnresolvableModelException e )
1289 {
1290 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
1291 .setMessage( e.getMessage() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
1292 throw problems.newModelBuildingException();
1293 }
1294 if ( candidateModel == null )
1295 {
1296 return null;
1297 }
1298 candidateSource = new FileModelSource( candidateModel.getPomFile() );
1299 }
1300
1301
1302
1303
1304
1305
1306
1307 String groupId = getGroupId( candidateModel );
1308 String artifactId = candidateModel.getArtifactId();
1309
1310 if ( groupId == null || !groupId.equals( parent.getGroupId() ) || artifactId == null
1311 || !artifactId.equals( parent.getArtifactId() ) )
1312 {
1313 StringBuilder buffer = new StringBuilder( 256 );
1314 buffer.append( "'parent.relativePath'" );
1315 if ( childModel != problems.getRootModel() )
1316 {
1317 buffer.append( " of POM " ).append( ModelProblemUtils.toSourceHint( childModel ) );
1318 }
1319 buffer.append( " points at " ).append( groupId ).append( ':' ).append( artifactId );
1320 buffer.append( " instead of " ).append( parent.getGroupId() ).append( ':' );
1321 buffer.append( parent.getArtifactId() ).append( ", please verify your project structure" );
1322
1323 problems.setSource( childModel );
1324 problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE )
1325 .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ) );
1326 return null;
1327 }
1328
1329 String version = getVersion( candidateModel );
1330 if ( version != null && parent.getVersion() != null && !version.equals( parent.getVersion() ) )
1331 {
1332 try
1333 {
1334 VersionRange parentRange = VersionRange.createFromVersionSpec( parent.getVersion() );
1335 if ( !parentRange.hasRestrictions() )
1336 {
1337
1338 return null;
1339 }
1340 if ( !parentRange.containsVersion( new DefaultArtifactVersion( version ) ) )
1341 {
1342
1343 return null;
1344 }
1345
1346
1347 String rawChildModelVersion = childModel.getVersion();
1348
1349 if ( rawChildModelVersion == null )
1350 {
1351
1352 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1353 .setMessage( "Version must be a constant" ).setLocation( childModel.getLocation( "" ) ) );
1354
1355 }
1356 else
1357 {
1358 if ( rawChildVersionReferencesParent( rawChildModelVersion ) )
1359 {
1360
1361 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1362 .setMessage( "Version must be a constant" )
1363 .setLocation( childModel.getLocation( "version" ) ) );
1364
1365 }
1366 }
1367
1368
1369 }
1370 catch ( InvalidVersionSpecificationException e )
1371 {
1372
1373 return null;
1374 }
1375 }
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386 return new ModelData( candidateSource, candidateModel, groupId, artifactId, version );
1387 }
1388
1389 private boolean rawChildVersionReferencesParent( String rawChildModelVersion )
1390 {
1391 return rawChildModelVersion.equals( "${pom.version}" )
1392 || rawChildModelVersion.equals( "${project.version}" )
1393 || rawChildModelVersion.equals( "${pom.parent.version}" )
1394 || rawChildModelVersion.equals( "${project.parent.version}" );
1395 }
1396
1397 private ModelSource getParentPomFile( Model childModel, Source source )
1398 {
1399 if ( !( source instanceof ModelSource2 ) )
1400 {
1401 return null;
1402 }
1403
1404 String parentPath = childModel.getParent().getRelativePath();
1405
1406 if ( parentPath == null || parentPath.length() <= 0 )
1407 {
1408 return null;
1409 }
1410
1411 return ( (ModelSource2) source ).getRelatedSource( parentPath );
1412 }
1413
1414 private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
1415 ModelBuildingResult result, DefaultModelProblemCollector problems )
1416 throws ModelBuildingException
1417 {
1418 problems.setSource( childModel );
1419
1420 Parent parent = childModel.getParent();
1421
1422 String groupId = parent.getGroupId();
1423 String artifactId = parent.getArtifactId();
1424 String version = parent.getVersion();
1425
1426 ModelResolver modelResolver = request.getModelResolver();
1427 Objects.requireNonNull( modelResolver,
1428 String.format( "request.modelResolver cannot be null (parent POM %s and POM %s)",
1429 ModelProblemUtils.toId( groupId, artifactId, version ),
1430 ModelProblemUtils.toSourceHint( childModel ) ) );
1431
1432 ModelSource modelSource;
1433 try
1434 {
1435 modelSource = modelResolver.resolveModel( parent );
1436 }
1437 catch ( UnresolvableModelException e )
1438 {
1439
1440 StringBuilder buffer = new StringBuilder( 256 );
1441 buffer.append( "Non-resolvable parent POM" );
1442 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
1443 {
1444 buffer.append( ' ' ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
1445 }
1446 if ( childModel != problems.getRootModel() )
1447 {
1448 buffer.append( " for " ).append( ModelProblemUtils.toId( childModel ) );
1449 }
1450 buffer.append( ": " ).append( e.getMessage() );
1451 if ( childModel.getProjectDirectory() != null )
1452 {
1453 if ( parent.getRelativePath() == null || parent.getRelativePath().length() <= 0 )
1454 {
1455 buffer.append( " and 'parent.relativePath' points at no local POM" );
1456 }
1457 else
1458 {
1459 buffer.append( " and 'parent.relativePath' points at wrong local POM" );
1460 }
1461 }
1462
1463 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
1464 .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
1465 throw problems.newModelBuildingException();
1466 }
1467
1468 int validationLevel = Math.min( request.getValidationLevel(), ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 );
1469 ModelBuildingRequest lenientRequest = new DefaultModelBuildingRequest( request )
1470 .setValidationLevel( validationLevel )
1471 .setFileModel( null )
1472 .setModelSource( modelSource );
1473
1474 Model parentModel = readRawModel( lenientRequest, problems );
1475
1476 if ( !parent.getVersion().equals( version ) )
1477 {
1478 String rawChildModelVersion = childModel.getVersion();
1479
1480 if ( rawChildModelVersion == null )
1481 {
1482
1483 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1484 .setMessage( "Version must be a constant" ).setLocation( childModel.getLocation( "" ) ) );
1485
1486 }
1487 else
1488 {
1489 if ( rawChildVersionReferencesParent( rawChildModelVersion ) )
1490 {
1491
1492 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1493 .setMessage( "Version must be a constant" )
1494 .setLocation( childModel.getLocation( "version" ) ) );
1495
1496 }
1497 }
1498
1499
1500 }
1501
1502 return new ModelData( modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(),
1503 parent.getVersion() );
1504 }
1505
1506 private Model getSuperModel()
1507 {
1508 return new Model( superPomProvider.getSuperModel( "4.0.0" ) );
1509 }
1510
1511 private void importDependencyManagement( Model model, ModelBuildingRequest request,
1512 DefaultModelProblemCollector problems, Collection<String> importIds )
1513 {
1514 DependencyManagement depMgmt = model.getDependencyManagement();
1515
1516 if ( depMgmt == null )
1517 {
1518 return;
1519 }
1520
1521 String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
1522
1523 importIds.add( importing );
1524
1525 List<org.apache.maven.api.model.DependencyManagement> importMgmts = null;
1526
1527 for ( Iterator<Dependency> it = depMgmt.getDependencies().iterator(); it.hasNext(); )
1528 {
1529 Dependency dependency = it.next();
1530
1531 if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) )
1532 {
1533 continue;
1534 }
1535
1536 it.remove();
1537
1538 DependencyManagement importMgmt = loadDependencyManagement( model, request, problems,
1539 dependency, importIds );
1540
1541 if ( importMgmt != null )
1542 {
1543 if ( importMgmts == null )
1544 {
1545 importMgmts = new ArrayList<>();
1546 }
1547
1548 importMgmts.add( importMgmt.getDelegate() );
1549 }
1550 }
1551
1552 importIds.remove( importing );
1553
1554 model.update( dependencyManagementImporter.importManagement(
1555 model.getDelegate(), importMgmts, request, problems ) );
1556 }
1557
1558 private DependencyManagement loadDependencyManagement( Model model, ModelBuildingRequest request,
1559 DefaultModelProblemCollector problems,
1560 Dependency dependency,
1561 Collection<String> importIds )
1562 {
1563 String groupId = dependency.getGroupId();
1564 String artifactId = dependency.getArtifactId();
1565 String version = dependency.getVersion();
1566
1567 if ( groupId == null || groupId.length() <= 0 )
1568 {
1569 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1570 .setMessage( "'dependencyManagement.dependencies.dependency.groupId' for "
1571 + dependency.getManagementKey() + " is missing." )
1572 .setLocation( dependency.getLocation( "" ) ) );
1573 return null;
1574 }
1575 if ( artifactId == null || artifactId.length() <= 0 )
1576 {
1577 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1578 .setMessage( "'dependencyManagement.dependencies.dependency.artifactId' for "
1579 + dependency.getManagementKey() + " is missing." )
1580 .setLocation( dependency.getLocation( "" ) ) );
1581 return null;
1582 }
1583 if ( version == null || version.length() <= 0 )
1584 {
1585 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1586 .setMessage( "'dependencyManagement.dependencies.dependency.version' for "
1587 + dependency.getManagementKey() + " is missing." )
1588 .setLocation( dependency.getLocation( "" ) ) );
1589 return null;
1590 }
1591
1592 String imported = groupId + ':' + artifactId + ':' + version;
1593
1594 if ( importIds.contains( imported ) )
1595 {
1596 StringBuilder message =
1597 new StringBuilder( "The dependencies of type=pom and with scope=import form a cycle: " );
1598 for ( String modelId : importIds )
1599 {
1600 message.append( modelId ).append( " -> " );
1601 }
1602 message.append( imported );
1603 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
1604 message.toString() ) );
1605
1606 return null;
1607 }
1608
1609 org.apache.maven.api.model.DependencyManagement importMgmt =
1610 fromCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
1611 if ( importMgmt == null )
1612 {
1613 DependencyManagement importMgmtV3 = doLoadDependencyManagement( model, request, problems, dependency,
1614 groupId, artifactId, version, importIds );
1615 if ( importMgmtV3 != null )
1616 {
1617 importMgmt = importMgmtV3.getDelegate();
1618 intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT,
1619 importMgmt );
1620 }
1621 }
1622
1623 return importMgmt != null ? new DependencyManagement( importMgmt ) : null;
1624 }
1625
1626 @SuppressWarnings( "checkstyle:parameternumber" )
1627 private DependencyManagement doLoadDependencyManagement( Model model, ModelBuildingRequest request,
1628 DefaultModelProblemCollector problems,
1629 Dependency dependency,
1630 String groupId,
1631 String artifactId,
1632 String version,
1633 Collection<String> importIds )
1634 {
1635 DependencyManagement importMgmt;
1636 final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
1637 final ModelResolver modelResolver = request.getModelResolver();
1638 if ( workspaceResolver == null && modelResolver == null )
1639 {
1640 throw new NullPointerException( String.format(
1641 "request.workspaceModelResolver and request.modelResolver cannot be null (parent POM %s and POM %s)",
1642 ModelProblemUtils.toId( groupId, artifactId, version ),
1643 ModelProblemUtils.toSourceHint( model ) ) );
1644 }
1645
1646 Model importModel = null;
1647 if ( workspaceResolver != null )
1648 {
1649 try
1650 {
1651 importModel = workspaceResolver.resolveEffectiveModel( groupId, artifactId, version );
1652 }
1653 catch ( UnresolvableModelException e )
1654 {
1655 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
1656 .setMessage( e.getMessage() ).setException( e ) );
1657 return null;
1658 }
1659 }
1660
1661
1662 if ( importModel == null )
1663 {
1664 final ModelSource importSource;
1665 try
1666 {
1667 importSource = modelResolver.resolveModel( dependency );
1668 }
1669 catch ( UnresolvableModelException e )
1670 {
1671 StringBuilder buffer = new StringBuilder( 256 );
1672 buffer.append( "Non-resolvable import POM" );
1673 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
1674 {
1675 buffer.append( ' ' ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
1676 }
1677 buffer.append( ": " ).append( e.getMessage() );
1678
1679 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1680 .setMessage( buffer.toString() ).setLocation( dependency.getLocation( "" ) )
1681 .setException( e ) );
1682 return null;
1683 }
1684
1685 final ModelBuildingResult importResult;
1686 try
1687 {
1688 ModelBuildingRequest importRequest = new DefaultModelBuildingRequest();
1689 importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
1690 importRequest.setModelCache( request.getModelCache() );
1691 importRequest.setSystemProperties( request.getSystemProperties() );
1692 importRequest.setUserProperties( request.getUserProperties() );
1693 importRequest.setLocationTracking( request.isLocationTracking() );
1694
1695 importRequest.setModelSource( importSource );
1696 importRequest.setModelResolver( modelResolver.newCopy() );
1697
1698 importResult = build( importRequest, importIds );
1699 }
1700 catch ( ModelBuildingException e )
1701 {
1702 problems.addAll( e.getProblems() );
1703 return null;
1704 }
1705
1706 problems.addAll( importResult.getProblems() );
1707
1708 importModel = importResult.getEffectiveModel();
1709 }
1710
1711 importMgmt = importModel.getDependencyManagement();
1712
1713 if ( importMgmt == null )
1714 {
1715 importMgmt = new DependencyManagement();
1716 }
1717 return importMgmt;
1718 }
1719
1720 private <T> void intoCache( ModelCache modelCache, String groupId, String artifactId, String version,
1721 ModelCacheTag<T> tag, T data )
1722 {
1723 if ( modelCache != null )
1724 {
1725 modelCache.put( groupId, artifactId, version, tag, data );
1726 }
1727 }
1728
1729 private <T> void intoCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag, T data )
1730 {
1731 if ( modelCache != null )
1732 {
1733 modelCache.put( source, tag, data );
1734 }
1735 }
1736
1737 private static <T> T fromCache( ModelCache modelCache, String groupId, String artifactId, String version,
1738 ModelCacheTag<T> tag )
1739 {
1740 if ( modelCache != null )
1741 {
1742 return modelCache.get( groupId, artifactId, version, tag );
1743 }
1744 return null;
1745 }
1746
1747 private static <T> T fromCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag )
1748 {
1749 if ( modelCache != null )
1750 {
1751 return modelCache.get( source, tag );
1752 }
1753 return null;
1754 }
1755
1756 private void fireEvent( Model model, ModelBuildingRequest request, ModelProblemCollector problems,
1757 ModelBuildingEventCatapult catapult )
1758 throws ModelBuildingException
1759 {
1760 ModelBuildingListener listener = request.getModelBuildingListener();
1761
1762 if ( listener != null )
1763 {
1764 ModelBuildingEvent event = new DefaultModelBuildingEvent( model, request, problems );
1765
1766 catapult.fire( listener, event );
1767 }
1768 }
1769
1770 private boolean containsCoordinates( String message, String groupId, String artifactId, String version )
1771 {
1772 return message != null && ( groupId == null || message.contains( groupId ) )
1773 && ( artifactId == null || message.contains( artifactId ) )
1774 && ( version == null || message.contains( version ) );
1775 }
1776
1777 protected boolean hasModelErrors( ModelProblemCollectorExt problems )
1778 {
1779 if ( problems instanceof DefaultModelProblemCollector )
1780 {
1781 return ( (DefaultModelProblemCollector) problems ).hasErrors();
1782 }
1783 else
1784 {
1785
1786
1787 throw new IllegalStateException();
1788 }
1789 }
1790
1791 protected boolean hasFatalErrors( ModelProblemCollectorExt problems )
1792 {
1793 if ( problems instanceof DefaultModelProblemCollector )
1794 {
1795 return ( (DefaultModelProblemCollector) problems ).hasFatalErrors();
1796 }
1797 else
1798 {
1799
1800
1801 throw new IllegalStateException();
1802 }
1803 }
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813 private class DefaultTransformerContextBuilder implements TransformerContextBuilder
1814 {
1815 private final DefaultTransformerContext context = new DefaultTransformerContext();
1816
1817 private final Map<DefaultTransformerContext.GAKey, Set<Source>> mappedSources
1818 = new ConcurrentHashMap<>( 64 );
1819
1820
1821
1822
1823
1824
1825
1826
1827 @Override
1828 public TransformerContext initialize( ModelBuildingRequest request, ModelProblemCollector collector )
1829 {
1830
1831 DefaultModelProblemCollector problems = (DefaultModelProblemCollector) collector;
1832 return new TransformerContext()
1833 {
1834 @Override
1835 public String getUserProperty( String key )
1836 {
1837 return context.userProperties.computeIfAbsent( key,
1838 k -> request.getUserProperties().getProperty( key ) );
1839 }
1840
1841 @Override
1842 public Model getRawModel( String gId, String aId )
1843 {
1844 return context.modelByGA.computeIfAbsent( new DefaultTransformerContext.GAKey( gId, aId ),
1845 k -> new DefaultTransformerContext.Holder() )
1846 .computeIfAbsent( () -> findRawModel( gId, aId ) );
1847 }
1848
1849 @Override
1850 public Model getRawModel( Path path )
1851 {
1852 return context.modelByPath.computeIfAbsent( path,
1853 k -> new DefaultTransformerContext.Holder() )
1854 .computeIfAbsent( () -> findRawModel( path ) );
1855 }
1856
1857 private Model findRawModel( String groupId, String artifactId )
1858 {
1859 Source source = getSource( groupId, artifactId );
1860 if ( source != null )
1861 {
1862 try
1863 {
1864 ModelBuildingRequest gaBuildingRequest = new DefaultModelBuildingRequest( request )
1865 .setModelSource( (ModelSource) source );
1866 Model model = readRawModel( gaBuildingRequest, problems );
1867 if ( source instanceof FileModelSource )
1868 {
1869 Path path = ( ( FileModelSource ) source ).getFile().toPath();
1870 context.modelByPath.computeIfAbsent( path, k -> new DefaultTransformerContext.Holder() )
1871 .computeIfAbsent( () -> model );
1872 }
1873 return model;
1874 }
1875 catch ( ModelBuildingException e )
1876 {
1877
1878 }
1879 }
1880 return null;
1881 }
1882
1883 private Model findRawModel( Path p )
1884 {
1885 if ( !Files.isRegularFile( p ) )
1886 {
1887 throw new IllegalArgumentException( "Not a regular file: " + p );
1888 }
1889
1890 DefaultModelBuildingRequest req = new DefaultModelBuildingRequest( request )
1891 .setPomFile( p.toFile() )
1892 .setModelSource( new FileModelSource( p.toFile() ) );
1893
1894 try
1895 {
1896 Model model = readRawModel( req, problems );
1897 DefaultTransformerContext.GAKey key =
1898 new DefaultTransformerContext.GAKey( getGroupId( model ), model.getArtifactId() );
1899 context.modelByGA.computeIfAbsent( key, k -> new DefaultTransformerContext.Holder() )
1900 .computeIfAbsent( () -> model );
1901 return model;
1902 }
1903 catch ( ModelBuildingException e )
1904 {
1905
1906 }
1907 return null;
1908 }
1909 };
1910 }
1911
1912 @Override
1913 public TransformerContext build()
1914 {
1915 return context;
1916 }
1917
1918 public Source getSource( String groupId, String artifactId )
1919 {
1920 Set<Source> sources = mappedSources.get( new DefaultTransformerContext.GAKey( groupId, artifactId ) );
1921 if ( sources == null )
1922 {
1923 return null;
1924 }
1925 return sources.stream().reduce( ( a, b ) ->
1926 {
1927 throw new IllegalStateException( String.format( "No unique Source for %s:%s: %s and %s",
1928 groupId, artifactId,
1929 a.getLocation(), b.getLocation() ) );
1930 } ).orElse( null );
1931 }
1932
1933 public void putSource( String groupId, String artifactId, Source source )
1934 {
1935 mappedSources.computeIfAbsent( new DefaultTransformerContext.GAKey( groupId, artifactId ),
1936 k -> new HashSet<>() ).add( source );
1937 }
1938
1939 }
1940 }