diff --git a/maven-core/src/main/java/org/apache/maven/artifact/handler/providers/BomArtifactHandlerProvider.java b/maven-core/src/main/java/org/apache/maven/artifact/handler/providers/BomArtifactHandlerProvider.java new file mode 100644 index 000000000000..7e15c27e9823 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/artifact/handler/providers/BomArtifactHandlerProvider.java @@ -0,0 +1,46 @@ +/* + * 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.artifact.handler.providers; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.artifact.handler.DefaultArtifactHandler; + +/** + * {@code pom} artifact handler provider. + */ +@Named("bom") +@Singleton +public class BomArtifactHandlerProvider implements Provider { + private final ArtifactHandler artifactHandler; + + @Inject + public BomArtifactHandlerProvider() { + this.artifactHandler = new DefaultArtifactHandler("pom", null, null, null, null, false, "none", false); + } + + @Override + public ArtifactHandler get() { + return artifactHandler; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/transformation/ConsumerPomArtifactTransformer.java b/maven-core/src/main/java/org/apache/maven/internal/transformation/ConsumerPomArtifactTransformer.java index c37a5e50ffd0..6416e3ebf396 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/transformation/ConsumerPomArtifactTransformer.java +++ b/maven-core/src/main/java/org/apache/maven/internal/transformation/ConsumerPomArtifactTransformer.java @@ -32,11 +32,17 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.stream.Collectors; +import org.apache.maven.api.Repository; import org.apache.maven.api.feature.Features; +import org.apache.maven.api.model.DistributionManagement; import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.FileModelSource; import org.apache.maven.model.building.ModelBuilder; import org.apache.maven.model.building.ModelBuildingRequest; @@ -63,6 +69,10 @@ @Named("consumer-pom") public final class ConsumerPomArtifactTransformer { + private static final String BOM_PACKAGING = "bom"; + + public static final String POM_PACKAGING = "pom"; + private static final String CONSUMER_POM_CLASSIFIER = "consumer"; private static final String BUILD_POM_CLASSIFIER = "build"; @@ -208,46 +218,67 @@ void transform(Path src, Path dest, Model model) { Model consumer = null; String version; - // This is a bit of a hack, but all models are cached, so not sure why we'd need to parse it again - ModelCache cache = DefaultModelCache.newInstance(session); - Object modelData = cache.get(new FileModelSource(src.toFile()), "raw"); - if (modelData != null) { - try { - Method getModel = modelData.getClass().getMethod("getModel"); - getModel.setAccessible(true); - org.apache.maven.model.Model cachedModel = - (org.apache.maven.model.Model) getModel.invoke(modelData); - consumer = cachedModel.getDelegate(); - } catch (Exception e) { - throw new RuntimeException(e); + String packaging = model.getPackaging(); + if (POM_PACKAGING.equals(packaging)) { + // This is a bit of a hack, but all models are cached, so not sure why we'd need to parse it again + ModelCache cache = DefaultModelCache.newInstance(session); + Object modelData = cache.get(new FileModelSource(src.toFile()), "raw"); + if (modelData != null) { + try { + Method getModel = modelData.getClass().getMethod("getModel"); + getModel.setAccessible(true); + org.apache.maven.model.Model cachedModel = + (org.apache.maven.model.Model) getModel.invoke(modelData); + consumer = cachedModel.getDelegate(); + } catch (Exception e) { + throw new RuntimeException(e); + } } - } - if (consumer == null) { - TransformerContext context = - (TransformerContext) session.getData().get(TransformerContext.KEY); - Result result = modelBuilder.buildRawModel( - src.toFile(), ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL, false, context); - if (result.hasErrors()) { - throw new IllegalStateException( - "Unable to build POM " + src, - result.getProblems().iterator().next().getException()); + if (consumer == null) { + TransformerContext context = + (TransformerContext) session.getData().get(TransformerContext.KEY); + Result result = modelBuilder.buildRawModel( + src.toFile(), ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL, false, context); + if (result.hasErrors()) { + throw new IllegalStateException( + "Unable to build POM " + src, + result.getProblems().iterator().next().getException()); + } + consumer = result.get().getDelegate(); } - consumer = result.get().getDelegate(); - } - // raw to consumer transform - consumer = consumer.withRoot(false).withModules(null); - if (consumer.getParent() != null) { - consumer = consumer.withParent(consumer.getParent().withRelativePath(null)); - } + // raw to consumer transform + consumer = consumer.withRoot(false).withModules(null); + if (consumer.getParent() != null) { + consumer = consumer.withParent(consumer.getParent().withRelativePath(null)); + } - if (!consumer.isPreserveModelVersion()) { - consumer = consumer.withPreserveModelVersion(false); + if (!consumer.isPreserveModelVersion()) { + consumer = consumer.withPreserveModelVersion(false); + version = new MavenModelVersion().getModelVersion(consumer); + consumer = consumer.withModelVersion(version); + } else { + version = consumer.getModelVersion(); + } + } else { + Model.Builder builder = prune( + Model.newBuilder(model, true) + .preserveModelVersion(false) + .root(false) + .parent(null) + .build(null), + model); + boolean isBom = BOM_PACKAGING.equals(packaging); + if (isBom) { + builder.packaging(POM_PACKAGING); + } + builder.profiles(model.getProfiles().stream() + .map(p -> prune(Profile.newBuilder(p, true), p).build()) + .collect(Collectors.toList())); + consumer = builder.build(); version = new MavenModelVersion().getModelVersion(consumer); consumer = consumer.withModelVersion(version); - } else { - version = consumer.getModelVersion(); } try { @@ -264,4 +295,26 @@ void transform(Path src, Path dest, Model model) { } } } + + private static T prune(T builder, ModelBase model) { + builder.properties(null).reporting(null); + if (model.getDistributionManagement() != null + && model.getDistributionManagement().getRelocation() != null) { + // keep relocation only + builder.distributionManagement(DistributionManagement.newBuilder() + .relocation(model.getDistributionManagement().getRelocation()) + .build()); + } + // only keep repositories others than 'central' + builder.pluginRepositories(pruneRepositories(model.getPluginRepositories())); + builder.repositories(pruneRepositories(model.getRepositories())); + return builder; + } + + private static List pruneRepositories( + List repositories) { + return repositories.stream() + .filter(r -> !Repository.CENTRAL_ID.equals(r.getId())) + .collect(Collectors.toList()); + } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/BomLifecycleMappingProvider.java b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/BomLifecycleMappingProvider.java new file mode 100644 index 000000000000..3c0e23c7ab2d --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/BomLifecycleMappingProvider.java @@ -0,0 +1,43 @@ +/* + * 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.lifecycle.providers.packaging; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +/** + * {@code bom} packaging plugins bindings provider for {@code default} lifecycle. + */ +@Named("bom") +@Singleton +public final class BomLifecycleMappingProvider extends AbstractLifecycleMappingProvider { + // START SNIPPET: bom + @SuppressWarnings("checkstyle:linelength") + private static final String[] BINDINGS = { + "install", "org.apache.maven.plugins:maven-install-plugin:" + INSTALL_PLUGIN_VERSION + ":install", + "deploy", "org.apache.maven.plugins:maven-deploy-plugin:" + DEPLOY_PLUGIN_VERSION + ":deploy" + }; + // END SNIPPET: bom + + @Inject + public BomLifecycleMappingProvider() { + super(BINDINGS); + } +}