blob: a25760c5f1eb3505b75b16207463666a515b6577 [file] [log] [blame]
package org.eclipse.cdt.core;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Properties;
import org.eclipse.cdt.internal.core.ProcessClosure;
import org.eclipse.cdt.utils.spawner.EnvironmentReader;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
public class CommandLauncher {
public final static int COMMAND_CANCELED= 1;
public final static int ILLEGAL_COMMAND= -1;
public final static int OK= 0;
protected Process fProcess;
protected boolean fShowCommand;
protected String[] fCommandArgs;
protected String fErrorMessage = "";
private String lineSeparator;
/**
* The number of milliseconds to pause
* between polling.
*/
protected static final long DELAY = 50L;
/**
* Creates a new launcher
* Fills in stderr and stdout output to the given streams.
* Streams can be set to <code>null</code>, if output not required
*/
public CommandLauncher() {
fProcess= null;
fShowCommand= false;
lineSeparator = System.getProperty("line.separator", "\n");
}
/**
* Sets if the command should be printed out first before executing
*/
public void showCommand(boolean show) {
fShowCommand= show;
}
public String getErrorMessage() {
return fErrorMessage;
}
public void setErrorMessage(String error) {
fErrorMessage = error;
}
public String[] getCommandArgs() {
return fCommandArgs;
}
public Properties getEnvironment() {
return EnvironmentReader.getEnvVars();
}
/**
* return the constructed Command line.
*
* @return
*/
public String getCommandLine() {
return getCommandLine(getCommandArgs());
}
/**
* Constructs a command array that will be passed to the process
*/
protected String[] constructCommandArray(String command, String[] commandArgs) {
String[] args = new String[1 + commandArgs.length];
args[0] = command;
System.arraycopy(commandArgs, 0, args, 1, commandArgs.length);
return args;
}
/**
* Execute a command
*/
public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory) {
try {
// add platform specific arguments (shell invocation)
fCommandArgs= constructCommandArray(commandPath.toOSString(), args);
fProcess= ProcessFactory.getFactory().exec(fCommandArgs, env, changeToDirectory.toFile());
fErrorMessage= "";
} catch (IOException e) {
setErrorMessage(e.getMessage());
fProcess= null;
}
return fProcess;
}
/**
* Reads output form the process to the streams.
*/
public int waitAndRead(OutputStream out, OutputStream err) {
if (fShowCommand) {
printCommandLine(out);
}
if (fProcess == null) {
return ILLEGAL_COMMAND;
}
ProcessClosure closure= new ProcessClosure(fProcess, out, err);
closure.runBlocking(); // a blocking call
return OK;
}
/**
* Reads output form the process to the streams. A progress monitor is polled to
* test if the cancel button has been pressed.
* Destroys the process if the monitor becomes canceled
* override to implement a different way to read the process inputs
*/
public int waitAndRead(OutputStream output, OutputStream err, IProgressMonitor monitor) {
if (fShowCommand) {
printCommandLine(output);
}
if (fProcess == null) {
return ILLEGAL_COMMAND;
}
PipedOutputStream errOutPipe = new PipedOutputStream();
PipedOutputStream outputPipe = new PipedOutputStream();
PipedInputStream errInPipe, inputPipe;
try {
errInPipe = new PipedInputStream(errOutPipe);
inputPipe = new PipedInputStream(outputPipe);
} catch( IOException e ) {
setErrorMessage("Command canceled");
return COMMAND_CANCELED;
}
ProcessClosure closure= new ProcessClosure(fProcess, outputPipe, errOutPipe);
closure.runNonBlocking();
byte buffer[] = new byte[1024];
int nbytes;
while (!monitor.isCanceled() && closure.isAlive()) {
nbytes = 0;
try {
if ( errInPipe.available() > 0 ) {
nbytes = errInPipe.read(buffer);
err.write(buffer, 0, nbytes);
err.flush();
}
if ( inputPipe.available() > 0 ) {
nbytes = inputPipe.read(buffer);
output.write(buffer, 0, nbytes);
output.flush();
}
} catch( IOException e) {
}
monitor.worked(0);
if (nbytes == 0) {
try {
Thread.sleep(DELAY);
} catch (InterruptedException ie) {
}
}
}
int state = OK;
// Operation canceled by the user, terminate abnormally.
if (monitor.isCanceled()) {
closure.terminate();
state = COMMAND_CANCELED;
setErrorMessage("Command canceled");
}
try {
fProcess.waitFor();
} catch (InterruptedException e) {
//System.err.println("Closure exception " +e);
//e.printStackTrace();
}
// Drain the pipes.
try {
while (errInPipe.available() > 0 || inputPipe.available() > 0) {
if ( errInPipe.available() > 0 ) {
nbytes = errInPipe.read(buffer);
err.write(buffer, 0, nbytes);
err.flush();
}
if ( inputPipe.available() > 0 ) {
nbytes = inputPipe.read(buffer);
output.write(buffer, 0, nbytes);
output.flush();
}
}
errInPipe.close();
inputPipe.close();
} catch (IOException e) {
}
return state;
}
protected void printCommandLine(OutputStream os) {
if (os != null) {
String cmd = getCommandLine(getCommandArgs());
try {
os.write(cmd.getBytes());
os.flush();
} catch (IOException e) {
// ignore;
}
}
}
protected String getCommandLine(String[] commandArgs) {
StringBuffer buf = new StringBuffer();
if (fCommandArgs != null) {
for (int i= 0; i < commandArgs.length; i++) {
buf.append(commandArgs[i]);
buf.append(' ');
}
buf.append(lineSeparator);
}
return buf.toString();
}
}