Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Sep 27, 2024
1 parent 12d2977 commit 6d78b75
Showing 1 changed file with 74 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -118,6 +117,10 @@
import org.slf4j.LoggerFactory;

/**
* The model builder is responsible for building the {@link Model} from the POM file.
* There are two ways to main use cases: the first one is to build the model from a POM file
* on the file system in order to actually build the project. The second one is to build the
* model for a dependency or an external parent.
*/
@Named
@Singleton
Expand Down Expand Up @@ -223,7 +226,7 @@ public ModelBuilderResult build(ModelBuilderRequest request) throws ModelBuilder
// simply build the effective model
session.buildEffectiveModel(new LinkedHashSet<>());
}
return session.result();
return session.result;
}
};
}
Expand All @@ -245,14 +248,10 @@ protected class DefaultModelBuilderSession implements ModelProblemCollector {
List<RemoteRepository> repositories;

DefaultModelBuilderSession(ModelBuilderRequest request) {
this(request, new DefaultModelBuilderResult());
}

DefaultModelBuilderSession(ModelBuilderRequest request, DefaultModelBuilderResult result) {
this(
request.getSession(),
request,
result,
new DefaultModelBuilderResult(),
request.getSession()
.getData()
.computeIfAbsent(SessionData.key(ModelCache.class), modelCacheFactory::newInstance),
Expand Down Expand Up @@ -300,6 +299,13 @@ DefaultModelBuilderSession derive(ModelSource source, DefaultModelBuilderResult
return derive(ModelBuilderRequest.build(request, source), result);
}

/**
* Creates a new session, sharing cached datas and propagating errors.
*/
DefaultModelBuilderSession derive(ModelBuilderRequest request) {
return derive(request, new DefaultModelBuilderResult(result));
}

DefaultModelBuilderSession derive(ModelBuilderRequest request, DefaultModelBuilderResult result) {
if (session != request.getSession()) {
throw new IllegalArgumentException("Session mismatch");
Expand All @@ -316,22 +322,6 @@ DefaultModelBuilderSession derive(ModelBuilderRequest request, DefaultModelBuild
repositories);
}

public Session session() {
return session;
}

public ModelBuilderRequest request() {
return request;
}

public ModelBuilderResult result() {
return result;
}

public ModelCache cache() {
return cache;
}

@Override
public String toString() {
return "ModelBuilderSession[" + "session="
Expand Down Expand Up @@ -361,7 +351,7 @@ private int getParallelism() {
public Model getRawModel(Path from, String groupId, String artifactId) {
ModelSource source = getSource(groupId, artifactId);
if (source != null) {
if (!addEdge(from, source.getPath())) {
if (addEdge(from, source.getPath())) {
return null;
}
try {
Expand All @@ -377,7 +367,7 @@ public Model getRawModel(Path from, Path path) {
if (!Files.isRegularFile(path)) {
throw new IllegalArgumentException("Not a regular file: " + path);
}
if (!addEdge(from, path)) {
if (addEdge(from, path)) {
return null;
}
try {
Expand All @@ -388,18 +378,21 @@ public Model getRawModel(Path from, Path path) {
return null;
}

/**
* Returns false if the edge was added, true if it caused a cycle.
*/
private boolean addEdge(Path from, Path p) {
try {
dag.addEdge(from.toString(), p.toString());
return true;
return false;
} catch (Graph.CycleDetectedException e) {
add(
Severity.FATAL,
ModelProblem.Version.BASE,
"Cycle detected between models at " + from + " and " + p,
null,
e);
return false;
return true;
}
}

Expand Down Expand Up @@ -686,7 +679,7 @@ private void buildBuildPom() throws ModelBuilderException {
}

// Locate and normalize the root POM if it exists, fallback to top otherwise
Path root = getModelProcessor().locateExistingPom(rootDirectory);
Path root = modelProcessor.locateExistingPom(rootDirectory);
if (root != null) {
root = root.toAbsolutePath().normalize();
} else {
Expand Down Expand Up @@ -779,13 +772,11 @@ private void loadFilePom(
Path pomDirectory = Files.isDirectory(pom) ? pom : pom.getParent();
ModelSource src = ModelSource.fromPath(pom);
Model model = derive(src, r).readFileModel();
// keep all loaded file models in memory, those will be needed
// during the raw to build transformation
putSource(getGroupId(model), model.getArtifactId(), src);
Model activated = activateFileModel(model);
List<String> subprojects = activated.getSubprojects();
if (subprojects.isEmpty()) {
subprojects = activated.getModules();
}
for (String subproject : subprojects) {
for (String subproject : getSubprojects(activated)) {
if (subproject == null || subproject.isEmpty()) {
continue;
}
Expand Down Expand Up @@ -905,12 +896,12 @@ void buildEffectiveModel(Collection<String> importIds) throws ModelBuilderExcept
}
}

Model readParent(Model childModel, ModelSource childSource) throws ModelBuilderException {
Model parentModel = null;
Model readParent(Model childModel) throws ModelBuilderException {
Model parentModel;

Parent parent = childModel.getParent();
if (parent != null) {
parentModel = readParentLocally(childModel, childSource);
parentModel = readParentLocally(childModel);
if (parentModel == null) {
parentModel = resolveAndReadParentExternally(childModel);
}
Expand All @@ -923,18 +914,28 @@ Model readParent(Model childModel, ModelSource childSource) throws ModelBuilderE
+ ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"",
parentModel.getLocation("packaging"));
}
result.setParentModel(parentModel);
} else {
String superModelVersion = childModel.getModelVersion();
if (superModelVersion == null || !VALID_MODEL_VERSIONS.contains(superModelVersion)) {
// Maven 3.x is always using 4.0.0 version to load the supermodel, so
// do the same when loading a dependency. The model validator will also
// check that field later.
superModelVersion = MODEL_VERSION_4_0_0;
}
parentModel = getSuperModel(superModelVersion);
}

return parentModel;
}

private Model readParentLocally(Model childModel, ModelSource childSource) throws ModelBuilderException {
ModelSource candidateSource = getParentPomFile(childModel, childSource);
private Model readParentLocally(Model childModel) throws ModelBuilderException {
ModelSource candidateSource = getParentPomFile(childModel, request.getSource());
if (candidateSource == null) {
return null;
}

Model candidateModel = derive(candidateSource).readParentModel();
Model candidateModel = derive(candidateSource).readAsParentModel();

//
// TODO jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
Expand Down Expand Up @@ -1022,14 +1023,15 @@ Model resolveAndReadParentExternally(Model childModel) throws ModelBuilderExcept

// add repositories specified by the current model so that we can resolve the parent
if (!childModel.getRepositories().isEmpty()) {
List<String> oldRepos =
repositories.stream().map(Object::toString).toList();
var previousRepositories = repositories;
mergeRepositories(childModel.getRepositories(), false);
List<String> newRepos =
repositories.stream().map(Object::toString).toList();
if (!Objects.equals(oldRepos, newRepos)) {
logger.debug("Merging repositories from " + childModel.getId() + "\n"
+ newRepos.stream().map(s -> " " + s).collect(Collectors.joining("\n")));
if (!Objects.equals(previousRepositories, repositories)) {
if (logger.isDebugEnabled()) {
logger.debug("Merging repositories from " + childModel.getId() + "\n"
+ repositories.stream()
.map(Object::toString)
.collect(Collectors.joining("\n", " ", "")));
}
}
}

Expand Down Expand Up @@ -1072,8 +1074,7 @@ Model resolveAndReadParentExternally(Model childModel) throws ModelBuilderExcept
.source(modelSource)
.build();

DefaultModelBuilderResult r = new DefaultModelBuilderResult(this.result);
Model parentModel = derive(lenientRequest, r).readParentModel();
Model parentModel = derive(lenientRequest).readAsParentModel();

if (!parent.getVersion().equals(version)) {
String rawChildModelVersion = childModel.getVersion();
Expand Down Expand Up @@ -1167,20 +1168,7 @@ private Model readEffectiveModel() throws ModelBuilderException {
profileActivationContext.setUserProperties(profileProps);
}

Model parentModel = readParent(inputModel, request.getSource());
if (parentModel == null) {
String superModelVersion =
inputModel.getModelVersion() != null ? inputModel.getModelVersion() : MODEL_VERSION_4_0_0;
if (!VALID_MODEL_VERSIONS.contains(superModelVersion)) {
// Maven 3.x is always using 4.0.0 version to load the supermodel, so
// do the same when loading a dependency. The model validator will also
// check that field later.
superModelVersion = MODEL_VERSION_4_0_0;
}
parentModel = getSuperModel(superModelVersion);
} else {
result.setParentModel(parentModel);
}
Model parentModel = readParent(inputModel);

List<Profile> parentInterpolatedProfiles =
interpolateActivations(parentModel.getProfiles(), profileActivationContext, this);
Expand Down Expand Up @@ -1347,7 +1335,7 @@ Model doReadFileModel() throws ModelBuilderException {
Path relativePath = Paths.get(path);
Path pomPath = pomFile.resolveSibling(relativePath).normalize();
if (Files.isDirectory(pomPath)) {
pomPath = getModelProcessor().locateExistingPom(pomPath);
pomPath = modelProcessor.locateExistingPom(pomPath);
}
if (pomPath != null && Files.isRegularFile(pomPath)) {
Model parentModel =
Expand All @@ -1370,8 +1358,7 @@ Model doReadFileModel() throws ModelBuilderException {
}

// subprojects discovery
if (model.getSubprojects().isEmpty()
&& model.getModules().isEmpty()
if (getSubprojects(model).isEmpty()
// only discover subprojects if POM > 4.0.0
&& !MODEL_VERSION_4_0_0.equals(model.getModelVersion())
// and if packaging is POM (we check type, but the session is not yet available,
Expand Down Expand Up @@ -1450,27 +1437,16 @@ private Model doReadRawModel() throws ModelBuilderException {
return rawModel;
}

Model readParentModel() {
return cache(request.getSource(), PARENT, this::doReadParentModel);
/**
* Reads the request source's parent.
*/
Model readAsParentModel() {
return cache(request.getSource(), PARENT, this::doReadAsParentModel);
}

private Model doReadParentModel() {
private Model doReadAsParentModel() throws ModelBuilderException {
Model raw = readRawModel();

Model parentData;
if (raw.getParent() != null) {
parentData = readParent(raw, request.getSource());
} else {
String superModelVersion = raw.getModelVersion() != null ? raw.getModelVersion() : "4.0.0";
if (!VALID_MODEL_VERSIONS.contains(superModelVersion)) {
// Maven 3.x is always using 4.0.0 version to load the supermodel, so
// do the same when loading a dependency. The model validator will also
// check that field later.
superModelVersion = MODEL_VERSION_4_0_0;
}
parentData = getSuperModel(superModelVersion);
}

Model parentData = readParent(raw);
Model parent = new DefaultInheritanceAssembler(new DefaultInheritanceAssembler.InheritanceModelMerger() {
@Override
protected void mergeModel_Modules(
Expand All @@ -1488,6 +1464,7 @@ protected void mergeModel_Subprojects(
boolean sourceDominant,
Map<Object, Object> context) {}

@SuppressWarnings("deprecation")
@Override
protected void mergeModel_Profiles(
Model.Builder builder,
Expand Down Expand Up @@ -1676,7 +1653,7 @@ private Model doLoadDependencyManagement(
DefaultModelBuilderSession modelBuilderSession = new DefaultModelBuilderSession(importRequest);
// build the effective model
modelBuilderSession.buildEffectiveModel(importIds);
importResult = modelBuilderSession.result();
importResult = modelBuilderSession.result;
} catch (ModelBuilderException e) {
e.getResult().getProblems().forEach(this::add);
return null;
Expand All @@ -1703,15 +1680,24 @@ ModelSource resolveReactorModel(String groupId, String artifactId, String versio
return null;
}

private <T> T cache(String groupId, String artifactId, String version, String tag, Callable<T> supplier) {
return cache.computeIfAbsent(groupId, artifactId, version, tag, asSupplier(supplier));
private <T> T cache(String groupId, String artifactId, String version, String tag, Supplier<T> supplier) {
return cache.computeIfAbsent(groupId, artifactId, version, tag, supplier);
}

private <T> T cache(Source source, String tag, Callable<T> supplier) {
return cache.computeIfAbsent(source, tag, asSupplier(supplier));
private <T> T cache(Source source, String tag, Supplier<T> supplier) {
return cache.computeIfAbsent(source, tag, supplier);
}
}

@SuppressWarnings("deprecation")
private static List<String> getSubprojects(Model activated) {
List<String> subprojects = activated.getSubprojects();
if (subprojects.isEmpty()) {
subprojects = activated.getModules();
}
return subprojects;
}

private List<Profile> interpolateActivations(
List<Profile> profiles, DefaultProfileActivationContext context, ModelProblemCollector problems) {
if (profiles.stream()
Expand Down Expand Up @@ -1914,31 +1900,12 @@ private boolean match(String match, String text) {
return match.equals("*") || match.equals(text);
}

private static <T> Supplier<T> asSupplier(Callable<T> supplier) {
return () -> {
try {
return supplier.call();
} catch (Exception e) {
uncheckedThrow(e);
return null;
}
};
}

static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
throw (T) t; // rely on vacuous cast
}

private boolean containsCoordinates(String message, String groupId, String artifactId, String version) {
return message != null
&& (groupId == null || message.contains(groupId))
&& (artifactId == null || message.contains(artifactId))
&& (version == null || message.contains(version));
}

ModelProcessor getModelProcessor() {
return modelProcessor;
}

record GAKey(String groupId, String artifactId) {}
}

0 comments on commit 6d78b75

Please sign in to comment.