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.api.services.model.ModelVersionParser;
52 import org.apache.maven.building.Source;
53 import org.apache.maven.model.Activation;
54 import org.apache.maven.model.Build;
55 import org.apache.maven.model.Dependency;
56 import org.apache.maven.model.DependencyManagement;
57 import org.apache.maven.model.InputLocation;
58 import org.apache.maven.model.Model;
59 import org.apache.maven.model.Parent;
60 import org.apache.maven.model.Plugin;
61 import org.apache.maven.model.PluginManagement;
62 import org.apache.maven.model.Profile;
63 import org.apache.maven.model.building.ModelProblem.Severity;
64 import org.apache.maven.model.building.ModelProblem.Version;
65 import org.apache.maven.model.composition.DependencyManagementImporter;
66 import org.apache.maven.model.inheritance.InheritanceAssembler;
67 import org.apache.maven.model.interpolation.ModelInterpolator;
68 import org.apache.maven.model.interpolation.ModelVersionProcessor;
69 import org.apache.maven.model.io.ModelParseException;
70 import org.apache.maven.model.io.ModelReader;
71 import org.apache.maven.model.management.DependencyManagementInjector;
72 import org.apache.maven.model.management.PluginManagementInjector;
73 import org.apache.maven.model.normalization.ModelNormalizer;
74 import org.apache.maven.model.path.ModelPathTranslator;
75 import org.apache.maven.model.path.ModelUrlNormalizer;
76 import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
77 import org.apache.maven.model.plugin.LifecycleBindingsInjector;
78 import org.apache.maven.model.plugin.PluginConfigurationExpander;
79 import org.apache.maven.model.plugin.ReportConfigurationExpander;
80 import org.apache.maven.model.plugin.ReportingConverter;
81 import org.apache.maven.model.profile.DefaultProfileActivationContext;
82 import org.apache.maven.model.profile.ProfileActivationContext;
83 import org.apache.maven.model.profile.ProfileInjector;
84 import org.apache.maven.model.profile.ProfileSelector;
85 import org.apache.maven.model.resolution.InvalidRepositoryException;
86 import org.apache.maven.model.resolution.ModelResolver;
87 import org.apache.maven.model.resolution.UnresolvableModelException;
88 import org.apache.maven.model.resolution.WorkspaceModelResolver;
89 import org.apache.maven.model.superpom.SuperPomProvider;
90 import org.apache.maven.model.v4.MavenTransformer;
91 import org.apache.maven.model.validation.DefaultModelValidator;
92 import org.apache.maven.model.validation.ModelValidator;
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 modelValidator.validateExternalProfiles(activeExternalProfiles, inputModel, request, problems);
758 for (Profile activeProfile : activeExternalProfiles) {
759 profileInjector.injectProfile(inputModel, activeProfile, request, problems);
760 }
761 }
762
763 @SuppressWarnings("checkstyle:methodlength")
764 private Model readEffectiveModel(
765 final ModelBuildingRequest request,
766 final DefaultModelBuildingResult result,
767 DefaultModelProblemCollector problems)
768 throws ModelBuildingException {
769 Model inputModel = readRawModel(request, problems);
770 if (problems.hasFatalErrors()) {
771 throw problems.newModelBuildingException();
772 }
773
774 problems.setRootModel(inputModel);
775
776 ModelData resultData = new ModelData(request.getModelSource(), inputModel);
777 String superModelVersion = inputModel.getModelVersion() != null ? inputModel.getModelVersion() : "4.0.0";
778 if (!DefaultModelValidator.VALID_MODEL_VERSIONS.contains(superModelVersion)) {
779
780
781
782 superModelVersion = "4.0.0";
783 }
784 ModelData superData = new ModelData(null, getSuperModel(superModelVersion));
785
786
787 DefaultProfileActivationContext profileActivationContext = getProfileActivationContext(request);
788
789 List<Profile> activeExternalProfiles = result.getActiveExternalProfiles();
790
791 if (!activeExternalProfiles.isEmpty()) {
792 Properties profileProps = new Properties();
793 for (Profile profile : activeExternalProfiles) {
794 profileProps.putAll(profile.getProperties());
795 }
796 profileProps.putAll(profileActivationContext.getUserProperties());
797 profileActivationContext.setUserProperties(profileProps);
798 }
799
800 Collection<String> parentIds = new LinkedHashSet<>();
801
802 List<Model> lineage = new ArrayList<>();
803
804 for (ModelData currentData = resultData; ; ) {
805 String modelId = currentData.getId();
806 result.addModelId(modelId);
807
808 Model model = currentData.getModel();
809 result.setRawModel(modelId, model);
810 problems.setSource(model);
811 org.apache.maven.api.model.Model modelv4 = model.getDelegate();
812
813
814 modelv4 = modelNormalizer.mergeDuplicates(modelv4, request, problems);
815
816
817 profileActivationContext.setProjectProperties(modelv4.getProperties());
818
819 List<org.apache.maven.api.model.Profile> interpolatedProfiles =
820 interpolateActivations(modelv4.getProfiles(), profileActivationContext, problems);
821
822
823 List<org.apache.maven.api.model.Profile> activePomProfiles =
824 profileSelector.getActiveProfilesV4(interpolatedProfiles, profileActivationContext, problems);
825 result.setActivePomProfiles(
826 modelId, activePomProfiles.stream().map(Profile::new).collect(Collectors.toList()));
827 modelv4 = profileInjector.injectProfiles(modelv4, activePomProfiles, request, problems);
828 if (currentData == resultData) {
829 for (Profile activeProfile : activeExternalProfiles) {
830 modelv4 = profileInjector.injectProfile(modelv4, activeProfile.getDelegate(), request, problems);
831 }
832 }
833
834 lineage.add(new Model(modelv4));
835
836 if (currentData == superData) {
837 break;
838 }
839
840
841 configureResolver(request.getModelResolver(), modelv4, problems, false);
842
843
844 ModelData parentData = readParent(new Model(modelv4), currentData.getSource(), request, problems);
845
846 if (parentData == null) {
847 currentData = superData;
848 } else if (!parentIds.add(parentData.getId())) {
849 StringBuilder message = new StringBuilder("The parents form a cycle: ");
850 for (String parentId : parentIds) {
851 message.append(parentId).append(" -> ");
852 }
853 message.append(parentData.getId());
854
855 problems.add(new ModelProblemCollectorRequest(ModelProblem.Severity.FATAL, ModelProblem.Version.BASE)
856 .setMessage(message.toString()));
857
858 throw problems.newModelBuildingException();
859 } else {
860 currentData = parentData;
861 }
862 }
863
864 Model tmpModel = lineage.get(0);
865
866
867 List<org.apache.maven.api.model.Profile> interpolated =
868 interpolateActivations(tmpModel.getDelegate().getProfiles(), profileActivationContext, problems);
869 if (interpolated != tmpModel.getDelegate().getProfiles()) {
870 tmpModel.update(tmpModel.getDelegate().withProfiles(interpolated));
871 }
872
873
874 tmpModel.update(profileInjector.injectProfiles(
875 tmpModel.getDelegate(),
876 activeExternalProfiles.stream().map(Profile::getDelegate).collect(Collectors.toList()),
877 request,
878 problems));
879
880 checkPluginVersions(lineage, request, problems);
881
882
883 Model resultModel = assembleInheritance(lineage, request, problems);
884
885
886
887 problems.setSource(resultModel);
888 problems.setRootModel(resultModel);
889
890
891 resultModel = interpolateModel(resultModel, request, problems);
892
893
894 modelUrlNormalizer.normalize(resultModel, request);
895
896 result.setEffectiveModel(resultModel);
897
898
899 configureResolver(request.getModelResolver(), resultModel.getDelegate(), problems, true);
900
901 return resultModel;
902 }
903
904 private List<org.apache.maven.api.model.Profile> interpolateActivations(
905 List<org.apache.maven.api.model.Profile> profiles,
906 DefaultProfileActivationContext context,
907 DefaultModelProblemCollector problems) {
908 if (profiles.stream()
909 .map(org.apache.maven.api.model.Profile::getActivation)
910 .noneMatch(Objects::nonNull)) {
911 return profiles;
912 }
913 final Interpolator xform = new RegexBasedInterpolator();
914 xform.setCacheAnswers(true);
915 Stream.of(context.getUserProperties(), context.getSystemProperties())
916 .map(MapBasedValueSource::new)
917 .forEach(xform::addValueSource);
918
919 class ProfileInterpolator extends MavenTransformer
920 implements UnaryOperator<org.apache.maven.api.model.Profile> {
921 ProfileInterpolator() {
922 super(s -> {
923 if (isNotEmpty(s)) {
924 try {
925 return xform.interpolate(s);
926 } catch (InterpolationException e) {
927 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
928 .setMessage(e.getMessage())
929 .setException(e));
930 }
931 }
932 return s;
933 });
934 }
935
936 @Override
937 public org.apache.maven.api.model.Profile apply(org.apache.maven.api.model.Profile p) {
938 return org.apache.maven.api.model.Profile.newBuilder(p)
939 .activation(transformActivation(p.getActivation()))
940 .build();
941 }
942
943 @Override
944 protected ActivationFile.Builder transformActivationFile_Missing(
945 Supplier<? extends ActivationFile.Builder> creator,
946 ActivationFile.Builder builder,
947 ActivationFile target) {
948 final String path = target.getMissing();
949 final String xformed = transformPath(path, target, "missing");
950 return xformed != path ? (builder != null ? builder : creator.get()).missing(xformed) : builder;
951 }
952
953 @Override
954 protected ActivationFile.Builder transformActivationFile_Exists(
955 Supplier<? extends ActivationFile.Builder> creator,
956 ActivationFile.Builder builder,
957 ActivationFile target) {
958 final String path = target.getExists();
959 final String xformed = transformPath(path, target, "exists");
960 return xformed != path ? (builder != null ? builder : creator.get()).exists(xformed) : builder;
961 }
962
963 private String transformPath(String path, ActivationFile target, String locationKey) {
964 if (isNotEmpty(path)) {
965 try {
966 return profileActivationFilePathInterpolator.interpolate(path, context);
967 } catch (InterpolationException e) {
968 addInterpolationProblem(problems, target, path, e, locationKey);
969 }
970 }
971 return path;
972 }
973 }
974 return profiles.stream().map(new ProfileInterpolator()).toList();
975 }
976
977 private static void addInterpolationProblem(
978 DefaultModelProblemCollector problems,
979 org.apache.maven.api.model.InputLocationTracker target,
980 String path,
981 InterpolationException e,
982 String locationKey) {
983 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
984 .setMessage("Failed to interpolate file location " + path + ": " + e.getMessage())
985 .setLocation(Optional.ofNullable(target.getLocation(locationKey))
986 .map(InputLocation::new)
987 .orElse(null))
988 .setException(e));
989 }
990
991 private static boolean isNotEmpty(String string) {
992 return string != null && !string.isEmpty();
993 }
994
995 @Override
996 public ModelBuildingResult build(final ModelBuildingRequest request, final ModelBuildingResult result)
997 throws ModelBuildingException {
998 return build(request, result, new LinkedHashSet<>());
999 }
1000
1001 public Model buildRawModel(final ModelBuildingRequest request) throws ModelBuildingException {
1002 DefaultModelProblemCollector problems = new DefaultModelProblemCollector(new DefaultModelBuildingResult());
1003 Model model = readRawModel(request, problems);
1004 if (hasModelErrors(problems)) {
1005 throw problems.newModelBuildingException();
1006 }
1007 return model;
1008 }
1009
1010 private ModelBuildingResult build(
1011 final ModelBuildingRequest request, final ModelBuildingResult phaseOneResult, Collection<String> imports)
1012 throws ModelBuildingException {
1013 DefaultModelBuildingResult result = asDefaultModelBuildingResult(phaseOneResult);
1014
1015 DefaultModelProblemCollector problems = new DefaultModelProblemCollector(result);
1016
1017
1018 Model resultModel = readEffectiveModel(request, result, problems);
1019 problems.setSource(resultModel);
1020 problems.setRootModel(resultModel);
1021
1022
1023 modelPathTranslator.alignToBaseDirectory(resultModel, resultModel.getProjectDirectoryPath(), request);
1024
1025
1026 pluginManagementInjector.injectManagement(resultModel, request, problems);
1027
1028 fireEvent(resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED);
1029
1030 if (request.isProcessPlugins()) {
1031 if (lifecycleBindingsInjector == null) {
1032 throw new IllegalStateException("lifecycle bindings injector is missing");
1033 }
1034
1035
1036 lifecycleBindingsInjector.injectLifecycleBindings(resultModel, request, problems);
1037 }
1038
1039
1040 importDependencyManagement(resultModel, request, problems, imports);
1041
1042
1043 dependencyManagementInjector.injectManagement(resultModel, request, problems);
1044
1045 resultModel.update(modelNormalizer.injectDefaultValues(resultModel.getDelegate(), request, problems));
1046
1047 if (request.isProcessPlugins()) {
1048
1049 reportConfigurationExpander.expandPluginConfiguration(resultModel, request, problems);
1050
1051
1052 pluginConfigurationExpander.expandPluginConfiguration(resultModel, request, problems);
1053 }
1054
1055
1056 modelValidator.validateEffectiveModel(resultModel, request, problems);
1057
1058 if (hasModelErrors(problems)) {
1059 throw problems.newModelBuildingException();
1060 }
1061
1062 return result;
1063 }
1064
1065 private DefaultModelBuildingResult asDefaultModelBuildingResult(ModelBuildingResult phaseOneResult) {
1066 if (phaseOneResult instanceof DefaultModelBuildingResult) {
1067 return (DefaultModelBuildingResult) phaseOneResult;
1068 } else {
1069 return new DefaultModelBuildingResult(phaseOneResult);
1070 }
1071 }
1072
1073 @Deprecated
1074 @Override
1075 public Result<? extends Model> buildRawModel(File pomFile, int validationLevel, boolean locationTracking) {
1076 return buildRawModel(pomFile.toPath(), validationLevel, locationTracking, null);
1077 }
1078
1079 @Override
1080 public Result<? extends Model> buildRawModel(Path pomFile, int validationLevel, boolean locationTracking) {
1081 return buildRawModel(pomFile, validationLevel, locationTracking, null);
1082 }
1083
1084 @Deprecated
1085 @Override
1086 public Result<? extends Model> buildRawModel(
1087 File pomFile, int validationLevel, boolean locationTracking, TransformerContext context) {
1088 return buildRawModel(pomFile.toPath(), validationLevel, locationTracking, context);
1089 }
1090
1091 @Override
1092 public Result<? extends Model> buildRawModel(
1093 Path pomFile, int validationLevel, boolean locationTracking, TransformerContext context) {
1094 final ModelBuildingRequest request = new DefaultModelBuildingRequest()
1095 .setValidationLevel(validationLevel)
1096 .setLocationTracking(locationTracking)
1097 .setModelSource(new FileModelSource(pomFile));
1098 DefaultModelProblemCollector problems = new DefaultModelProblemCollector(new DefaultModelBuildingResult());
1099 try {
1100 Model model = readFileModel(request, problems);
1101
1102 try {
1103 if (transformer != null && context != null) {
1104 transformer.transform(pomFile, context, model);
1105 }
1106 } catch (TransformerException e) {
1107 problems.add(
1108 new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.V40).setException(e));
1109 }
1110
1111 return newResult(model, problems.getProblems());
1112 } catch (ModelBuildingException e) {
1113 return error(problems.getProblems());
1114 }
1115 }
1116
1117 Model readFileModel(ModelBuildingRequest request, DefaultModelProblemCollector problems)
1118 throws ModelBuildingException {
1119 ModelSource modelSource = request.getModelSource();
1120 org.apache.maven.api.model.Model model = cache(
1121 request.getModelCache(),
1122 modelSource,
1123 ModelCacheTag.FILE,
1124 () -> doReadFileModel(modelSource, request, problems));
1125
1126 if (modelSource instanceof FileModelSource) {
1127 if (request.getTransformerContextBuilder() instanceof DefaultTransformerContextBuilder) {
1128 DefaultTransformerContextBuilder contextBuilder =
1129 (DefaultTransformerContextBuilder) request.getTransformerContextBuilder();
1130 contextBuilder.putSource(getGroupId(model), model.getArtifactId(), (FileModelSource) modelSource);
1131 }
1132 }
1133
1134 return new Model(model);
1135 }
1136
1137 @SuppressWarnings("checkstyle:methodlength")
1138 private org.apache.maven.api.model.Model doReadFileModel(
1139 ModelSource modelSource, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1140 throws ModelBuildingException {
1141 org.apache.maven.api.model.Model model;
1142 problems.setSource(modelSource.getLocation());
1143 try {
1144 boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
1145
1146 Map<String, Object> options = new HashMap<>(3);
1147 options.put(ModelProcessor.IS_STRICT, strict);
1148 options.put(ModelProcessor.SOURCE, modelSource);
1149 options.put(ModelReader.ROOT_DIRECTORY, request.getRootDirectory());
1150
1151 InputSource source;
1152 if (request.isLocationTracking()) {
1153 source = new InputSource(null, modelSource.getLocation());
1154 options.put(ModelProcessor.INPUT_SOURCE, new org.apache.maven.model.InputSource(source));
1155 } else {
1156 source = null;
1157 }
1158
1159 try {
1160 model = modelProcessor
1161 .read(modelSource.getInputStream(), options)
1162 .getDelegate();
1163 } catch (ModelParseException e) {
1164 if (!strict) {
1165 throw e;
1166 }
1167
1168 options.put(ModelProcessor.IS_STRICT, Boolean.FALSE);
1169
1170 try {
1171 model = modelProcessor
1172 .read(modelSource.getInputStream(), options)
1173 .getDelegate();
1174 } catch (ModelParseException ne) {
1175
1176 throw e;
1177 }
1178
1179 Severity severity = (modelSource instanceof FileModelSource) ? Severity.ERROR : Severity.WARNING;
1180 problems.add(new ModelProblemCollectorRequest(severity, ModelProblem.Version.V20)
1181 .setMessage("Malformed POM " + modelSource.getLocation() + ": " + e.getMessage())
1182 .setException(e));
1183 }
1184
1185 if (source != null) {
1186 try {
1187 org.apache.maven.api.model.InputLocation loc = model.getLocation("");
1188 org.apache.maven.api.model.InputSource v4src = loc != null ? loc.getSource() : null;
1189 if (v4src != null) {
1190 Field field = InputSource.class.getDeclaredField("modelId");
1191 field.setAccessible(true);
1192 field.set(v4src, ModelProblemUtils.toId(model));
1193 }
1194 } catch (Throwable t) {
1195
1196 throw new IllegalStateException("Unable to set modelId on InputSource", t);
1197 }
1198 }
1199 } catch (ModelParseException e) {
1200 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.BASE)
1201 .setMessage("Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage())
1202 .setException(e));
1203 throw problems.newModelBuildingException();
1204 } catch (IOException e) {
1205 String msg = e.getMessage();
1206 if (msg == null || msg.isEmpty()) {
1207
1208 if (e.getClass().getName().endsWith("MalformedInputException")) {
1209 msg = "Some input bytes do not match the file encoding.";
1210 } else {
1211 msg = e.getClass().getSimpleName();
1212 }
1213 }
1214 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.BASE)
1215 .setMessage("Non-readable POM " + modelSource.getLocation() + ": " + msg)
1216 .setException(e));
1217 throw problems.newModelBuildingException();
1218 }
1219
1220 if (modelSource instanceof FileModelSource) {
1221 model = model.withPomFile(((FileModelSource) modelSource).getPath());
1222 }
1223
1224 Model retModel = new Model(model);
1225
1226 problems.setSource(retModel);
1227
1228 modelValidator.validateFileModel(retModel, request, problems);
1229
1230 if (hasFatalErrors(problems)) {
1231 throw problems.newModelBuildingException();
1232 }
1233
1234 return model;
1235 }
1236
1237 Model readRawModel(ModelBuildingRequest request, DefaultModelProblemCollector problems)
1238 throws ModelBuildingException {
1239 ModelSource modelSource = request.getModelSource();
1240
1241 ModelData modelData = cache(
1242 request.getModelCache(),
1243 modelSource,
1244 ModelCacheTag.RAW,
1245 () -> doReadRawModel(modelSource, request, problems));
1246
1247 return modelData.getModel();
1248 }
1249
1250 private ModelData doReadRawModel(
1251 ModelSource modelSource, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1252 throws ModelBuildingException {
1253 Model rawModel;
1254 if (Features.buildConsumer(request.getUserProperties()) && modelSource instanceof FileModelSource) {
1255 rawModel = readFileModel(request, problems);
1256 File pomFile = ((FileModelSource) modelSource).getFile();
1257
1258 try {
1259 if (request.getTransformerContextBuilder() != null) {
1260 TransformerContext context =
1261 request.getTransformerContextBuilder().initialize(request, problems);
1262 transformer.transform(pomFile.toPath(), context, rawModel);
1263 }
1264 } catch (TransformerException e) {
1265 problems.add(
1266 new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.V40).setException(e));
1267 }
1268 } else if (request.getFileModel() == null) {
1269 rawModel = readFileModel(request, problems);
1270 } else {
1271 rawModel = request.getFileModel().clone();
1272 }
1273
1274 modelValidator.validateRawModel(rawModel, request, problems);
1275
1276 if (hasFatalErrors(problems)) {
1277 throw problems.newModelBuildingException();
1278 }
1279
1280 String groupId = getGroupId(rawModel);
1281 String artifactId = rawModel.getArtifactId();
1282 String version = getVersion(rawModel);
1283
1284 return new ModelData(modelSource, rawModel, groupId, artifactId, version);
1285 }
1286
1287 String getGroupId(Model model) {
1288 return getGroupId(model.getDelegate());
1289 }
1290
1291 private String getGroupId(org.apache.maven.api.model.Model model) {
1292 String groupId = model.getGroupId();
1293 if (groupId == null && model.getParent() != null) {
1294 groupId = model.getParent().getGroupId();
1295 }
1296 return groupId;
1297 }
1298
1299 private String getVersion(Model model) {
1300 String version = model.getVersion();
1301 if (version == null && model.getParent() != null) {
1302 version = model.getParent().getVersion();
1303 }
1304 return version;
1305 }
1306
1307 private DefaultProfileActivationContext getProfileActivationContext(ModelBuildingRequest request) {
1308 DefaultProfileActivationContext context = new DefaultProfileActivationContext();
1309
1310 context.setActiveProfileIds(request.getActiveProfileIds());
1311 context.setInactiveProfileIds(request.getInactiveProfileIds());
1312 context.setSystemProperties(request.getSystemProperties());
1313
1314 Properties userProperties = request.getUserProperties();
1315 if (!userProperties.containsKey(ProfileActivationContext.PROPERTY_NAME_PACKAGING)) {
1316 userProperties.put(
1317 ProfileActivationContext.PROPERTY_NAME_PACKAGING,
1318 request.getFileModel().getPackaging());
1319 }
1320 context.setUserProperties(userProperties);
1321 context.setProjectDirectory(
1322 (request.getPomFile() != null) ? request.getPomFile().getParentFile() : null);
1323
1324 return context;
1325 }
1326
1327 private void configureResolver(
1328 ModelResolver modelResolver,
1329 org.apache.maven.api.model.Model model,
1330 DefaultModelProblemCollector problems,
1331 boolean replaceRepositories) {
1332 if (modelResolver != null) {
1333 for (org.apache.maven.api.model.Repository repository : model.getRepositories()) {
1334 try {
1335 modelResolver.addRepository(repository, replaceRepositories);
1336 } catch (InvalidRepositoryException e) {
1337 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1338 .setMessage("Invalid repository " + repository.getId() + ": " + e.getMessage())
1339 .setLocation(new InputLocation(repository.getLocation("")))
1340 .setException(e));
1341 }
1342 }
1343 }
1344 }
1345
1346 private void checkPluginVersions(
1347 List<Model> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
1348 if (request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
1349 return;
1350 }
1351
1352 Map<String, Plugin> plugins = new HashMap<>();
1353 Map<String, String> versions = new HashMap<>();
1354 Map<String, String> managedVersions = new HashMap<>();
1355
1356 for (int i = lineage.size() - 1; i >= 0; i--) {
1357 Model model = lineage.get(i);
1358 Build build = model.getBuild();
1359 if (build != null) {
1360 for (Plugin plugin : build.getPlugins()) {
1361 String key = plugin.getKey();
1362 if (versions.get(key) == null) {
1363 versions.put(key, plugin.getVersion());
1364 plugins.put(key, plugin);
1365 }
1366 }
1367 PluginManagement mgmt = build.getPluginManagement();
1368 if (mgmt != null) {
1369 for (Plugin plugin : mgmt.getPlugins()) {
1370 String key = plugin.getKey();
1371 managedVersions.computeIfAbsent(key, k -> plugin.getVersion());
1372 }
1373 }
1374 }
1375 }
1376
1377 for (String key : versions.keySet()) {
1378 if (versions.get(key) == null && managedVersions.get(key) == null) {
1379 InputLocation location = plugins.get(key).getLocation("");
1380 problems.add(new ModelProblemCollectorRequest(Severity.WARNING, ModelProblem.Version.V20)
1381 .setMessage("'build.plugins.plugin.version' for " + key + " is missing.")
1382 .setLocation(location));
1383 }
1384 }
1385 }
1386
1387 private Model assembleInheritance(
1388 List<Model> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
1389 org.apache.maven.api.model.Model parent =
1390 lineage.get(lineage.size() - 1).getDelegate();
1391 for (int i = lineage.size() - 2; i >= 0; i--) {
1392 Model child = lineage.get(i);
1393 parent = inheritanceAssembler.assembleModelInheritance(child.getDelegate(), parent, request, problems);
1394 }
1395 return new Model(parent);
1396 }
1397
1398 private Map<String, Activation> getProfileActivations(Model model, boolean clone) {
1399 Map<String, Activation> activations = new HashMap<>();
1400 for (Profile profile : model.getProfiles()) {
1401 Activation activation = profile.getActivation();
1402
1403 if (activation == null) {
1404 continue;
1405 }
1406
1407 if (clone) {
1408 activation = activation.clone();
1409 }
1410
1411 activations.put(profile.getId(), activation);
1412 }
1413
1414 return activations;
1415 }
1416
1417 private void injectProfileActivations(Model model, Map<String, Activation> activations) {
1418 for (Profile profile : model.getProfiles()) {
1419 Activation activation = profile.getActivation();
1420
1421 if (activation == null) {
1422 continue;
1423 }
1424
1425
1426 profile.setActivation(activations.get(profile.getId()));
1427 }
1428 }
1429
1430 private Model interpolateModel(Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
1431
1432 Map<String, Activation> originalActivations = getProfileActivations(model, true);
1433
1434 Model interpolatedModel = new Model(modelInterpolator.interpolateModel(
1435 model.getDelegate(), model.getProjectDirectoryPath(), request, problems));
1436 if (interpolatedModel.getParent() != null) {
1437 StringSearchInterpolator ssi = new StringSearchInterpolator();
1438 ssi.addValueSource(new MapBasedValueSource(request.getUserProperties()));
1439
1440 ssi.addValueSource(new MapBasedValueSource(model.getProperties()));
1441
1442 ssi.addValueSource(new MapBasedValueSource(request.getSystemProperties()));
1443
1444 try {
1445 String interpolated =
1446 ssi.interpolate(interpolatedModel.getParent().getVersion());
1447 interpolatedModel.getParent().setVersion(interpolated);
1448 } catch (Exception e) {
1449 ModelProblemCollectorRequest mpcr = new ModelProblemCollectorRequest(
1450 Severity.ERROR, ModelProblem.Version.BASE)
1451 .setMessage("Failed to interpolate field: "
1452 + interpolatedModel.getParent().getVersion()
1453 + " on class: ")
1454 .setException(e);
1455 problems.add(mpcr);
1456 }
1457 }
1458 interpolatedModel.setPomPath(model.getPomPath());
1459
1460
1461 injectProfileActivations(model, originalActivations);
1462
1463 return interpolatedModel;
1464 }
1465
1466 private ModelData readParent(
1467 Model childModel, Source childSource, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1468 throws ModelBuildingException {
1469 ModelData parentData = null;
1470
1471 Parent parent = childModel.getParent();
1472 if (parent != null) {
1473 parentData = readParentLocally(childModel, childSource, request, problems);
1474 if (parentData == null) {
1475 parentData = readParentExternally(childModel, request, problems);
1476 }
1477
1478 Model parentModel = parentData.getModel();
1479 if (!"pom".equals(parentModel.getPackaging())) {
1480 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1481 .setMessage("Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint(parentModel)
1482 + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"")
1483 .setLocation(parentModel.getLocation("packaging")));
1484 }
1485 }
1486
1487 return parentData;
1488 }
1489
1490 private ModelData readParentLocally(
1491 Model childModel, Source childSource, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1492 throws ModelBuildingException {
1493 final Parent parent = childModel.getParent();
1494 final ModelSource2 candidateSource;
1495 final Model candidateModel;
1496 final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
1497 if (resolver == null) {
1498 candidateSource = getParentPomFile(childModel, childSource);
1499
1500 if (candidateSource == null) {
1501 return null;
1502 }
1503
1504 ModelBuildingRequest candidateBuildRequest =
1505 new DefaultModelBuildingRequest(request).setModelSource(candidateSource);
1506
1507 candidateModel = readRawModel(candidateBuildRequest, problems);
1508 } else {
1509 try {
1510 candidateModel =
1511 resolver.resolveRawModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
1512 } catch (UnresolvableModelException e) {
1513 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.BASE)
1514 .setMessage(e.getMessage())
1515 .setLocation(parent.getLocation(""))
1516 .setException(e));
1517 throw problems.newModelBuildingException();
1518 }
1519 if (candidateModel == null) {
1520 return null;
1521 }
1522 candidateSource = new FileModelSource(candidateModel.getPomPath());
1523 }
1524
1525
1526
1527
1528
1529
1530
1531 String groupId = getGroupId(candidateModel);
1532 String artifactId = candidateModel.getArtifactId();
1533
1534 if (groupId == null
1535 || !groupId.equals(parent.getGroupId())
1536 || artifactId == null
1537 || !artifactId.equals(parent.getArtifactId())) {
1538 StringBuilder buffer = new StringBuilder(256);
1539 buffer.append("'parent.relativePath'");
1540 if (childModel != problems.getRootModel()) {
1541 buffer.append(" of POM ").append(ModelProblemUtils.toSourceHint(childModel));
1542 }
1543 buffer.append(" points at ").append(groupId).append(':').append(artifactId);
1544 buffer.append(" instead of ").append(parent.getGroupId()).append(':');
1545 buffer.append(parent.getArtifactId()).append(", please verify your project structure");
1546
1547 problems.setSource(childModel);
1548 problems.add(new ModelProblemCollectorRequest(Severity.WARNING, ModelProblem.Version.BASE)
1549 .setMessage(buffer.toString())
1550 .setLocation(parent.getLocation("")));
1551 return null;
1552 }
1553
1554 String version = getVersion(candidateModel);
1555 if (version != null && parent.getVersion() != null && !version.equals(parent.getVersion())) {
1556 try {
1557 VersionRange parentRange = versionParser.parseVersionRange(parent.getVersion());
1558 if (!parentRange.contains(versionParser.parseVersion(version))) {
1559
1560 return null;
1561 }
1562
1563
1564 String rawChildModelVersion = childModel.getVersion();
1565
1566 if (rawChildModelVersion == null) {
1567
1568 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.V31)
1569 .setMessage("Version must be a constant")
1570 .setLocation(childModel.getLocation("")));
1571
1572 } else {
1573 if (rawChildVersionReferencesParent(rawChildModelVersion)) {
1574
1575 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.V31)
1576 .setMessage("Version must be a constant")
1577 .setLocation(childModel.getLocation("version")));
1578 }
1579 }
1580
1581
1582 } catch (VersionParserException e) {
1583
1584 return null;
1585 }
1586 }
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597 return new ModelData(candidateSource, candidateModel, groupId, artifactId, version);
1598 }
1599
1600 private boolean rawChildVersionReferencesParent(String rawChildModelVersion) {
1601 return rawChildModelVersion.equals("${pom.version}")
1602 || rawChildModelVersion.equals("${project.version}")
1603 || rawChildModelVersion.equals("${pom.parent.version}")
1604 || rawChildModelVersion.equals("${project.parent.version}");
1605 }
1606
1607 private ModelSource2 getParentPomFile(Model childModel, Source source) {
1608 if (!(source instanceof ModelSource2)) {
1609 return null;
1610 }
1611
1612 String parentPath = childModel.getParent().getRelativePath();
1613
1614 if (parentPath == null || parentPath.isEmpty()) {
1615 return null;
1616 }
1617
1618 if (source instanceof ModelSource3) {
1619 return ((ModelSource3) source).getRelatedSource(modelProcessor, parentPath);
1620 } else {
1621 return ((ModelSource2) source).getRelatedSource(parentPath);
1622 }
1623 }
1624
1625 private ModelData readParentExternally(
1626 Model childModel, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1627 throws ModelBuildingException {
1628 problems.setSource(childModel);
1629
1630 Parent parent = childModel.getParent();
1631
1632 String groupId = parent.getGroupId();
1633 String artifactId = parent.getArtifactId();
1634 String version = parent.getVersion();
1635
1636 ModelResolver modelResolver = request.getModelResolver();
1637 Objects.requireNonNull(
1638 modelResolver,
1639 String.format(
1640 "request.modelResolver cannot be null (parent POM %s and POM %s)",
1641 ModelProblemUtils.toId(groupId, artifactId, version),
1642 ModelProblemUtils.toSourceHint(childModel)));
1643
1644 ModelSource modelSource;
1645 try {
1646 modelSource = modelResolver.resolveModel(parent);
1647 } catch (UnresolvableModelException e) {
1648
1649 StringBuilder buffer = new StringBuilder(256);
1650 buffer.append("Non-resolvable parent POM");
1651 if (!containsCoordinates(e.getMessage(), groupId, artifactId, version)) {
1652 buffer.append(' ').append(ModelProblemUtils.toId(groupId, artifactId, version));
1653 }
1654 if (childModel != problems.getRootModel()) {
1655 buffer.append(" for ").append(ModelProblemUtils.toId(childModel));
1656 }
1657 buffer.append(": ").append(e.getMessage());
1658 if (childModel.getProjectDirectoryPath() != null) {
1659 if (parent.getRelativePath() == null || parent.getRelativePath().isEmpty()) {
1660 buffer.append(" and 'parent.relativePath' points at no local POM");
1661 } else {
1662 buffer.append(" and 'parent.relativePath' points at wrong local POM");
1663 }
1664 }
1665
1666 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.BASE)
1667 .setMessage(buffer.toString())
1668 .setLocation(parent.getLocation(""))
1669 .setException(e));
1670 throw problems.newModelBuildingException();
1671 }
1672
1673 int validationLevel = Math.min(request.getValidationLevel(), ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0);
1674 ModelBuildingRequest lenientRequest = new DefaultModelBuildingRequest(request)
1675 .setValidationLevel(validationLevel)
1676 .setFileModel(null)
1677 .setModelSource(modelSource);
1678
1679 Model parentModel = readRawModel(lenientRequest, problems);
1680
1681 if (!parent.getVersion().equals(version)) {
1682 String rawChildModelVersion = childModel.getVersion();
1683
1684 if (rawChildModelVersion == null) {
1685
1686 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.V31)
1687 .setMessage("Version must be a constant")
1688 .setLocation(childModel.getLocation("")));
1689
1690 } else {
1691 if (rawChildVersionReferencesParent(rawChildModelVersion)) {
1692
1693 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.V31)
1694 .setMessage("Version must be a constant")
1695 .setLocation(childModel.getLocation("version")));
1696 }
1697 }
1698
1699
1700 }
1701
1702 return new ModelData(
1703 modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
1704 }
1705
1706 private Model getSuperModel(String modelVersion) {
1707 return superPomProvider.getSuperModel(modelVersion);
1708 }
1709
1710 private void importDependencyManagement(
1711 Model model,
1712 ModelBuildingRequest request,
1713 DefaultModelProblemCollector problems,
1714 Collection<String> importIds) {
1715 DependencyManagement depMgmt = model.getDependencyManagement();
1716
1717 if (depMgmt == null) {
1718 return;
1719 }
1720
1721 String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
1722
1723 importIds.add(importing);
1724
1725
1726 List<org.apache.maven.api.model.DependencyManagement> importMgmts = new ArrayList<>();
1727
1728 for (Iterator<Dependency> it = depMgmt.getDependencies().iterator(); it.hasNext(); ) {
1729 Dependency dependency = it.next();
1730
1731 if (!("pom".equals(dependency.getType()) && "import".equals(dependency.getScope()))
1732 || "bom".equals(dependency.getType())) {
1733 continue;
1734 }
1735
1736 it.remove();
1737
1738
1739 DependencyManagement importMgmt = loadDependencyManagement(model, request, problems, dependency, importIds);
1740 if (importMgmt == null) {
1741 continue;
1742 }
1743
1744 if (request.isLocationTracking()) {
1745
1746
1747 importMgmts.add(
1748 org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true)
1749 .build());
1750 } else {
1751 importMgmts.add(importMgmt.getDelegate());
1752 }
1753 }
1754
1755 importIds.remove(importing);
1756
1757 model.update(
1758 dependencyManagementImporter.importManagement(model.getDelegate(), importMgmts, request, problems));
1759 }
1760
1761 private DependencyManagement loadDependencyManagement(
1762 Model model,
1763 ModelBuildingRequest request,
1764 DefaultModelProblemCollector problems,
1765 Dependency dependency,
1766 Collection<String> importIds) {
1767 String groupId = dependency.getGroupId();
1768 String artifactId = dependency.getArtifactId();
1769 String version = dependency.getVersion();
1770
1771 if (groupId == null || groupId.isEmpty()) {
1772 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1773 .setMessage("'dependencyManagement.dependencies.dependency.groupId' for "
1774 + dependency.getManagementKey() + " is missing.")
1775 .setLocation(dependency.getLocation("")));
1776 return null;
1777 }
1778 if (artifactId == null || artifactId.isEmpty()) {
1779 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1780 .setMessage("'dependencyManagement.dependencies.dependency.artifactId' for "
1781 + dependency.getManagementKey() + " is missing.")
1782 .setLocation(dependency.getLocation("")));
1783 return null;
1784 }
1785 if (version == null || version.isEmpty()) {
1786 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1787 .setMessage("'dependencyManagement.dependencies.dependency.version' for "
1788 + dependency.getManagementKey() + " is missing.")
1789 .setLocation(dependency.getLocation("")));
1790 return null;
1791 }
1792
1793 String imported = groupId + ':' + artifactId + ':' + version;
1794
1795 if (importIds.contains(imported)) {
1796 StringBuilder message =
1797 new StringBuilder("The dependencies of type=pom and with scope=import form a cycle: ");
1798 for (String modelId : importIds) {
1799 message.append(modelId).append(" -> ");
1800 }
1801 message.append(imported);
1802 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1803 .setMessage(message.toString()));
1804
1805 return null;
1806 }
1807
1808 org.apache.maven.api.model.DependencyManagement importMgmt = cache(
1809 request.getModelCache(),
1810 groupId,
1811 artifactId,
1812 version,
1813 ModelCacheTag.IMPORT,
1814 () -> doLoadDependencyManagement(
1815 model, request, problems, dependency, groupId, artifactId, version, importIds));
1816
1817
1818 List<Exclusion> exclusions = dependency.getDelegate().getExclusions();
1819 if (importMgmt != null && !exclusions.isEmpty()) {
1820
1821 List<org.apache.maven.api.model.Dependency> dependencies = importMgmt.getDependencies().stream()
1822 .filter(candidate -> exclusions.stream().noneMatch(exclusion -> match(exclusion, candidate)))
1823 .map(candidate -> addExclusions(candidate, exclusions))
1824 .collect(Collectors.toList());
1825 importMgmt = importMgmt.withDependencies(dependencies);
1826 }
1827
1828 return importMgmt != null ? new DependencyManagement(importMgmt) : null;
1829 }
1830
1831 private static org.apache.maven.api.model.Dependency addExclusions(
1832 org.apache.maven.api.model.Dependency candidate, List<Exclusion> exclusions) {
1833 return candidate.withExclusions(Stream.concat(candidate.getExclusions().stream(), exclusions.stream())
1834 .toList());
1835 }
1836
1837 private boolean match(Exclusion exclusion, org.apache.maven.api.model.Dependency candidate) {
1838 return match(exclusion.getGroupId(), candidate.getGroupId())
1839 && match(exclusion.getArtifactId(), candidate.getArtifactId());
1840 }
1841
1842 private boolean match(String match, String text) {
1843 return match.equals("*") || match.equals(text);
1844 }
1845
1846 @SuppressWarnings("checkstyle:parameternumber")
1847 private org.apache.maven.api.model.DependencyManagement doLoadDependencyManagement(
1848 Model model,
1849 ModelBuildingRequest request,
1850 DefaultModelProblemCollector problems,
1851 Dependency dependency,
1852 String groupId,
1853 String artifactId,
1854 String version,
1855 Collection<String> importIds) {
1856 DependencyManagement importMgmt;
1857 final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
1858 final ModelResolver modelResolver = request.getModelResolver();
1859 if (workspaceResolver == null && modelResolver == null) {
1860 throw new NullPointerException(String.format(
1861 "request.workspaceModelResolver and request.modelResolver cannot be null (parent POM %s and POM %s)",
1862 ModelProblemUtils.toId(groupId, artifactId, version), ModelProblemUtils.toSourceHint(model)));
1863 }
1864
1865 Model importModel = null;
1866 if (workspaceResolver != null) {
1867 try {
1868 importModel = workspaceResolver.resolveEffectiveModel(groupId, artifactId, version);
1869 } catch (UnresolvableModelException e) {
1870 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, ModelProblem.Version.BASE)
1871 .setMessage(e.getMessage())
1872 .setException(e));
1873 return null;
1874 }
1875 }
1876
1877
1878 if (importModel == null) {
1879 final ModelSource importSource;
1880 try {
1881 importSource = modelResolver.resolveModel(dependency);
1882 } catch (UnresolvableModelException e) {
1883 StringBuilder buffer = new StringBuilder(256);
1884 buffer.append("Non-resolvable import POM");
1885 if (!containsCoordinates(e.getMessage(), groupId, artifactId, version)) {
1886 buffer.append(' ').append(ModelProblemUtils.toId(groupId, artifactId, version));
1887 }
1888 buffer.append(": ").append(e.getMessage());
1889
1890 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE)
1891 .setMessage(buffer.toString())
1892 .setLocation(dependency.getLocation(""))
1893 .setException(e));
1894 return null;
1895 }
1896
1897 if (importSource instanceof FileModelSource && request.getRootDirectory() != null) {
1898 Path sourcePath = ((FileModelSource) importSource).getPath();
1899 if (sourcePath.startsWith(request.getRootDirectory())) {
1900 problems.add(new ModelProblemCollectorRequest(Severity.WARNING, ModelProblem.Version.BASE)
1901 .setMessage("BOM imports from within reactor should be avoided")
1902 .setLocation(dependency.getLocation("")));
1903 }
1904 }
1905
1906 final ModelBuildingResult importResult;
1907 try {
1908 ModelBuildingRequest importRequest = new DefaultModelBuildingRequest();
1909 importRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
1910 importRequest.setModelCache(request.getModelCache());
1911 importRequest.setSystemProperties(request.getSystemProperties());
1912 importRequest.setUserProperties(request.getUserProperties());
1913 importRequest.setLocationTracking(request.isLocationTracking());
1914
1915 importRequest.setModelSource(importSource);
1916 importRequest.setModelResolver(modelResolver.newCopy());
1917
1918 importResult = build(importRequest, importIds);
1919 } catch (ModelBuildingException e) {
1920 problems.addAll(e.getProblems());
1921 return null;
1922 }
1923
1924 problems.addAll(importResult.getProblems());
1925
1926 importModel = importResult.getEffectiveModel();
1927 }
1928
1929 importMgmt = importModel.getDependencyManagement();
1930
1931 if (importMgmt == null) {
1932 importMgmt = new DependencyManagement();
1933 }
1934 return importMgmt.getDelegate();
1935 }
1936
1937 private static <T> T cache(
1938 ModelCache cache,
1939 String groupId,
1940 String artifactId,
1941 String version,
1942 ModelCacheTag<T> tag,
1943 Callable<T> supplier) {
1944 Supplier<T> s = asSupplier(supplier);
1945 if (cache == null) {
1946 return s.get();
1947 } else {
1948 return cache.computeIfAbsent(groupId, artifactId, version, tag.getName(), s);
1949 }
1950 }
1951
1952 private static <T> T cache(ModelCache cache, Source source, ModelCacheTag<T> tag, Callable<T> supplier) {
1953 Supplier<T> s = asSupplier(supplier);
1954 if (cache == null) {
1955 return s.get();
1956 } else {
1957 return cache.computeIfAbsent(source, tag.getName(), s);
1958 }
1959 }
1960
1961 private static <T> Supplier<T> asSupplier(Callable<T> supplier) {
1962 return () -> {
1963 try {
1964 return supplier.call();
1965 } catch (Exception e) {
1966 uncheckedThrow(e);
1967 return null;
1968 }
1969 };
1970 }
1971
1972 static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
1973 throw (T) t;
1974 }
1975
1976 private void fireEvent(
1977 Model model,
1978 ModelBuildingRequest request,
1979 ModelProblemCollector problems,
1980 ModelBuildingEventCatapult catapult) {
1981 ModelBuildingListener listener = request.getModelBuildingListener();
1982
1983 if (listener != null) {
1984 ModelBuildingEvent event = new DefaultModelBuildingEvent(model, request, problems);
1985
1986 catapult.fire(listener, event);
1987 }
1988 }
1989
1990 private boolean containsCoordinates(String message, String groupId, String artifactId, String version) {
1991 return message != null
1992 && (groupId == null || message.contains(groupId))
1993 && (artifactId == null || message.contains(artifactId))
1994 && (version == null || message.contains(version));
1995 }
1996
1997 protected boolean hasModelErrors(ModelProblemCollectorExt problems) {
1998 if (problems instanceof DefaultModelProblemCollector) {
1999 return ((DefaultModelProblemCollector) problems).hasErrors();
2000 } else {
2001
2002
2003 throw new IllegalStateException();
2004 }
2005 }
2006
2007 protected boolean hasFatalErrors(ModelProblemCollectorExt problems) {
2008 if (problems instanceof DefaultModelProblemCollector) {
2009 return ((DefaultModelProblemCollector) problems).hasFatalErrors();
2010 } else {
2011
2012
2013 throw new IllegalStateException();
2014 }
2015 }
2016
2017 ModelProcessor getModelProcessor() {
2018 return modelProcessor;
2019 }
2020 }