Package org.apache.tools.ant.taskdefs

Source Code of org.apache.tools.ant.taskdefs.Redirector

/*
* Copyright  2003-2004 The Apache Software Foundation
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/
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.FileInputStream;
import java.io.FileNotFoundException;
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.LazyFileOutputStream;
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 {
    /**
     * The file receiving standard output. Will also receive standard error
     * unless standard error is redirected or logError is true.
     */
    private File out;

    /**
     * The file to which standard error is being redirected
     */
    private File error;

    /**
     * The file from which standard input is being taken.
     */
    private File input;

    /**
      * Indicates if standard error should be logged to Ant's log system
      * rather than the output. This has no effect if standard error is
      * redirected to a file or property.
      */
    private boolean logError = false;

    /**
     * Buffer used to capture output for storage into a property
     */
    private ByteArrayOutputStream baos = null;

    /**
     * Buffer used to capture error output for storage into a property
     */
    private ByteArrayOutputStream errorBaos = null;

    /** The name of the property into which output is to be stored */
    private String outputProperty;

    /** The name of the property into which error output is to be stored */
    private String errorProperty;

    /** String from which input is taken */
    private String inputString;

    /** Flag which indicates if error and output files are to be appended. */
    private boolean append = false;

    /** The task for which this redirector is working */
    private Task managingTask;

    /** The stream for output data */
    private OutputStream outputStream = null;

    /** The stream for error output */
    private OutputStream errorStream = null;

    /** The stream for input */
    private InputStream inputStream = null;

    /** Stream which are used for line oriented output */
    private PrintStream outPrintStream = null;

    /** Stream which is used for line oriented error output */
    private PrintStream errorPrintStream = null;

    /**
     * Create a redirector instance for the given task
     *
     * @param managingTask the task for which the redirector is to work
     */
    public Redirector(Task managingTask) {
        this.managingTask = managingTask;
    }

    /**
     * Set the input to use for the task
     *
     * @param input the file from which input is read.
     */
    public void setInput(File input) {
        this.input = input;
    }

    /**
     * Set the string to use as input
     *
     * @param inputString the string which is used as the input source
     */
    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
     *
     * @param out the file to which output stream is written
     */
    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
     *
     * @param logError if true the standard error is sent to the Ant log system
     *        and not sent to output.
     */
    public void setLogError(boolean logError) {
        this.logError = logError;
    }

    /**
     * Set the file to which standard error is to be redirected.
     *
     * @param error the file to which error is to be written
     */
    public void setError(File error) {
        this.error = error;
    }

    /**
     * Property name whose value should be set to the output of
     * the process.
     *
     * @param outputProperty the name of the property to be set with the
     *        task's output.
     */
    public void setOutputProperty(String outputProperty) {
        this.outputProperty = outputProperty;
    }

    /**
     * Whether output should be appended to or overwrite an existing file.
     * Defaults to false.
     *
     * @param append if true output and error streams are appended to their
     *        respective files, if specified.
     */
    public void setAppend(boolean append) {
        this.append = append;
    }

    /**
     * Property name whose value should be set to the error of
     * the process.
     *
     * @param errorProperty the name of the property to be set
     *        with the error output.
     */
    public void setErrorProperty(String errorProperty) {
        this.errorProperty = errorProperty;
    }

    /**
     * Set a property from a ByteArrayOutputStream
     *
     * @param baos contains the property value.
     * @param propertyName the property name.
     *
     * @exception IOException if the value cannot be read form the stream.
     */
    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());
    }


    /**
     * Create the input, error and output streams based on the
     * configuration options.
     */
    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)  {
                outputStream = new LazyFileOutputStream(out, append);
                managingTask.log("Output redirected to " + out,
                                 Project.MSG_VERBOSE);
            }

            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)  {
            errorStream = new LazyFileOutputStream(error, append);
            managingTask.log("Error redirected to " + error,
                             Project.MSG_VERBOSE);
        }

        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.
     *
     * @return the execute stream handler to manage the input, output and
     * error streams.
     *
     * @throws BuildException if the execute stream handler cannot be created.
     */
    public ExecuteStreamHandler createHandler() throws BuildException {
        createStreams();
        return new PumpStreamHandler(outputStream, errorStream, inputStream);
    }

    /**
     * Pass output sent to System.out to specified output.
     *
     * @param output the data to be output
     */
    protected void handleOutput(String output) {
        if (outPrintStream == null) {
            outPrintStream = new PrintStream(outputStream);
        }
        outPrintStream.print(output);
    }

    /**
     * Handle an input request
     *
     * @param buffer the buffer into which data is to be read.
     * @param offset the offset into the buffer at which data is stored.
     * @param length the amount of data to read
     *
     * @return the number of bytes read
     *
     * @exception IOException if the data cannot be read
     */
    protected int handleInput(byte[] buffer, int offset, int length)
        throws IOException {
        if (inputStream == null) {
            return managingTask.getProject().defaultInput(buffer, offset,
                                                          length);
        } else {
            return inputStream.read(buffer, offset, length);
        }
    }

    /**
     * Process data due to a flush operation.
     *
     * @param output the data being flushed.
     */
    protected void handleFlush(String output) {
        if (outPrintStream == null) {
            outPrintStream = new PrintStream(outputStream);
        }
        outPrintStream.print(output);
        outPrintStream.flush();
    }

    /**
     * Process error output
     *
     * @param output the error output data.
     */
    protected void handleErrorOutput(String output) {
        if (errorPrintStream == null) {
            errorPrintStream = new PrintStream(errorStream);
        }
        errorPrintStream.print(output);
    }

    /**
     * Handle a flush operation on the error stream
     *
     * @param output the error information being flushed.
     */
    protected void handleErrorFlush(String output) {
        if (errorPrintStream == null) {
            errorPrintStream = new PrintStream(errorStream);
        }
        errorPrintStream.print(output);
    }

    /**
     * Get the output stream for the redirector
     *
     * @return the redirector's output stream or null if no output
     *         has been configured
     */
    public OutputStream getOutputStream() {
        return outputStream;
    }

    /**
     * Get the error stream for the redirector
     *
     * @return the redirector's error stream or null if no output
     *         has been configured
     */
    public OutputStream getErrorStream() {
        return errorStream;
    }

    /**
     * Get the input stream for the redirector
     *
     * @return the redirector's input stream or null if no output
     *         has been configured
     */
    public InputStream getInputStream() {
        return inputStream;
    }

    /**
     * Complete redirection.
     *
     * This operation will close any streams and create any specified
     * property values.
     *
     * @throws IOException if the output properties cannot be read from their
     * output streams.
     */
    public void complete() throws IOException {
        System.out.flush();
        System.err.flush();

        if (inputStream != null) {
            inputStream.close();
        }

        if (outputStream instanceof LazyFileOutputStream) {
            ((LazyFileOutputStream) outputStream).open();
        }
        outputStream.close();

        if (errorStream != outputStream) {
            if (errorStream instanceof LazyFileOutputStream) {
                ((LazyFileOutputStream) errorStream).open();
            }
            errorStream.close();
        }

        if (baos != null) {
            setPropertyFromBAOS(baos, outputProperty);
        }
        if (errorBaos != null) {
            setPropertyFromBAOS(errorBaos, errorProperty);
        }
    }
}
TOP

Related Classes of org.apache.tools.ant.taskdefs.Redirector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.