Split AbstractLoggingSpy into an abstract BuildEventListener and

ClientDispatcher to avoid circular package dependencies
This commit is contained in:
Peter Palaga
2021-01-06 17:23:56 +01:00
parent d6464ed790
commit 519424deba
6 changed files with 124 additions and 60 deletions

View File

@@ -92,7 +92,7 @@ import org.codehaus.plexus.util.StringUtils;
import org.eclipse.aether.transfer.TransferListener;
import org.mvndaemon.mvnd.common.Environment;
import org.mvndaemon.mvnd.logging.internal.Slf4jLoggerManager;
import org.mvndaemon.mvnd.logging.smart.AbstractLoggingSpy;
import org.mvndaemon.mvnd.logging.smart.BuildEventListener;
import org.mvndaemon.mvnd.logging.smart.LoggingExecutionListener;
import org.mvndaemon.mvnd.logging.smart.LoggingOutputStream;
import org.slf4j.ILoggerFactory;
@@ -155,7 +155,7 @@ public class DaemonMavenCli {
private final Map<String, ConfigurationProcessor> configurationProcessors;
/** Non-volatile, assuming that it is accessed only from the main thread */
private AbstractLoggingSpy loggingSpy = AbstractLoggingSpy.dummy();
private BuildEventListener buildEventListener = BuildEventListener.dummy();
public DaemonMavenCli() throws Exception {
slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
@@ -181,8 +181,8 @@ public class DaemonMavenCli {
String workingDirectory,
String projectDirectory,
Map<String, String> clientEnv,
AbstractLoggingSpy loggingSpy) throws Exception {
this.loggingSpy = loggingSpy;
BuildEventListener buildEventListener) throws Exception {
this.buildEventListener = buildEventListener;
try {
CliRequest req = new CliRequest(null, null);
req.args = arguments.toArray(new String[0]);
@@ -190,7 +190,7 @@ public class DaemonMavenCli {
req.multiModuleProjectDirectory = new File(projectDirectory);
return doMain(req, clientEnv);
} finally {
this.loggingSpy = AbstractLoggingSpy.dummy();
this.buildEventListener = BuildEventListener.dummy();
}
}
@@ -270,7 +270,7 @@ public class DaemonMavenCli {
}
} catch (ParseException e) {
System.err.println("Unable to parse maven.config: " + e.getMessage());
loggingSpy.log(MvndHelpFormatter.displayHelp(cliManager));
buildEventListener.log(MvndHelpFormatter.displayHelp(cliManager));
throw e;
}
@@ -282,14 +282,14 @@ public class DaemonMavenCli {
}
} catch (ParseException e) {
System.err.println("Unable to parse command line options: " + e.getMessage());
loggingSpy.log(MvndHelpFormatter.displayHelp(cliManager));
buildEventListener.log(MvndHelpFormatter.displayHelp(cliManager));
throw e;
}
}
private void help(CliRequest cliRequest) throws Exception {
if (cliRequest.commandLine.hasOption(CLIManager.HELP)) {
loggingSpy.log(MvndHelpFormatter.displayHelp(new CLIManager()));
buildEventListener.log(MvndHelpFormatter.displayHelp(new CLIManager()));
throw new ExitException(0);
}
@@ -387,7 +387,7 @@ public class DaemonMavenCli {
private void version(CliRequest cliRequest) throws ExitException {
if (cliRequest.debug || cliRequest.commandLine.hasOption(CLIManager.VERSION)) {
loggingSpy.log(CLIReportingUtils.showVersion());
buildEventListener.log(CLIReportingUtils.showVersion());
if (cliRequest.commandLine.hasOption(CLIManager.VERSION)) {
throw new ExitException(0);
}
@@ -544,7 +544,7 @@ public class DaemonMavenCli {
properties(cliRequest);
configure(cliRequest, eventSpyDispatcher, configurationProcessors);
populateRequest(cliRequest, cliRequest.request, slf4jLogger, eventSpyDispatcher,
container.lookup(ModelProcessor.class), createTransferListener(cliRequest), loggingSpy);
container.lookup(ModelProcessor.class), createTransferListener(cliRequest), buildEventListener);
executionRequestPopulator.populateDefaults(cliRequest.request);
BootstrapCoreExtensionManager resolver = container.lookup(BootstrapCoreExtensionManager.class);
return Collections
@@ -951,7 +951,7 @@ public class DaemonMavenCli {
private void populateRequest(CliRequest cliRequest) {
populateRequest(cliRequest, cliRequest.request, slf4jLogger, eventSpyDispatcher, modelProcessor,
createTransferListener(cliRequest), loggingSpy);
createTransferListener(cliRequest), buildEventListener);
}
private static void populateRequest(
@@ -961,7 +961,7 @@ public class DaemonMavenCli {
EventSpyDispatcher eventSpyDispatcher,
ModelProcessor modelProcessor,
TransferListener transferListener,
AbstractLoggingSpy loggingSpy) {
BuildEventListener buildEventListener) {
CommandLine commandLine = cliRequest.commandLine;
String workingDirectory = cliRequest.workingDirectory;
boolean showErrors = cliRequest.showErrors;
@@ -1064,7 +1064,7 @@ public class DaemonMavenCli {
if (eventSpyDispatcher != null) {
executionListener = new LoggingExecutionListener(
eventSpyDispatcher.chainListener(executionListener),
loggingSpy);
buildEventListener);
}
String alternatePomFile = null;

View File

@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.logging.smart;
package org.mvndaemon.mvnd.daemon;
import java.util.Collection;
import java.util.function.Consumer;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
@@ -24,27 +23,15 @@ import org.mvndaemon.mvnd.builder.DependencyGraph;
import org.mvndaemon.mvnd.common.Message;
import org.mvndaemon.mvnd.common.Message.BuildException;
import org.mvndaemon.mvnd.common.Message.BuildStarted;
import org.mvndaemon.mvnd.logging.smart.BuildEventListener;
/**
* Sends events back to the client.
*/
public class AbstractLoggingSpy {
private static final AbstractLoggingSpy DUMMY = new AbstractLoggingSpy(m -> {
});
private final Consumer<Message> queue;
public class ClientDispatcher extends BuildEventListener {
private final Collection<Message> queue;
/**
* @return a dummy {@link AbstractLoggingSpy} that just swallows the messages and does not send them anywhere
*/
public static AbstractLoggingSpy dummy() {
return DUMMY;
}
public AbstractLoggingSpy(Collection<Message> queue) {
this(queue::add);
}
public AbstractLoggingSpy(Consumer<Message> queue) {
public ClientDispatcher(Collection<Message> queue) {
this.queue = queue;
}
@@ -55,38 +42,38 @@ public class AbstractLoggingSpy {
session.getRequest().getData().put(DependencyGraph.class.getName(), dependencyGraph);
final int maxThreads = degreeOfConcurrency == 1 ? 1 : dependencyGraph.computeMaxWidth(degreeOfConcurrency, 1000);
queue.accept(new BuildStarted(getCurrentProject(session).getName(), session.getProjects().size(), maxThreads));
queue.add(new BuildStarted(getCurrentProject(session).getName(), session.getProjects().size(), maxThreads));
}
public void projectStarted(ExecutionEvent event) {
queue.accept(Message.projectStarted(getProjectId(event), getProjectDisplay(event)));
queue.add(Message.projectStarted(getProjectId(event), getProjectDisplay(event)));
}
public void projectLogMessage(String projectId, String event) {
String msg = event.endsWith("\n") ? event.substring(0, event.length() - 1) : event;
queue.accept(projectId == null ? Message.log(msg) : Message.log(projectId, msg));
queue.add(projectId == null ? Message.log(msg) : Message.log(projectId, msg));
}
public void projectFinished(ExecutionEvent event) {
queue.accept(Message.projectStopped(getProjectId(event), getProjectDisplay(event)));
queue.add(Message.projectStopped(getProjectId(event), getProjectDisplay(event)));
}
public void mojoStarted(ExecutionEvent event) {
queue.accept(Message.mojoStarted(getProjectId(event), getProjectDisplay(event)));
queue.add(Message.mojoStarted(getProjectId(event), getProjectDisplay(event)));
}
public void finish(int exitCode) throws Exception {
queue.accept(new Message.BuildFinished(exitCode));
queue.accept(Message.STOP_SINGLETON);
queue.add(new Message.BuildFinished(exitCode));
queue.add(Message.STOP_SINGLETON);
}
public void fail(Throwable t) throws Exception {
queue.accept(new BuildException(t));
queue.accept(Message.STOP_SINGLETON);
queue.add(new BuildException(t));
queue.add(Message.STOP_SINGLETON);
}
public void log(String msg) {
queue.accept(Message.log(msg));
queue.add(Message.log(msg));
}
private MavenProject getCurrentProject(MavenSession mavenSession) {

View File

@@ -55,7 +55,7 @@ import org.mvndaemon.mvnd.common.Message.BuildRequest;
import org.mvndaemon.mvnd.common.Os;
import org.mvndaemon.mvnd.daemon.DaemonExpiration.DaemonExpirationResult;
import org.mvndaemon.mvnd.daemon.DaemonExpiration.DaemonExpirationStrategy;
import org.mvndaemon.mvnd.logging.smart.AbstractLoggingSpy;
import org.mvndaemon.mvnd.logging.smart.BuildEventListener;
import org.mvndaemon.mvnd.logging.smart.ProjectBuildLogAppender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -427,8 +427,8 @@ public class Server implements AutoCloseable, Runnable {
final BlockingQueue<Message> sendQueue = new PriorityBlockingQueue<>(64,
Comparator.comparingInt(this::getClassOrder).thenComparingLong(Message::timestamp));
final BlockingQueue<Message> recvQueue = new LinkedBlockingDeque<>();
final AbstractLoggingSpy loggingSpy = new AbstractLoggingSpy(sendQueue);
try (ProjectBuildLogAppender logAppender = new ProjectBuildLogAppender(loggingSpy)) {
final BuildEventListener buildEventListener = new ClientDispatcher(sendQueue);
try (ProjectBuildLogAppender logAppender = new ProjectBuildLogAppender(buildEventListener)) {
LOGGER.info("Executing request");
@@ -532,12 +532,12 @@ public class Server implements AutoCloseable, Runnable {
buildRequest.getWorkingDir(),
buildRequest.getProjectDir(),
buildRequest.getEnv(),
loggingSpy);
buildEventListener);
LOGGER.info("Build finished, finishing message dispatch");
loggingSpy.finish(exitCode);
buildEventListener.finish(exitCode);
} catch (Throwable t) {
LOGGER.error("Error while building project", t);
loggingSpy.fail(t);
buildEventListener.fail(t);
} finally {
sender.join();
ProjectBuildLogAppender.setProjectId(null);

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed 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.mvndaemon.mvnd.logging.smart;
import org.apache.maven.execution.ExecutionEvent;
/**
* An abstract build event sink.
*/
public abstract class BuildEventListener {
private static final BuildEventListener DUMMY = new BuildEventListener() {
public void sessionStarted(ExecutionEvent event) {
}
public void projectStarted(ExecutionEvent event) {
}
public void projectLogMessage(String projectId, String event) {
}
public void projectFinished(ExecutionEvent event) {
}
public void mojoStarted(ExecutionEvent event) {
}
public void finish(int exitCode) throws Exception {
}
public void fail(Throwable t) throws Exception {
}
public void log(String msg) {
}
};
/**
* @return a dummy {@link BuildEventListener} that just swallows the messages and does not send them anywhere
*/
public static BuildEventListener dummy() {
return DUMMY;
}
protected BuildEventListener() {
}
public abstract void sessionStarted(ExecutionEvent event);
public abstract void projectStarted(ExecutionEvent event);
public abstract void projectLogMessage(String projectId, String event);
public abstract void projectFinished(ExecutionEvent event);
public abstract void mojoStarted(ExecutionEvent event);
public abstract void finish(int exitCode) throws Exception;
public abstract void fail(Throwable t) throws Exception;
public abstract void log(String msg);
}

View File

@@ -21,11 +21,11 @@ import org.apache.maven.execution.ExecutionListener;
public class LoggingExecutionListener implements ExecutionListener {
private final ExecutionListener delegate;
private final AbstractLoggingSpy loggingSpy;
private final BuildEventListener buildEventListener;
public LoggingExecutionListener(ExecutionListener delegate, AbstractLoggingSpy loggingSpy) {
public LoggingExecutionListener(ExecutionListener delegate, BuildEventListener buildEventListener) {
this.delegate = delegate;
this.loggingSpy = loggingSpy;
this.buildEventListener = buildEventListener;
}
@Override
@@ -37,7 +37,7 @@ public class LoggingExecutionListener implements ExecutionListener {
@Override
public void sessionStarted(ExecutionEvent event) {
setMdc(event);
loggingSpy.sessionStarted(event);
buildEventListener.sessionStarted(event);
delegate.sessionStarted(event);
}
@@ -50,7 +50,7 @@ public class LoggingExecutionListener implements ExecutionListener {
@Override
public void projectStarted(ExecutionEvent event) {
setMdc(event);
loggingSpy.projectStarted(event);
buildEventListener.projectStarted(event);
delegate.projectStarted(event);
}
@@ -58,27 +58,27 @@ public class LoggingExecutionListener implements ExecutionListener {
public void projectSucceeded(ExecutionEvent event) {
setMdc(event);
delegate.projectSucceeded(event);
loggingSpy.projectFinished(event);
buildEventListener.projectFinished(event);
}
@Override
public void projectFailed(ExecutionEvent event) {
setMdc(event);
delegate.projectFailed(event);
loggingSpy.projectFinished(event);
buildEventListener.projectFinished(event);
}
@Override
public void projectSkipped(ExecutionEvent event) {
setMdc(event);
delegate.projectSkipped(event);
loggingSpy.projectFinished(event);
buildEventListener.projectFinished(event);
}
@Override
public void mojoStarted(ExecutionEvent event) {
setMdc(event);
loggingSpy.mojoStarted(event);
buildEventListener.mojoStarted(event);
delegate.mojoStarted(event);
}

View File

@@ -61,10 +61,10 @@ public class ProjectBuildLogAppender extends AppenderBase<ILoggingEvent> impleme
private static final String pattern = "[%level] %msg%n";
private final PatternLayout layout;
private final AbstractLoggingSpy loggingSpy;
private final BuildEventListener buildEventListener;
public ProjectBuildLogAppender(AbstractLoggingSpy loggingSpy) {
this.loggingSpy = loggingSpy;
public ProjectBuildLogAppender(BuildEventListener buildEventListener) {
this.buildEventListener = buildEventListener;
this.name = ProjectBuildLogAppender.class.getName();
this.context = (Context) LoggerFactory.getILoggerFactory();
@@ -94,7 +94,7 @@ public class ProjectBuildLogAppender extends AppenderBase<ILoggingEvent> impleme
protected void append(ILoggingEvent event) {
Map<String, String> mdc = event.getMDCPropertyMap();
String projectId = mdc != null ? mdc.get(KEY_PROJECT_ID) : null;
loggingSpy.projectLogMessage(projectId, layout.doLayout(event));
buildEventListener.projectLogMessage(projectId, layout.doLayout(event));
}
public static class LevelConverter extends ClassicConverter {