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

com.telenav.cactus.maven.util.CliCommand Maven / Gradle / Ivy

The newest version!
package com.telenav.cactus.maven.util;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

/**
 * A utility program we need to run, which takes care of the general ugliness of
 * java process management, and converting output into a usable object.
 *
 * @author Tim Boudreau
 */
public abstract class CliCommand implements Supplier
{

    protected final String name;
    protected final ProcessResultConverter resultCreator;

    public CliCommand(String name, ProcessResultConverter resultCreator)
    {
        this.name = name;
        this.resultCreator = resultCreator;
    }

    public static CliCommand fixed(String command, Path workingDir, String... fixedArgs)
    {
        return new SimpleCommand(command, workingDir, fixedArgs);
    }

    static class SimpleCommand extends CliCommand
    {

        private final Path workingDir;
        private final String[] fixedArgs;

        public SimpleCommand(String name, Path workingDir, String... fixedArgs)
        {
            super(name, new StringProcessResultConverterImpl());
            this.workingDir = workingDir;
            this.fixedArgs = fixedArgs;
        }

        @Override
        protected Optional workingDirectory()
        {
            return Optional.ofNullable(workingDir);
        }

        @Override
        protected void configureArguments(List list)
        {
            list.addAll(Arrays.asList(fixedArgs));
        }
    }

    public String get()
    {
        return toString();
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder(name);
        List args = new ArrayList<>();
        configureArguments(args);
        for (String arg : args)
        {
            sb.append(' ').append(arg);
        }
        workingDirectory().ifPresent(dir ->
        {
            sb.append(" (in ").append(dir).append(')');
        });
        return sb.toString();
    }

    protected Optional workingDirectory()
    {
        return Optional.empty();
    }

    /**
     * Append command-line arguments passed to the found binary to the list.
     *
     * @param list A list
     */
    protected abstract void configureArguments(List list);

    /**
     * Do any customization of the process builder (env, etc) here.
     *
     * @param bldr A process builder
     */
    protected void configureProcessBulder(ProcessBuilder bldr)
    {
        // for subclasses
    }

    /**
     * Throw here if the command is misconfigured and cannot be run.
     */
    protected void validate()
    {
        // do nothing
    }

    private void internalConfigureProcessBuilder(ProcessBuilder bldr)
    {
        workingDirectory().ifPresent(dir ->
        {
            bldr.directory(dir.toFile());
        });
        configureProcessBulder(bldr);
    }

    public AwaitableCompletionStage run()
    {
        return AwaitableCompletionStage.from(() ->
        {
            ThrowingOptional p = launch();
            if (!p.isPresent())
            {
                return CompletableFuture.failedStage(
                        new IOException("Could not find executable for " + this));
            }
            return resultCreator.onProcessStarted(this, p.get());
        });
    }

    /**
     * Override to log process start or similar.
     *
     * @param proc A process
     */
    protected void onLaunch(Process proc)
    {

    }

    protected ThrowingOptional launch()
    {
        validate();
        return ThrowingOptional.from(PathUtils.findExecutable(name)).map(path ->
        {
            List commandLine = new ArrayList<>();
            commandLine.add(path.toString());
            configureArguments(commandLine);
            ProcessBuilder pb = new ProcessBuilder(commandLine);
            internalConfigureProcessBuilder(pb);
            Process proc = pb.start();
            onLaunch(proc);
            return proc;
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy