Use SessionData to store ProjectIndex (#1423)

This commit is contained in:
Guillaume Nodet 2024-02-29 00:31:09 +01:00 committed by GitHub
parent 3c2f8ebdb7
commit 5307bcba09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 91 additions and 54 deletions

View File

@ -18,6 +18,7 @@
*/
package org.apache.maven.api;
import java.util.Objects;
import java.util.function.Supplier;
import org.apache.maven.api.annotations.Experimental;
@ -49,7 +50,7 @@ public interface SessionData {
* @param key the key under which to store the session data, must not be {@code null}
* @param value the data to associate with the key, may be {@code null} to remove the mapping
*/
void set(@Nonnull Object key, @Nullable Object value);
<T> void set(@Nonnull Key<T> key, @Nullable T value);
/**
* Associates the specified session data with the given key if the key is currently mapped to the given value. This
@ -61,7 +62,7 @@ public interface SessionData {
* @return {@code true} if the key mapping was successfully updated from the old value to the new value,
* {@code false} if the current key mapping didn't match the expected value and was not updated.
*/
boolean set(@Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue);
<T> boolean replace(@Nonnull Key<T> key, @Nullable T oldValue, @Nullable T newValue);
/**
* Gets the session data associated with the specified key.
@ -70,7 +71,7 @@ public interface SessionData {
* @return the session data associated with the key or {@code null} if none
*/
@Nullable
Object get(@Nonnull Object key);
<T> T get(@Nonnull Key<T> key);
/**
* Retrieve of compute the data associated with the specified key.
@ -80,5 +81,55 @@ public interface SessionData {
* @return the session data associated with the key
*/
@Nullable
Object computeIfAbsent(@Nonnull Object key, @Nonnull Supplier<Object> supplier);
<T> T computeIfAbsent(@Nonnull Key<T> key, @Nonnull Supplier<T> supplier);
/**
* Create a key using the given class as an identifier and as the type of the object.
*/
static <T> Key<T> key(Class<T> clazz) {
return new Key<>(clazz, clazz);
}
/**
* Create a key using the given class and id.
*/
static <T> Key<T> key(Class<T> clazz, Object id) {
return new Key<>(clazz, id);
}
/**
* Key used to query the session data
* @param <T> the type of the object associated to this key
*/
final class Key<T> {
private final Class<T> type;
private final Object id;
private Key(Class<T> type, Object id) {
this.type = type;
this.id = id;
}
public Class<T> type() {
return type;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Key<?> key = (Key<?>) o;
return Objects.equals(id, key.id) && Objects.equals(type, key.type);
}
@Override
public int hashCode() {
return Objects.hash(id, type);
}
}
}

View File

@ -177,25 +177,27 @@ public class DefaultSession extends AbstractSession {
org.eclipse.aether.SessionData data = session.getData();
return new SessionData() {
@Override
public void set(@Nonnull Object key, @Nullable Object value) {
public <T> void set(@Nonnull Key<T> key, @Nullable T value) {
data.set(key, value);
}
@Override
public boolean set(@Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue) {
public <T> boolean replace(@Nonnull Key<T> key, @Nullable T oldValue, @Nullable T newValue) {
return data.set(key, oldValue, newValue);
}
@Nullable
@Override
public Object get(@Nonnull Object key) {
return data.get(key);
@SuppressWarnings("unchecked")
public <T> T get(@Nonnull Key<T> key) {
return (T) data.get(key);
}
@Nullable
@Override
public Object computeIfAbsent(@Nonnull Object key, @Nonnull Supplier<Object> supplier) {
return data.computeIfAbsent(key, supplier);
@SuppressWarnings("unchecked")
public <T> T computeIfAbsent(@Nonnull Key<T> key, @Nonnull Supplier<T> supplier) {
return (T) data.computeIfAbsent(key, (Supplier<Object>) supplier);
}
};
}

View File

@ -32,7 +32,6 @@ import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.LifecycleStarter;
import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.MojoExecutor;
import org.apache.maven.lifecycle.internal.ProjectIndex;
import org.apache.maven.lifecycle.internal.TaskSegment;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
@ -146,6 +145,6 @@ public class DefaultLifecycleExecutor implements LifecycleExecutor {
// Site 3.x
public List<MavenProject> executeForkedExecutions(MojoExecution mojoExecution, MavenSession session)
throws LifecycleExecutionException {
return mojoExecutor.executeForkedExecutions(mojoExecution, session, new ProjectIndex(session.getProjects()));
return mojoExecutor.executeForkedExecutions(mojoExecution, session);
}
}

View File

@ -104,7 +104,7 @@ public class LifecycleModuleBuilder {
projectExecutionListener.beforeProjectLifecycleExecution(
new ProjectExecutionEvent(session, currentProject, mojoExecutions));
mojoExecutor.execute(session, mojoExecutions, reactorContext.getProjectIndex());
mojoExecutor.execute(session, mojoExecutions);
long buildEndTime = System.currentTimeMillis();

View File

@ -107,7 +107,7 @@ public class LifecycleStarter {
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus(session.getProjectDependencyGraph());
reactorContext = new ReactorContext(result, projectIndex, oldContextClassLoader, reactorBuildStatus);
reactorContext = new ReactorContext(result, oldContextClassLoader, reactorBuildStatus);
String builderId = session.getRequest().getBuilderId();
Builder builder = builders.get(builderId);

View File

@ -36,6 +36,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.maven.api.SessionData;
import org.apache.maven.api.services.MessageBuilderFactory;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
@ -57,7 +58,6 @@ import org.apache.maven.plugin.PluginIncompatibleException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.SessionData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -74,6 +74,11 @@ import org.slf4j.LoggerFactory;
public class MojoExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(MojoExecutor.class);
private static final SessionData.Key<ProjectIndex> PROJECT_INDEX = SessionData.key(ProjectIndex.class);
@SuppressWarnings({"unchecked", "rawtypes"})
private static final SessionData.Key<Map<MavenProject, OwnerReentrantLock>> PROJECT_LOCKS =
(SessionData.Key) SessionData.key(Map.class, ProjectLock.class);
private final BuildPluginManager pluginManager;
private final MavenPluginManager mavenPluginManager;
@ -149,8 +154,7 @@ public class MojoExecutor {
return Collections.unmodifiableCollection(scopes);
}
public void execute(
final MavenSession session, final List<MojoExecution> mojoExecutions, final ProjectIndex projectIndex)
public void execute(final MavenSession session, final List<MojoExecution> mojoExecutions)
throws LifecycleExecutionException {
final DependencyContext dependencyContext = newDependencyContext(session, mojoExecutions);
@ -160,7 +164,7 @@ public class MojoExecutor {
mojosExecutionStrategy.get().execute(mojoExecutions, session, new MojoExecutionRunner() {
@Override
public void run(MojoExecution mojoExecution) throws LifecycleExecutionException {
MojoExecutor.this.execute(session, mojoExecution, projectIndex, dependencyContext, phaseRecorder);
MojoExecutor.this.execute(session, mojoExecution, dependencyContext, phaseRecorder);
}
});
}
@ -168,19 +172,14 @@ public class MojoExecutor {
private void execute(
MavenSession session,
MojoExecution mojoExecution,
ProjectIndex projectIndex,
DependencyContext dependencyContext,
PhaseRecorder phaseRecorder)
throws LifecycleExecutionException {
execute(session, mojoExecution, projectIndex, dependencyContext);
execute(session, mojoExecution, dependencyContext);
phaseRecorder.observeExecution(mojoExecution);
}
private void execute(
MavenSession session,
MojoExecution mojoExecution,
ProjectIndex projectIndex,
DependencyContext dependencyContext)
private void execute(MavenSession session, MojoExecution mojoExecution, DependencyContext dependencyContext)
throws LifecycleExecutionException {
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
@ -211,7 +210,7 @@ public class MojoExecutor {
}
}
doExecute(session, mojoExecution, projectIndex, dependencyContext);
doExecute(session, mojoExecution, dependencyContext);
}
/**
@ -273,11 +272,9 @@ public class MojoExecutor {
mojos.remove(Thread.currentThread());
}
@SuppressWarnings({"unchecked", "rawtypes"})
private OwnerReentrantLock getProjectLock(MavenSession session) {
SessionData data = session.getRepositorySession().getData();
Map<MavenProject, OwnerReentrantLock> locks =
(Map) data.computeIfAbsent(ProjectLock.class, ConcurrentHashMap::new);
SessionData data = session.getSession().getData();
Map<MavenProject, OwnerReentrantLock> locks = data.computeIfAbsent(PROJECT_LOCKS, ConcurrentHashMap::new);
return locks.computeIfAbsent(session.getCurrentProject(), p -> new OwnerReentrantLock());
}
}
@ -302,15 +299,11 @@ public class MojoExecutor {
}
}
private void doExecute(
MavenSession session,
MojoExecution mojoExecution,
ProjectIndex projectIndex,
DependencyContext dependencyContext)
private void doExecute(MavenSession session, MojoExecution mojoExecution, DependencyContext dependencyContext)
throws LifecycleExecutionException {
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
List<MavenProject> forkedProjects = executeForkedExecutions(mojoExecution, session, projectIndex);
List<MavenProject> forkedProjects = executeForkedExecutions(mojoExecution, session);
ensureDependenciesAreResolved(mojoDescriptor, session, dependencyContext);
@ -407,8 +400,7 @@ public class MojoExecutor {
}
}
public List<MavenProject> executeForkedExecutions(
MojoExecution mojoExecution, MavenSession session, ProjectIndex projectIndex)
public List<MavenProject> executeForkedExecutions(MojoExecution mojoExecution, MavenSession session)
throws LifecycleExecutionException {
List<MavenProject> forkedProjects = Collections.emptyList();
@ -425,6 +417,10 @@ public class MojoExecutor {
for (Map.Entry<String, List<MojoExecution>> fork : forkedExecutions.entrySet()) {
String projectId = fork.getKey();
ProjectIndex projectIndex = session.getSession()
.getData()
.computeIfAbsent(PROJECT_INDEX, () -> new ProjectIndex(session.getProjects()));
int index = projectIndex.getIndices().get(projectId);
MavenProject forkedProject = projectIndex.getProjects().get(projectId);
@ -448,7 +444,7 @@ public class MojoExecutor {
eventCatapult.fire(ExecutionEvent.Type.ForkedProjectStarted, session, mojoExecution);
execute(session, mojoExecutions, projectIndex);
execute(session, mojoExecutions);
eventCatapult.fire(ExecutionEvent.Type.ForkedProjectSucceeded, session, mojoExecution);
} catch (LifecycleExecutionException e) {

View File

@ -29,19 +29,15 @@ import org.apache.maven.execution.MavenExecutionResult;
public class ReactorContext {
private final MavenExecutionResult result;
private final ProjectIndex projectIndex;
private final ClassLoader originalContextClassLoader;
private final ReactorBuildStatus reactorBuildStatus;
public ReactorContext(
MavenExecutionResult result,
ProjectIndex projectIndex,
ClassLoader originalContextClassLoader,
ReactorBuildStatus reactorBuildStatus) {
this.result = result;
this.projectIndex = projectIndex;
this.originalContextClassLoader = originalContextClassLoader;
this.reactorBuildStatus = reactorBuildStatus;
}
@ -54,10 +50,6 @@ public class ReactorContext {
return result;
}
public ProjectIndex getProjectIndex() {
return projectIndex;
}
public ClassLoader getOriginalContextClassLoader() {
return originalContextClassLoader;
}

View File

@ -53,9 +53,9 @@ class LifecycleModuleBuilderTest {
List<MavenProject> currentProjects = new ArrayList<>();
MojoExecutorStub mojoExecutor = new MojoExecutorStub() {
@Override
public void execute(MavenSession session, List<MojoExecution> mojoExecutions, ProjectIndex projectIndex)
public void execute(MavenSession session, List<MojoExecution> mojoExecutions)
throws LifecycleExecutionException {
super.execute(session, mojoExecutions, projectIndex);
super.execute(session, mojoExecutions);
currentProjects.add(session.getCurrentProject());
}
};

View File

@ -30,7 +30,6 @@ import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver;
import org.apache.maven.lifecycle.internal.MojoExecutor;
import org.apache.maven.lifecycle.internal.ProjectIndex;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.MavenPluginManager;
@ -67,14 +66,12 @@ public class MojoExecutorStub extends MojoExecutor { // This is being lazy inste
}
@Override
public void execute(MavenSession session, List<MojoExecution> mojoExecutions, ProjectIndex projectIndex)
throws LifecycleExecutionException {
public void execute(MavenSession session, List<MojoExecution> mojoExecutions) throws LifecycleExecutionException {
executions.addAll(mojoExecutions);
}
@Override
public List<MavenProject> executeForkedExecutions(
MojoExecution mojoExecution, MavenSession session, ProjectIndex projectIndex)
public List<MavenProject> executeForkedExecutions(MojoExecution mojoExecution, MavenSession session)
throws LifecycleExecutionException {
return null;
}