use this in Java task to get access to features such as separate error stream, redirected input, etc. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274020 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -54,24 +54,14 @@ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import java.io.BufferedReader; | |||
| 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; | |||
| import org.apache.tools.ant.types.Commandline; | |||
| import org.apache.tools.ant.types.Environment; | |||
| import org.apache.tools.ant.util.StringUtils; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.ant.util.TeeOutputStream; | |||
| /** | |||
| * Executes a given command if the os platform is appropriate. | |||
| @@ -89,11 +79,6 @@ import org.apache.tools.ant.util.TeeOutputStream; | |||
| public class ExecTask extends Task { | |||
| private String os; | |||
| private File out; | |||
| private File error; | |||
| private File input; | |||
| private boolean logError = false; | |||
| private File dir; | |||
| protected boolean failOnError = false; | |||
| @@ -101,17 +86,13 @@ public class ExecTask extends Task { | |||
| private Long timeout = null; | |||
| private Environment env = new Environment(); | |||
| protected Commandline cmdl = new Commandline(); | |||
| private FileOutputStream fos = null; | |||
| private ByteArrayOutputStream baos = null; | |||
| private ByteArrayOutputStream errorBaos = null; | |||
| private String outputprop; | |||
| private String errorProperty; | |||
| private String resultProperty; | |||
| private boolean failIfExecFails = true; | |||
| private boolean append = false; | |||
| private String executable; | |||
| private boolean resolveExecutable = false; | |||
| private Redirector redirector = new Redirector(this); | |||
| /** | |||
| * Controls whether the VM (1.3 and above) is used to execute the | |||
| * command | |||
| @@ -170,28 +151,32 @@ 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 | |||
| */ | |||
| public void setOutput(File out) { | |||
| this.out = out; | |||
| redirector.setOutput(out); | |||
| } | |||
| /** | |||
| * Set the input to use for the task | |||
| */ | |||
| public void setInput(File input) { | |||
| redirector.setInput(input); | |||
| } | |||
| public void setInputString(String inputString) { | |||
| redirector.setInputString(inputString); | |||
| } | |||
| /** | |||
| * Controls whether error output of exec is logged. This is only useful | |||
| * when output is being redirected and error output is desired in the | |||
| * Ant log | |||
| */ | |||
| public void setLogError(boolean logError) { | |||
| this.logError = logError; | |||
| redirector.setLogError(logError); | |||
| } | |||
| /** | |||
| @@ -200,15 +185,15 @@ public class ExecTask extends Task { | |||
| * @since ant 1.6 | |||
| */ | |||
| public void setError(File error) { | |||
| this.error = error; | |||
| redirector.setError(error); | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the output of | |||
| * the process. | |||
| */ | |||
| public void setOutputproperty(String outputprop) { | |||
| this.outputprop = outputprop; | |||
| public void setOutputproperty(String outputProp) { | |||
| redirector.setOutputProperty(outputProp); | |||
| } | |||
| /** | |||
| @@ -218,7 +203,7 @@ public class ExecTask extends Task { | |||
| * @since ant 1.6 | |||
| */ | |||
| public void setErrorProperty(String errorProperty) { | |||
| this.errorProperty = errorProperty; | |||
| redirector.setErrorProperty(errorProperty); | |||
| } | |||
| /** | |||
| @@ -293,7 +278,7 @@ public class ExecTask extends Task { | |||
| * @since 1.30, Ant 1.5 | |||
| */ | |||
| public void setAppend(boolean append) { | |||
| this.append = append; | |||
| redirector.setAppend(append); | |||
| } | |||
| @@ -382,7 +367,7 @@ public class ExecTask extends Task { | |||
| /** | |||
| * If true, launch new process with VM, otherwise use the OS's shell. | |||
| */ | |||
| public void setVMLauncher(boolean vmLauncher) { | |||
| public void setVMLauncher(boolean vmLauncher) { | |||
| this.vmLauncher = vmLauncher; | |||
| } | |||
| @@ -410,22 +395,6 @@ public class ExecTask extends Task { | |||
| return exe; | |||
| } | |||
| private void setPropertyFromBAOS(ByteArrayOutputStream baos, | |||
| String propertyName) throws IOException { | |||
| BufferedReader in = | |||
| new BufferedReader(new StringReader(Execute.toString(baos))); | |||
| String line = null; | |||
| StringBuffer val = new StringBuffer(); | |||
| while ((line = in.readLine()) != null) { | |||
| if (val.length() != 0) { | |||
| val.append(StringUtils.LINE_SEP); | |||
| } | |||
| val.append(line); | |||
| } | |||
| getProject().setNewProperty(propertyName, val.toString()); | |||
| } | |||
| /** | |||
| * A Utility method for this classes and subclasses to run an | |||
| * Execute instance (an external command). | |||
| @@ -447,12 +416,7 @@ public class ExecTask extends Task { | |||
| log("Result: " + returnCode, Project.MSG_ERR); | |||
| } | |||
| } | |||
| if (baos != null) { | |||
| setPropertyFromBAOS(baos, outputprop); | |||
| } | |||
| if (errorBaos != null) { | |||
| setPropertyFromBAOS(errorBaos, errorProperty); | |||
| } | |||
| redirector.complete(); | |||
| } | |||
| /** | |||
| @@ -483,86 +447,7 @@ public class ExecTask extends Task { | |||
| * Create the StreamHandler to use with our Execute instance. | |||
| */ | |||
| 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); | |||
| errorStream = new LogOutputStream(this, Project.MSG_WARN); | |||
| } else { | |||
| if (out != null) { | |||
| try { | |||
| outputStream | |||
| = new FileOutputStream(out.getAbsolutePath(), append); | |||
| log("Output redirected to " + out, Project.MSG_VERBOSE); | |||
| } catch (FileNotFoundException fne) { | |||
| throw new BuildException("Cannot write to " + out, fne, | |||
| getLocation()); | |||
| } catch (IOException ioe) { | |||
| throw new BuildException("Cannot write to " + out, ioe, | |||
| getLocation()); | |||
| } | |||
| } | |||
| if (outputprop != null) { | |||
| baos = new ByteArrayOutputStream(); | |||
| log("Output redirected to property: " + outputprop, | |||
| Project.MSG_VERBOSE); | |||
| if (out == null) { | |||
| outputStream = baos; | |||
| } else { | |||
| outputStream = new TeeOutputStream(outputStream, baos); | |||
| } | |||
| } else { | |||
| baos = null; | |||
| } | |||
| errorStream = outputStream; | |||
| } | |||
| if (logError) { | |||
| errorStream = new LogOutputStream(this, Project.MSG_WARN); | |||
| } | |||
| if (error != null) { | |||
| try { | |||
| errorStream | |||
| = new FileOutputStream(error.getAbsolutePath(), append); | |||
| log("Error redirected to " + error, Project.MSG_VERBOSE); | |||
| } catch (FileNotFoundException fne) { | |||
| throw new BuildException("Cannot write to " + error, fne, | |||
| getLocation()); | |||
| } catch (IOException ioe) { | |||
| throw new BuildException("Cannot write to " + error, ioe, | |||
| getLocation()); | |||
| } | |||
| } | |||
| if (errorProperty != null) { | |||
| errorBaos = new ByteArrayOutputStream(); | |||
| log("Error redirected to property: " + errorProperty, | |||
| Project.MSG_VERBOSE); | |||
| if (error == null) { | |||
| errorStream = errorBaos; | |||
| } else { | |||
| errorStream = new TeeOutputStream(errorStream, errorBaos); | |||
| } | |||
| } 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, inputStream, | |||
| true, true, true); | |||
| return redirector.createHandler(); | |||
| } | |||
| /** | |||
| @@ -579,14 +464,6 @@ public class ExecTask extends Task { | |||
| * Flush the output stream - if there is one. | |||
| */ | |||
| protected void logFlush() { | |||
| try { | |||
| if (fos != null) { | |||
| fos.close(); | |||
| } | |||
| if (baos != null) { | |||
| baos.close(); | |||
| } | |||
| } catch (IOException io) {} | |||
| } | |||
| } | |||
| @@ -55,9 +55,7 @@ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import java.io.File; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.PrintStream; | |||
| import java.util.Vector; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.ExitException; | |||
| @@ -89,12 +87,10 @@ public class Java extends Task { | |||
| private boolean fork = false; | |||
| private boolean newEnvironment = false; | |||
| private File dir = null; | |||
| private File out; | |||
| private PrintStream outStream = null; | |||
| private boolean failOnError = false; | |||
| private boolean append = false; | |||
| private Long timeout = null; | |||
| private Redirector redirector = new Redirector(this); | |||
| /** | |||
| * Do the execution. | |||
| */ | |||
| @@ -302,7 +298,54 @@ public class Java extends Task { | |||
| * File the output of the process is redirected to. | |||
| */ | |||
| public void setOutput(File out) { | |||
| this.out = out; | |||
| redirector.setOutput(out); | |||
| } | |||
| /** | |||
| * Set the input to use for the task | |||
| */ | |||
| public void setInput(File input) { | |||
| redirector.setInput(input); | |||
| } | |||
| public void setInputString(String inputString) { | |||
| redirector.setInputString(inputString); | |||
| } | |||
| /** | |||
| * Controls whether error output of exec is logged. This is only useful | |||
| * when output is being redirected and error output is desired in the | |||
| * Ant log | |||
| */ | |||
| public void setLogError(boolean logError) { | |||
| redirector.setLogError(logError); | |||
| } | |||
| /** | |||
| * File the error stream of the process is redirected to. | |||
| * | |||
| * @since ant 1.6 | |||
| */ | |||
| public void setError(File error) { | |||
| redirector.setError(error); | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the output of | |||
| * the process. | |||
| */ | |||
| public void setOutputproperty(String outputProp) { | |||
| redirector.setOutputProperty(outputProp); | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the error of | |||
| * the process. | |||
| * | |||
| * @since ant 1.6 | |||
| */ | |||
| public void setErrorProperty(String errorProperty) { | |||
| redirector.setErrorProperty(errorProperty); | |||
| } | |||
| /** | |||
| @@ -366,8 +409,8 @@ public class Java extends Task { | |||
| * @since Ant 1.5 | |||
| */ | |||
| protected void handleOutput(String line) { | |||
| if (outStream != null) { | |||
| outStream.println(line); | |||
| if (redirector.getOutputStream() != null) { | |||
| redirector.handleOutput(line); | |||
| } else { | |||
| super.handleOutput(line); | |||
| } | |||
| @@ -379,8 +422,8 @@ public class Java extends Task { | |||
| * @since Ant 1.5.2 | |||
| */ | |||
| protected void handleFlush(String line) { | |||
| if (outStream != null) { | |||
| outStream.print(line); | |||
| if (redirector.getOutputStream() != null) { | |||
| redirector.handleFlush(line); | |||
| } else { | |||
| super.handleFlush(line); | |||
| } | |||
| @@ -392,8 +435,8 @@ public class Java extends Task { | |||
| * @since Ant 1.5 | |||
| */ | |||
| protected void handleErrorOutput(String line) { | |||
| if (outStream != null) { | |||
| outStream.println(line); | |||
| if (redirector.getErrorStream() != null) { | |||
| redirector.handleErrorOutput(line); | |||
| } else { | |||
| super.handleErrorOutput(line); | |||
| } | |||
| @@ -405,8 +448,8 @@ public class Java extends Task { | |||
| * @since Ant 1.5.2 | |||
| */ | |||
| protected void handleErrorFlush(String line) { | |||
| if (outStream != null) { | |||
| outStream.println(line); | |||
| if (redirector.getErrorStream() != null) { | |||
| redirector.handleErrorFlush(line); | |||
| } else { | |||
| super.handleErrorOutput(line); | |||
| } | |||
| @@ -417,28 +460,17 @@ public class Java extends Task { | |||
| * was a command line application. | |||
| */ | |||
| private void run(CommandlineJava command) throws BuildException { | |||
| ExecuteJava exe = new ExecuteJava(); | |||
| exe.setJavaCommand(command.getJavaCommand()); | |||
| exe.setClasspath(command.getClasspath()); | |||
| exe.setSystemProperties(command.getSystemProperties()); | |||
| exe.setTimeout(timeout); | |||
| if (out != null) { | |||
| try { | |||
| outStream = | |||
| new PrintStream(new FileOutputStream(out.getAbsolutePath(), | |||
| append)); | |||
| exe.execute(getProject()); | |||
| System.out.flush(); | |||
| System.err.flush(); | |||
| } catch (IOException io) { | |||
| throw new BuildException(io, getLocation()); | |||
| } finally { | |||
| if (outStream != null) { | |||
| outStream.close(); | |||
| } | |||
| } | |||
| } else { | |||
| try { | |||
| ExecuteJava exe = new ExecuteJava(); | |||
| exe.setJavaCommand(command.getJavaCommand()); | |||
| exe.setClasspath(command.getClasspath()); | |||
| exe.setSystemProperties(command.getSystemProperties()); | |||
| exe.setTimeout(timeout); | |||
| redirector.createStreams(); | |||
| exe.execute(getProject()); | |||
| redirector.complete(); | |||
| } catch (IOException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| @@ -446,19 +478,9 @@ public class Java extends Task { | |||
| * Executes the given classname with the given arguments in a separate VM. | |||
| */ | |||
| private int run(String[] command) throws BuildException { | |||
| FileOutputStream fos = null; | |||
| try { | |||
| Execute exe = null; | |||
| if (out == null) { | |||
| exe = new Execute(new LogStreamHandler(this, Project.MSG_INFO, | |||
| Project.MSG_WARN), | |||
| createWatchdog()); | |||
| } else { | |||
| fos = new FileOutputStream(out.getAbsolutePath(), append); | |||
| exe = new Execute(new PumpStreamHandler(fos), | |||
| createWatchdog()); | |||
| } | |||
| Execute exe | |||
| = new Execute(redirector.createHandler(), createWatchdog()); | |||
| exe.setAntRun(getProject()); | |||
| if (dir == null) { | |||
| @@ -487,17 +509,11 @@ public class Java extends Task { | |||
| if (exe.killedProcess()) { | |||
| log("Timeout: killed the sub-process", Project.MSG_WARN); | |||
| } | |||
| redirector.complete(); | |||
| return rc; | |||
| } catch (IOException e) { | |||
| throw new BuildException(e, getLocation()); | |||
| } | |||
| } catch (IOException io) { | |||
| throw new BuildException(io, getLocation()); | |||
| } finally { | |||
| if (fos != null) { | |||
| try {fos.close();} catch (IOException io) {} | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| @@ -77,24 +77,15 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||
| private OutputStream err; | |||
| private InputStream input; | |||
| private boolean closeOutOnStop = false; | |||
| private boolean closeErrOnStop = false; | |||
| private boolean closeInputOnStop = false; | |||
| public PumpStreamHandler(OutputStream out, OutputStream err, | |||
| InputStream input, | |||
| boolean closeOutOnStop, boolean closeErrOnStop, | |||
| boolean closeInputOnStop) { | |||
| InputStream input) { | |||
| 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, null, false, false, false); | |||
| this(out, err, null); | |||
| } | |||
| public PumpStreamHandler(OutputStream outAndErr) { | |||
| @@ -151,29 +142,18 @@ public class PumpStreamHandler implements ExecuteStreamHandler { | |||
| 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) { | |||
| // ignore | |||
| } | |||
| try { | |||
| out.flush(); | |||
| if (closeOutOnStop) { | |||
| out.close(); | |||
| } | |||
| } catch (IOException e) { | |||
| // ignore | |||
| } | |||
| @@ -0,0 +1,344 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import java.io.BufferedReader; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.io.ByteArrayInputStream; | |||
| 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 java.io.PrintStream; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.util.StringUtils; | |||
| import org.apache.tools.ant.util.TeeOutputStream; | |||
| /** | |||
| * The Redirector class manages the setup and connection of | |||
| * input and output redirection for an Ant task. | |||
| * | |||
| * @author Conor MacNeill | |||
| * @since Ant 1.6 | |||
| */ | |||
| public class Redirector { | |||
| private File out; | |||
| private File error; | |||
| private File input; | |||
| private boolean logError = false; | |||
| private ByteArrayOutputStream baos = null; | |||
| private ByteArrayOutputStream errorBaos = null; | |||
| private String outputProperty; | |||
| private String errorProperty; | |||
| private String inputString; | |||
| private boolean append = false; | |||
| private Task managingTask; | |||
| private OutputStream outputStream = null; | |||
| private OutputStream errorStream = null; | |||
| private InputStream inputStream = null; | |||
| private PrintStream outPrintStream = null; | |||
| private PrintStream errorPrintStream = null; | |||
| public Redirector(Task managingTask) { | |||
| this.managingTask = managingTask; | |||
| } | |||
| /** | |||
| * Set the input to use for the task | |||
| */ | |||
| public void setInput(File input) { | |||
| this.input = input; | |||
| } | |||
| public void setInputString(String inputString) { | |||
| this.inputString = inputString; | |||
| } | |||
| /** | |||
| * File the output of the process is redirected to. If error is not | |||
| * redirected, it too will appear in the output | |||
| */ | |||
| public void setOutput(File out) { | |||
| this.out = out; | |||
| } | |||
| /** | |||
| * Controls whether error output of exec is logged. This is only useful | |||
| * when output is being redirected and error output is desired in the | |||
| * Ant log | |||
| */ | |||
| public void setLogError(boolean logError) { | |||
| this.logError = logError; | |||
| } | |||
| /** | |||
| * File the error stream of the process is redirected to. | |||
| * | |||
| */ | |||
| public void setError(File error) { | |||
| this.error = error; | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the output of | |||
| * the process. | |||
| */ | |||
| public void setOutputProperty(String outputProperty) { | |||
| this.outputProperty = outputProperty; | |||
| } | |||
| /** | |||
| * Whether output should be appended to or overwrite an existing file. | |||
| * Defaults to false. | |||
| * | |||
| */ | |||
| public void setAppend(boolean append) { | |||
| this.append = append; | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the error of | |||
| * the process. | |||
| * | |||
| */ | |||
| public void setErrorProperty(String errorProperty) { | |||
| this.errorProperty = errorProperty; | |||
| } | |||
| private void setPropertyFromBAOS(ByteArrayOutputStream baos, | |||
| String propertyName) throws IOException { | |||
| BufferedReader in = | |||
| new BufferedReader(new StringReader(Execute.toString(baos))); | |||
| String line = null; | |||
| StringBuffer val = new StringBuffer(); | |||
| while ((line = in.readLine()) != null) { | |||
| if (val.length() != 0) { | |||
| val.append(StringUtils.LINE_SEP); | |||
| } | |||
| val.append(line); | |||
| } | |||
| managingTask.getProject().setNewProperty(propertyName, val.toString()); | |||
| } | |||
| public void createStreams() { | |||
| if (out == null && outputProperty == null) { | |||
| outputStream = new LogOutputStream(managingTask, Project.MSG_INFO); | |||
| errorStream = new LogOutputStream(managingTask, Project.MSG_WARN); | |||
| } else { | |||
| if (out != null) { | |||
| try { | |||
| outputStream | |||
| = new FileOutputStream(out.getAbsolutePath(), append); | |||
| managingTask.log("Output redirected to " + out, | |||
| Project.MSG_VERBOSE); | |||
| } catch (FileNotFoundException fne) { | |||
| throw new BuildException("Cannot write to " + out, fne); | |||
| } catch (IOException ioe) { | |||
| throw new BuildException("Cannot write to " + out, ioe); | |||
| } | |||
| } | |||
| if (outputProperty != null) { | |||
| baos = new ByteArrayOutputStream(); | |||
| managingTask.log("Output redirected to property: " | |||
| + outputProperty, Project.MSG_VERBOSE); | |||
| if (out == null) { | |||
| outputStream = baos; | |||
| } else { | |||
| outputStream = new TeeOutputStream(outputStream, baos); | |||
| } | |||
| } else { | |||
| baos = null; | |||
| } | |||
| errorStream = outputStream; | |||
| } | |||
| if (logError) { | |||
| errorStream = new LogOutputStream(managingTask, Project.MSG_WARN); | |||
| } | |||
| if (error != null) { | |||
| try { | |||
| errorStream | |||
| = new FileOutputStream(error.getAbsolutePath(), append); | |||
| managingTask.log("Error redirected to " + error, | |||
| Project.MSG_VERBOSE); | |||
| } catch (FileNotFoundException fne) { | |||
| throw new BuildException("Cannot write to " + error, fne); | |||
| } catch (IOException ioe) { | |||
| throw new BuildException("Cannot write to " + error, ioe); | |||
| } | |||
| } | |||
| if (errorProperty != null) { | |||
| errorBaos = new ByteArrayOutputStream(); | |||
| managingTask.log("Error redirected to property: " + errorProperty, | |||
| Project.MSG_VERBOSE); | |||
| if (error == null) { | |||
| errorStream = errorBaos; | |||
| } else { | |||
| errorStream = new TeeOutputStream(errorStream, errorBaos); | |||
| } | |||
| } else { | |||
| errorBaos = null; | |||
| } | |||
| if (input != null && inputString != null) { | |||
| throw new BuildException("The \"input\" and \"inputstring\" " | |||
| + "attributes cannot both be specified"); | |||
| } | |||
| if (input != null) { | |||
| try { | |||
| inputStream = new FileInputStream(input); | |||
| } catch (FileNotFoundException fne) { | |||
| throw new BuildException("Cannot read from " + input, fne); | |||
| } | |||
| } else if (inputString != null) { | |||
| inputStream = new ByteArrayInputStream(inputString.getBytes()); | |||
| } | |||
| } | |||
| /** | |||
| * Create the StreamHandler to use with our Execute instance. | |||
| */ | |||
| public ExecuteStreamHandler createHandler() throws BuildException { | |||
| createStreams(); | |||
| return new PumpStreamHandler(outputStream, errorStream, inputStream); | |||
| } | |||
| /** | |||
| * Pass output sent to System.out to specified output file. | |||
| * | |||
| */ | |||
| protected void handleOutput(String line) { | |||
| if (outPrintStream == null) { | |||
| outPrintStream = new PrintStream(outputStream); | |||
| } | |||
| outPrintStream.println(line); | |||
| } | |||
| /** | |||
| * Pass output sent to System.out to specified output file. | |||
| * | |||
| */ | |||
| protected void handleFlush(String line) { | |||
| if (outPrintStream == null) { | |||
| outPrintStream = new PrintStream(outputStream); | |||
| } | |||
| outPrintStream.print(line); | |||
| } | |||
| /** | |||
| * Pass output sent to System.err to specified output file. | |||
| * | |||
| */ | |||
| protected void handleErrorOutput(String line) { | |||
| if (errorPrintStream == null) { | |||
| errorPrintStream = new PrintStream(errorStream); | |||
| } | |||
| errorPrintStream.println(line); | |||
| } | |||
| /** | |||
| * Pass output sent to System.err to specified output file. | |||
| * | |||
| */ | |||
| protected void handleErrorFlush(String line) { | |||
| if (errorPrintStream == null) { | |||
| errorPrintStream = new PrintStream(errorStream); | |||
| } | |||
| errorPrintStream.print(line); | |||
| } | |||
| public OutputStream getOutputStream() { | |||
| return outputStream; | |||
| } | |||
| public OutputStream getErrorStream() { | |||
| return errorStream; | |||
| } | |||
| public void complete() throws IOException { | |||
| System.out.flush(); | |||
| System.err.flush(); | |||
| if (inputStream != null) { | |||
| inputStream.close(); | |||
| } | |||
| outputStream.close(); | |||
| errorStream.close(); | |||
| if (baos != null) { | |||
| setPropertyFromBAOS(baos, outputProperty); | |||
| } | |||
| if (errorBaos != null) { | |||
| setPropertyFromBAOS(errorBaos, errorProperty); | |||
| } | |||
| } | |||
| } | |||