ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From co...@apache.org
Subject cvs commit: jakarta-ant/src/main/org/apache/tools/ant/util TeeOutputStream.java
Date Thu, 06 Feb 2003 12:53:49 GMT
conor       2003/02/06 04:53:49

  Modified:    .        WHATSNEW
               docs/manual/CoreTasks exec.html
               src/main/org/apache/tools/ant/taskdefs ExecTask.java
                        PumpStreamHandler.java
  Added:       src/main/org/apache/tools/ant/util TeeOutputStream.java
  Log:
  Allow <exec>'s error and output streams to be redirected independently
  
  This is primarily to address bug 7330 but it includes a few other changes.
  
  You can now use both output and outputproperty. While it was not documented,
  previously, these used to be mutually exclusive. A simple TeeOutptuStream
  is used to write the value to both a property and a file, if required.
  
  The LogStreamHandler is no longer used by Exec. The main thing it did over
  the PumpStreamHandler was to close the output streams when the stream
  handler's stop method was called. This needed to be done in the
  PumpStreamHandler in any case or the output file would be left open.
  The PumpStreamHandler can now close its streams on stop() although the
  default is still to leave them open
  
  There are new attributes "error" and "errorProperty" which if present
  separate output and error streams. If not present the current
  behaviour is unchanged.
  
  PR:	7330
  
  Revision  Changes    Path
  1.355     +3 -0      jakarta-ant/WHATSNEW
  
  Index: WHATSNEW
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/WHATSNEW,v
  retrieving revision 1.354
  retrieving revision 1.355
  diff -u -w -u -r1.354 -r1.355
  --- WHATSNEW	6 Feb 2003 11:50:45 -0000	1.354
  +++ WHATSNEW	6 Feb 2003 12:53:48 -0000	1.355
  @@ -122,6 +122,9 @@
   
   * splash screen wouldn't disppear when build was finished.
   
  +* <exec> output and error streams can now be redirected independently to either
  +  a property or a file (or both)
  +
   Other changes:
   --------------
   * The filesetmanifest attribute of <jar> has been reenabled.
  
  
  
  1.22      +17 -3     jakarta-ant/docs/manual/CoreTasks/exec.html
  
  Index: exec.html
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/docs/manual/CoreTasks/exec.html,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -w -u -r1.21 -r1.22
  --- exec.html	1 Feb 2003 14:21:27 -0000	1.21
  +++ exec.html	6 Feb 2003 12:53:49 -0000	1.22
  @@ -54,18 +54,32 @@
     <tr>
       <td valign="top">output</td>
       <td valign="top">the file to which the output of the command should be
  +      redirected. If the error stream is not also redirected to a file
  +      or poerperty, it will appear in the 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>
       <td align="center" valign="top">No</td>
     </tr>
     <tr>
       <td valign="top">append</td>
  -    <td valign="top">whether output should be appended to or overwrite
  -    an existing file.  Defaults to false.</td>
  +    <td valign="top">whether output and error files should be appended to or overwritten.
  +    Defaults to false.</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>
  +    <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 align="center" valign="top">No</td>
     </tr>
  
  
  
  1.46      +109 -31   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.45
  retrieving revision 1.46
  diff -u -w -u -r1.45 -r1.46
  --- ExecTask.java	28 Jan 2003 11:44:31 -0000	1.45
  +++ ExecTask.java	6 Feb 2003 12:53:49 -0000	1.46
  @@ -61,6 +61,7 @@
   import java.io.FileOutputStream;
   import java.io.IOException;
   import java.io.StringReader;
  +import java.io.OutputStream;
   import org.apache.tools.ant.BuildException;
   import org.apache.tools.ant.Project;
   import org.apache.tools.ant.Task;
  @@ -68,6 +69,7 @@
   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.
  @@ -86,6 +88,8 @@
   
       private String os;
       private File out;
  +    private File error;
  +    
       private File dir;
       protected boolean failOnError = false;
       protected boolean newEnvironment = false;
  @@ -94,7 +98,9 @@
       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;
  @@ -160,13 +166,23 @@
       }
   
       /**
  -     * File the output of the process is redirected to.
  +     * 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;
       }
   
       /**
  +     * File the error stream of the process is redirected to.
  +     *
  +     * @since ant 1.6
  +     */
  +    public void setError(File error) {
  +        this.error = error;
  +    }
  +
  +    /**
        * Property name whose value should be set to the output of
        * the process.
        */
  @@ -175,6 +191,16 @@
       }
   
       /**
  +     * Property name whose value should be set to the error of
  +     * the process.
  +     *
  +     * @since ant 1.6
  +     */
  +    public void setErrorProperty(String errorProperty) {
  +        this.errorProperty = errorProperty;
  +    }
  +
  +    /**
        * Fail if the command exits with a non-zero return code.
        */
       public void setFailonerror(boolean fail) {
  @@ -363,39 +389,48 @@
           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).
        */
       protected final void runExecute(Execute exe) throws IOException {
  -        int err = -1; // assume the worst
  +        int returnCode = -1; // assume the worst
   
  -        err = exe.execute();
  +        returnCode = exe.execute();
           //test for and handle a forced process death
           if (exe.killedProcess()) {
               log("Timeout: killed the sub-process", Project.MSG_WARN);
           }
  -        maybeSetResultPropertyValue(err);
  -        if (err != 0) {
  +        maybeSetResultPropertyValue(returnCode);
  +        if (returnCode != 0) {
               if (failOnError) {
  -                throw new BuildException(getTaskType() + " returned: " + err,
  -                                         getLocation());
  +                throw new BuildException(getTaskType() + " returned: " 
  +                    + returnCode, getLocation());
               } else {
  -                log("Result: " + err, Project.MSG_ERR);
  +                log("Result: " + returnCode, Project.MSG_ERR);
               }
           }
           if (baos != null) {
  -            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);
  +            setPropertyFromBAOS(baos, outputprop);
                   }
  -                val.append(line);
  -            }
  -            getProject().setNewProperty(outputprop, val.toString());
  +        if (errorBaos != null) {
  +            setPropertyFromBAOS(errorBaos, errorProperty);
           }
       }
   
  @@ -427,11 +462,18 @@
        * Create the StreamHandler to use with our Execute instance.
        */
       protected ExecuteStreamHandler createHandler() throws BuildException {
  +        OutputStream outputStream = null;
  +        OutputStream errorStream = 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 {
  -                fos = new FileOutputStream(out.getAbsolutePath(), append);
  +                    outputStream 
  +                        = new FileOutputStream(out.getAbsolutePath(), append);
                   log("Output redirected to " + out, Project.MSG_VERBOSE);
  -                return new PumpStreamHandler(fos);
               } catch (FileNotFoundException fne) {
                   throw new BuildException("Cannot write to " + out, fne,
                                            getLocation());
  @@ -439,14 +481,50 @@
                   throw new BuildException("Cannot write to " + out, ioe,
                                            getLocation());
               }
  -        } else if (outputprop != null) {
  +            }
  +        
  +            if (outputprop != null) {
               baos = new ByteArrayOutputStream();
               log("Output redirected to ByteArray", Project.MSG_VERBOSE);
  -            return new PumpStreamHandler(baos);
  +                if (out == null) {
  +                    outputStream = baos;
  +                } else {
  +                    outputStream = new TeeOutputStream(outputStream, baos);
  +                }
  +            } else {
  +                baos = null;
  +            }
  +            
  +            errorStream = outputStream;
  +        } 
  +
  +        if (error != null)  {
  +            try {
  +                errorStream 
  +                    = new FileOutputStream(error.getAbsolutePath(), append);
  +                log("Error redirected to " + out, 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 ByteArray", Project.MSG_VERBOSE);
  +            if (error == null) {
  +                errorStream = errorBaos;
           } else {
  -            return new LogStreamHandler(this,
  -                                        Project.MSG_INFO, Project.MSG_WARN);
  +                errorStream = new TeeOutputStream(errorStream, errorBaos);
           }
  +        } else {
  +            errorBaos = null;
  +        }
  +        
  +        return new PumpStreamHandler(outputStream, errorStream, true, true);         
       }
   
       /**
  
  
  
  1.8       +18 -2     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.7
  retrieving revision 1.8
  diff -u -w -u -r1.7 -r1.8
  --- PumpStreamHandler.java	25 Jul 2002 15:21:05 -0000	1.7
  +++ PumpStreamHandler.java	6 Feb 2003 12:53:49 -0000	1.8
  @@ -72,11 +72,21 @@
       private Thread inputThread;
       private Thread errorThread;
   
  -    private OutputStream out, err;
  +    private OutputStream out;
  +    private OutputStream err;
  +    private boolean closeOutOnStop = false;
  +    private boolean closeErrOnStop = false;
   
  -    public PumpStreamHandler(OutputStream out, OutputStream err) {
  +    public PumpStreamHandler(OutputStream out, OutputStream err, 
  +                             boolean closeOutOnStop, boolean closeErrOnStop) {
           this.out = out;
           this.err = err;
  +        this.closeOutOnStop = closeOutOnStop;
  +        this.closeErrOnStop = closeErrOnStop;
  +    }
  +
  +    public PumpStreamHandler(OutputStream out, OutputStream err) {
  +        this(out, err, false, false);
       }
   
       public PumpStreamHandler(OutputStream outAndErr) {
  @@ -116,9 +126,15 @@
           } catch (InterruptedException e) {}
           try {
               err.flush();
  +            if (closeErrOnStop) {
  +                err.close();
  +            }
           } catch (IOException e) {}
           try {
               out.flush();
  +            if (closeOutOnStop) {
  +                out.close();
  +            }
           } catch (IOException e) {}
       }
   
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/util/TeeOutputStream.java
  
  Index: TeeOutputStream.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 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.util;
  
  import java.io.OutputStream;
  import java.io.IOException;
  
  /**
   * A simple T-piece to replicate an output stream into two separate streams
   *
   * @author Conor MacNeill
   */
  public class TeeOutputStream extends OutputStream {
      private OutputStream left;
      private OutputStream right;
      
      public TeeOutputStream(OutputStream left, OutputStream right) {
          this.left = left;
          this.right = right;
      }
      
      public void close() throws IOException {
          left.close();
          right.close();
      }
      
      public void flush() throws IOException {
          left.flush();
          right.flush();
      }
  
      public void write(byte[] b) throws IOException {
          left.write(b);
          right.write(b);
      }
      
      public void write(byte[] b, int off, int len) throws IOException {
          left.write(b, off, len);
          right.write(b, off, len);
      }
      
      public void write(int b) throws IOException {
          left.write(b);
          right.write(b);
      }
  }
  
  
  
  

Mime
View raw message