blob: eaa4da66c0bb89a83b8a6ca0c77ef79997d5a33a [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* 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.gwt.ant.taskdefs;
import org.apache.tools.ant.BuildException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
/**
* Utility class to run external commands.
*/
class CommandRunner {
/**
* Returns the output of running a command as a string. Will fail if the
* invoked process returns a non-zero status code and
* <code>checkStatusCode</code> is <code>true</code>.
*/
public static String getCommandOutput(boolean checkStatusCode, File workDir,
String... cmd) {
Process process = runCommandIgnoringErr(workDir, cmd);
StringBuilder output = new StringBuilder();
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(
process.getInputStream()));
try {
for (String line = lnr.readLine(); line != null; line = lnr.readLine()) {
output.append(line);
output.append('\n');
}
int statusCode = process.waitFor();
if (checkStatusCode && statusCode != 0) {
throw new BuildException("Non-zero status code result (" + statusCode
+ ") running command: " + makeCmdString(cmd));
}
return output.toString();
} catch (IOException e) {
throw new BuildException("Unable to read command: " + makeCmdString(cmd),
e);
} catch (InterruptedException e) {
throw new BuildException("Interrupted waiting for command: "
+ makeCmdString(cmd), e);
} finally {
if (lnr != null) {
try {
lnr.close();
} catch (IOException e) {
// do nothing
}
}
}
}
/**
* Returns the output of running a command as a string. Will fail if the
* invoked process returns a non-zero status code.
*/
public static String getCommandOutput(File workDir, String... cmd) {
return getCommandOutput(true, workDir, cmd);
}
/**
* Runs the specified command and returns the {@link Process}. The caller
* must handle both the output and error streams to avoid blocking the
* underlying process.
*/
public static Process runCommand(File workDir, String... cmd) {
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.directory(workDir);
try {
return pb.start();
} catch (IOException e) {
throw new BuildException("Unable to launch command: "
+ makeCmdString(cmd), e);
}
}
/**
* Runs the specified command and returns the {@link Process}. The resulting
* process's error stream will be continually drained in a daemon thread to
* prevent the underlying process from blocking. The caller must handle both
* output stream to avoid blocking the underlying process.
*/
public static Process runCommandIgnoringErr(File workDir, String... cmd) {
final Process process = runCommand(workDir, cmd);
// Consume error output on another thread to avoid blocking.
Thread errThread = new Thread(new Runnable() {
public void run() {
InputStream errorStream = process.getErrorStream();
try {
byte[] buf = new byte[8192];
int read;
do {
read = errorStream.read(buf);
} while (read >= 0);
} catch (IOException e) {
} finally {
try {
errorStream.close();
} catch (IOException e) {
}
}
}
});
errThread.setDaemon(true);
errThread.start();
return process;
}
/**
* Turns a command array into a printable string.
*/
static String makeCmdString(String... cmd) {
StringBuilder sb = new StringBuilder();
for (String arg : cmd) {
if (sb.length() > 0) {
sb.append(' ');
}
sb.append(arg);
}
String cmdString = sb.toString();
return cmdString;
}
}