Exit Full View

Feather2 / feather2-runtime / src / main / java / uk / co / nickthecoder / feather / runtime / command / CommandBase.java

package uk.co.nickthecoder.feather.runtime.command;

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

/**
 * The base interface for Command, Pipe and Redirect.
 * <p>
 * Ideally, this would be sealed, but that feature is only available from Java 17 onwards,
 * and I want to support earlier versions too.
 * Do NOT create additional implementations!
 * </p>
 */
public abstract class CommandBase implements Commandable {

    /**
     * Redirects stdout to a file. The file is cleared (if it exists).
     */
    public Redirect redirect(File file) {
        return redirect(file, false);
    }

    public Redirect redirect(String filename) {
        return redirect(new File(filename));
    }

    /**
     * Redirects stdout to a file.
     */
    public Redirect redirect(File file, boolean append) {
        return new Redirect(this, file, append, null, false, null);
    }

    public Redirect redirect(String filename, boolean append) {
        return redirect(new File(filename), append);
    }

    /**
     * Redirects stdout to a file. The file is cleared (if it exists).
     */
    public Redirect redirectOutAndErr(File file) {
        return redirectOutAndErr(file, false);
    }

    public Redirect redirectOutAndErr(String filename) {
        return redirectOutAndErr(new File(filename));
    }

    /**
     * Redirects stdout and stderr to a file.
     */
    public Redirect redirectOutAndErr(File file, boolean append) {
        return new Redirect(this, file, append, file, append, null);
    }

    public Redirect redirectOutAndErr(String filename, boolean append) {
        return redirectOutAndErr(new File(filename), append);
    }

    /**
     * Redirects stderr to a file. The file is cleared (if it exists).
     */
    public Redirect redirectErr(File file) {
        return redirectErr(file, false);
    }

    public Redirect redirectErr(String filename) {
        return redirectErr(new File(filename));
    }

    /**
     * Redirects stderr to a file. The file is cleared (if it exists).
     */
    public Redirect redirectErr(File file, boolean append) {
        return new Redirect(this, null, false, file, append, null);
    }

    public Redirect redirectErr(String filename, boolean append) {
        return redirectErr(new File(filename), append);
    }


    /**
     * Redirects standard input from a file.
     */
    public Redirect redirectIn(File file) {
        return new Redirect(this, null, false, null, false, file);
    }

    public Redirect redirectIn(String filename) {
        return redirectIn(new File(filename));
    }

    /**
     * Pipes the stdout from this command to the input of `consumer`.
     * <p>
     * NOTE. Piping stderr is NOT supported.
     * </p>
     */
    public Pipe pipe(CommandBase consumer) {
        return new Pipe(this, consumer);
    }

    @Override
    public CommandRunner dir(File dir) {
        return new CommandRunner(this).dir(dir);
    }

    @Override
    public CommandRunner dir(String directoryName) {
        return dir(new File(directoryName));
    }

    @Override
    public CommandRunner env(Map<String, String> env) {
        return new CommandRunner(this).env(env);
    }

    @Override
    public CommandRunner shell(Shell shell) {
        return new CommandRunner(this).shell(shell);
    }

    @Override
    public Process runAsync() throws IOException {
        return runAsync(null, null);
    }

    @Override
    public Process runAsync(Consumer stdout, Consumer stderr) throws IOException {
        return new CommandRunner(this).runAsync();
    }

    @Override
    public CommandResult run() {
        return new CommandRunner(this).run();
    }

    @Override
    public CommandResult run(Consumer stdout, Consumer stderr) {
        return new CommandRunner(this).run(stdout, stderr);
    }

    @Override
    public CommandResult collect() {
        return new CommandRunner(this).collect();
    }

    @Override
    public String eval() {
        return collect().out;
    }

    @Override
    public String evalOk() {
        CommandResult result = collect();
        if (result.ok()) {
            return result.out;
        } else {
            return null;
        }
    }

    /**
     * Prints the command (using the default shell).
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String arg : CommandRunner.defaultShell.buildShell(this)) {
            if (first) {
                first = false;
            } else {
                sb.append(" ");
            }
            sb.append(arg);
        }
        return sb.toString();
    }

}