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