public ExecutionResult execute()

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));
                    }
                }
            }
        }
    }