All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.sdorra.buildfrontend.NodeExecutionBuilder Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package com.github.sdorra.buildfrontend;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.ProcessResult;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class NodeExecutionBuilder {

    private static final Logger LOG = LoggerFactory.getLogger(NodeExecutionBuilder.class);

    private static final String ENV_PATH = "PATH";

    private final File workingDirectory;
    private final File node;

    private final Map systemEnvironment;
    private final Map environment;
    private final List binPath;


    NodeExecutionBuilder(File workingDirectory, File node) {
        this(workingDirectory, node, System.getenv());
    }

    @VisibleForTesting
    NodeExecutionBuilder(File workingDirectory, File node, Map systemEnvironment) {
        this.workingDirectory = workingDirectory;
        this.node = node;

        this.systemEnvironment = systemEnvironment;
        this.environment = new HashMap<>();
        this.binPath = parseBinPath(systemEnvironment.get(ENV_PATH));
    }

    private List parseBinPath(String path) {
        // splitter returns an unmodifiable list, so we have to create a new list in order to modify it
        return new ArrayList<>(
                Splitter.on(File.pathSeparator).omitEmptyStrings().trimResults().splitToList(Strings.nullToEmpty(path))
        );
    }

    public File getWorkingDirectory() {
        return workingDirectory;
    }

    public NodeExecutionBuilder appendBinaryToPath(String path) {
        this.binPath.add(path);
        return this;
    }

    public NodeExecutionBuilder prependBinaryToPath(String path) {
        this.binPath.add(0, path);
        return this;
    }

    public NodeExecutionBuilder addEnvironmentVariable(String key, String value) {
        this.environment.put(key, value);
        return this;
    }

    public void execute(String command, String... args) {
        List cmds = createCommand(command, args);
        LOG.info("execute {}", cmds);

        Map env = createEnvironment();
        try {
            ProcessExecutor executor = create(env, cmds);
            ProcessResult result = executor.execute();
            int exitValue = result.getExitValue();
            if (exitValue != 0) {
                throw new IOException("process ends with exit value " + exitValue);
            }
        } catch (Exception ex) {
            throw Throwables.propagate(ex);
        }
    }

    @SuppressWarnings("squid:S106") // avoid system.out, but it is required
    private ProcessExecutor create(Map environment, List cmds) {
        return newExecutor(cmds)
                .directory(workingDirectory)
                .environment(environment)
                .redirectErrorStream(true)
                .redirectOutput(System.out);
    }

    @VisibleForTesting
    ProcessExecutor newExecutor(List cmds) {
        return new ProcessExecutor(cmds);
    }

    private List createCommand(String command, String... args) {
        List cmd = new ArrayList<>();
        cmd.add(node.getPath());
        cmd.add(command);
        cmd.addAll(Arrays.asList(args));
        return cmd;
    }

    private Map createEnvironment() {
        Map env = new HashMap<>(systemEnvironment);
        env.putAll(environment);
        env.put(ENV_PATH, createBinPath());

        if (LOG.isDebugEnabled()) {
            LOG.debug(envToString(env));
        }
        return env;
    }

    private String envToString(Map env) {
        String separator = System.getProperty("line.separator", "\n");
        StringBuilder builder = new StringBuilder("execution environment:");
        for (Map.Entry e : env.entrySet()) {
            builder.append(separator).append(" - ").append(e.getKey()).append(": ").append(e.getValue());
        }
        return builder.toString();
    }

    private String createBinPath() {
        StringBuilder builder = new StringBuilder(node.getParent());
        for ( String directory : binPath ) {
            builder.append(File.pathSeparator).append(directory);
        }
        return builder.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy