| // Copyright 2016 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.shell; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableMap; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.util.Map; | |
| /** | |
| * A builder class that starts a subprocess. | |
| */ | |
| public class SubprocessBuilder { | |
| /** | |
| * What to do with an output stream of the process. | |
| */ | |
| public enum StreamAction { | |
| /** Redirect to a file */ | |
| REDIRECT, | |
| /** Discard. */ | |
| DISCARD, | |
| /** Stream back to the parent process using an output stream. */ | |
| STREAM }; | |
| private ImmutableList<String> argv; | |
| private ImmutableMap<String, String> env; | |
| private StreamAction stdoutAction; | |
| private File stdoutFile; | |
| private StreamAction stderrAction; | |
| private File stderrFile; | |
| private File workingDirectory; | |
| private long timeoutMillis = -1; | |
| private static Subprocess.Factory factory = JavaSubprocessFactory.INSTANCE; | |
| public static void setSubprocessFactory(Subprocess.Factory factory) { | |
| SubprocessBuilder.factory = factory; | |
| } | |
| public SubprocessBuilder() { | |
| stdoutAction = StreamAction.STREAM; | |
| stderrAction = StreamAction.STREAM; | |
| } | |
| public ImmutableList<String> getArgv() { | |
| return argv; | |
| } | |
| /** | |
| * Sets the argv, including argv[0], that is, the binary to execute. | |
| */ | |
| public SubprocessBuilder setArgv(Iterable<String> argv) { | |
| this.argv = ImmutableList.copyOf(argv); | |
| return this; | |
| } | |
| public ImmutableMap<String, String> getEnv() { | |
| return env; | |
| } | |
| /** | |
| * Sets the environment passed to the child process. If null, inherit the environment of the | |
| * server. | |
| */ | |
| public SubprocessBuilder setEnv(Map<String, String> env) { | |
| this.env = env == null | |
| ? null : ImmutableMap.copyOf(env); | |
| return this; | |
| } | |
| public StreamAction getStdout() { | |
| return stdoutAction; | |
| } | |
| public File getStdoutFile() { | |
| return stdoutFile; | |
| } | |
| /** | |
| * Tells the object what to do with stdout: either stream as a {@code InputStream} or discard. | |
| * | |
| * <p>It can also be redirected to a file using {@link #setStdout(File)}. | |
| */ | |
| public SubprocessBuilder setStdout(StreamAction action) { | |
| if (action == StreamAction.REDIRECT) { | |
| throw new IllegalStateException(); | |
| } | |
| this.stdoutAction = action; | |
| this.stdoutFile = null; | |
| return this; | |
| } | |
| /** | |
| * Sets the file stdout is appended to. If null, the stdout will be available as an input stream | |
| * on the resulting object representing the process. | |
| */ | |
| public SubprocessBuilder setStdout(File file) { | |
| this.stdoutAction = StreamAction.REDIRECT; | |
| this.stdoutFile = file; | |
| return this; | |
| } | |
| public SubprocessBuilder setTimeoutMillis(long timeoutMillis) { | |
| this.timeoutMillis = timeoutMillis; | |
| return this; | |
| } | |
| public long getTimeoutMillis() { | |
| return timeoutMillis; | |
| } | |
| public StreamAction getStderr() { | |
| return stderrAction; | |
| } | |
| public File getStderrFile() { | |
| return stderrFile; | |
| } | |
| /** | |
| * Tells the object what to do with stderr: either stream as a {@code InputStream} or discard. | |
| * | |
| * <p>It can also be redirected to a file using {@link #setStderr(File)}. | |
| */ | |
| public SubprocessBuilder setStderr(StreamAction action) { | |
| if (action == StreamAction.REDIRECT) { | |
| throw new IllegalStateException(); | |
| } | |
| this.stderrAction = action; | |
| this.stderrFile = null; | |
| return this; | |
| } | |
| /** | |
| * Sets the file stderr is appended to. If null, the stderr will be available as an input stream | |
| * on the resulting object representing the process. | |
| */ | |
| public SubprocessBuilder setStderr(File file) { | |
| this.stderrAction = StreamAction.REDIRECT; | |
| this.stderrFile = file; | |
| return this; | |
| } | |
| public File getWorkingDirectory() { | |
| return workingDirectory; | |
| } | |
| /** | |
| * Sets the current working directory. If null, it will be that of this process. | |
| */ | |
| public SubprocessBuilder setWorkingDirectory(File workingDirectory) { | |
| this.workingDirectory = workingDirectory; | |
| return this; | |
| } | |
| public Subprocess start() throws IOException { | |
| return factory.create(this); | |
| } | |
| } |