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