Skip to content

Commit a810482

Browse files
committed
[MNG-5102] Add support for POM mixins
1 parent adc13ea commit a810482

File tree

2 files changed

+138
-90
lines changed

2 files changed

+138
-90
lines changed

api/maven-api-model/src/main/mdo/maven.mdo

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,20 @@
113113
</association>
114114
</field>
115115

116+
<!-- ====================================================================== -->
117+
<!-- Mixins -->
118+
<!-- ====================================================================== -->
119+
120+
<field xdoc.separator="blank">
121+
<name>mixins</name>
122+
<version>4.1.0+</version>
123+
<description>Mixins...</description>
124+
<association>
125+
<type>Parent</type>
126+
<multiplicity>*</multiplicity>
127+
</association>
128+
</field>
129+
116130
<!-- ====================================================================== -->
117131
<!-- groupId/artifactId/Version/Packaging -->
118132
<!-- ====================================================================== -->

maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java

Lines changed: 124 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,27 @@ private void activateFileModel(
719719
}
720720
}
721721

722+
static class Lineage {
723+
final Model model;
724+
final List<Lineage> parents;
725+
726+
Lineage(Model model, List<Lineage> parents) {
727+
this.model = model;
728+
this.parents = parents;
729+
}
730+
731+
List<Model> getAllModels() {
732+
List<Model> models = new ArrayList<>();
733+
doGetModels(models);
734+
return models;
735+
}
736+
737+
void doGetModels(List<Model> models) {
738+
models.add(model);
739+
parents.forEach(p -> p.doGetModels(models));
740+
}
741+
}
742+
722743
@SuppressWarnings("checkstyle:methodlength")
723744
private Model readEffectiveModel(
724745
final ModelBuildingRequest request,
@@ -746,100 +767,119 @@ private Model readEffectiveModel(
746767
profileActivationContext.setUserProperties(profileProps);
747768
}
748769

749-
Collection<String> parentIds = new LinkedHashSet<>();
770+
LinkedHashSet<String> parentIds = new LinkedHashSet<>();
771+
Lineage lineage =
772+
getLineage(request, result, problems, resultData, superData, profileActivationContext, parentIds);
750773

751-
List<Model> lineage = new ArrayList<>();
774+
Model tmpModel = lineage.model;
775+
for (Profile activeProfile : activeExternalProfiles) {
776+
profileInjector.injectProfile(tmpModel, activeProfile, request, problems);
777+
}
778+
result.setEffectiveModel(tmpModel);
752779

753-
for (ModelData currentData = resultData; ; ) {
754-
String modelId = currentData.getId();
755-
result.addModelId(modelId);
780+
problems.setSource(result.getRawModel());
781+
checkPluginVersions(lineage, request, problems);
756782

757-
Model rawModel = currentData.getModel();
758-
result.setRawModel(modelId, rawModel);
783+
// inheritance assembly
784+
Model resultModel = assembleInheritance(lineage, request, problems);
759785

760-
profileActivationContext.setProjectProperties(rawModel.getProperties());
761-
problems.setSource(rawModel);
762-
List<Profile> activePomProfiles =
763-
profileSelector.getActiveProfiles(rawModel.getProfiles(), profileActivationContext, problems);
764-
result.setActivePomProfiles(modelId, activePomProfiles);
786+
// consider caching inherited model
765787

766-
Model tmpModel = rawModel.clone();
788+
problems.setSource(resultModel);
789+
problems.setRootModel(resultModel);
767790

768-
problems.setSource(tmpModel);
791+
// model interpolation
792+
resultModel = interpolateModel(resultModel, request, problems);
769793

770-
// model normalization
771-
tmpModel = new Model(modelNormalizer.mergeDuplicates(tmpModel.getDelegate(), request, problems));
794+
// url normalization
795+
modelUrlNormalizer.normalize(resultModel, request);
772796

773-
profileActivationContext.setProjectProperties(tmpModel.getProperties());
797+
result.setEffectiveModel(resultModel);
774798

775-
Map<String, Activation> interpolatedActivations =
776-
getInterpolatedActivations(rawModel, profileActivationContext, problems);
777-
injectProfileActivations(tmpModel, interpolatedActivations);
799+
// Now the fully interpolated model is available: reconfigure the resolver
800+
configureResolver(request.getModelResolver(), resultModel, problems, true);
778801

779-
// profile injection
780-
for (Profile activeProfile : result.getActivePomProfiles(modelId)) {
781-
profileInjector.injectProfile(tmpModel, activeProfile, request, problems);
782-
}
802+
return resultModel;
803+
}
783804

784-
if (currentData == resultData) {
785-
for (Profile activeProfile : activeExternalProfiles) {
786-
profileInjector.injectProfile(tmpModel, activeProfile, request, problems);
787-
}
788-
result.setEffectiveModel(tmpModel);
789-
}
805+
private Lineage getLineage(
806+
ModelBuildingRequest request,
807+
DefaultModelBuildingResult result,
808+
DefaultModelProblemCollector problems,
809+
ModelData resultData,
810+
ModelData superData,
811+
DefaultProfileActivationContext profileActivationContext,
812+
LinkedHashSet<String> parentIds)
813+
throws ModelBuildingException {
790814

791-
lineage.add(tmpModel);
815+
ModelData currentData = resultData;
792816

793-
if (currentData == superData) {
794-
break;
795-
}
817+
String modelId = currentData.getId();
818+
result.addModelId(modelId);
796819

797-
configureResolver(request.getModelResolver(), tmpModel, problems);
820+
Model rawModel = currentData.getModel();
821+
result.setRawModel(modelId, rawModel);
798822

799-
ModelData parentData =
800-
readParent(currentData.getModel(), currentData.getSource(), request, result, problems);
823+
profileActivationContext.setProjectProperties(rawModel.getProperties());
824+
problems.setSource(rawModel);
825+
List<Profile> activePomProfiles =
826+
profileSelector.getActiveProfiles(rawModel.getProfiles(), profileActivationContext, problems);
827+
result.setActivePomProfiles(modelId, activePomProfiles);
801828

802-
if (parentData == null) {
803-
currentData = superData;
804-
} else if (!parentIds.add(parentData.getId())) {
805-
StringBuilder message = new StringBuilder("The parents form a cycle: ");
806-
for (String parentId : parentIds) {
807-
message.append(parentId).append(" -> ");
808-
}
809-
message.append(parentData.getId());
829+
Model tmpModel = rawModel.clone();
810830

811-
problems.add(new ModelProblemCollectorRequest(ModelProblem.Severity.FATAL, ModelProblem.Version.BASE)
812-
.setMessage(message.toString()));
831+
problems.setSource(tmpModel);
813832

814-
throw problems.newModelBuildingException();
815-
} else {
816-
currentData = parentData;
817-
}
818-
}
833+
// model normalization
834+
tmpModel = new Model(modelNormalizer.mergeDuplicates(tmpModel.getDelegate(), request, problems));
819835

820-
problems.setSource(result.getRawModel());
821-
checkPluginVersions(lineage, request, problems);
836+
profileActivationContext.setProjectProperties(tmpModel.getProperties());
822837

823-
// inheritance assembly
824-
Model resultModel = assembleInheritance(lineage, request, problems);
838+
Map<String, Activation> interpolatedActivations =
839+
getInterpolatedActivations(rawModel, profileActivationContext, problems);
840+
injectProfileActivations(tmpModel, interpolatedActivations);
825841

826-
// consider caching inherited model
842+
// profile injection
843+
for (Profile activeProfile : result.getActivePomProfiles(modelId)) {
844+
profileInjector.injectProfile(tmpModel, activeProfile, request, problems);
845+
}
827846

828-
problems.setSource(resultModel);
829-
problems.setRootModel(resultModel);
847+
if (currentData == superData) {
848+
return new Lineage(tmpModel, Collections.emptyList());
849+
}
830850

831-
// model interpolation
832-
resultModel = interpolateModel(resultModel, request, problems);
851+
configureResolver(request.getModelResolver(), tmpModel, problems, false);
833852

834-
// url normalization
835-
modelUrlNormalizer.normalize(resultModel, request);
853+
List<Lineage> parents = new ArrayList<>();
836854

837-
result.setEffectiveModel(resultModel);
855+
List<Parent> list = new ArrayList<>();
856+
list.add(currentData.getModel().getParent());
857+
list.addAll(currentData.getModel().getMixins());
858+
for (Parent parent : list) {
838859

839-
// Now the fully interpolated model is available: reconfigure the resolver
840-
configureResolver(request.getModelResolver(), resultModel, problems, true);
860+
ModelData parentData =
861+
readParent(currentData.getModel(), parent, currentData.getSource(), request, result, problems);
862+
if (parents.isEmpty() && parentData == null) {
863+
parentData = superData;
864+
}
865+
LinkedHashSet<String> newParentIds = new LinkedHashSet<>(parentIds.size() + 1);
866+
newParentIds.addAll(parentIds);
867+
if (!newParentIds.add(parentData.getId())) {
868+
StringBuilder message = new StringBuilder("The parents form a cycle: ");
869+
for (String parentId : newParentIds) {
870+
message.append(parentId).append(" -> ");
871+
}
872+
message.append(parentData.getId());
873+
problems.add(
874+
new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE).setMessage(message.toString()));
841875

842-
return resultModel;
876+
throw problems.newModelBuildingException();
877+
}
878+
parents.add(getLineage(
879+
request, result, problems, parentData, superData, profileActivationContext, newParentIds));
880+
}
881+
882+
return new Lineage(tmpModel, parents);
843883
}
844884

845885
private Map<String, Activation> getInterpolatedActivations(
@@ -1179,10 +1219,6 @@ private DefaultProfileActivationContext getProfileActivationContext(ModelBuildin
11791219
return context;
11801220
}
11811221

1182-
private void configureResolver(ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems) {
1183-
configureResolver(modelResolver, model, problems, false);
1184-
}
1185-
11861222
private void configureResolver(
11871223
ModelResolver modelResolver,
11881224
Model model,
@@ -1208,8 +1244,7 @@ private void configureResolver(
12081244
}
12091245
}
12101246

1211-
private void checkPluginVersions(
1212-
List<Model> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
1247+
private void checkPluginVersions(Lineage lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
12131248
if (request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
12141249
return;
12151250
}
@@ -1218,8 +1253,9 @@ private void checkPluginVersions(
12181253
Map<String, String> versions = new HashMap<>();
12191254
Map<String, String> managedVersions = new HashMap<>();
12201255

1221-
for (int i = lineage.size() - 1; i >= 0; i--) {
1222-
Model model = lineage.get(i);
1256+
List<Model> models = lineage.getAllModels();
1257+
Collections.reverse(models);
1258+
for (Model model : models) {
12231259
Build build = model.getBuild();
12241260
if (build != null) {
12251261
for (Plugin plugin : build.getPlugins()) {
@@ -1249,12 +1285,11 @@ private void checkPluginVersions(
12491285
}
12501286
}
12511287

1252-
private Model assembleInheritance(
1253-
List<Model> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
1254-
org.apache.maven.api.model.Model parent =
1255-
lineage.get(lineage.size() - 1).getDelegate();
1256-
for (int i = lineage.size() - 2; i >= 0; i--) {
1257-
Model child = lineage.get(i);
1288+
private Model assembleInheritance(Lineage lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
1289+
List<Model> models = lineage.getAllModels();
1290+
org.apache.maven.api.model.Model parent = models.get(models.size() - 1).getDelegate();
1291+
for (int i = models.size() - 2; i >= 0; i--) {
1292+
Model child = models.get(i);
12581293
parent = inheritanceAssembler.assembleModelInheritance(child.getDelegate(), parent, request, problems);
12591294
}
12601295
return new Model(parent);
@@ -1329,18 +1364,18 @@ private Model interpolateModel(Model model, ModelBuildingRequest request, ModelP
13291364

13301365
private ModelData readParent(
13311366
Model childModel,
1367+
Parent parent,
13321368
Source childSource,
13331369
ModelBuildingRequest request,
13341370
ModelBuildingResult result,
13351371
DefaultModelProblemCollector problems)
13361372
throws ModelBuildingException {
13371373
ModelData parentData = null;
13381374

1339-
Parent parent = childModel.getParent();
13401375
if (parent != null) {
1341-
parentData = readParentLocally(childModel, childSource, request, result, problems);
1376+
parentData = readParentLocally(childModel, parent, childSource, request, result, problems);
13421377
if (parentData == null) {
1343-
parentData = readParentExternally(childModel, request, result, problems);
1378+
parentData = readParentExternally(childModel, parent, request, result, problems);
13441379
}
13451380

13461381
Model parentModel = parentData.getModel();
@@ -1357,17 +1392,17 @@ private ModelData readParent(
13571392

13581393
private ModelData readParentLocally(
13591394
Model childModel,
1395+
Parent parent,
13601396
Source childSource,
13611397
ModelBuildingRequest request,
13621398
ModelBuildingResult result,
13631399
DefaultModelProblemCollector problems)
13641400
throws ModelBuildingException {
1365-
final Parent parent = childModel.getParent();
13661401
final ModelSource candidateSource;
13671402
final Model candidateModel;
13681403
final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
13691404
if (resolver == null) {
1370-
candidateSource = getParentPomFile(childModel, childSource);
1405+
candidateSource = getParentPomFile(parent, childSource);
13711406

13721407
if (candidateSource == null) {
13731408
return null;
@@ -1480,12 +1515,12 @@ private boolean rawChildVersionReferencesParent(String rawChildModelVersion) {
14801515
|| rawChildModelVersion.equals("${project.parent.version}");
14811516
}
14821517

1483-
private ModelSource getParentPomFile(Model childModel, Source source) {
1518+
private ModelSource getParentPomFile(Parent parent, Source source) {
14841519
if (!(source instanceof ModelSource2)) {
14851520
return null;
14861521
}
14871522

1488-
String parentPath = childModel.getParent().getRelativePath();
1523+
String parentPath = parent.getRelativePath();
14891524

14901525
if (parentPath == null || parentPath.length() <= 0) {
14911526
return null;
@@ -1496,14 +1531,13 @@ private ModelSource getParentPomFile(Model childModel, Source source) {
14961531

14971532
private ModelData readParentExternally(
14981533
Model childModel,
1534+
Parent parent,
14991535
ModelBuildingRequest request,
15001536
ModelBuildingResult result,
15011537
DefaultModelProblemCollector problems)
15021538
throws ModelBuildingException {
15031539
problems.setSource(childModel);
15041540

1505-
Parent parent = childModel.getParent();
1506-
15071541
String groupId = parent.getGroupId();
15081542
String artifactId = parent.getArtifactId();
15091543
String version = parent.getVersion();

0 commit comments

Comments
 (0)