git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276889 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -77,13 +77,15 @@ Other changes: | |||
| * Enable to choose the regexp implementation without system property. | |||
| Bugzilla Report 15390. | |||
| * Expose objects and methods in IntrospectionHelper. Bugzilla Report 30794. | |||
| * Expose objects and methods in IntrospectionHelper. Bugzilla Report 30794. | |||
| * Allow file attribute of <move> to rename a directory. | |||
| Bugzilla Report 22863. | |||
| * Add xmlcatalog nested element to XmlProperty. Bugzilla report 27053. | |||
| * New attribute alwayslog for <redirector> type. | |||
| Fixed bugs: | |||
| ----------- | |||
| @@ -27,62 +27,66 @@ source (input) and destination (output/error) files. <em>Since Ant 1.6.2</em> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">output</td> | |||
| <td valign="top">Name of a file to which to write the output. If the error stream | |||
| is not also redirected to a file or property, it will appear in this output.</td> | |||
| <td valign="top">Name of a file to which output should be written. | |||
| If the error stream is not also redirected to a file or property, | |||
| it will appear in this output.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">error</td> | |||
| <td valign="top">The file to which the standard error of the | |||
| command should be redirected.</td> | |||
| command should be redirected.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">logError</td> | |||
| <td valign="top">This attribute is used when you wish to see error output in Ant's | |||
| log and you are redirecting output to a file/property. The error | |||
| output will not be included in the output file/property. If you | |||
| redirect error with the <i>error</i> or <i>errorProperty</i> | |||
| attributes, this will have no effect.</td> | |||
| <td valign="top">This attribute is used when you wish to see | |||
| error output in Ant's log and you are redirecting output to | |||
| a file/property. The error output will not be included in | |||
| the output file/property. If you redirect error with the | |||
| <i>error</i> or <i>errorProperty</i> attributes, this will | |||
| have no effect.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">append</td> | |||
| <td valign="top">Whether output and error files should be appended to or overwritten. | |||
| Defaults to <code>false</code>.</td> | |||
| <td valign="top">Whether output and error files should be | |||
| appended to rather than overwritten. Defaults to | |||
| <code>false</code>.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">createemptyfiles</td> | |||
| <td valign="top">Whether output and error files should be created even when empty. | |||
| Defaults to <code>true</code>.</td> | |||
| <td valign="top">Whether output and error files should be | |||
| created even when empty. Defaults to <code>true</code>.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">outputproperty</td> | |||
| <td valign="top">The name of a property in which the output of the | |||
| command should be stored. Unless the error stream is redirected to a separate | |||
| file or stream, this property will include the error output.</td> | |||
| command should be stored. Unless the error stream is redirected | |||
| to a separate file or stream, this property will include the | |||
| error output.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">errorproperty</td> | |||
| <td valign="top">The name of a property in which the standard error of the | |||
| command should be stored.</td> | |||
| <td valign="top">The name of a property in which the standard error | |||
| of the command should be stored.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">input</td> | |||
| <td valign="top">A file from which the executed command's standard input | |||
| is taken. This attribute is mutually exclusive with the | |||
| <i>inputstring</i> attribute.</td> | |||
| is taken. This attribute is mutually exclusive with the | |||
| <i>inputstring</i> attribute.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">inputstring</td> | |||
| <td valign="top">A string which serves as the input stream for the | |||
| executed command. This attribute is mutually exclusive with the | |||
| <i>input</i> attribute.</td> | |||
| executed command. This attribute is mutually exclusive with the | |||
| <i>input</i> attribute.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| @@ -100,6 +104,14 @@ source (input) and destination (output/error) files. <em>Since Ant 1.6.2</em> | |||
| <td valign="top">The error encoding.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">alwayslog</td> | |||
| <td valign="top">Always send to the log in addition to | |||
| any other destination. Default <code>false</code>. | |||
| <i>Since Ant 1.6.3</i>. | |||
| </td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <h3>Parameters specified as nested elements</h3> | |||
| <h4>inputmapper</h4> | |||
| @@ -122,13 +134,13 @@ consult the documentation of the individual task for more details. | |||
| A nested <errormapper> is not compatible with the | |||
| <i>error</i> attribute.</p> | |||
| <h4>inputfilterchain</h4> | |||
| <p>One or more <a href="./filterchain.html">FilterChain</a>s can be | |||
| <p>A <a href="./filterchain.html">FilterChain</a> can be | |||
| applied to the process input.</p> | |||
| <h4>outputfilterchain</h4> | |||
| <p>One or more <a href="./filterchain.html">FilterChain</a>s can be | |||
| <p>A <a href="./filterchain.html">FilterChain</a> can be | |||
| applied to the process output.</p> | |||
| <h4>errorfilterchain</h4> | |||
| <p>One or more <a href="./filterchain.html">FilterChain</a>s can be | |||
| <p>A <a href="./filterchain.html">FilterChain</a> can be | |||
| applied to the error output.</p> | |||
| <h3>Usage</h3> | |||
| Tasks known to support I/O redirection: | |||
| @@ -313,6 +313,22 @@ | |||
| <fail if="17fail">Files were created.</fail> | |||
| </target> | |||
| <target name="redirector18" depends="init" if="test.can.run"> | |||
| <exec executable="sh"> | |||
| <arg value="parrot.sh"/> | |||
| <arg value="${ant.file}" /> | |||
| <redirector alwayslog="true" logerror="true" | |||
| outputproperty="redirector.out" /> | |||
| </exec> | |||
| <fail message="property redirector.out has unexpected content"> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${ant.file} out" arg2="${redirector.out}" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="cleanup"> | |||
| <delete> | |||
| <fileset file="${logFile}" /> | |||
| @@ -122,6 +122,9 @@ public class Redirector { | |||
| /** Flag which indicates if error and output files are to be appended. */ | |||
| private boolean append = false; | |||
| /** Flag which indicates that output should be always sent to the log */ | |||
| private boolean alwaysLog = false; | |||
| /** Flag which indicates whether files should be created even when empty. */ | |||
| private boolean createEmptyFiles = true; | |||
| @@ -333,12 +336,23 @@ public class Redirector { | |||
| this.append = append; | |||
| } | |||
| /** | |||
| * If true, (error and non-error) output will be "teed", redirected | |||
| * as specified while being sent to Ant's logging mechanism as if no | |||
| * redirection had taken place. Defaults to false. | |||
| * @param alwaysLog <code>boolean</code> | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public synchronized void setAlwaysLog(boolean alwaysLog) { | |||
| this.alwaysLog = alwaysLog; | |||
| } | |||
| /** | |||
| * Whether output and error files should be created even when empty. | |||
| * Defaults to true. | |||
| * @param createEmptyFiles <CODE>boolean</CODE>. | |||
| */ | |||
| public void setCreateEmptyFiles(boolean createEmptyFiles) { | |||
| public synchronized void setCreateEmptyFiles(boolean createEmptyFiles) { | |||
| this.createEmptyFiles = createEmptyFiles; | |||
| } | |||
| @@ -371,7 +385,7 @@ public class Redirector { | |||
| * | |||
| * @param outputFilterChains <CODE>Vector</CODE> containing <CODE>FilterChain</CODE>. | |||
| */ | |||
| public void setOutputFilterChains(Vector outputFilterChains) { | |||
| public synchronized void setOutputFilterChains(Vector outputFilterChains) { | |||
| this.outputFilterChains = outputFilterChains; | |||
| } | |||
| @@ -380,7 +394,7 @@ public class Redirector { | |||
| * | |||
| * @param errorFilterChains <CODE>Vector</CODE> containing <CODE>FilterChain</CODE>. | |||
| */ | |||
| public void setErrorFilterChains(Vector errorFilterChains) { | |||
| public synchronized void setErrorFilterChains(Vector errorFilterChains) { | |||
| this.errorFilterChains = errorFilterChains; | |||
| } | |||
| @@ -413,35 +427,24 @@ public class Redirector { | |||
| * configuration options. | |||
| */ | |||
| public synchronized void createStreams() { | |||
| if ((out == null || out.length == 0) && outputProperty == null) { | |||
| outputStream = new LogOutputStream(managingTask, Project.MSG_INFO); | |||
| } else { | |||
| if (out != null && out.length > 0) { | |||
| String logHead = new StringBuffer("Output ").append( | |||
| ((append) ? "appended" : "redirected")).append( | |||
| " to ").toString(); | |||
| outputStream = foldFiles(out, logHead, Project.MSG_VERBOSE); | |||
| } | |||
| if (outputProperty != null) { | |||
| if (baos == null) { | |||
| baos = new PropertyOutputStream(outputProperty); | |||
| managingTask.log("Output redirected to property: " | |||
| + outputProperty, Project.MSG_VERBOSE); | |||
| } | |||
| //shield it from being closed by a filtering StreamPumper | |||
| OutputStream keepAliveOutput = new KeepAliveOutputStream(baos); | |||
| if (outputStream == null) { | |||
| outputStream = keepAliveOutput; | |||
| } else { | |||
| outputStream | |||
| = new TeeOutputStream(outputStream, keepAliveOutput); | |||
| } | |||
| } else { | |||
| baos = null; | |||
| if (out != null && out.length > 0) { | |||
| String logHead = new StringBuffer("Output ").append( | |||
| ((append) ? "appended" : "redirected")).append( | |||
| " to ").toString(); | |||
| outputStream = foldFiles(out, logHead, Project.MSG_VERBOSE); | |||
| } | |||
| if (outputProperty != null) { | |||
| if (baos == null) { | |||
| baos = new PropertyOutputStream(outputProperty); | |||
| managingTask.log("Output redirected to property: " | |||
| + outputProperty, Project.MSG_VERBOSE); | |||
| } | |||
| errorStream = outputStream; | |||
| //shield it from being closed by a filtering StreamPumper | |||
| OutputStream keepAliveOutput = new KeepAliveOutputStream(baos); | |||
| outputStream = (outputStream == null) ? keepAliveOutput | |||
| : new TeeOutputStream(outputStream, keepAliveOutput); | |||
| } else { | |||
| baos = null; | |||
| } | |||
| if (error != null && error.length > 0) { | |||
| @@ -449,10 +452,7 @@ public class Redirector { | |||
| ((append) ? "appended" : "redirected")).append( | |||
| " to ").toString(); | |||
| errorStream = foldFiles(error, logHead, Project.MSG_VERBOSE); | |||
| } else if (logError || errorStream == null) { | |||
| errorStream = new LogOutputStream(managingTask, Project.MSG_WARN); | |||
| } else { //must be errorStream == outputStream | |||
| } else if (!(logError || outputStream == null)) { | |||
| long funnelTimeout = 0L; | |||
| OutputStreamFunneler funneler | |||
| = new OutputStreamFunneler(outputStream, funnelTimeout); | |||
| @@ -464,7 +464,6 @@ public class Redirector { | |||
| "error splitting output/error streams", eyeOhEx); | |||
| } | |||
| } | |||
| if (errorProperty != null) { | |||
| if (errorBaos == null) { | |||
| errorBaos = new PropertyOutputStream(errorProperty); | |||
| @@ -478,7 +477,18 @@ public class Redirector { | |||
| } else { | |||
| errorBaos = null; | |||
| } | |||
| if (alwaysLog || outputStream == null) { | |||
| OutputStream outputLog | |||
| = new LogOutputStream(managingTask, Project.MSG_INFO); | |||
| outputStream = (outputStream == null) | |||
| ? outputLog : new TeeOutputStream(outputLog, outputStream); | |||
| } | |||
| if (alwaysLog || errorStream == null) { | |||
| OutputStream errorLog | |||
| = new LogOutputStream(managingTask, Project.MSG_WARN); | |||
| errorStream = (errorStream == null) | |||
| ? errorLog : new TeeOutputStream(errorLog, errorStream); | |||
| } | |||
| if ((outputFilterChains != null && outputFilterChains.size() > 0) | |||
| || !(outputEncoding.equalsIgnoreCase(inputEncoding))) { | |||
| try { | |||
| @@ -65,6 +65,9 @@ public class RedirectorElement extends DataType { | |||
| /** Flag which indicates if error and output files are to be appended. */ | |||
| private Boolean append; | |||
| /** Flag which indicates that output should be always sent to the log */ | |||
| private Boolean alwaysLog; | |||
| /** Flag which indicates whether files should be created even if empty. */ | |||
| private Boolean createEmptyFiles; | |||
| @@ -316,6 +319,21 @@ public class RedirectorElement extends DataType { | |||
| this.append = ((append) ? Boolean.TRUE : Boolean.FALSE); | |||
| } | |||
| /** | |||
| * If true, (error and non-error) output will be "teed", redirected | |||
| * as specified while being sent to Ant's logging mechanism as if no | |||
| * redirection had taken place. Defaults to false. | |||
| * @param alwaysLog <code>boolean</code> | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public void setAlwaysLog(boolean alwaysLog) { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| //pre JDK 1.4 compatible | |||
| this.alwaysLog = ((alwaysLog) ? Boolean.TRUE : Boolean.FALSE); | |||
| } | |||
| /** | |||
| * Whether output and error files should be created even when empty. | |||
| * Defaults to true. | |||
| @@ -400,6 +418,9 @@ public class RedirectorElement extends DataType { | |||
| * @param sourcefile <CODE>String</CODE>. | |||
| */ | |||
| public void configure(Redirector redirector, String sourcefile) { | |||
| if (alwaysLog != null) { | |||
| redirector.setAlwaysLog(alwaysLog.booleanValue()); | |||
| } | |||
| if (logError != null) { | |||
| redirector.setLogError(logError.booleanValue()); | |||
| } | |||
| @@ -329,6 +329,14 @@ public class ExecTaskTest extends BuildFileTest { | |||
| executeTarget("redirector17"); | |||
| } | |||
| public void testRedirector18() { | |||
| if (getProject().getProperty("test.can.run") == null) { | |||
| return; | |||
| } | |||
| expectLog("redirector18", getProject().getProperty("ant.file") | |||
| + " out" + getProject().getProperty("ant.file") + " err"); | |||
| } | |||
| public void testspawn() { | |||
| project.executeTarget("init"); | |||
| if (project.getProperty("test.can.run") == null) { | |||