9797@ Named
9898@ Singleton
9999public class DefaultModelBuilder implements ModelBuilder {
100+ /**
101+ * Key for "fail on invalid model" property.
102+ * <p>
103+ * Visible for testing.
104+ */
105+ static final String FAIL_ON_INVALID_MODEL = "maven.modelBuilder.failOnInvalidModel" ;
106+
107+ /**
108+ * Checks user and system properties (in this order) for value of {@link #FAIL_ON_INVALID_MODEL} property key, if
109+ * set and returns it. If not set, defaults to {@code true}.
110+ * <p>
111+ * This is only meant to provide "escape hatch" for those builds, that are for some reason stuck with invalid models.
112+ */
113+ private static boolean isFailOnInvalidModel (ModelBuildingRequest request ) {
114+ String val = request .getUserProperties ().getProperty (FAIL_ON_INVALID_MODEL );
115+ if (val == null ) {
116+ val = request .getSystemProperties ().getProperty (FAIL_ON_INVALID_MODEL );
117+ }
118+ if (val != null ) {
119+ return Boolean .parseBoolean (val );
120+ }
121+ return true ;
122+ }
123+
100124 @ Inject
101125 private ModelProcessor modelProcessor ;
102126
@@ -253,6 +277,7 @@ public ModelBuildingResult build(ModelBuildingRequest request) throws ModelBuild
253277 protected ModelBuildingResult build (ModelBuildingRequest request , Collection <String > importIds )
254278 throws ModelBuildingException {
255279 // phase 1
280+ boolean failOnInvalidModel = isFailOnInvalidModel (request );
256281 DefaultModelBuildingResult result = new DefaultModelBuildingResult ();
257282
258283 DefaultModelProblemCollector problems = new DefaultModelProblemCollector (result );
@@ -306,7 +331,7 @@ protected ModelBuildingResult build(ModelBuildingRequest request, Collection<Str
306331 profileActivationContext .setProjectProperties (tmpModel .getProperties ());
307332
308333 Map <String , Activation > interpolatedActivations =
309- getInterpolatedActivations (rawModel , profileActivationContext , problems );
334+ getInterpolatedActivations (rawModel , profileActivationContext , failOnInvalidModel , problems );
310335 injectProfileActivations (tmpModel , interpolatedActivations );
311336
312337 List <Profile > activePomProfiles =
@@ -430,8 +455,12 @@ private interface InterpolateString {
430455 }
431456
432457 private Map <String , Activation > getInterpolatedActivations (
433- Model rawModel , DefaultProfileActivationContext context , DefaultModelProblemCollector problems ) {
434- Map <String , Activation > interpolatedActivations = getProfileActivations (rawModel , true );
458+ Model rawModel ,
459+ DefaultProfileActivationContext context ,
460+ boolean failOnInvalidModel ,
461+ DefaultModelProblemCollector problems ) {
462+ Map <String , Activation > interpolatedActivations =
463+ getProfileActivations (rawModel , true , failOnInvalidModel , problems );
435464
436465 if (interpolatedActivations .isEmpty ()) {
437466 return Collections .emptyMap ();
@@ -753,7 +782,8 @@ private void assembleInheritance(
753782 }
754783 }
755784
756- private Map <String , Activation > getProfileActivations (Model model , boolean clone ) {
785+ private Map <String , Activation > getProfileActivations (
786+ Model model , boolean clone , boolean failOnInvalidModel , ModelProblemCollector problems ) {
757787 Map <String , Activation > activations = new HashMap <>();
758788 for (Profile profile : model .getProfiles ()) {
759789 Activation activation = profile .getActivation ();
@@ -766,7 +796,11 @@ private Map<String, Activation> getProfileActivations(Model model, boolean clone
766796 activation = activation .clone ();
767797 }
768798
769- activations .put (profile .getId (), activation );
799+ if (activations .put (profile .getId (), activation ) != null ) {
800+ problems .add (new ModelProblemCollectorRequest (
801+ failOnInvalidModel ? Severity .FATAL : Severity .WARNING , ModelProblem .Version .BASE )
802+ .setMessage ("Duplicate activation for profile " + profile .getId ()));
803+ }
770804 }
771805
772806 return activations ;
@@ -787,7 +821,8 @@ private void injectProfileActivations(Model model, Map<String, Activation> activ
787821
788822 private Model interpolateModel (Model model , ModelBuildingRequest request , ModelProblemCollector problems ) {
789823 // save profile activations before interpolation, since they are evaluated with limited scope
790- Map <String , Activation > originalActivations = getProfileActivations (model , true );
824+ // at this stage we already failed if wanted to
825+ Map <String , Activation > originalActivations = getProfileActivations (model , true , false , problems );
791826
792827 Model interpolatedModel =
793828 modelInterpolator .interpolateModel (model , model .getProjectDirectory (), request , problems );
0 commit comments