Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.apache.maven.api.model.Repository;
import org.apache.maven.api.services.ArtifactCoordinatesFactory;
import org.apache.maven.api.services.DependencyCoordinatesFactory;
import org.apache.maven.api.services.ModelProblem;
import org.apache.maven.api.services.ProblemCollector;
import org.apache.maven.api.services.VersionResolverException;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.api.toolchain.ToolchainModel;
Expand Down Expand Up @@ -93,6 +95,25 @@ public interface Session extends ProtoSession {
@Nonnull
SessionData getData();

/**
* Returns the model problems encountered while discovering the projects in this session's reactor.
*
* @return the session model problem collector, never {@code null}
*/
@Nonnull
default ProblemCollector<ModelProblem> getModelProblemCollector() {
return SessionModelProblems.getProblemCollector(this);
}

/**
* Returns whether model problems were encountered while discovering the projects in this session's reactor.
*
* @return {@code true} if at least one model problem was encountered
*/
default boolean hasModelProblems() {
return getModelProblemCollector().hasWarningProblems();
}

/**
* Default implementation at {@link ProtoSession} level, as the notion of project
* does not exist there.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.api;

import org.apache.maven.api.services.ModelProblem;
import org.apache.maven.api.services.ProblemCollector;

final class SessionModelProblems {

private static final SessionData.Key<State> KEY = SessionData.key(State.class, SessionModelProblems.class);

private SessionModelProblems() {}

static ProblemCollector<ModelProblem> getProblemCollector(Session session) {
return session.getData()
.computeIfAbsent(KEY, () -> new State(ProblemCollector.create(session)))
.problemCollector;
}

private static final class State {

private final ProblemCollector<ModelProblem> problemCollector;

private State(ProblemCollector<ModelProblem> problemCollector) {
this.problemCollector = problemCollector;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.RepositoryCache;
import org.apache.maven.impl.SettingsUtilsV4;
import org.apache.maven.internal.impl.SessionModelProblemsBridge;
import org.apache.maven.model.Profile;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
Expand Down Expand Up @@ -295,6 +296,8 @@ public void setAllProjects(List<MavenProject> allProjects) {

private Session session;

private boolean modelProblems;

@Deprecated
/** @deprecated This appears not to be used anywhere within Maven itself. */
public Map<String, MavenProject> getProjectMap() {
Expand Down Expand Up @@ -496,8 +499,34 @@ public Session getSession() {
return session;
}

/**
* Returns whether the reactor projects had model problems.
*
* @return {@code true} if model problems were encountered
* @since 3.10.0
*/
public boolean hasModelProblems() {
return modelProblems || (session != null && session.hasModelProblems());
}

/**
* Sets whether the reactor projects had model problems.
*
* @param modelProblems whether model problems were encountered
* @since 3.10.0
*/
public void setModelProblems(boolean modelProblems) {
this.modelProblems = modelProblems;
if (session != null) {
SessionModelProblemsBridge.setLegacyFlag(session, modelProblems);
}
}

public void setSession(Session session) {
this.session = session;
if (session != null) {
SessionModelProblemsBridge.setLegacyFlag(session, modelProblems);
}
}
/*end[MAVEN4]*/
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import org.apache.maven.MavenExecutionException;
import org.apache.maven.ProjectCycleException;
Expand Down Expand Up @@ -349,22 +350,48 @@ private String formatProjects(List<MavenProject> projects) {
private List<MavenProject> getProjectsForMavenReactor(MavenSession session) throws ProjectBuildingException {
MavenExecutionRequest request = session.getRequest();
request.getProjectBuildingRequest().setRepositorySession(session.getRepositorySession());
Consumer<org.apache.maven.model.building.ModelProblem> modelProblemConsumer = getModelProblemConsumer(session);

// 1. Collect project for invocation without a POM.
if (request.getPom() == null) {
return pomlessCollectionStrategy.collectProjects(request);
return pomlessCollectionStrategy.collectProjects(request, modelProblemConsumer);
}

// 2. Collect projects for all modules in the multi-module project.
if (request.getMakeBehavior() != null || !request.getProjectActivation().isEmpty()) {
List<MavenProject> projects = multiModuleCollectionStrategy.collectProjects(request);
List<MavenProject> projects = multiModuleCollectionStrategy.collectProjects(request, modelProblemConsumer);
if (!projects.isEmpty()) {
return projects;
}
}

// 3. Collect projects for explicitly requested POM.
return requestPomCollectionStrategy.collectProjects(request);
return requestPomCollectionStrategy.collectProjects(request, modelProblemConsumer);
}

private Consumer<org.apache.maven.model.building.ModelProblem> getModelProblemConsumer(MavenSession session) {
org.apache.maven.api.Session apiSession = session.getSession();
if (apiSession == null) {
return problem -> session.setModelProblems(true);
}
return problem -> apiSession.getModelProblemCollector().reportProblem(toApiModelProblem(problem));
}

private org.apache.maven.api.services.ModelProblem toApiModelProblem(
org.apache.maven.model.building.ModelProblem problem) {
return new org.apache.maven.impl.model.DefaultModelProblem(
problem.getMessage(),
org.apache.maven.api.services.BuilderProblem.Severity.valueOf(
problem.getSeverity().name()),
problem.getVersion() != null
? org.apache.maven.api.services.ModelProblem.Version.valueOf(
problem.getVersion().name())
: org.apache.maven.api.services.ModelProblem.Version.BASE,
problem.getSource(),
problem.getLineNumber(),
problem.getColumnNumber(),
problem.getModelId(),
problem.getException());
}

private void validateProjects(List<MavenProject> projects, MavenExecutionRequest request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ public List<Project> getProjects() {
return getProjects(getMavenSession().getProjects());
}

@Override
public boolean hasModelProblems() {
return SessionModelProblemsBridge.hasModelProblems(this);
}

@Nonnull
@Override
public Map<String, Object> getPluginContext(Project project) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.impl;

import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.maven.api.Session;
import org.apache.maven.api.SessionData;

import static java.util.Objects.requireNonNull;

/**
* Stores the legacy model-problem flag in session data so that derived sessions see the same state.
*/
public final class SessionModelProblemsBridge {

private static final SessionData.Key<State> KEY = SessionData.key(State.class, SessionModelProblemsBridge.class);

private SessionModelProblemsBridge() {}

public static boolean hasModelProblems(Session session) {
return getState(session).legacyFlag.get()
|| session.getModelProblemCollector().hasWarningProblems();
}

public static void setLegacyFlag(Session session, boolean value) {
getState(session).legacyFlag.set(value);
}

private static State getState(Session session) {
requireNonNull(session, "session");
return session.getData().computeIfAbsent(KEY, State::new);
}

private static final class State {

private final AtomicBoolean legacyFlag = new AtomicBoolean();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.model.building.ModelProblem;
Expand Down Expand Up @@ -54,6 +55,13 @@ public DefaultProjectsSelector(ProjectBuilder projectBuilder) {
@Override
public List<MavenProject> selectProjects(List<File> files, MavenExecutionRequest request)
throws ProjectBuildingException {
return selectProjects(files, request, problem -> {});
}

@Override
public List<MavenProject> selectProjects(
List<File> files, MavenExecutionRequest request, Consumer<ModelProblem> problemConsumer)
throws ProjectBuildingException {
ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();

boolean hasProjectSelection = !request.getProjectActivation().isEmpty();
Expand All @@ -66,6 +74,7 @@ public List<MavenProject> selectProjects(List<File> files, MavenExecutionRequest

for (ProjectBuildingResult result : results) {
projects.add(result.getProject());
result.getProblems().forEach(problemConsumer);

int problemsCount = result.getProblems().size();
totalProblemsCount += problemsCount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;

import org.apache.maven.api.services.model.ModelProcessor;
Expand Down Expand Up @@ -62,12 +63,19 @@ public MultiModuleCollectionStrategy(ModelProcessor modelProcessor, ProjectsSele

@Override
public List<MavenProject> collectProjects(MavenExecutionRequest request) throws ProjectBuildingException {
return collectProjects(request, problem -> {});
}

public List<MavenProject> collectProjects(MavenExecutionRequest request, Consumer<ModelProblem> problemConsumer)
throws ProjectBuildingException {
File moduleProjectPomFile = getRootProject(request);
List<File> files = Collections.singletonList(moduleProjectPomFile.getAbsoluteFile());
try {
List<MavenProject> projects = projectsSelector.selectProjects(files, request);
List<ModelProblem> problems = new ArrayList<>();
List<MavenProject> projects = projectsSelector.selectProjects(files, request, problems::add);
boolean isRequestedProjectCollected = isRequestedProjectCollected(request, projects);
if (isRequestedProjectCollected) {
problems.forEach(problemConsumer);
return projects;
} else {
LOGGER.debug(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

import org.apache.maven.DefaultMaven;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelSource;
import org.apache.maven.model.building.UrlModelSource;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingResult;

/**
* Strategy to collect projects for building when the Maven invocation is not in a directory that contains a pom.xml.
Expand All @@ -49,10 +52,16 @@ public PomlessCollectionStrategy(ProjectBuilder projectBuilder) {

@Override
public List<MavenProject> collectProjects(final MavenExecutionRequest request) throws ProjectBuildingException {
return collectProjects(request, problem -> {});
}

public List<MavenProject> collectProjects(MavenExecutionRequest request, Consumer<ModelProblem> problemConsumer)
throws ProjectBuildingException {
ProjectBuildingRequest buildingRequest = request.getProjectBuildingRequest();
ModelSource modelSource = new UrlModelSource(DefaultMaven.class.getResource("project/standalone.xml"));
MavenProject project =
projectBuilder.build(modelSource, buildingRequest).getProject();
ProjectBuildingResult result = projectBuilder.build(modelSource, buildingRequest);
result.getProblems().forEach(problemConsumer);
MavenProject project = result.getProject();
project.setExecutionRoot(true);
request.setProjectPresent(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@

import java.io.File;
import java.util.List;
import java.util.function.Consumer;

import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;

Expand All @@ -37,4 +39,19 @@ public interface ProjectsSelector {
* @throws ProjectBuildingException In case the POMs are not used.
*/
List<MavenProject> selectProjects(List<File> files, MavenExecutionRequest request) throws ProjectBuildingException;

/**
* Select Maven projects from a list of POM files and report model problems encountered while building them.
*
* @param files List of POM files.
* @param request The {@link MavenExecutionRequest}
* @param problemConsumer Consumer for model problems encountered while building the selected projects.
* @return A list of projects that have been found in the specified POM files.
* @throws ProjectBuildingException In case the POMs are not used.
*/
default List<MavenProject> selectProjects(
List<File> files, MavenExecutionRequest request, Consumer<ModelProblem> problemConsumer)
throws ProjectBuildingException {
return selectProjects(files, request);
}
}
Loading