git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274016 13f79535-47bb-0310-9956-ffa450edef68master
@@ -59,9 +59,11 @@ import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileNotFoundException; | |||
import java.io.FileOutputStream; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.StringReader; | |||
import java.io.OutputStream; | |||
import java.io.InputStream; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.Task; | |||
@@ -89,6 +91,7 @@ public class ExecTask extends Task { | |||
private String os; | |||
private File out; | |||
private File error; | |||
private File input; | |||
private boolean logError = false; | |||
@@ -167,6 +170,13 @@ public class ExecTask extends Task { | |||
this.cmdl = cmdl; | |||
} | |||
/** | |||
* Set the input to use for the task | |||
*/ | |||
public void setInput(File input) { | |||
this.input = input; | |||
} | |||
/** | |||
* File the output of the process is redirected to. If error is not | |||
* redirected, it too will appear in the output | |||
@@ -475,6 +485,7 @@ public class ExecTask extends Task { | |||
protected ExecuteStreamHandler createHandler() throws BuildException { | |||
OutputStream outputStream = null; | |||
OutputStream errorStream = null; | |||
InputStream inputStream = null; | |||
if (out == null && outputprop == null) { | |||
outputStream = new LogOutputStream(this, Project.MSG_INFO); | |||
@@ -540,8 +551,18 @@ public class ExecTask extends Task { | |||
} else { | |||
errorBaos = null; | |||
} | |||
if (input != null) { | |||
try { | |||
inputStream = new FileInputStream(input); | |||
} catch (FileNotFoundException fne) { | |||
throw new BuildException("Cannot read from " + input, fne, | |||
getLocation()); | |||
} | |||
} | |||
return new PumpStreamHandler(outputStream, errorStream, true, true); | |||
return new PumpStreamHandler(outputStream, errorStream, inputStream, | |||
true, true, true); | |||
} | |||
/** | |||
@@ -69,24 +69,32 @@ import java.io.OutputStream; | |||
*/ | |||
public class PumpStreamHandler implements ExecuteStreamHandler { | |||
private Thread inputThread; | |||
private Thread outputThread; | |||
private Thread errorThread; | |||
private Thread inputThread; | |||
private OutputStream out; | |||
private OutputStream err; | |||
private InputStream input; | |||
private boolean closeOutOnStop = false; | |||
private boolean closeErrOnStop = false; | |||
private boolean closeInputOnStop = false; | |||
public PumpStreamHandler(OutputStream out, OutputStream err, | |||
boolean closeOutOnStop, boolean closeErrOnStop) { | |||
InputStream input, | |||
boolean closeOutOnStop, boolean closeErrOnStop, | |||
boolean closeInputOnStop) { | |||
this.out = out; | |||
this.err = err; | |||
this.input = input; | |||
this.closeOutOnStop = closeOutOnStop; | |||
this.closeErrOnStop = closeErrOnStop; | |||
this.closeInputOnStop = closeInputOnStop; | |||
} | |||
public PumpStreamHandler(OutputStream out, OutputStream err) { | |||
this(out, err, false, false); | |||
this(out, err, null, false, false, false); | |||
} | |||
public PumpStreamHandler(OutputStream outAndErr) { | |||
@@ -103,39 +111,70 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||
public void setProcessErrorStream(InputStream is) { | |||
createProcessErrorPump(is, err); | |||
if (err != null) { | |||
createProcessErrorPump(is, err); | |||
} | |||
} | |||
public void setProcessInputStream(OutputStream os) { | |||
if (input != null) { | |||
inputThread = createPump(input, os, true); | |||
} else { | |||
try { | |||
os.close(); | |||
} catch (IOException e) { | |||
//ignore | |||
} | |||
} | |||
} | |||
public void start() { | |||
inputThread.start(); | |||
outputThread.start(); | |||
errorThread.start(); | |||
inputThread.start(); | |||
} | |||
public void stop() { | |||
try { | |||
inputThread.join(); | |||
} catch (InterruptedException e) {} | |||
outputThread.join(); | |||
} catch (InterruptedException e) { | |||
// ignore | |||
} | |||
try { | |||
errorThread.join(); | |||
} catch (InterruptedException e) {} | |||
} catch (InterruptedException e) { | |||
// ignore | |||
} | |||
if (inputThread != null) { | |||
try { | |||
inputThread.join(); | |||
if (closeInputOnStop) { | |||
input.close(); | |||
} | |||
} catch (InterruptedException e) { | |||
// ignore | |||
} catch (IOException e) { | |||
// ignore | |||
} | |||
} | |||
try { | |||
err.flush(); | |||
if (closeErrOnStop) { | |||
err.close(); | |||
} | |||
} catch (IOException e) {} | |||
} catch (IOException e) { | |||
// ignore | |||
} | |||
try { | |||
out.flush(); | |||
if (closeOutOnStop) { | |||
out.close(); | |||
} | |||
} catch (IOException e) {} | |||
} catch (IOException e) { | |||
// ignore | |||
} | |||
} | |||
protected OutputStream getErr() { | |||
@@ -147,7 +186,7 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||
} | |||
protected void createProcessOutputPump(InputStream is, OutputStream os) { | |||
inputThread = createPump(is, os); | |||
outputThread = createPump(is, os); | |||
} | |||
protected void createProcessErrorPump(InputStream is, OutputStream os) { | |||
@@ -160,7 +199,17 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||
* given output stream. | |||
*/ | |||
protected Thread createPump(InputStream is, OutputStream os) { | |||
final Thread result = new Thread(new StreamPumper(is, os)); | |||
return createPump(is, os, false); | |||
} | |||
/** | |||
* Creates a stream pumper to copy the given input stream to the | |||
* given output stream. | |||
*/ | |||
protected Thread createPump(InputStream is, OutputStream os, | |||
boolean closeWhenExhausted) { | |||
final Thread result | |||
= new Thread(new StreamPumper(is, os, closeWhenExhausted)); | |||
result.setDaemon(true); | |||
return result; | |||
} | |||
@@ -66,23 +66,38 @@ import java.io.OutputStream; | |||
*/ | |||
public class StreamPumper implements Runnable { | |||
// TODO: make SIZE and SLEEP instance variables. | |||
// TODO: make SIZE an instance variable. | |||
// TODO: add a status flag to note if an error occured in run. | |||
private static final int SIZE = 128; | |||
private InputStream is; | |||
private OutputStream os; | |||
private boolean finished; | |||
private boolean closeWhenExhausted; | |||
/** | |||
* Create a new stream pumper. | |||
* | |||
* @param is input stream to read data from | |||
* @param os output stream to write data to. | |||
* @param closeWhenExhausted if true, the output stream will be closed when | |||
* the input is exhausted. | |||
*/ | |||
public StreamPumper(InputStream is, OutputStream os) { | |||
public StreamPumper(InputStream is, OutputStream os, | |||
boolean closeWhenExhausted) { | |||
this.is = is; | |||
this.os = os; | |||
this.closeWhenExhausted = closeWhenExhausted; | |||
} | |||
/** | |||
* Create a new stream pumper. | |||
* | |||
* @param is input stream to read data from | |||
* @param os output stream to write data to. | |||
*/ | |||
public StreamPumper(InputStream is, OutputStream os) { | |||
this(is, os, false); | |||
} | |||
@@ -104,6 +119,9 @@ public class StreamPumper implements Runnable { | |||
while ((length = is.read(buf)) > 0) { | |||
os.write(buf, 0, length); | |||
} | |||
if (closeWhenExhausted) { | |||
os.close(); | |||
} | |||
} catch (IOException e) { | |||
// ignore errors | |||
} finally { | |||