diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/RedirectorElement.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/RedirectorElement.java | 630 |
1 files changed, 630 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/RedirectorElement.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/RedirectorElement.java new file mode 100644 index 00000000..d27b199c --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/RedirectorElement.java @@ -0,0 +1,630 @@ +/* + * 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.tools.ant.types; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Stack; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Redirector; + +/** + * Element representation of a <code>Redirector</code>. + * @since Ant 1.6.2 + */ +public class RedirectorElement extends DataType { + + /** + * Whether the input mapper was set via <code>setOutput</code>. + */ + private boolean usingInput = false; + + /** + * Whether the output mapper was set via <code>setOutput</code>. + */ + private boolean usingOutput = false; + + /** + * Whether the error mapper was set via <code>setError</code>. + */ + private boolean usingError = false; + + /** + * 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; + + /** 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; + + /** 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; + + /** Input file mapper. */ + private Mapper inputMapper; + + /** Output file mapper. */ + private Mapper outputMapper; + + /** Error file mapper. */ + private Mapper errorMapper; + + /** input filter chains. */ + private Vector<FilterChain> inputFilterChains = new Vector<FilterChain>(); + + /** output filter chains. */ + private Vector<FilterChain> outputFilterChains = new Vector<FilterChain>(); + + /** error filter chains. */ + private Vector<FilterChain> errorFilterChains = new Vector<FilterChain>(); + + /** The output encoding */ + private String outputEncoding; + + /** The error encoding */ + private String errorEncoding; + + /** The input encoding */ + private String inputEncoding; + + /** whether to log the inputstring */ + private Boolean logInputString; + + /** Is the output binary or can we safely split it into lines? */ + private boolean outputIsBinary = false; + + /** + * Add the input file mapper. + * @param inputMapper <code>Mapper</code>. + */ + public void addConfiguredInputMapper(Mapper inputMapper) { + if (isReference()) { + throw noChildrenAllowed(); + } + if (this.inputMapper != null) { + if (usingInput) { + throw new BuildException("attribute \"input\"" + + " cannot coexist with a nested <inputmapper>"); + } else { + throw new BuildException("Cannot have > 1 <inputmapper>"); + } + } + setChecked(false); + this.inputMapper = inputMapper; + } + + /** + * Add the output file mapper. + * @param outputMapper <code>Mapper</code>. + */ + public void addConfiguredOutputMapper(Mapper outputMapper) { + if (isReference()) { + throw noChildrenAllowed(); + } + if (this.outputMapper != null) { + if (usingOutput) { + throw new BuildException("attribute \"output\"" + + " cannot coexist with a nested <outputmapper>"); + } else { + throw new BuildException("Cannot have > 1 <outputmapper>"); + } + } + setChecked(false); + this.outputMapper = outputMapper; + } + + /** + * Add the error file mapper. + * @param errorMapper <code>Mapper</code>. + */ + public void addConfiguredErrorMapper(Mapper errorMapper) { + if (isReference()) { + throw noChildrenAllowed(); + } + if (this.errorMapper != null) { + if (usingError) { + throw new BuildException("attribute \"error\"" + + " cannot coexist with a nested <errormapper>"); + } else { + throw new BuildException("Cannot have > 1 <errormapper>"); + } + } + setChecked(false); + this.errorMapper = errorMapper; + } + + /** + * Make this instance in effect a reference to another instance. + * + * <p>You must not set another attribute or nest elements inside + * this element if you make it a reference.</p> + * @param r the reference to use. + * @throws BuildException on error. + */ + public void setRefid(Reference r) throws BuildException { + if (usingInput + || usingOutput + || usingError + || inputString != null + || logError != null + || append != null + || createEmptyFiles != null + || inputEncoding != null + || outputEncoding != null + || errorEncoding != null + || outputProperty != null + || errorProperty != null + || logInputString != null) { + throw tooManyAttributes(); + } + super.setRefid(r); + } + + /** + * Set the input to use for the task. + * @param input the file from which input is read. + */ + public void setInput(File input) { + if (isReference()) { + throw tooManyAttributes(); + } + if (inputString != null) { + throw new BuildException("The \"input\" and \"inputstring\" " + + "attributes cannot both be specified"); + } + usingInput = true; + inputMapper = createMergeMapper(input); + } + + /** + * Set the string to use as input + * @param inputString the string which is used as the input source + */ + public void setInputString(String inputString) { + if (isReference()) { + throw tooManyAttributes(); + } + if (usingInput) { + throw new BuildException("The \"input\" and \"inputstring\" " + + "attributes cannot both be specified"); + } + this.inputString = inputString; + } + + /** + * Set whether to include the value of the input string in log messages. + * Defaults to true. + * @param logInputString true or false. + * @since Ant 1.7 + */ + public void setLogInputString(boolean logInputString) { + if (isReference()) { + throw tooManyAttributes(); + } + this.logInputString = logInputString ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * 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) { + if (isReference()) { + throw tooManyAttributes(); + } + if (out == null) { + throw new IllegalArgumentException("output file specified as null"); + } + usingOutput = true; + outputMapper = createMergeMapper(out); + } + + /** + * Set the output encoding. + * @param outputEncoding <code>String</code>. + */ + public void setOutputEncoding(String outputEncoding) { + if (isReference()) { + throw tooManyAttributes(); + } + this.outputEncoding = outputEncoding; + } + + /** + * Set the error encoding. + * + * @param errorEncoding <code>String</code>. + */ + public void setErrorEncoding(String errorEncoding) { + if (isReference()) { + throw tooManyAttributes(); + } + this.errorEncoding = errorEncoding; + } + + /** + * Set the input encoding. + * @param inputEncoding <code>String</code>. + */ + public void setInputEncoding(String inputEncoding) { + if (isReference()) { + throw tooManyAttributes(); + } + this.inputEncoding = inputEncoding; + } + + /** + * 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) { + if (isReference()) { + throw tooManyAttributes(); + } + this.logError = ((logError) ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * 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) { + if (isReference()) { + throw tooManyAttributes(); + } + if (error == null) { + throw new IllegalArgumentException("error file specified as null"); + } + usingError = true; + errorMapper = createMergeMapper(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) { + if (isReference()) { + throw tooManyAttributes(); + } + 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) { + if (isReference()) { + throw tooManyAttributes(); + } + 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(); + } + this.alwaysLog = ((alwaysLog) ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Whether output and error files should be created even when empty. + * Defaults to true. + * @param createEmptyFiles <code>boolean</code>. + */ + public void setCreateEmptyFiles(boolean createEmptyFiles) { + if (isReference()) { + throw tooManyAttributes(); + } + this.createEmptyFiles = ((createEmptyFiles) + ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * 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) { + if (isReference()) { + throw tooManyAttributes(); + } + this.errorProperty = errorProperty; + } + + /** + * Create a nested input <code>FilterChain</code>. + * @return <code>FilterChain</code>. + */ + public FilterChain createInputFilterChain() { + if (isReference()) { + throw noChildrenAllowed(); + } + FilterChain result = new FilterChain(); + result.setProject(getProject()); + inputFilterChains.add(result); + setChecked(false); + return result; + } + + /** + * Create a nested output <code>FilterChain</code>. + * @return <code>FilterChain</code>. + */ + public FilterChain createOutputFilterChain() { + if (isReference()) { + throw noChildrenAllowed(); + } + FilterChain result = new FilterChain(); + result.setProject(getProject()); + outputFilterChains.add(result); + setChecked(false); + return result; + } + + /** + * Create a nested error <code>FilterChain</code>. + * @return <code>FilterChain</code>. + */ + public FilterChain createErrorFilterChain() { + if (isReference()) { + throw noChildrenAllowed(); + } + FilterChain result = new FilterChain(); + result.setProject(getProject()); + errorFilterChains.add(result); + setChecked(false); + return result; + } + + /** + * Whether to consider the output created by the process binary. + * + * <p>Binary output will not be split into lines which may make + * error and normal output look mixed up when they get written to + * the same stream.</p> + * @since 1.9.4 + */ + public void setBinaryOutput(boolean b) { + outputIsBinary = b; + } + + /** + * Configure the specified <code>Redirector</code>. + * @param redirector <code>Redirector</code>. + */ + public void configure(Redirector redirector) { + configure(redirector, null); + } + + /** + * Configure the specified <code>Redirector</code> + * for the specified sourcefile. + * @param redirector <code>Redirector</code>. + * @param sourcefile <code>String</code>. + */ + public void configure(Redirector redirector, String sourcefile) { + if (isReference()) { + getRef().configure(redirector, sourcefile); + return; + } + dieOnCircularReference(); + if (alwaysLog != null) { + redirector.setAlwaysLog(alwaysLog.booleanValue()); + } + if (logError != null) { + redirector.setLogError(logError.booleanValue()); + } + if (append != null) { + redirector.setAppend(append.booleanValue()); + } + if (createEmptyFiles != null) { + redirector.setCreateEmptyFiles(createEmptyFiles.booleanValue()); + } + if (outputProperty != null) { + redirector.setOutputProperty(outputProperty); + } + if (errorProperty != null) { + redirector.setErrorProperty(errorProperty); + } + if (inputString != null) { + redirector.setInputString(inputString); + } + if (logInputString != null) { + redirector.setLogInputString(logInputString.booleanValue()); + } + if (inputMapper != null) { + String[] inputTargets = null; + try { + inputTargets = + inputMapper.getImplementation().mapFileName(sourcefile); + } catch (NullPointerException enPeaEx) { + if (sourcefile != null) { + throw enPeaEx; + } + } + if (inputTargets != null && inputTargets.length > 0) { + redirector.setInput(toFileArray(inputTargets)); + } + } + if (outputMapper != null) { + String[] outputTargets = null; + try { + outputTargets = + outputMapper.getImplementation().mapFileName(sourcefile); + } catch (NullPointerException enPeaEx) { + if (sourcefile != null) { + throw enPeaEx; + } + } + if (outputTargets != null && outputTargets.length > 0) { + redirector.setOutput(toFileArray(outputTargets)); + } + } + if (errorMapper != null) { + String[] errorTargets = null; + try { + errorTargets = + errorMapper.getImplementation().mapFileName(sourcefile); + } catch (NullPointerException enPeaEx) { + if (sourcefile != null) { + throw enPeaEx; + } + } + if (errorTargets != null && errorTargets.length > 0) { + redirector.setError(toFileArray(errorTargets)); + } + } + if (inputFilterChains.size() > 0) { + redirector.setInputFilterChains(inputFilterChains); + } + if (outputFilterChains.size() > 0) { + redirector.setOutputFilterChains(outputFilterChains); + } + if (errorFilterChains.size() > 0) { + redirector.setErrorFilterChains(errorFilterChains); + } + if (inputEncoding != null) { + redirector.setInputEncoding(inputEncoding); + } + if (outputEncoding != null) { + redirector.setOutputEncoding(outputEncoding); + } + if (errorEncoding != null) { + redirector.setErrorEncoding(errorEncoding); + } + redirector.setBinaryOutput(outputIsBinary); + } + + /** + * Create a merge mapper pointing to the specified destination file. + * @param destfile <code>File</code> + * @return <code>Mapper</code>. + */ + protected Mapper createMergeMapper(File destfile) { + Mapper result = new Mapper(getProject()); + result.setClassname( + org.apache.tools.ant.util.MergingMapper.class.getName()); + result.setTo(destfile.getAbsolutePath()); + return result; + } + + /** + * Return a <code>File[]</code> from the specified set of filenames. + * @param name <code>String[]</code> + * @return <code>File[]</code>. + */ + protected File[] toFileArray(String[] name) { + if (name == null) { + return null; + } + //remove any null elements + ArrayList<File> list = new ArrayList<File>(name.length); + for (int i = 0; i < name.length; i++) { + if (name[i] != null) { + list.add(getProject().resolveFile(name[i])); + } + } + return (File[]) (list.toArray(new File[list.size()])); + } + + /** + * Overrides the version of DataType to recurse on all DataType + * child elements that may have been added. + * @param stk the stack of data types to use (recursively). + * @param p the project to use to dereference the references. + * @throws BuildException on error. + */ + protected void dieOnCircularReference(Stack<Object> stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + Mapper[] m = new Mapper[] {inputMapper, outputMapper, errorMapper}; + for (int i = 0; i < m.length; i++) { + if (m[i] != null) { + stk.push(m[i]); + m[i].dieOnCircularReference(stk, p); + stk.pop(); + } + } + @SuppressWarnings("unchecked") + final List<? extends List<FilterChain>> filterChainLists = Arrays + .<List<FilterChain>> asList(inputFilterChains, outputFilterChains, + errorFilterChains); + for (List<FilterChain> filterChains : filterChainLists) { + if (filterChains != null) { + for (FilterChain fc : filterChains) { + pushAndInvokeCircularReferenceCheck(fc, stk, p); + } + } + } + setChecked(true); + } + } + + /** + * Perform the check for circular references, returning the + * referenced RedirectorElement. + * @return the referenced RedirectorElement. + */ + private RedirectorElement getRef() { + return (RedirectorElement) getCheckedRef(); + } + +} |