in client/src/main/java-mvnd/org/mvndaemon/mvnd/client/DefaultClient.java [240:406]
public ExecutionResult execute(ClientOutput output, List<String> argv) {
LOGGER.debug("Starting client");
final List<String> args = new ArrayList<>(argv);
final String completionShell = Environment.COMPLETION.removeCommandLineOption(args);
if (completionShell != null) {
output.accept(Message.out(Completion.getCompletion(completionShell, parameters)));
return DefaultResult.success(argv);
}
boolean version = Environment.MAVEN_VERSION.hasCommandLineOption(args);
boolean showVersion = Environment.MAVEN_SHOW_VERSION.hasCommandLineOption(args);
boolean verbose = Environment.MAVEN_VERBOSE.hasCommandLineOption(args);
// Print version if needed
if (version || showVersion || verbose) {
// Print mvnd version
BuildProperties buildProperties = BuildProperties.getInstance();
final String mvndVersionString = "Apache Maven Daemon (mvnd) " + buildProperties.getVersion() + " "
+ (Environment.isNative()
? buildProperties.getOsName() + "-" + buildProperties.getOsArch() + " native client"
: "JVM client")
+ " (" + buildProperties.getRevision() + ")";
boolean isColored = !"never".equals(Environment.MAVEN_COLOR.getCommandLineOption(args));
final String v = isColored
? new AttributedStringBuilder()
.style(AttributedStyle.BOLD)
.append(mvndVersionString)
.toAnsi()
: mvndVersionString;
output.accept(Message.log(v));
// Print terminal information
output.describeTerminal();
/*
* Do not return, rather pass -v to the server so that the client module does not need to depend on any
* Maven artifacts
*/
}
try (DaemonRegistry registry = new DaemonRegistry(parameters.registry())) {
if (Environment.STATUS.removeCommandLineOption(args) != null) {
final String template = "%8s %7s %24s %7s %5s %23s %s";
output.accept(Message.out(String.format(
template, "ID", "PID", "Address", "Status", "RSS", "Last activity", "Java home")));
for (DaemonInfo d : registry.getAll()) {
if (ProcessHandle.of(d.getPid()).isEmpty()) {
/* The process does not exist anymore - remove it from the registry */
registry.remove(d.getId());
} else {
output.accept(Message.out(String.format(
template,
d.getId(),
d.getPid(),
d.getAddress(),
d.getState(),
OsUtils.kbToHumanReadable(OsUtils.findProcessRssInKb(d.getPid())),
LocalDateTime.ofInstant(
Instant.ofEpochMilli(Math.max(d.getLastIdle(), d.getLastBusy())),
ZoneId.systemDefault()),
d.getJavaHome())));
}
}
return DefaultResult.success(argv);
}
if (Environment.STOP.removeCommandLineOption(args) != null) {
DaemonInfo[] dis = registry.getAll().toArray(new DaemonInfo[0]);
if (dis.length > 0) {
output.accept(Message.out("Stopping " + dis.length + " running daemons"));
for (DaemonInfo di : dis) {
try {
ProcessHandle.of(di.getPid()).ifPresent(ProcessHandle::destroyForcibly);
} catch (Exception t) {
System.out.println("Daemon " + di.getId() + ": " + t);
} finally {
registry.remove(di.getId());
}
}
}
return DefaultResult.success(argv);
}
if (Environment.PURGE.removeCommandLineOption(args) != null) {
String result = purgeLogs();
output.accept(Message.out(result != null ? result : "Nothing to purge"));
return DefaultResult.success(argv);
}
Optional<String> threads = Optional.ofNullable(Environment.MVND_THREADS.removeCommandLineOption(args));
Environment.MVND_THREADS.addCommandLineOption(args, threads.orElseGet(parameters::threads));
Optional<String> builder = Optional.ofNullable(Environment.MVND_BUILDER.removeCommandLineOption(args));
Environment.MVND_BUILDER.addCommandLineOption(args, builder.orElseGet(parameters::builder));
Optional<String> settings = Optional.ofNullable(Environment.MAVEN_SETTINGS.removeCommandLineOption(args))
.or(() -> Optional.ofNullable(parameters.settings()).map(Path::toString));
settings.ifPresent(s -> Environment.MAVEN_SETTINGS.addCommandLineOption(args, s));
Optional<String> repo = Optional.ofNullable(Environment.MAVEN_REPO_LOCAL.removeCommandLineOption(args))
.or(() -> Optional.ofNullable(parameters.mavenRepoLocal()).map(Path::toString));
repo.ifPresent(r -> Environment.MAVEN_REPO_LOCAL.addCommandLineOption(args, r));
if (Environment.MVND_DEBUG.removeCommandLineOption(args) != null) {
System.setProperty(Environment.MVND_DEBUG.getProperty(), "true");
}
String width = Optional.ofNullable(Environment.MVND_TERMINAL_WIDTH.removeCommandLineOption(args))
.orElseGet(() -> {
int w = output.getTerminalWidth();
return Integer.toString(w > 0 ? Math.max(w, 80) : 120);
});
Environment.MVND_TERMINAL_WIDTH.addCommandLineOption(args, width);
final DaemonConnector connector = new DaemonConnector(parameters, registry);
try (DaemonClientConnection daemon = connector.connect(output)) {
output.setDaemonId(daemon.getDaemon().getId());
output.setDaemonDispatch(daemon::dispatch);
output.setDaemonReceive(daemon::enqueue);
daemon.dispatch(new Message.BuildRequest(
args,
parameters.userDir().toString(),
parameters.multiModuleProjectDirectory().toString(),
System.getenv()));
output.accept(Message.buildStatus(
"Connected to daemon " + daemon.getDaemon().getId() + ", scanning for projects..."));
// We've sent the request, so it gives us a bit of time to purge the logs
AtomicReference<String> purgeMessage = new AtomicReference<>();
Thread purgeLog = new Thread(
() -> {
purgeMessage.set(purgeLogs());
},
"Log purge");
purgeLog.setDaemon(true);
purgeLog.start();
try {
while (true) {
final List<Message> messages = daemon.receive();
output.accept(messages);
for (Message m : messages) {
switch (m.getType()) {
case Message.CANCEL_BUILD:
return new DefaultResult(
argv, new InterruptedException("The build was canceled"), 130);
case Message.BUILD_EXCEPTION:
final BuildException e = (BuildException) m;
return new DefaultResult(
argv,
new Exception(e.getClassName() + ": " + e.getMessage() + "\n"
+ e.getStackTrace()),
1);
case Message.BUILD_FINISHED:
return new DefaultResult(argv, null, ((BuildFinished) m).getExitCode());
}
}
}
} finally {
String msg = purgeMessage.get();
if (msg != null) {
output.accept(Message.err(msg));
}
}
}
}
}