mirror of https://github.com/apache/maven.git
[MNG-7945] Fix profile settings being injected into consumer POM (#1323)
This commit is contained in:
parent
3927ca1843
commit
69bc993b80
|
@ -18,45 +18,10 @@
|
|||
*/
|
||||
package org.apache.maven.internal.transformation;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
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;
|
||||
import org.apache.maven.model.building.ModelCache;
|
||||
import org.apache.maven.model.building.Result;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.model.v4.MavenModelVersion;
|
||||
import org.apache.maven.model.v4.MavenStaxWriter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.artifact.ProjectArtifact;
|
||||
import org.apache.maven.repository.internal.DefaultModelCache;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.artifact.DefaultArtifact;
|
||||
import org.eclipse.aether.deployment.DeployRequest;
|
||||
import org.eclipse.aether.installation.InstallRequest;
|
||||
|
||||
|
@ -65,260 +30,12 @@ import org.eclipse.aether.installation.InstallRequest;
|
|||
*
|
||||
* @since TBD
|
||||
*/
|
||||
@Singleton
|
||||
@Named("consumer-pom")
|
||||
public final class ConsumerPomArtifactTransformer {
|
||||
public interface ConsumerPomArtifactTransformer {
|
||||
|
||||
private static final String BOM_PACKAGING = "bom";
|
||||
InstallRequest remapInstallArtifacts(RepositorySystemSession session, InstallRequest request);
|
||||
|
||||
public static final String POM_PACKAGING = "pom";
|
||||
DeployRequest remapDeployArtifacts(RepositorySystemSession session, DeployRequest request);
|
||||
|
||||
private static final String CONSUMER_POM_CLASSIFIER = "consumer";
|
||||
|
||||
private static final String BUILD_POM_CLASSIFIER = "build";
|
||||
|
||||
private static final String NAMESPACE_FORMAT = "http://maven.apache.org/POM/%s";
|
||||
|
||||
private static final String SCHEMA_LOCATION_FORMAT = "https://maven.apache.org/xsd/maven-%s.xsd";
|
||||
|
||||
private final Set<Path> toDelete = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final ModelBuilder modelBuilder;
|
||||
|
||||
@Inject
|
||||
ConsumerPomArtifactTransformer(ModelBuilder modelBuilder) {
|
||||
this.modelBuilder = modelBuilder;
|
||||
}
|
||||
|
||||
public void injectTransformedArtifacts(MavenProject project, RepositorySystemSession session) throws IOException {
|
||||
if (project.getFile() == null) {
|
||||
// If there is no build POM there is no reason to inject artifacts for the consumer POM.
|
||||
return;
|
||||
}
|
||||
if (Features.buildConsumer(session.getUserProperties())) {
|
||||
Path buildDir =
|
||||
project.getBuild() != null ? Paths.get(project.getBuild().getDirectory()) : null;
|
||||
if (buildDir != null) {
|
||||
Files.createDirectories(buildDir);
|
||||
}
|
||||
Path consumer = buildDir != null
|
||||
? Files.createTempFile(buildDir, CONSUMER_POM_CLASSIFIER + "-", ".pom")
|
||||
: Files.createTempFile(CONSUMER_POM_CLASSIFIER + "-", ".pom");
|
||||
deferDeleteFile(consumer);
|
||||
|
||||
project.addAttachedArtifact(createConsumerPomArtifact(project, consumer, session));
|
||||
} else if (project.getModel().getDelegate().isRoot()) {
|
||||
throw new IllegalStateException(
|
||||
"The use of the root attribute on the model requires the buildconsumer feature to be active");
|
||||
}
|
||||
}
|
||||
|
||||
public ConsumerPomArtifact createConsumerPomArtifact(
|
||||
MavenProject project, Path consumer, RepositorySystemSession session) {
|
||||
return new ConsumerPomArtifact(project, consumer, session);
|
||||
}
|
||||
|
||||
private void deferDeleteFile(Path generatedFile) {
|
||||
toDelete.add(generatedFile.toAbsolutePath());
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
private void doDeleteFiles() {
|
||||
for (Path file : toDelete) {
|
||||
try {
|
||||
Files.delete(file);
|
||||
} catch (IOException e) {
|
||||
// ignore, we did our best...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InstallRequest remapInstallArtifacts(RepositorySystemSession session, InstallRequest request) {
|
||||
if (Features.buildConsumer(session.getUserProperties()) && consumerPomPresent(request.getArtifacts())) {
|
||||
request.setArtifacts(replacePom(request.getArtifacts()));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public DeployRequest remapDeployArtifacts(RepositorySystemSession session, DeployRequest request) {
|
||||
if (Features.buildConsumer(session.getUserProperties()) && consumerPomPresent(request.getArtifacts())) {
|
||||
request.setArtifacts(replacePom(request.getArtifacts()));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private boolean consumerPomPresent(Collection<Artifact> artifacts) {
|
||||
return artifacts.stream()
|
||||
.anyMatch(a -> "pom".equals(a.getExtension()) && CONSUMER_POM_CLASSIFIER.equals(a.getClassifier()));
|
||||
}
|
||||
|
||||
private Collection<Artifact> replacePom(Collection<Artifact> artifacts) {
|
||||
List<Artifact> consumers = new ArrayList<>();
|
||||
List<Artifact> mains = new ArrayList<>();
|
||||
for (Artifact artifact : artifacts) {
|
||||
if ("pom".equals(artifact.getExtension()) || artifact.getExtension().startsWith("pom.")) {
|
||||
if (CONSUMER_POM_CLASSIFIER.equals(artifact.getClassifier())) {
|
||||
consumers.add(artifact);
|
||||
} else if ("".equals(artifact.getClassifier())) {
|
||||
mains.add(artifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mains.isEmpty() && !consumers.isEmpty()) {
|
||||
ArrayList<Artifact> result = new ArrayList<>(artifacts);
|
||||
for (Artifact main : mains) {
|
||||
result.remove(main);
|
||||
result.add(new DefaultArtifact(
|
||||
main.getGroupId(),
|
||||
main.getArtifactId(),
|
||||
BUILD_POM_CLASSIFIER,
|
||||
main.getExtension(),
|
||||
main.getVersion(),
|
||||
main.getProperties(),
|
||||
main.getFile()));
|
||||
}
|
||||
for (Artifact consumer : consumers) {
|
||||
result.remove(consumer);
|
||||
result.add(new DefaultArtifact(
|
||||
consumer.getGroupId(),
|
||||
consumer.getArtifactId(),
|
||||
"",
|
||||
consumer.getExtension(),
|
||||
consumer.getVersion(),
|
||||
consumer.getProperties(),
|
||||
consumer.getFile()));
|
||||
}
|
||||
artifacts = result;
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer POM is transformed from original POM.
|
||||
*/
|
||||
class ConsumerPomArtifact extends TransformedArtifact {
|
||||
|
||||
private MavenProject project;
|
||||
private RepositorySystemSession session;
|
||||
|
||||
ConsumerPomArtifact(MavenProject mavenProject, Path target, RepositorySystemSession session) {
|
||||
super(
|
||||
new ProjectArtifact(mavenProject),
|
||||
() -> mavenProject.getFile().toPath(),
|
||||
CONSUMER_POM_CLASSIFIER,
|
||||
"pom",
|
||||
target);
|
||||
this.project = mavenProject;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(Path src, Path dest) {
|
||||
Model model = project.getModel().getDelegate();
|
||||
transform(src, dest, model);
|
||||
}
|
||||
|
||||
void transform(Path src, Path dest, Model model) {
|
||||
Model consumer = null;
|
||||
String version;
|
||||
|
||||
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<? extends org.apache.maven.model.Model> 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();
|
||||
}
|
||||
|
||||
// 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);
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
Files.createDirectories(dest.getParent());
|
||||
try (Writer w = Files.newBufferedWriter(dest)) {
|
||||
MavenStaxWriter writer = new MavenStaxWriter();
|
||||
writer.setNamespace(String.format(NAMESPACE_FORMAT, version));
|
||||
writer.setSchemaLocation(String.format(SCHEMA_LOCATION_FORMAT, version));
|
||||
writer.setAddLocationInformation(false);
|
||||
writer.write(w, consumer);
|
||||
}
|
||||
} catch (XMLStreamException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends ModelBase.Builder> 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<org.apache.maven.api.model.Repository> pruneRepositories(
|
||||
List<org.apache.maven.api.model.Repository> repositories) {
|
||||
return repositories.stream()
|
||||
.filter(r -> !Repository.CENTRAL_ID.equals(r.getId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
void injectTransformedArtifacts(RepositorySystemSession repositorySession, MavenProject currentProject)
|
||||
throws IOException;
|
||||
}
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* 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.internal.transformation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Keeps transformed file up-to-date relative to its source file. It manages state (i.e. hashing the content) using
|
||||
* passed in stateFunction, and transforms when needed using passed in transformer bi-consumer.
|
||||
* <p>
|
||||
* Covered cases:
|
||||
* <ul>
|
||||
* <li>when source supplier returns {@code null}, this class will return {@code null}.</li>
|
||||
* <li>when source supplier returns non existing path, this class will return non existing path.</li>
|
||||
* <li>when source supplier returns existing path, this class will ensure transformation is in sync.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since TBD
|
||||
*/
|
||||
final class OnChangeTransformer implements Supplier<Path> {
|
||||
|
||||
private final Supplier<Path> source;
|
||||
|
||||
private final Path target;
|
||||
|
||||
private final Function<Path, String> stateFunction;
|
||||
|
||||
private final BiConsumer<Path, Path> transformerConsumer;
|
||||
|
||||
private final AtomicReference<String> sourceState;
|
||||
|
||||
OnChangeTransformer(
|
||||
Supplier<Path> source,
|
||||
Path target,
|
||||
Function<Path, String> stateFunction,
|
||||
BiConsumer<Path, Path> transformerConsumer) {
|
||||
this.source = requireNonNull(source);
|
||||
this.target = requireNonNull(target);
|
||||
this.stateFunction = requireNonNull(stateFunction);
|
||||
this.transformerConsumer = requireNonNull(transformerConsumer);
|
||||
this.sourceState = new AtomicReference<>(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Path get() {
|
||||
String state = mayUpdate();
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private String mayUpdate() {
|
||||
String result;
|
||||
try {
|
||||
Path src = source.get();
|
||||
if (src == null) {
|
||||
Files.deleteIfExists(target);
|
||||
result = null;
|
||||
} else if (!Files.exists(src)) {
|
||||
Files.deleteIfExists(target);
|
||||
result = "";
|
||||
} else {
|
||||
String current = stateFunction.apply(src);
|
||||
String existing = sourceState.get();
|
||||
if (!Objects.equals(current, existing)) {
|
||||
transformerConsumer.accept(src, target);
|
||||
Files.setLastModifiedTime(target, Files.getLastModifiedTime(src));
|
||||
}
|
||||
result = current;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
sourceState.set(result);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.internal.transformation;
|
||||
|
||||
/**
|
||||
* Exception that may be thrown by the {@link org.apache.maven.artifact.Artifact#getFile()}
|
||||
* implementation.
|
||||
*/
|
||||
public class TransformationFailedException extends RuntimeException {
|
||||
|
||||
public TransformationFailedException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* 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.internal.transformation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.artifact.DefaultArtifact;
|
||||
import org.apache.maven.artifact.handler.ArtifactHandler;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Transformed artifact is derived with some transformation from source artifact.
|
||||
*
|
||||
* @since TBD
|
||||
*/
|
||||
abstract class TransformedArtifact extends DefaultArtifact {
|
||||
|
||||
private final OnChangeTransformer onChangeTransformer;
|
||||
|
||||
TransformedArtifact(
|
||||
Artifact source, Supplier<Path> sourcePathProvider, String classifier, String extension, Path targetPath) {
|
||||
super(
|
||||
source.getGroupId(),
|
||||
source.getArtifactId(),
|
||||
source.getVersionRange(),
|
||||
source.getScope(),
|
||||
extension,
|
||||
classifier,
|
||||
new TransformedArtifactHandler(
|
||||
classifier, extension, source.getArtifactHandler().getPackaging()));
|
||||
this.onChangeTransformer =
|
||||
new OnChangeTransformer(sourcePathProvider, targetPath, TransformedArtifact::sha1, this::transform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResolved() {
|
||||
return getFile() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFile(File file) {
|
||||
throw new IllegalStateException("transformed artifact file cannot be set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
Path result = onChangeTransformer.get();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return result.toFile();
|
||||
}
|
||||
|
||||
private static final int BUFFER_SIZE = 8192;
|
||||
|
||||
private static String sha1(Path path) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
try (InputStream fis = Files.newInputStream(path)) {
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int read;
|
||||
while ((read = fis.read(buffer)) != -1) {
|
||||
md.update(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte b : md.digest()) {
|
||||
result.append(String.format("%02x", b));
|
||||
}
|
||||
return result.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void transform(Path src, Path dst);
|
||||
|
||||
private static class TransformedArtifactHandler implements ArtifactHandler {
|
||||
private final String classifier;
|
||||
|
||||
private final String extension;
|
||||
|
||||
private final String packaging;
|
||||
|
||||
private TransformedArtifactHandler(String classifier, String extension, String packaging) {
|
||||
this.classifier = classifier;
|
||||
this.extension = requireNonNull(extension);
|
||||
this.packaging = requireNonNull(packaging);
|
||||
}
|
||||
|
||||
public String getClassifier() {
|
||||
return classifier;
|
||||
}
|
||||
|
||||
public String getDirectory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return "none";
|
||||
}
|
||||
|
||||
public String getPackaging() {
|
||||
return packaging;
|
||||
}
|
||||
|
||||
public boolean isAddedToClasspath() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIncludesDependencies() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.internal.transformation.impl;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.apache.maven.api.model.Model;
|
||||
import org.apache.maven.model.building.ModelBuildingException;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
|
||||
/**
|
||||
* This interface is not public and the purpose is to allow easy unit testing
|
||||
* of {@link DefaultConsumerPomArtifactTransformer}.
|
||||
*/
|
||||
interface ConsumerPomBuilder {
|
||||
|
||||
Model build(RepositorySystemSession session, MavenProject project, Path src)
|
||||
throws ModelBuildingException, ComponentLookupException, IOException, XMLStreamException;
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* 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.internal.transformation.impl;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
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 org.apache.maven.api.feature.Features;
|
||||
import org.apache.maven.api.model.Model;
|
||||
import org.apache.maven.internal.transformation.ConsumerPomArtifactTransformer;
|
||||
import org.apache.maven.model.building.ModelBuildingException;
|
||||
import org.apache.maven.model.v4.MavenStaxWriter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.artifact.ProjectArtifact;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.artifact.DefaultArtifact;
|
||||
import org.eclipse.aether.deployment.DeployRequest;
|
||||
import org.eclipse.aether.installation.InstallRequest;
|
||||
|
||||
/**
|
||||
* Consumer POM transformer.
|
||||
*
|
||||
* @since TBD
|
||||
*/
|
||||
@Singleton
|
||||
@Named("consumer-pom")
|
||||
class DefaultConsumerPomArtifactTransformer implements ConsumerPomArtifactTransformer {
|
||||
|
||||
private static final String CONSUMER_POM_CLASSIFIER = "consumer";
|
||||
|
||||
private static final String BUILD_POM_CLASSIFIER = "build";
|
||||
|
||||
private static final String NAMESPACE_FORMAT = "http://maven.apache.org/POM/%s";
|
||||
|
||||
private static final String SCHEMA_LOCATION_FORMAT = "https://maven.apache.org/xsd/maven-%s.xsd";
|
||||
|
||||
private final Set<Path> toDelete = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final ConsumerPomBuilder builder;
|
||||
|
||||
@Inject
|
||||
DefaultConsumerPomArtifactTransformer(ConsumerPomBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void injectTransformedArtifacts(RepositorySystemSession session, MavenProject project) throws IOException {
|
||||
if (project.getFile() == null) {
|
||||
// If there is no build POM there is no reason to inject artifacts for the consumer POM.
|
||||
return;
|
||||
}
|
||||
if (Features.buildConsumer(session.getUserProperties())) {
|
||||
Path buildDir =
|
||||
project.getBuild() != null ? Paths.get(project.getBuild().getDirectory()) : null;
|
||||
if (buildDir != null) {
|
||||
Files.createDirectories(buildDir);
|
||||
}
|
||||
Path consumer = buildDir != null
|
||||
? Files.createTempFile(buildDir, CONSUMER_POM_CLASSIFIER + "-", ".pom")
|
||||
: Files.createTempFile(CONSUMER_POM_CLASSIFIER + "-", ".pom");
|
||||
deferDeleteFile(consumer);
|
||||
|
||||
project.addAttachedArtifact(createConsumerPomArtifact(project, consumer, session));
|
||||
} else if (project.getModel().getDelegate().isRoot()) {
|
||||
throw new IllegalStateException(
|
||||
"The use of the root attribute on the model requires the buildconsumer feature to be active");
|
||||
}
|
||||
}
|
||||
|
||||
TransformedArtifact createConsumerPomArtifact(
|
||||
MavenProject project, Path consumer, RepositorySystemSession session) {
|
||||
return new TransformedArtifact(
|
||||
this,
|
||||
project,
|
||||
consumer,
|
||||
session,
|
||||
new ProjectArtifact(project),
|
||||
() -> project.getFile().toPath(),
|
||||
CONSUMER_POM_CLASSIFIER,
|
||||
"pom");
|
||||
}
|
||||
|
||||
void transform(MavenProject project, RepositorySystemSession session, Path src, Path tgt)
|
||||
throws ModelBuildingException, ComponentLookupException, XMLStreamException, IOException {
|
||||
Model model = builder.build(session, project, src);
|
||||
write(model, tgt);
|
||||
}
|
||||
|
||||
private void deferDeleteFile(Path generatedFile) {
|
||||
toDelete.add(generatedFile.toAbsolutePath());
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
private void doDeleteFiles() {
|
||||
for (Path file : toDelete) {
|
||||
try {
|
||||
Files.delete(file);
|
||||
} catch (IOException e) {
|
||||
// ignore, we did our best...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InstallRequest remapInstallArtifacts(RepositorySystemSession session, InstallRequest request) {
|
||||
if (Features.buildConsumer(session.getUserProperties()) && consumerPomPresent(request.getArtifacts())) {
|
||||
request.setArtifacts(replacePom(request.getArtifacts()));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public DeployRequest remapDeployArtifacts(RepositorySystemSession session, DeployRequest request) {
|
||||
if (Features.buildConsumer(session.getUserProperties()) && consumerPomPresent(request.getArtifacts())) {
|
||||
request.setArtifacts(replacePom(request.getArtifacts()));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private boolean consumerPomPresent(Collection<Artifact> artifacts) {
|
||||
return artifacts.stream()
|
||||
.anyMatch(a -> "pom".equals(a.getExtension()) && CONSUMER_POM_CLASSIFIER.equals(a.getClassifier()));
|
||||
}
|
||||
|
||||
private Collection<Artifact> replacePom(Collection<Artifact> artifacts) {
|
||||
List<Artifact> consumers = new ArrayList<>();
|
||||
List<Artifact> mains = new ArrayList<>();
|
||||
for (Artifact artifact : artifacts) {
|
||||
if ("pom".equals(artifact.getExtension()) || artifact.getExtension().startsWith("pom.")) {
|
||||
if (CONSUMER_POM_CLASSIFIER.equals(artifact.getClassifier())) {
|
||||
consumers.add(artifact);
|
||||
} else if ("".equals(artifact.getClassifier())) {
|
||||
mains.add(artifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mains.isEmpty() && !consumers.isEmpty()) {
|
||||
ArrayList<Artifact> result = new ArrayList<>(artifacts);
|
||||
for (Artifact main : mains) {
|
||||
result.remove(main);
|
||||
result.add(new DefaultArtifact(
|
||||
main.getGroupId(),
|
||||
main.getArtifactId(),
|
||||
BUILD_POM_CLASSIFIER,
|
||||
main.getExtension(),
|
||||
main.getVersion(),
|
||||
main.getProperties(),
|
||||
main.getFile()));
|
||||
}
|
||||
for (Artifact consumer : consumers) {
|
||||
result.remove(consumer);
|
||||
result.add(new DefaultArtifact(
|
||||
consumer.getGroupId(),
|
||||
consumer.getArtifactId(),
|
||||
"",
|
||||
consumer.getExtension(),
|
||||
consumer.getVersion(),
|
||||
consumer.getProperties(),
|
||||
consumer.getFile()));
|
||||
}
|
||||
artifacts = result;
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
void write(Model model, Path dest) throws IOException, XMLStreamException {
|
||||
String version = model.getModelVersion();
|
||||
Files.createDirectories(dest.getParent());
|
||||
try (Writer w = Files.newBufferedWriter(dest)) {
|
||||
MavenStaxWriter writer = new MavenStaxWriter();
|
||||
writer.setNamespace(String.format(NAMESPACE_FORMAT, version));
|
||||
writer.setSchemaLocation(String.format(SCHEMA_LOCATION_FORMAT, version));
|
||||
writer.setAddLocationInformation(false);
|
||||
writer.write(w, model);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* 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.internal.transformation.impl;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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.api.model.Repository;
|
||||
import org.apache.maven.model.building.DefaultModelBuilder;
|
||||
import org.apache.maven.model.building.DefaultModelBuilderFactory;
|
||||
import org.apache.maven.model.building.DefaultModelBuildingRequest;
|
||||
import org.apache.maven.model.building.ModelBuildingException;
|
||||
import org.apache.maven.model.building.ModelBuildingRequest;
|
||||
import org.apache.maven.model.building.ModelBuildingResult;
|
||||
import org.apache.maven.model.building.ModelProblemCollector;
|
||||
import org.apache.maven.model.building.ModelProcessor;
|
||||
import org.apache.maven.model.composition.DependencyManagementImporter;
|
||||
import org.apache.maven.model.inheritance.InheritanceAssembler;
|
||||
import org.apache.maven.model.interpolation.ModelInterpolator;
|
||||
import org.apache.maven.model.management.DependencyManagementInjector;
|
||||
import org.apache.maven.model.management.PluginManagementInjector;
|
||||
import org.apache.maven.model.normalization.ModelNormalizer;
|
||||
import org.apache.maven.model.path.ModelPathTranslator;
|
||||
import org.apache.maven.model.path.ModelUrlNormalizer;
|
||||
import org.apache.maven.model.plugin.LifecycleBindingsInjector;
|
||||
import org.apache.maven.model.plugin.PluginConfigurationExpander;
|
||||
import org.apache.maven.model.plugin.ReportConfigurationExpander;
|
||||
import org.apache.maven.model.profile.DefaultProfileSelector;
|
||||
import org.apache.maven.model.profile.ProfileActivationContext;
|
||||
import org.apache.maven.model.profile.ProfileInjector;
|
||||
import org.apache.maven.model.profile.ProfileSelector;
|
||||
import org.apache.maven.model.superpom.SuperPomProvider;
|
||||
import org.apache.maven.model.v4.MavenModelVersion;
|
||||
import org.apache.maven.model.validation.ModelValidator;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
import org.apache.maven.project.ProjectModelResolver;
|
||||
import org.apache.maven.repository.internal.ModelCacheFactory;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.RequestTrace;
|
||||
import org.eclipse.aether.impl.RemoteRepositoryManager;
|
||||
|
||||
@Named
|
||||
class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
|
||||
|
||||
private static final String BOM_PACKAGING = "bom";
|
||||
|
||||
public static final String POM_PACKAGING = "pom";
|
||||
|
||||
@Inject
|
||||
PlexusContainer container;
|
||||
|
||||
@Inject
|
||||
ModelCacheFactory modelCacheFactory;
|
||||
|
||||
public Model build(RepositorySystemSession session, MavenProject project, Path src)
|
||||
throws ModelBuildingException, ComponentLookupException {
|
||||
Model model = project.getModel().getDelegate();
|
||||
String packaging = model.getPackaging();
|
||||
if (POM_PACKAGING.equals(packaging)) {
|
||||
return buildPom(session, project, src);
|
||||
} else {
|
||||
return buildNonPom(session, project, src);
|
||||
}
|
||||
}
|
||||
|
||||
protected Model buildPom(RepositorySystemSession session, MavenProject project, Path src)
|
||||
throws ModelBuildingException, ComponentLookupException {
|
||||
ModelBuildingResult result = buildModel(session, project, src);
|
||||
Model model = result.getRawModel().getDelegate();
|
||||
return transform(model);
|
||||
}
|
||||
|
||||
protected Model buildNonPom(RepositorySystemSession session, MavenProject project, Path src)
|
||||
throws ModelBuildingException, ComponentLookupException {
|
||||
ModelBuildingResult result = buildModel(session, project, src);
|
||||
Model model = result.getEffectiveModel().getDelegate();
|
||||
return transform(model);
|
||||
}
|
||||
|
||||
private ModelBuildingResult buildModel(RepositorySystemSession session, MavenProject project, Path src)
|
||||
throws ModelBuildingException, ComponentLookupException {
|
||||
ProfileSelector customSelector = new DefaultProfileSelector() {
|
||||
@Override
|
||||
public List<Profile> getActiveProfilesV4(
|
||||
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
};
|
||||
DefaultModelBuilder modelBuilder = new DefaultModelBuilderFactory()
|
||||
.setProfileSelector(customSelector)
|
||||
// apply currently active ModelProcessor etc. to support extensions like jgitver
|
||||
.setProfileInjector(lookup(ProfileInjector.class))
|
||||
.setInheritanceAssembler(lookup(InheritanceAssembler.class))
|
||||
.setDependencyManagementImporter(lookup(DependencyManagementImporter.class))
|
||||
.setDependencyManagementInjector(lookup(DependencyManagementInjector.class))
|
||||
.setLifecycleBindingsInjector(lookup(LifecycleBindingsInjector.class))
|
||||
.setModelInterpolator(lookup(ModelInterpolator.class))
|
||||
.setModelNormalizer(lookup(ModelNormalizer.class))
|
||||
.setModelPathTranslator(lookup(ModelPathTranslator.class))
|
||||
.setModelProcessor(lookup(ModelProcessor.class))
|
||||
.setModelUrlNormalizer(lookup(ModelUrlNormalizer.class))
|
||||
.setModelValidator(lookup(ModelValidator.class))
|
||||
.setPluginConfigurationExpander(lookup(PluginConfigurationExpander.class))
|
||||
.setPluginManagementInjector(lookup(PluginManagementInjector.class))
|
||||
.setReportConfigurationExpander(lookup(ReportConfigurationExpander.class))
|
||||
.setSuperPomProvider(lookup(SuperPomProvider.class))
|
||||
.newInstance();
|
||||
DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
|
||||
try {
|
||||
request.setRootDirectory(project.getRootDirectory());
|
||||
} catch (IllegalStateException e) {
|
||||
// ignore if we don't have a root directory
|
||||
}
|
||||
request.setPomFile(src.toFile());
|
||||
request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
|
||||
request.setLocationTracking(false);
|
||||
request.setModelResolver(new ProjectModelResolver(
|
||||
session,
|
||||
new RequestTrace(null),
|
||||
lookup(RepositorySystem.class),
|
||||
lookup(RemoteRepositoryManager.class),
|
||||
project.getRemoteProjectRepositories(),
|
||||
ProjectBuildingRequest.RepositoryMerging.POM_DOMINANT,
|
||||
null));
|
||||
request.setTransformerContextBuilder(modelBuilder.newTransformerContextBuilder());
|
||||
request.setSystemProperties(toProperties(session.getSystemProperties()));
|
||||
request.setUserProperties(toProperties(session.getUserProperties()));
|
||||
request.setModelCache(modelCacheFactory.createCache(session));
|
||||
return modelBuilder.build(request);
|
||||
}
|
||||
|
||||
private Properties toProperties(Map<String, String> map) {
|
||||
Properties props = new Properties();
|
||||
props.putAll(map);
|
||||
return props;
|
||||
}
|
||||
|
||||
private <T> T lookup(Class<T> clazz) throws ComponentLookupException {
|
||||
return container.lookup(clazz);
|
||||
}
|
||||
|
||||
static Model transform(Model model) {
|
||||
String packaging = model.getPackaging();
|
||||
if (POM_PACKAGING.equals(packaging)) {
|
||||
// raw to consumer transform
|
||||
model = model.withRoot(false).withModules(null);
|
||||
if (model.getParent() != null) {
|
||||
model = model.withParent(model.getParent().withRelativePath(null));
|
||||
}
|
||||
|
||||
if (!model.isPreserveModelVersion()) {
|
||||
model = model.withPreserveModelVersion(false);
|
||||
String version = new MavenModelVersion().getModelVersion(model);
|
||||
model = model.withModelVersion(version);
|
||||
}
|
||||
} 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()));
|
||||
model = builder.build();
|
||||
String version = new MavenModelVersion().getModelVersion(model);
|
||||
model = model.withModelVersion(version);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private static <T extends ModelBase.Builder> 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 other than 'central'
|
||||
builder.pluginRepositories(pruneRepositories(model.getPluginRepositories()));
|
||||
builder.repositories(pruneRepositories(model.getRepositories()));
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static List<Repository> pruneRepositories(List<Repository> repositories) {
|
||||
return repositories.stream()
|
||||
.filter(r -> !org.apache.maven.api.Repository.CENTRAL_ID.equals(r.getId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* 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.internal.transformation.impl;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.maven.artifact.DefaultArtifact;
|
||||
import org.apache.maven.internal.transformation.TransformationFailedException;
|
||||
import org.apache.maven.model.building.ModelBuildingException;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
|
||||
/**
|
||||
* Transformed artifact is derived with some transformation from source artifact.
|
||||
*
|
||||
* @since TBD
|
||||
*/
|
||||
class TransformedArtifact extends DefaultArtifact {
|
||||
|
||||
private static final int SHA1_BUFFER_SIZE = 8192;
|
||||
private final DefaultConsumerPomArtifactTransformer defaultConsumerPomArtifactTransformer;
|
||||
private final MavenProject project;
|
||||
private final Supplier<Path> sourcePathProvider;
|
||||
private final Path target;
|
||||
private final RepositorySystemSession session;
|
||||
private final AtomicReference<String> sourceState;
|
||||
|
||||
TransformedArtifact(
|
||||
DefaultConsumerPomArtifactTransformer defaultConsumerPomArtifactTransformer,
|
||||
MavenProject project,
|
||||
Path target,
|
||||
RepositorySystemSession session,
|
||||
org.apache.maven.artifact.Artifact source,
|
||||
Supplier<Path> sourcePathProvider,
|
||||
String classifier,
|
||||
String extension) {
|
||||
super(
|
||||
source.getGroupId(),
|
||||
source.getArtifactId(),
|
||||
source.getVersionRange(),
|
||||
source.getScope(),
|
||||
extension,
|
||||
classifier,
|
||||
new TransformedArtifactHandler(
|
||||
classifier, extension, source.getArtifactHandler().getPackaging()));
|
||||
this.defaultConsumerPomArtifactTransformer = defaultConsumerPomArtifactTransformer;
|
||||
this.project = project;
|
||||
this.target = target;
|
||||
this.session = session;
|
||||
this.sourcePathProvider = sourcePathProvider;
|
||||
this.sourceState = new AtomicReference<>(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResolved() {
|
||||
return getFile() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFile(File file) {
|
||||
throw new UnsupportedOperationException("transformed artifact file cannot be set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized File getFile() {
|
||||
try {
|
||||
String state = mayUpdate();
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
return target.toFile();
|
||||
} catch (IOException
|
||||
| NoSuchAlgorithmException
|
||||
| XMLStreamException
|
||||
| ModelBuildingException
|
||||
| ComponentLookupException e) {
|
||||
throw new TransformationFailedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String mayUpdate()
|
||||
throws IOException, NoSuchAlgorithmException, XMLStreamException, ModelBuildingException,
|
||||
ComponentLookupException {
|
||||
String result;
|
||||
Path src = sourcePathProvider.get();
|
||||
if (src == null) {
|
||||
Files.deleteIfExists(target);
|
||||
result = null;
|
||||
} else if (!Files.exists(src)) {
|
||||
Files.deleteIfExists(target);
|
||||
result = "";
|
||||
} else {
|
||||
String current = sha1(src);
|
||||
String existing = sourceState.get();
|
||||
if (!Objects.equals(current, existing)) {
|
||||
defaultConsumerPomArtifactTransformer.transform(project, session, src, target);
|
||||
Files.setLastModifiedTime(target, Files.getLastModifiedTime(src));
|
||||
}
|
||||
result = current;
|
||||
}
|
||||
sourceState.set(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static String sha1(Path path) throws NoSuchAlgorithmException, IOException {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
try (InputStream fis = Files.newInputStream(path)) {
|
||||
byte[] buffer = new byte[SHA1_BUFFER_SIZE];
|
||||
int read;
|
||||
while ((read = fis.read(buffer)) != -1) {
|
||||
md.update(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte b : md.digest()) {
|
||||
result.append(String.format("%02x", b));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.internal.transformation.impl;
|
||||
|
||||
import org.apache.maven.artifact.handler.ArtifactHandler;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
class TransformedArtifactHandler implements ArtifactHandler {
|
||||
|
||||
private final String classifier;
|
||||
|
||||
private final String extension;
|
||||
|
||||
private final String packaging;
|
||||
|
||||
TransformedArtifactHandler(String classifier, String extension, String packaging) {
|
||||
this.classifier = classifier;
|
||||
this.extension = requireNonNull(extension);
|
||||
this.packaging = requireNonNull(packaging);
|
||||
}
|
||||
|
||||
public String getClassifier() {
|
||||
return classifier;
|
||||
}
|
||||
|
||||
public String getDirectory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return "none";
|
||||
}
|
||||
|
||||
public String getPackaging() {
|
||||
return packaging;
|
||||
}
|
||||
|
||||
public boolean isAddedToClasspath() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIncludesDependencies() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -94,7 +94,7 @@ public class LifecycleModuleBuilder {
|
|||
return;
|
||||
}
|
||||
|
||||
consumerPomArtifactTransformer.injectTransformedArtifacts(currentProject, session.getRepositorySession());
|
||||
consumerPomArtifactTransformer.injectTransformedArtifacts(session.getRepositorySession(), currentProject);
|
||||
|
||||
BuilderCommon.attachToThread(currentProject);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.apache.maven.execution.DefaultMavenExecutionRequest;
|
|||
import org.apache.maven.execution.DefaultMavenExecutionResult;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.internal.impl.DefaultSession;
|
||||
import org.apache.maven.internal.impl.DefaultSessionFactory;
|
||||
import org.apache.maven.model.Build;
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.model.Exclusion;
|
||||
|
@ -146,11 +146,14 @@ public abstract class AbstractCoreMavenComponentTestCase {
|
|||
|
||||
initRepoSession(configuration);
|
||||
|
||||
DefaultSessionFactory defaultSessionFactory =
|
||||
new DefaultSessionFactory(mock(RepositorySystem.class), null, null, null);
|
||||
|
||||
MavenSession session = new MavenSession(
|
||||
getContainer(), configuration.getRepositorySession(), request, new DefaultMavenExecutionResult());
|
||||
session.setProjects(projects);
|
||||
session.setAllProjects(session.getProjects());
|
||||
session.setSession(new DefaultSession(session, mock(RepositorySystem.class), null, null, null, null));
|
||||
session.setSession(defaultSessionFactory.getSession(session));
|
||||
|
||||
return session;
|
||||
}
|
||||
|
|
|
@ -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.internal.transformation;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
import org.codehaus.plexus.testing.PlexusTest;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositoryListener;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.repository.LocalRepository;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.aether.transfer.TransferListener;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.codehaus.plexus.testing.PlexusExtension.getTestFile;
|
||||
|
||||
@PlexusTest
|
||||
public abstract class AbstractRepositoryTestCase {
|
||||
@Inject
|
||||
protected RepositorySystem system;
|
||||
|
||||
@Inject
|
||||
protected PlexusContainer container;
|
||||
|
||||
protected RepositorySystemSession session;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
session = newMavenRepositorySystemSession(system);
|
||||
}
|
||||
|
||||
protected PlexusContainer getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public static RepositorySystemSession newMavenRepositorySystemSession(RepositorySystem system) {
|
||||
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
|
||||
|
||||
LocalRepository localRepo = new LocalRepository("target/local-repo");
|
||||
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
|
||||
|
||||
session.setTransferListener(Mockito.mock(TransferListener.class));
|
||||
session.setRepositoryListener(Mockito.mock(RepositoryListener.class));
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public static RemoteRepository newTestRepository() throws MalformedURLException {
|
||||
return new RemoteRepository.Builder(
|
||||
"repo",
|
||||
"default",
|
||||
getTestFile("target/test-classes/repo").toURI().toURL().toString())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.internal.transformation;
|
||||
package org.apache.maven.internal.transformation.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -25,8 +25,6 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.building.DefaultModelBuilderFactory;
|
||||
import org.apache.maven.model.building.ModelBuilder;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.model.v4.MavenStaxReader;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
@ -42,8 +40,6 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
class ConsumerPomArtifactTransformerTest {
|
||||
|
||||
ModelBuilder modelBuilder = new DefaultModelBuilderFactory().newInstance();
|
||||
|
||||
@Test
|
||||
void transform() throws Exception {
|
||||
RepositorySystemSession systemSessionMock = Mockito.mock(RepositorySystemSession.class);
|
||||
|
@ -60,9 +56,13 @@ class ConsumerPomArtifactTransformerTest {
|
|||
try (InputStream expected = Files.newInputStream(beforePomFile)) {
|
||||
Model model = new Model(new MavenStaxReader().read(expected));
|
||||
MavenProject project = new MavenProject(model);
|
||||
ConsumerPomArtifactTransformer t = new ConsumerPomArtifactTransformer(modelBuilder);
|
||||
t.createConsumerPomArtifact(project, tempFile, systemSessionMock)
|
||||
.transform(beforePomFile, tempFile, model.getDelegate());
|
||||
DefaultConsumerPomArtifactTransformer t = new DefaultConsumerPomArtifactTransformer((s, p, f) -> {
|
||||
try (InputStream is = Files.newInputStream(f)) {
|
||||
return DefaultConsumerPomBuilder.transform(new MavenStaxReader().read(is));
|
||||
}
|
||||
});
|
||||
|
||||
t.transform(project, systemSessionMock, beforePomFile, tempFile);
|
||||
}
|
||||
XmlAssert.assertThat(afterPomFile.toFile()).and(tempFile.toFile()).areIdentical();
|
||||
}
|
||||
|
@ -76,7 +76,8 @@ class ConsumerPomArtifactTransformerTest {
|
|||
when(systemSessionMock.getData()).thenReturn(sessionDataMock);
|
||||
when(sessionDataMock.get(any())).thenReturn(new NoTransformerContext());
|
||||
|
||||
new ConsumerPomArtifactTransformer(modelBuilder).injectTransformedArtifacts(emptyProject, systemSessionMock);
|
||||
new DefaultConsumerPomArtifactTransformer((session, project, src) -> null)
|
||||
.injectTransformedArtifacts(systemSessionMock, emptyProject);
|
||||
|
||||
assertThat(emptyProject.getAttachedArtifacts()).isEmpty();
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.internal.transformation.impl;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.maven.api.model.Model;
|
||||
import org.apache.maven.artifact.repository.MavenArtifactRepository;
|
||||
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
|
||||
import org.apache.maven.internal.transformation.AbstractRepositoryTestCase;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ConsumerPomBuilderTest extends AbstractRepositoryTestCase {
|
||||
|
||||
@Inject
|
||||
ConsumerPomBuilder builder;
|
||||
|
||||
@Test
|
||||
void testTrivialConsumer() throws Exception {
|
||||
MavenProject project = new MavenProject();
|
||||
project.setRootDirectory(Paths.get("src/test/resources/consumer/trivial"));
|
||||
project.setRemoteArtifactRepositories(Collections.singletonList(new MavenArtifactRepository(
|
||||
"central", "http://repo.maven.apache.org/", new DefaultRepositoryLayout(), null, null)));
|
||||
Path file = Paths.get("src/test/resources/consumer/trivial/child/pom.xml");
|
||||
Model model = builder.build(session, project, file);
|
||||
|
||||
assertNotNull(model);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleConsumer() throws Exception {
|
||||
MavenProject project = new MavenProject();
|
||||
project.setRootDirectory(Paths.get("src/test/resources/consumer/simple"));
|
||||
project.setRemoteArtifactRepositories(Collections.singletonList(new MavenArtifactRepository(
|
||||
"central", "http://repo.maven.apache.org/", new DefaultRepositoryLayout(), null, null)));
|
||||
Path file = Paths.get("src/test/resources/consumer/simple/simple-parent/simple-weather/pom.xml");
|
||||
((DefaultRepositorySystemSession) session).setUserProperty("changelist", "MNG6957");
|
||||
Model model = builder.build(session, project, file);
|
||||
|
||||
assertNotNull(model);
|
||||
assertTrue(model.getProfiles().isEmpty());
|
||||
}
|
||||
}
|
|
@ -192,8 +192,9 @@ class ProjectBuilderTest extends AbstractCoreMavenComponentTestCase {
|
|||
|
||||
@Test
|
||||
void testReadErroneousMavenProjectContainsReference() throws Exception {
|
||||
File pomFile = new File("src/test/resources/projects/artifactMissingVersion.xml").getAbsoluteFile();
|
||||
File pomFile = new File("src/test/resources/projects/artifactMissingVersion/pom.xml").getAbsoluteFile();
|
||||
MavenSession mavenSession = createMavenSession(null);
|
||||
mavenSession.getRequest().setRootDirectory(pomFile.getParentFile().toPath());
|
||||
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
|
||||
configuration.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
|
||||
configuration.setRepositorySession(mavenSession.getRepositorySession());
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project root="true" xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 https://maven.apache.org/xsd/maven-4.1.0-alpha-8.xsd">
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.9-${changelist}-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Multi Chapter Parent Project</name>
|
||||
|
||||
<!-- Optimized from https://github.com/sonatype/maven-example-en/tree/master/examples/ch-multi -->
|
||||
<modules>
|
||||
<module>simple-parent</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 https://maven.apache.org/xsd/maven-4.1.0-alpha-8.xsd">
|
||||
<parent>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
</parent>
|
||||
<artifactId>simple-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Multi Chapter Simple Parent Project</name>
|
||||
|
||||
<modules>
|
||||
<module>simple-weather</module>
|
||||
<module>simple-webapp</module>
|
||||
|
||||
<!-- On purpose at the end, project graph is responsible for ordering -->
|
||||
<!-- Build/consumer should not be effected by reverse order -->
|
||||
<module>simple-testutils</module>
|
||||
<module>utils-parent</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>0.1-stub-SNAPSHOT</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 https://maven.apache.org/xsd/maven-4.1.0-alpha-8.xsd">
|
||||
<parent>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>utils-parent</artifactId>
|
||||
<relativePath>../utils-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>simple-testutils</artifactId>
|
||||
</project>
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 https://maven.apache.org/xsd/maven-4.1.0-alpha-8.xsd">
|
||||
<parent>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>simple-parent</artifactId>
|
||||
</parent>
|
||||
<artifactId>simple-weather</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Multi Chapter Simple Weather API</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>simple-testutils</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>simple-parent</artifactId>
|
||||
</parent>
|
||||
|
||||
<artifactId>simple-webapp</artifactId>
|
||||
<name>Multi Chapter Simple Web Application Project</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>simple-weather</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>simple-webapp</finalName>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.3.2</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 https://maven.apache.org/xsd/maven-4.1.0-alpha-8.xsd">
|
||||
<parent>
|
||||
<groupId>org.sonatype.mavenbook.multi</groupId>
|
||||
<artifactId>simple-parent</artifactId>
|
||||
</parent>
|
||||
<artifactId>utils-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
</project>
|
|
@ -0,0 +1,18 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.1.0">
|
||||
<parent>
|
||||
<groupId>org.my.group</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
</parent>
|
||||
<artifactId>child</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<prop-child>bar</prop-child>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,47 @@
|
|||
<project root="true" xmlns="http://maven.apache.org/POM/4.1.0">
|
||||
<groupId>org.my.group</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>child.xml</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.9</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<properties>
|
||||
<prop>foo</prop>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -1045,7 +1045,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private Model readFileModel(ModelBuildingRequest request, DefaultModelProblemCollector problems)
|
||||
Model readFileModel(ModelBuildingRequest request, DefaultModelProblemCollector problems)
|
||||
throws ModelBuildingException {
|
||||
ModelSource modelSource = request.getModelSource();
|
||||
org.apache.maven.api.model.Model model = cache(
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
*/
|
||||
package org.apache.maven.model.building;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -56,6 +59,9 @@ class DefaultTransformerContextBuilder implements TransformerContextBuilder {
|
|||
// We must assume the TransformerContext was created using this.newTransformerContextBuilder()
|
||||
DefaultModelProblemCollector problems = (DefaultModelProblemCollector) collector;
|
||||
return new TransformerContext() {
|
||||
|
||||
private volatile boolean fullReactorLoaded;
|
||||
|
||||
@Override
|
||||
public Path locate(Path path) {
|
||||
return context.locate(path);
|
||||
|
@ -91,6 +97,11 @@ class DefaultTransformerContextBuilder implements TransformerContextBuilder {
|
|||
|
||||
private Model findRawModel(Path from, String groupId, String artifactId) {
|
||||
FileModelSource source = getSource(groupId, artifactId);
|
||||
if (source == null) {
|
||||
// we need to check the whole reactor in case it's a dependency
|
||||
loadFullReactor();
|
||||
source = getSource(groupId, artifactId);
|
||||
}
|
||||
if (source != null) {
|
||||
if (!addEdge(from, source.getFile().toPath(), problems)) {
|
||||
return null;
|
||||
|
@ -106,6 +117,45 @@ class DefaultTransformerContextBuilder implements TransformerContextBuilder {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void loadFullReactor() {
|
||||
if (!fullReactorLoaded) {
|
||||
synchronized (this) {
|
||||
if (!fullReactorLoaded) {
|
||||
doLoadFullReactor();
|
||||
fullReactorLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doLoadFullReactor() {
|
||||
Path rootDirectory = request.getRootDirectory();
|
||||
if (rootDirectory == null) {
|
||||
return;
|
||||
}
|
||||
List<File> toLoad = new ArrayList<>();
|
||||
File root = defaultModelBuilder.getModelProcessor().locateExistingPom(rootDirectory.toFile());
|
||||
toLoad.add(root);
|
||||
while (!toLoad.isEmpty()) {
|
||||
File pom = toLoad.remove(0);
|
||||
try {
|
||||
ModelBuildingRequest gaBuildingRequest =
|
||||
new DefaultModelBuildingRequest(request).setModelSource(new FileModelSource(pom));
|
||||
Model rawModel = defaultModelBuilder.readFileModel(gaBuildingRequest, problems);
|
||||
for (String module : rawModel.getModules()) {
|
||||
File moduleFile = defaultModelBuilder
|
||||
.getModelProcessor()
|
||||
.locateExistingPom(new File(pom.getParent(), module));
|
||||
if (moduleFile != null) {
|
||||
toLoad.add(moduleFile);
|
||||
}
|
||||
}
|
||||
} catch (ModelBuildingException e) {
|
||||
// gathered with problem collector
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Model findRawModel(Path from, Path p) {
|
||||
if (!Files.isRegularFile(p)) {
|
||||
throw new IllegalArgumentException("Not a regular file: " + p);
|
||||
|
|
Loading…
Reference in New Issue