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.File; | ||||
import java.io.FileNotFoundException; | import java.io.FileNotFoundException; | ||||
import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||||
import java.io.FileInputStream; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.StringReader; | import java.io.StringReader; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.InputStream; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
@@ -89,6 +91,7 @@ public class ExecTask extends Task { | |||||
private String os; | private String os; | ||||
private File out; | private File out; | ||||
private File error; | private File error; | ||||
private File input; | |||||
private boolean logError = false; | private boolean logError = false; | ||||
@@ -167,6 +170,13 @@ public class ExecTask extends Task { | |||||
this.cmdl = cmdl; | 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 | * File the output of the process is redirected to. If error is not | ||||
* redirected, it too will appear in the output | * redirected, it too will appear in the output | ||||
@@ -475,6 +485,7 @@ public class ExecTask extends Task { | |||||
protected ExecuteStreamHandler createHandler() throws BuildException { | protected ExecuteStreamHandler createHandler() throws BuildException { | ||||
OutputStream outputStream = null; | OutputStream outputStream = null; | ||||
OutputStream errorStream = null; | OutputStream errorStream = null; | ||||
InputStream inputStream = null; | |||||
if (out == null && outputprop == null) { | if (out == null && outputprop == null) { | ||||
outputStream = new LogOutputStream(this, Project.MSG_INFO); | outputStream = new LogOutputStream(this, Project.MSG_INFO); | ||||
@@ -540,8 +551,18 @@ public class ExecTask extends Task { | |||||
} else { | } else { | ||||
errorBaos = null; | 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 { | public class PumpStreamHandler implements ExecuteStreamHandler { | ||||
private Thread inputThread; | |||||
private Thread outputThread; | |||||
private Thread errorThread; | private Thread errorThread; | ||||
private Thread inputThread; | |||||
private OutputStream out; | private OutputStream out; | ||||
private OutputStream err; | private OutputStream err; | ||||
private InputStream input; | |||||
private boolean closeOutOnStop = false; | private boolean closeOutOnStop = false; | ||||
private boolean closeErrOnStop = false; | private boolean closeErrOnStop = false; | ||||
private boolean closeInputOnStop = false; | |||||
public PumpStreamHandler(OutputStream out, OutputStream err, | public PumpStreamHandler(OutputStream out, OutputStream err, | ||||
boolean closeOutOnStop, boolean closeErrOnStop) { | |||||
InputStream input, | |||||
boolean closeOutOnStop, boolean closeErrOnStop, | |||||
boolean closeInputOnStop) { | |||||
this.out = out; | this.out = out; | ||||
this.err = err; | this.err = err; | ||||
this.input = input; | |||||
this.closeOutOnStop = closeOutOnStop; | this.closeOutOnStop = closeOutOnStop; | ||||
this.closeErrOnStop = closeErrOnStop; | this.closeErrOnStop = closeErrOnStop; | ||||
this.closeInputOnStop = closeInputOnStop; | |||||
} | } | ||||
public PumpStreamHandler(OutputStream out, OutputStream err) { | public PumpStreamHandler(OutputStream out, OutputStream err) { | ||||
this(out, err, false, false); | |||||
this(out, err, null, false, false, false); | |||||
} | } | ||||
public PumpStreamHandler(OutputStream outAndErr) { | public PumpStreamHandler(OutputStream outAndErr) { | ||||
@@ -103,39 +111,70 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||||
public void setProcessErrorStream(InputStream is) { | public void setProcessErrorStream(InputStream is) { | ||||
createProcessErrorPump(is, err); | |||||
if (err != null) { | |||||
createProcessErrorPump(is, err); | |||||
} | |||||
} | } | ||||
public void setProcessInputStream(OutputStream os) { | public void setProcessInputStream(OutputStream os) { | ||||
if (input != null) { | |||||
inputThread = createPump(input, os, true); | |||||
} else { | |||||
try { | |||||
os.close(); | |||||
} catch (IOException e) { | |||||
//ignore | |||||
} | |||||
} | |||||
} | } | ||||
public void start() { | public void start() { | ||||
inputThread.start(); | |||||
outputThread.start(); | |||||
errorThread.start(); | errorThread.start(); | ||||
inputThread.start(); | |||||
} | } | ||||
public void stop() { | public void stop() { | ||||
try { | try { | ||||
inputThread.join(); | |||||
} catch (InterruptedException e) {} | |||||
outputThread.join(); | |||||
} catch (InterruptedException e) { | |||||
// ignore | |||||
} | |||||
try { | try { | ||||
errorThread.join(); | 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 { | try { | ||||
err.flush(); | err.flush(); | ||||
if (closeErrOnStop) { | if (closeErrOnStop) { | ||||
err.close(); | err.close(); | ||||
} | } | ||||
} catch (IOException e) {} | |||||
} catch (IOException e) { | |||||
// ignore | |||||
} | |||||
try { | try { | ||||
out.flush(); | out.flush(); | ||||
if (closeOutOnStop) { | if (closeOutOnStop) { | ||||
out.close(); | out.close(); | ||||
} | } | ||||
} catch (IOException e) {} | |||||
} catch (IOException e) { | |||||
// ignore | |||||
} | |||||
} | } | ||||
protected OutputStream getErr() { | protected OutputStream getErr() { | ||||
@@ -147,7 +186,7 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||||
} | } | ||||
protected void createProcessOutputPump(InputStream is, OutputStream os) { | protected void createProcessOutputPump(InputStream is, OutputStream os) { | ||||
inputThread = createPump(is, os); | |||||
outputThread = createPump(is, os); | |||||
} | } | ||||
protected void createProcessErrorPump(InputStream is, OutputStream os) { | protected void createProcessErrorPump(InputStream is, OutputStream os) { | ||||
@@ -160,7 +199,17 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||||
* given output stream. | * given output stream. | ||||
*/ | */ | ||||
protected Thread createPump(InputStream is, OutputStream os) { | 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); | result.setDaemon(true); | ||||
return result; | return result; | ||||
} | } | ||||
@@ -66,23 +66,38 @@ import java.io.OutputStream; | |||||
*/ | */ | ||||
public class StreamPumper implements Runnable { | 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. | // TODO: add a status flag to note if an error occured in run. | ||||
private static final int SIZE = 128; | private static final int SIZE = 128; | ||||
private InputStream is; | private InputStream is; | ||||
private OutputStream os; | private OutputStream os; | ||||
private boolean finished; | private boolean finished; | ||||
private boolean closeWhenExhausted; | |||||
/** | /** | ||||
* Create a new stream pumper. | * Create a new stream pumper. | ||||
* | * | ||||
* @param is input stream to read data from | * @param is input stream to read data from | ||||
* @param os output stream to write data to. | * @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.is = is; | ||||
this.os = os; | 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) { | while ((length = is.read(buf)) > 0) { | ||||
os.write(buf, 0, length); | os.write(buf, 0, length); | ||||
} | } | ||||
if (closeWhenExhausted) { | |||||
os.close(); | |||||
} | |||||
} catch (IOException e) { | } catch (IOException e) { | ||||
// ignore errors | // ignore errors | ||||
} finally { | } finally { | ||||