conor 2003/02/08 06:14:27
Modified: src/main/org/apache/tools/ant/taskdefs ExecTask.java Java.java PumpStreamHandler.java Added: src/main/org/apache/tools/ant/taskdefs Redirector.java Log: Refactor output handling from Exec into a new class Redirector and use this in Java task to get access to features such as separate error stream, redirected input, etc. Revision Changes Path 1.49 +23 -146 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java Index: ExecTask.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java,v retrieving revision 1.48 retrieving revision 1.49 diff -u -w -u -r1.48 -r1.49 --- ExecTask.java 7 Feb 2003 13:57:41 -0000 1.48 +++ ExecTask.java 8 Feb 2003 14:14:27 -0000 1.49 @@ -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 @@ 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 @@ 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 @@ -171,18 +152,22 @@ } /** - * Set the input to use for the task + * File the output of the process is redirected to. If error is not + * redirected, it too will appear in the output */ - public void setInput(File input) { - this.input = input; + public void setOutput(File out) { + redirector.setOutput(out); } /** - * File the output of the process is redirected to. If error is not - * redirected, it too will appear in the output + * Set the input to use for the task */ - public void setOutput(File out) { - this.out = out; + public void setInput(File input) { + redirector.setInput(input); + } + + public void setInputString(String inputString) { + redirector.setInputString(inputString); } /** @@ -191,7 +176,7 @@ * Ant log */ public void setLogError(boolean logError) { - this.logError = logError; + redirector.setLogError(logError); } /** @@ -200,15 +185,15 @@ * @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 @@ * @since ant 1.6 */ public void setErrorProperty(String errorProperty) { - this.errorProperty = errorProperty; + redirector.setErrorProperty(errorProperty); } /** @@ -293,7 +278,7 @@ * @since 1.30, Ant 1.5 */ public void setAppend(boolean append) { - this.append = append; + redirector.setAppend(append); } @@ -410,22 +395,6 @@ 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 @@ log("Result: " + returnCode, Project.MSG_ERR); } } - if (baos != null) { - setPropertyFromBAOS(baos, outputprop); - } - if (errorBaos != null) { - setPropertyFromBAOS(errorBaos, errorProperty); - } + redirector.complete(); } /** @@ -483,86 +447,7 @@ * 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 @@ * 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) {} } } 1.53 +70 -54 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Java.java Index: Java.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Java.java,v retrieving revision 1.52 retrieving revision 1.53 diff -u -w -u -r1.52 -r1.53 --- Java.java 31 Jan 2003 07:57:41 -0000 1.52 +++ Java.java 8 Feb 2003 14:14:27 -0000 1.53 @@ -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 @@ 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 @@ * 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 @@ * @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 @@ * @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 @@ * @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 @@ * @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 @@ * was a command line application. */ private void run(CommandlineJava command) throws BuildException { + try { 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 { + redirector.createStreams(); exe.execute(getProject()); + redirector.complete(); + } catch (IOException e) { + throw new BuildException(e); } } @@ -446,19 +478,9 @@ * 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 @@ 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) {} - } - } } /** 1.12 +2 -22 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java Index: PumpStreamHandler.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -w -u -r1.11 -r1.12 --- PumpStreamHandler.java 7 Feb 2003 23:14:12 -0000 1.11 +++ PumpStreamHandler.java 8 Feb 2003 14:14:27 -0000 1.12 @@ -77,24 +77,15 @@ 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 @@ 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 } 1.1 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Redirector.java Index: Redirector.java =================================================================== /* * 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 [EMAIL PROTECTED] * * 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); } } }