6666import org .apache .maven .api .model .Exclusion ;
6767import org .apache .maven .api .model .InputLocation ;
6868import org .apache .maven .api .model .InputSource ;
69+ import org .apache .maven .api .model .Mixin ;
6970import org .apache .maven .api .model .Model ;
7071import org .apache .maven .api .model .Parent ;
7172import org .apache .maven .api .model .Profile ;
@@ -838,12 +839,11 @@ void buildEffectiveModel(Collection<String> importIds) throws ModelBuilderExcept
838839 }
839840 }
840841
841- Model readParent (Model childModel , DefaultProfileActivationContext profileActivationContext ) {
842+ Model readParent (Model childModel , Parent parent , DefaultProfileActivationContext profileActivationContext ) {
842843 Model parentModel ;
843844
844- Parent parent = childModel .getParent ();
845845 if (parent != null ) {
846- parentModel = resolveParent (childModel , profileActivationContext );
846+ parentModel = resolveParent (childModel , parent , profileActivationContext );
847847
848848 if (!"pom" .equals (parentModel .getPackaging ())) {
849849 add (
@@ -868,23 +868,26 @@ Model readParent(Model childModel, DefaultProfileActivationContext profileActiva
868868 return parentModel ;
869869 }
870870
871- private Model resolveParent (Model childModel , DefaultProfileActivationContext profileActivationContext )
871+ private Model resolveParent (
872+ Model childModel , Parent parent , DefaultProfileActivationContext profileActivationContext )
872873 throws ModelBuilderException {
873874 Model parentModel = null ;
874875 if (isBuildRequest ()) {
875- parentModel = readParentLocally (childModel , profileActivationContext );
876+ parentModel = readParentLocally (childModel , parent , profileActivationContext );
876877 }
877878 if (parentModel == null ) {
878- parentModel = resolveAndReadParentExternally (childModel , profileActivationContext );
879+ parentModel = resolveAndReadParentExternally (childModel , parent , profileActivationContext );
879880 }
880881 return parentModel ;
881882 }
882883
883- private Model readParentLocally (Model childModel , DefaultProfileActivationContext profileActivationContext )
884+ private Model readParentLocally (
885+ Model childModel , Parent parent , DefaultProfileActivationContext profileActivationContext )
884886 throws ModelBuilderException {
885887 ModelSource candidateSource ;
886888
887- Parent parent = childModel .getParent ();
889+ boolean isParentOrSimpleMixin = !(parent instanceof Mixin )
890+ || (((Mixin ) parent ).getClassifier () == null && ((Mixin ) parent ).getExtension () == null );
888891 String parentPath = parent .getRelativePath ();
889892 if (request .getRequestType () == ModelBuilderRequest .RequestType .BUILD_PROJECT ) {
890893 if (parentPath != null && !parentPath .isEmpty ()) {
@@ -893,14 +896,16 @@ private Model readParentLocally(Model childModel, DefaultProfileActivationContex
893896 wrongParentRelativePath (childModel );
894897 return null ;
895898 }
896- } else {
899+ } else if ( isParentOrSimpleMixin ) {
897900 candidateSource =
898901 resolveReactorModel (parent .getGroupId (), parent .getArtifactId (), parent .getVersion ());
899902 if (candidateSource == null && parentPath == null ) {
900903 candidateSource = request .getSource ().resolve (modelProcessor ::locateExistingPom , ".." );
901904 }
905+ } else {
906+ candidateSource = null ;
902907 }
903- } else {
908+ } else if ( isParentOrSimpleMixin ) {
904909 candidateSource = resolveReactorModel (parent .getGroupId (), parent .getArtifactId (), parent .getVersion ());
905910 if (candidateSource == null ) {
906911 if (parentPath == null ) {
@@ -910,6 +915,8 @@ private Model readParentLocally(Model childModel, DefaultProfileActivationContex
910915 candidateSource = request .getSource ().resolve (modelProcessor ::locateExistingPom , parentPath );
911916 }
912917 }
918+ } else {
919+ candidateSource = null ;
913920 }
914921
915922 if (candidateSource == null ) {
@@ -925,11 +932,10 @@ private Model readParentLocally(Model childModel, DefaultProfileActivationContex
925932 String version = getVersion (candidateModel );
926933
927934 // Ensure that relative path and GA match, if both are provided
928- if (groupId == null
929- || !groupId .equals (parent .getGroupId ())
930- || artifactId == null
931- || !artifactId .equals (parent .getArtifactId ())) {
932- mismatchRelativePathAndGA (childModel , groupId , artifactId );
935+ if (parent .getGroupId () != null && (groupId == null || !groupId .equals (parent .getGroupId ()))
936+ || parent .getArtifactId () != null
937+ && (artifactId == null || !artifactId .equals (parent .getArtifactId ()))) {
938+ mismatchRelativePathAndGA (childModel , parent , groupId , artifactId );
933939 return null ;
934940 }
935941
@@ -968,8 +974,7 @@ private Model readParentLocally(Model childModel, DefaultProfileActivationContex
968974 return candidateModel ;
969975 }
970976
971- private void mismatchRelativePathAndGA (Model childModel , String groupId , String artifactId ) {
972- Parent parent = childModel .getParent ();
977+ private void mismatchRelativePathAndGA (Model childModel , Parent parent , String groupId , String artifactId ) {
973978 StringBuilder buffer = new StringBuilder (256 );
974979 buffer .append ("'parent.relativePath'" );
975980 if (childModel != getRootModel ()) {
@@ -1000,16 +1005,17 @@ private void wrongParentRelativePath(Model childModel) {
10001005 add (Severity .FATAL , Version .BASE , buffer .toString (), parent .getLocation ("" ));
10011006 }
10021007
1003- Model resolveAndReadParentExternally (Model childModel , DefaultProfileActivationContext profileActivationContext )
1008+ Model resolveAndReadParentExternally (
1009+ Model childModel , Parent parent , DefaultProfileActivationContext profileActivationContext )
10041010 throws ModelBuilderException {
10051011 ModelBuilderRequest request = this .request ;
10061012 setSource (childModel );
10071013
1008- Parent parent = childModel .getParent ();
1009-
10101014 String groupId = parent .getGroupId ();
10111015 String artifactId = parent .getArtifactId ();
10121016 String version = parent .getVersion ();
1017+ String classifier = parent instanceof Mixin ? ((Mixin ) parent ).getClassifier () : null ;
1018+ String extension = parent instanceof Mixin ? ((Mixin ) parent ).getExtension () : null ;
10131019
10141020 // add repositories specified by the current model so that we can resolve the parent
10151021 if (!childModel .getRepositories ().isEmpty ()) {
@@ -1027,12 +1033,23 @@ Model resolveAndReadParentExternally(Model childModel, DefaultProfileActivationC
10271033
10281034 ModelSource modelSource ;
10291035 try {
1030- modelSource = resolveReactorModel (parent .getGroupId (), parent .getArtifactId (), parent .getVersion ());
1036+ modelSource = classifier == null && extension == null
1037+ ? resolveReactorModel (groupId , artifactId , version )
1038+ : null ;
10311039 if (modelSource == null ) {
1032- AtomicReference <Parent > modified = new AtomicReference <>();
1033- modelSource = modelResolver .resolveModel (request .getSession (), repositories , parent , modified );
1034- if (modified .get () != null ) {
1035- parent = modified .get ();
1040+ ModelResolver .ModelResolverRequest req = new ModelResolver .ModelResolverRequest (
1041+ request .getSession (),
1042+ null ,
1043+ repositories ,
1044+ groupId ,
1045+ artifactId ,
1046+ version ,
1047+ classifier ,
1048+ extension != null ? extension : "pom" );
1049+ ModelResolver .ModelResolverResult result = modelResolver .resolveModel (req );
1050+ modelSource = result .source ();
1051+ if (result .version () != null ) {
1052+ parent = parent .withVersion (result .version ());
10361053 }
10371054 }
10381055 } catch (ModelResolverException e ) {
@@ -1148,7 +1165,8 @@ private Model readEffectiveModel() throws ModelBuilderException {
11481165 profileActivationContext .setUserProperties (profileProps );
11491166 }
11501167
1151- Model parentModel = readParent (activatedFileModel , profileActivationContext );
1168+ Model parentModel =
1169+ readParent (activatedFileModel , activatedFileModel .getParent (), profileActivationContext );
11521170
11531171 // Now that we have read the parent, we can set the relative
11541172 // path correctly if it was not set in the input model
@@ -1170,6 +1188,15 @@ private Model readEffectiveModel() throws ModelBuilderException {
11701188
11711189 Model model = inheritanceAssembler .assembleModelInheritance (inputModel , parentModel , request , this );
11721190
1191+ // Mixins
1192+ for (Mixin mixin : model .getMixins ()) {
1193+ Model parent = resolveParent (model , mixin , profileActivationContext );
1194+ model = inheritanceAssembler .assembleModelInheritance (model , parent , request , this );
1195+ }
1196+
1197+ // model normalization
1198+ model = modelNormalizer .mergeDuplicates (model , request , this );
1199+
11731200 // profile activation
11741201 profileActivationContext .setModel (model );
11751202
@@ -1354,7 +1381,7 @@ Model doReadFileModel() throws ModelBuilderException {
13541381 .version (parentVersion )
13551382 .build ());
13561383 } else {
1357- mismatchRelativePathAndGA (model , parentGroupId , parentArtifactId );
1384+ mismatchRelativePathAndGA (model , parent , parentGroupId , parentArtifactId );
13581385 }
13591386 } else {
13601387 if (!MODEL_VERSION_4_0_0 .equals (model .getModelVersion ()) && path != null ) {
@@ -1575,8 +1602,9 @@ Model readAsParentModel(DefaultProfileActivationContext profileActivationContext
15751602 private ParentModelWithProfiles doReadAsParentModel (
15761603 DefaultProfileActivationContext childProfileActivationContext ) throws ModelBuilderException {
15771604 Model raw = readRawModel ();
1578- Model parentData = readParent (raw , childProfileActivationContext );
1579- Model parent = new DefaultInheritanceAssembler (new DefaultInheritanceAssembler .InheritanceModelMerger () {
1605+ Model parentData = readParent (raw , raw .getParent (), childProfileActivationContext );
1606+ DefaultInheritanceAssembler defaultInheritanceAssembler =
1607+ new DefaultInheritanceAssembler (new DefaultInheritanceAssembler .InheritanceModelMerger () {
15801608 @ Override
15811609 protected void mergeModel_Modules (
15821610 Model .Builder builder ,
@@ -1592,8 +1620,12 @@ protected void mergeModel_Subprojects(
15921620 Model source ,
15931621 boolean sourceDominant ,
15941622 Map <Object , Object > context ) {}
1595- })
1596- .assembleModelInheritance (raw , parentData , request , this );
1623+ });
1624+ Model parent = defaultInheritanceAssembler .assembleModelInheritance (raw , parentData , request , this );
1625+ for (Mixin mixin : parent .getMixins ()) {
1626+ Model parentModel = resolveParent (parent , mixin , childProfileActivationContext );
1627+ parent = defaultInheritanceAssembler .assembleModelInheritance (parent , parentModel , request , this );
1628+ }
15971629
15981630 // Profile injection SHOULD be performed on parent models to ensure
15991631 // that profile content becomes part of the parent model before inheritance.
0 commit comments