diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelTransformerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelTransformerException.java index bf866c29a95c..c68456beb433 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelTransformerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelTransformerException.java @@ -18,10 +18,14 @@ */ package org.apache.maven.api.services; +import org.apache.maven.api.annotations.Experimental; + /** + * Exception thrown when a {@link ModelTransformer} fails. * * @since 4.0.0 */ +@Experimental public class ModelTransformerException extends MavenException { public ModelTransformerException(Exception e) { diff --git a/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/ModelTransformer.java b/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/ModelTransformer.java new file mode 100644 index 000000000000..3682eb691f2c --- /dev/null +++ b/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/ModelTransformer.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.api.spi; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.services.ModelTransformerException; + +/** + * Marker interface for model transformers. + * + * @since 4.0.0 + */ +@Experimental +public interface ModelTransformer extends SpiService { + + /** + * Apply a transformation on the file model. + * + * This method will be called on each file model being loaded, + * just before validation. + * + * @param model the input model + * @return the transformed model, or the input model if no transformation is needed + * @throws ModelTransformerException + */ + @Nonnull + default Model transformFileModel(@Nonnull Model model) throws ModelTransformerException { + return model; + } + + /** + * Apply a transformation on the raw models. + * + * This method will be called on each raw model being loaded, + * just before validation. + * + * @param model the input model + * @return the transformed model, or the input model if no transformation is needed + * @throws ModelTransformerException + */ + @Nonnull + default Model transformRawModel(@Nonnull Model model) throws ModelTransformerException { + return model; + } + + /** + * Apply a transformation on the effective models. + * + * This method will be called on each effective model being loaded, + * just before validation. + * + * @param model the input model + * @return the transformed model, or the input model if no transformation is needed + * @throws ModelTransformerException + */ + @Nonnull + default Model transformEffectiveModel(@Nonnull Model model) throws ModelTransformerException { + return model; + } +} diff --git a/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/ModelTransformerException.java b/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/ModelTransformerException.java new file mode 100644 index 000000000000..d2f844382690 --- /dev/null +++ b/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/ModelTransformerException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.api.spi; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.services.MavenException; + +@Experimental +public class ModelTransformerException extends MavenException { + + public ModelTransformerException() { + this(null, null); + } + + public ModelTransformerException(String message) { + this(message, null); + } + + public ModelTransformerException(Throwable cause) { + this(null, cause); + } + + public ModelTransformerException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java index 3839704d46bf..5a63189db5ef 100644 --- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java +++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java @@ -144,6 +144,7 @@ public class DefaultModelBuilder implements ModelBuilder { private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; private final ModelTransformer transformer; private final ModelVersionParser versionParser; + private final List transformers; @SuppressWarnings("checkstyle:ParameterNumber") @Inject @@ -165,7 +166,8 @@ public DefaultModelBuilder( PluginConfigurationExpander pluginConfigurationExpander, ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator, ModelTransformer transformer, - ModelVersionParser versionParser) { + ModelVersionParser versionParser, + List transformers) { this.modelProcessor = modelProcessor; this.modelValidator = modelValidator; this.modelNormalizer = modelNormalizer; @@ -184,6 +186,7 @@ public DefaultModelBuilder( this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator; this.transformer = transformer; this.versionParser = versionParser; + this.transformers = transformers; } @Override @@ -588,6 +591,10 @@ private ModelBuilderResult build( resultModel = pluginConfigurationExpander.expandPluginConfiguration(resultModel, request, problems); } + for (var transformer : transformers) { + resultModel = transformer.transformEffectiveModel(resultModel); + } + result.setEffectiveModel(resultModel); // effective model validation @@ -767,6 +774,10 @@ private Model doReadFileModel( } } + for (var transformer : transformers) { + model = transformer.transformFileModel(model); + } + problems.setSource(model); modelValidator.validateFileModel(model, request, problems); if (hasFatalErrors(problems)) { @@ -809,6 +820,10 @@ private ModelData doReadRawModel( rawModel = rawModel.withModelVersion(namespace.substring(NAMESPACE_PREFIX.length())); } + for (var transformer : transformers) { + rawModel = transformer.transformRawModel(rawModel); + } + modelValidator.validateRawModel(rawModel, request, problems); if (hasFatalErrors(problems)) { diff --git a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java index e49924faeb96..5115153bef53 100644 --- a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java +++ b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java @@ -1059,7 +1059,8 @@ protected ModelBuilder createModelBuilder() { new DefaultPluginConfigurationExpander(), new ProfileActivationFilePathInterpolator(new DefaultPathTranslator(), new DefaultRootLocator()), new BuildModelTransformer(), - new DefaultModelVersionParser(getVersionScheme())); + new DefaultModelVersionParser(getVersionScheme()), + List.of()); } private RepositorySystem repositorySystem; diff --git a/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java index 8fee91057c6d..ad434baf8b8c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java @@ -138,6 +138,9 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder { @Inject private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; + @Inject + private List transformers; + Logger logger = LoggerFactory.getLogger(getClass()); @Override @@ -193,7 +196,8 @@ public List getActiveProfiles( pluginConfigurationExpander, profileActivationFilePathInterpolator, modelTransformer, - versionParser); + versionParser, + transformers); InternalSession iSession = InternalSession.from(session); ModelBuilderRequest.ModelBuilderRequestBuilder request = ModelBuilderRequest.builder(); request.projectBuild(true); diff --git a/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject b/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject index 18acc039de88..b6a2e598106e 100644 --- a/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject +++ b/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject @@ -2,6 +2,7 @@ org.apache.maven.api.services.model.ProfileActivator org.apache.maven.api.spi.LanguageProvider org.apache.maven.api.spi.LifecycleProvider org.apache.maven.api.spi.ModelParser +org.apache.maven.api.spi.ModelTransformer org.apache.maven.api.spi.PackagingProvider org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory org.apache.maven.internal.aether.LegacyRepositorySystemSessionExtender diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java index 9b321edba4c3..82baf4890ace 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java @@ -1061,7 +1061,8 @@ protected ModelBuilder createModelBuilder() { new DefaultPluginConfigurationExpander(), new ProfileActivationFilePathInterpolator(new DefaultPathTranslator(), new DefaultRootLocator()), new BuildModelTransformer(), - new DefaultModelVersionParser(getVersionScheme())); + new DefaultModelVersionParser(getVersionScheme()), + List.of()); } private RepositorySystem repositorySystem;