diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index bc84b81c2144..e2c36b0761a5 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -38,10 +38,13 @@ import java.util.Properties; import java.util.concurrent.Callable; import java.util.function.Supplier; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.maven.api.VersionRange; import org.apache.maven.api.feature.Features; +import org.apache.maven.api.model.ActivationFile; import org.apache.maven.api.model.Exclusion; import org.apache.maven.api.model.InputSource; import org.apache.maven.api.services.VersionParserException; @@ -57,6 +60,7 @@ import org.apache.maven.model.PluginManagement; import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblem.Severity; +import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.composition.DependencyManagementImporter; import org.apache.maven.model.inheritance.InheritanceAssembler; import org.apache.maven.model.interpolation.ModelInterpolator; @@ -82,11 +86,14 @@ import org.apache.maven.model.resolution.UnresolvableModelException; import org.apache.maven.model.resolution.WorkspaceModelResolver; import org.apache.maven.model.superpom.SuperPomProvider; +import org.apache.maven.model.v4.MavenTransformer; import org.apache.maven.model.validation.DefaultModelValidator; import org.apache.maven.model.validation.ModelValidator; import org.apache.maven.model.version.ModelVersionParser; import org.codehaus.plexus.interpolation.InterpolationException; +import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.MapBasedValueSource; +import org.codehaus.plexus.interpolation.RegexBasedInterpolator; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.eclipse.sisu.Nullable; @@ -897,69 +904,89 @@ private List interpolateActivations( List profiles, DefaultProfileActivationContext context, DefaultModelProblemCollector problems) { - List newProfiles = null; - for (int index = 0; index < profiles.size(); index++) { - org.apache.maven.api.model.Profile profile = profiles.get(index); - org.apache.maven.api.model.Activation activation = profile.getActivation(); - if (activation != null) { - org.apache.maven.api.model.ActivationFile file = activation.getFile(); - if (file != null) { - String oldExists = file.getExists(); - if (isNotEmpty(oldExists)) { + if (profiles.stream() + .map(org.apache.maven.api.model.Profile::getActivation) + .filter(Objects::nonNull) + .findFirst() + .isEmpty()) { + return profiles; + } + final Interpolator xform = new RegexBasedInterpolator(); + xform.setCacheAnswers(true); + Stream.of(context.getUserProperties(), context.getSystemProperties()) + .map(MapBasedValueSource::new) + .forEach(xform::addValueSource); + + class ProfileInterpolator extends MavenTransformer + implements UnaryOperator { + ProfileInterpolator() { + super(s -> { + if (isNotEmpty(s)) { try { - String newExists = interpolate(oldExists, context); - if (!Objects.equals(oldExists, newExists)) { - if (newProfiles == null) { - newProfiles = new ArrayList<>(profiles); - } - newProfiles.set( - index, profile.withActivation(activation.withFile(file.withExists(newExists)))); - } + return xform.interpolate(s); } catch (InterpolationException e) { - addInterpolationProblem(problems, file, oldExists, e, "exists"); - } - } else { - String oldMissing = file.getMissing(); - if (isNotEmpty(oldMissing)) { - try { - String newMissing = interpolate(oldMissing, context); - if (!Objects.equals(oldMissing, newMissing)) { - if (newProfiles == null) { - newProfiles = new ArrayList<>(profiles); - } - newProfiles.set( - index, - profile.withActivation(activation.withFile(file.withMissing(newMissing)))); - } - } catch (InterpolationException e) { - addInterpolationProblem(problems, file, oldMissing, e, "missing"); - } + problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE) + .setMessage(e.getMessage()) + .setException(e)); } } + return s; + }); + } + + @Override + public org.apache.maven.api.model.Profile apply(org.apache.maven.api.model.Profile p) { + return org.apache.maven.api.model.Profile.newBuilder(p) + .activation(transformActivation(p.getActivation())) + .build(); + } + + @Override + protected void transformActivationFile_Missing(ActivationFile.Builder builder, ActivationFile target) { + final String path = target.getMissing(); + final String xformed = transformPath(path, target, "missing"); + if (xformed != path) { + builder.missing(xformed); } } + + @Override + protected void transformActivationFile_Exists(ActivationFile.Builder builder, ActivationFile target) { + final String path = target.getExists(); + final String xformed = transformPath(path, target, "exists"); + if (xformed != path) { + builder.exists(xformed); + } + } + + private String transformPath(String path, ActivationFile target, String locationKey) { + if (isNotEmpty(path)) { + try { + return profileActivationFilePathInterpolator.interpolate(path, context); + } catch (InterpolationException e) { + addInterpolationProblem(problems, target, path, e, locationKey); + } + } + return path; + } } - return newProfiles != null ? newProfiles : profiles; + return profiles.stream().map(new ProfileInterpolator()).toList(); } private static void addInterpolationProblem( DefaultModelProblemCollector problems, - org.apache.maven.api.model.ActivationFile file, + org.apache.maven.api.model.InputLocationTracker target, String path, InterpolationException e, String locationKey) { problems.add(new ModelProblemCollectorRequest(Severity.ERROR, ModelProblem.Version.BASE) .setMessage("Failed to interpolate file location " + path + ": " + e.getMessage()) - .setLocation(Optional.ofNullable(file.getLocation(locationKey)) + .setLocation(Optional.ofNullable(target.getLocation(locationKey)) .map(InputLocation::new) .orElse(null)) .setException(e)); } - private String interpolate(String path, ProfileActivationContext context) throws InterpolationException { - return isNotEmpty(path) ? profileActivationFilePathInterpolator.interpolate(path, context) : path; - } - private static boolean isNotEmpty(String string) { return string != null && !string.isEmpty(); }