BaseRedirectorHelperTask.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.catalina.ant;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
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.taskdefs.Redirector;
import org.apache.tools.ant.types.RedirectorElement;
/**
* Abstract base class to add output redirection support for Catalina Ant tasks. These tasks require Ant 1.5 or later.
* <br>
* <strong>WARNING:</strong> due to depends chain, Ant could call a Task more than once and this can affect the output
* redirection when configured. If you are collecting the output in a property, it will collect the output of only the
* first run, since Ant properties are immutable and once created they cannot be changed. <br>
* If you are collecting output in a file the file will be overwritten with the output of the last run, unless you set
* append="true", in which case each run will append it's output to the file.
*
* @author Gabriele Garuglieri
*
* @since 5.5
*/
public abstract class BaseRedirectorHelperTask extends Task {
/** Redirector helper */
protected final Redirector redirector = new Redirector(this);
/** Redirector element for this task */
protected RedirectorElement redirectorElement = null;
/** The stream for info output */
protected OutputStream redirectOutStream = null;
/** The stream for error output */
protected OutputStream redirectErrStream = null;
/** The print stream for info output */
PrintStream redirectOutPrintStream = null;
/** The print stream for error output */
PrintStream redirectErrPrintStream = null;
/**
* Whether to fail (with a BuildException) if ManagerServlet returns an error. The default behavior is to do so. <b>
* This flag does not control parameters checking. If the task is called with wrong or invalid parameters, it will
* throw BuildException independently from the setting of this flag. </b>
*/
protected boolean failOnError = true;
/**
* <code>true</code> true when output redirection is requested for this task. Default is to log on Ant log.
*/
protected boolean redirectOutput = false;
/**
* will be set to <code>true</code> when the configuration of the Redirector is complete.
*/
protected boolean redirectorConfigured = false;
/**
* Flag which indicates that, if redirected, output should also be always sent to the log. Default is that output is
* sent only to redirected streams.
*/
protected boolean alwaysLog = false;
/**
* Whether to fail (with a BuildException) if ManagerServlet returns an error. The default behavior is to do so.
*
* @param fail The new value of failonerror
*/
public void setFailonerror(boolean fail) {
failOnError = fail;
}
/**
* Returns the value of the failOnError property.
*
* @return <code>true</code> if the task should will if an error occurs, otherwise <code>false</code>
*/
public boolean isFailOnError() {
return failOnError;
}
/**
* File the output of the task is redirected to.
*
* @param out name of the output file
*/
public void setOutput(File out) {
redirector.setOutput(out);
redirectOutput = true;
}
/**
* File the error output of the task is redirected to.
*
* @param error name of the error file
*/
public void setError(File error) {
redirector.setError(error);
redirectOutput = true;
}
/**
* Controls whether error output 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 stream.
*/
public void setLogError(boolean logError) {
redirector.setLogError(logError);
redirectOutput = true;
}
/**
* Property name whose value should be set to the output of the task.
*
* @param outputProperty property name
*/
public void setOutputproperty(String outputProperty) {
redirector.setOutputProperty(outputProperty);
redirectOutput = true;
}
/**
* Property name whose value should be set to the error of the task.
*
* @param errorProperty property name
*/
public void setErrorProperty(String errorProperty) {
redirector.setErrorProperty(errorProperty);
redirectOutput = true;
}
/**
* If true, append output to existing file.
*
* @param append if true, append output to existing file
*/
public void setAppend(boolean append) {
redirector.setAppend(append);
redirectOutput = true;
}
/**
* If true, (error and non-error) output will be redirected as specified while being sent to Ant's logging mechanism
* as if no redirection had taken place. Defaults to false. <br>
* Actually handled internally, with Ant 1.6.3 it will be handled by the <code>Redirector</code> itself.
*
* @param alwaysLog <code>boolean</code>
*/
public void setAlwaysLog(boolean alwaysLog) {
this.alwaysLog = alwaysLog;
redirectOutput = true;
}
/**
* Whether output and error files should be created even when empty. Defaults to true.
*
* @param createEmptyFiles <CODE>boolean</CODE>.
*/
public void setCreateEmptyFiles(boolean createEmptyFiles) {
redirector.setCreateEmptyFiles(createEmptyFiles);
redirectOutput = true;
}
/**
* Add a <CODE>RedirectorElement</CODE> to this task.
*
* @param redirectorElement <CODE>RedirectorElement</CODE>.
*/
public void addConfiguredRedirector(RedirectorElement redirectorElement) {
if (this.redirectorElement != null) {
throw new BuildException("Cannot have > 1 nested <redirector>s");
} else {
this.redirectorElement = redirectorElement;
}
}
/**
* Set up properties on the Redirector from RedirectorElement if present.
*/
private void configureRedirector() {
if (redirectorElement != null) {
redirectorElement.configure(redirector);
redirectOutput = true;
}
/*
* Due to depends chain, Ant could call the Task more than once, this is to prevent that we attempt to configure
* uselessly more than once the Redirector.
*/
redirectorConfigured = true;
}
/**
* Set up properties on the Redirector and create output streams.
*/
protected void openRedirector() {
if (!redirectorConfigured) {
configureRedirector();
}
if (redirectOutput) {
redirector.createStreams();
redirectOutStream = redirector.getOutputStream();
redirectOutPrintStream = new PrintStream(redirectOutStream);
redirectErrStream = redirector.getErrorStream();
redirectErrPrintStream = new PrintStream(redirectErrStream);
}
}
/**
* Ask redirector to close all the streams. It is necessary to call this method before leaving the Task to have the
* Streams flush their contents. If you are collecting output in a property, it will be created only if this method
* is called, otherwise you'll find it unset.
*/
protected void closeRedirector() {
try {
if (redirectOutput && redirectOutPrintStream != null) {
redirector.complete();
}
} catch (IOException ioe) {
log("Error closing redirector: " + ioe.getMessage(), Project.MSG_ERR);
}
/*
* Due to depends chain, Ant could call the Task more than once, this is to prevent that we attempt to reuse the
* previously closed Streams.
*/
redirectOutStream = null;
redirectOutPrintStream = null;
redirectErrStream = null;
redirectErrPrintStream = null;
}
/**
* Handles output with the INFO priority.
*
* @param output The output to log. Should not be <code>null</code>.
*/
@Override
protected void handleOutput(String output) {
if (redirectOutput) {
if (redirectOutPrintStream == null) {
openRedirector();
}
redirectOutPrintStream.println(output);
if (alwaysLog) {
log(output, Project.MSG_INFO);
}
} else {
log(output, Project.MSG_INFO);
}
}
/**
* Handles output with the INFO priority and flushes the stream.
*
* @param output The output to log. Should not be <code>null</code>.
*/
@Override
protected void handleFlush(String output) {
handleOutput(output);
redirectOutPrintStream.flush();
}
/**
* Handles error output with the ERR priority.
*
* @param output The error output to log. Should not be <code>null</code>.
*/
@Override
protected void handleErrorOutput(String output) {
if (redirectOutput) {
if (redirectErrPrintStream == null) {
openRedirector();
}
redirectErrPrintStream.println(output);
if (alwaysLog) {
log(output, Project.MSG_ERR);
}
} else {
log(output, Project.MSG_ERR);
}
}
/**
* Handles error output with the ERR priority and flushes the stream.
*
* @param output The error output to log. Should not be <code>null</code>.
*/
@Override
protected void handleErrorFlush(String output) {
handleErrorOutput(output);
redirectErrPrintStream.flush();
}
/**
* Handles output with ERR priority to error stream and all other priorities to output stream.
*
* @param output The output to log. Should not be <code>null</code>.
* @param priority The priority level that should be used
*/
protected void handleOutput(String output, int priority) {
if (priority == Project.MSG_ERR) {
handleErrorOutput(output);
} else {
handleOutput(output);
}
}
}