Non-forked Java tasks can now have their input redirected. Note that it would be possible to add a noninteractive flag to Ant preventing any input from System.in in any java classes druing a build. Would prevent locking up waiting for input git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274021 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -0,0 +1,100 @@ | |||||
| /* | |||||
| * 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; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| /** | |||||
| * | |||||
| * Passes input requests tot he project objetc for demuxing into | |||||
| * individual tasks and threads. | |||||
| * | |||||
| * @since Ant 1.6 | |||||
| * @author Conor MacNeill | |||||
| */ | |||||
| public class DemuxInputStream extends InputStream { | |||||
| /** | |||||
| * The project to from which to get input. | |||||
| */ | |||||
| private Project project; | |||||
| /** | |||||
| * Create a DemuxInputStream for the given project | |||||
| * | |||||
| * @param project the project instance | |||||
| */ | |||||
| public DemuxInputStream(Project project) { | |||||
| this.project = project; | |||||
| } | |||||
| /** | |||||
| * @see InputStream.read() | |||||
| */ | |||||
| public int read() throws IOException { | |||||
| byte[] buffer = new byte[1]; | |||||
| project.demuxInput(buffer, 0, 1); | |||||
| return buffer[0]; | |||||
| } | |||||
| /** | |||||
| * @see InputStream.read(byte[], int, int) | |||||
| */ | |||||
| public int read(byte[] buffer, int offset, int length) throws IOException { | |||||
| return project.demuxInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| @@ -572,6 +572,8 @@ public class Main { | |||||
| //System.setSecurityManager(new NoExitSecurityManager()); | //System.setSecurityManager(new NoExitSecurityManager()); | ||||
| } | } | ||||
| try { | try { | ||||
| project.setDefaultInputStream(System.in); | |||||
| System.setIn(new DemuxInputStream(project)); | |||||
| System.setOut(new PrintStream(new DemuxOutputStream(project, false))); | System.setOut(new PrintStream(new DemuxOutputStream(project, false))); | ||||
| System.setErr(new PrintStream(new DemuxOutputStream(project, true))); | System.setErr(new PrintStream(new DemuxOutputStream(project, true))); | ||||
| @@ -662,7 +664,7 @@ public class Main { | |||||
| * @exception BuildException if a specified InputHandler | * @exception BuildException if a specified InputHandler | ||||
| * implementation could not be loaded. | * implementation could not be loaded. | ||||
| */ | */ | ||||
| private void addInputHandler(Project project) { | |||||
| private void addInputHandler(Project project) throws BuildException { | |||||
| InputHandler handler = null; | InputHandler handler = null; | ||||
| if (inputHandlerClassname == null) { | if (inputHandlerClassname == null) { | ||||
| handler = new DefaultInputHandler(); | handler = new DefaultInputHandler(); | ||||
| @@ -675,8 +677,7 @@ public class Main { | |||||
| + inputHandlerClassname | + inputHandlerClassname | ||||
| + " does not implement the InputHandler interface"; | + " does not implement the InputHandler interface"; | ||||
| throw new BuildException(msg); | throw new BuildException(msg); | ||||
| } | |||||
| catch (Exception e) { | |||||
| } catch (Exception e) { | |||||
| String msg = "Unable to instantiate specified input handler " | String msg = "Unable to instantiate specified input handler " | ||||
| + "class " + inputHandlerClassname + " : " | + "class " + inputHandlerClassname + " : " | ||||
| + e.getClass().getName(); | + e.getClass().getName(); | ||||
| @@ -866,8 +867,8 @@ public class Main { | |||||
| maxLength); | maxLength); | ||||
| //if there were no main targets, we list all subtargets | //if there were no main targets, we list all subtargets | ||||
| //as it means nothing has a description | //as it means nothing has a description | ||||
| if(topNames.size()==0) { | |||||
| printSubTargets=true; | |||||
| if (topNames.size() == 0) { | |||||
| printSubTargets = true; | |||||
| } | } | ||||
| if (printSubTargets) { | if (printSubTargets) { | ||||
| printTargets(project, subNames, null, "Subtargets:", 0); | printTargets(project, subNames, null, "Subtargets:", 0); | ||||
| @@ -918,8 +919,8 @@ public class Main { | |||||
| * position so they line up (so long as the names really | * position so they line up (so long as the names really | ||||
| * <i>are</i> shorter than this). | * <i>are</i> shorter than this). | ||||
| */ | */ | ||||
| private static void printTargets(Project project,Vector names, | |||||
| Vector descriptions,String heading, | |||||
| private static void printTargets(Project project, Vector names, | |||||
| Vector descriptions, String heading, | |||||
| int maxlen) { | int maxlen) { | ||||
| // now, start printing the targets and their descriptions | // now, start printing the targets and their descriptions | ||||
| String lSep = System.getProperty("line.separator"); | String lSep = System.getProperty("line.separator"); | ||||
| @@ -90,7 +90,6 @@ import org.apache.tools.ant.util.LazyHashtable; | |||||
| */ | */ | ||||
| public class Project { | public class Project { | ||||
| /** Message priority of "error". */ | /** Message priority of "error". */ | ||||
| public static final int MSG_ERR = 0; | public static final int MSG_ERR = 0; | ||||
| /** Message priority of "warning". */ | /** Message priority of "warning". */ | ||||
| @@ -113,6 +112,13 @@ public class Project { | |||||
| */ | */ | ||||
| private static final String VISITED = "VISITED"; | private static final String VISITED = "VISITED"; | ||||
| /** | |||||
| * The class name of the Ant class loader to use for | |||||
| * JDK 1.2 and above | |||||
| */ | |||||
| private static final String ANTCLASSLOADER_JDK12 | |||||
| = "org.apache.tools.ant.loader.AntClassLoader2"; | |||||
| /** | /** | ||||
| * Version constant for Java 1.0 | * Version constant for Java 1.0 | ||||
| * | * | ||||
| @@ -204,15 +210,37 @@ public class Project { | |||||
| */ | */ | ||||
| private InputHandler inputHandler = null; | private InputHandler inputHandler = null; | ||||
| /** | |||||
| * The default input stream used to read any input | |||||
| */ | |||||
| private InputStream defaultInputStream = null; | |||||
| /** | /** | ||||
| * Sets the input handler | * Sets the input handler | ||||
| * | |||||
| * @param handler the InputHandler instance to use for gathering input. | |||||
| */ | */ | ||||
| public void setInputHandler(InputHandler handler) { | public void setInputHandler(InputHandler handler) { | ||||
| inputHandler = handler; | inputHandler = handler; | ||||
| } | } | ||||
| /** | |||||
| * Set the default System input stream. Normally this stream is set to | |||||
| * System.in. This inputStream is used when no task inptu redirection is | |||||
| * being performed. | |||||
| * | |||||
| * @param defaultInputStream the default input stream to use when input | |||||
| * is reuested. | |||||
| */ | |||||
| public void setDefaultInputStream(InputStream defaultInputStream) { | |||||
| this.defaultInputStream = defaultInputStream; | |||||
| } | |||||
| /** | /** | ||||
| * Retrieves the current input handler. | * Retrieves the current input handler. | ||||
| * | |||||
| * @return the InputHandler instance currently in place for the project | |||||
| * instance. | |||||
| */ | */ | ||||
| public InputHandler getInputHandler() { | public InputHandler getInputHandler() { | ||||
| return inputHandler; | return inputHandler; | ||||
| @@ -250,7 +278,7 @@ public class Project { | |||||
| } | } | ||||
| props.load(in); | props.load(in); | ||||
| in.close(); | in.close(); | ||||
| ((AntTaskTable)taskClassDefinitions).addDefinitions( props ); | |||||
| ((AntTaskTable) taskClassDefinitions).addDefinitions(props); | |||||
| } catch (IOException ioe) { | } catch (IOException ioe) { | ||||
| @@ -268,7 +296,7 @@ public class Project { | |||||
| props.load(in); | props.load(in); | ||||
| in.close(); | in.close(); | ||||
| ((AntTaskTable)dataClassDefinitions).addDefinitions(props); | |||||
| ((AntTaskTable) dataClassDefinitions).addDefinitions(props); | |||||
| } catch (IOException ioe) { | } catch (IOException ioe) { | ||||
| @@ -278,13 +306,18 @@ public class Project { | |||||
| setSystemProperties(); | setSystemProperties(); | ||||
| } | } | ||||
| /** | |||||
| * Factory method to create a class loader for loading classes | |||||
| * | |||||
| * @return an appropriate classloader | |||||
| */ | |||||
| private AntClassLoader createClassLoader() { | private AntClassLoader createClassLoader() { | ||||
| AntClassLoader loader = null; | AntClassLoader loader = null; | ||||
| if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { | if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { | ||||
| try { | try { | ||||
| // 1.2+ - create advanced helper dynamically | // 1.2+ - create advanced helper dynamically | ||||
| Class loaderClass | Class loaderClass | ||||
| = Class.forName("org.apache.tools.ant.loader.AntClassLoader2"); | |||||
| = Class.forName(ANTCLASSLOADER_JDK12); | |||||
| loader = (AntClassLoader) loaderClass.newInstance(); | loader = (AntClassLoader) loaderClass.newInstance(); | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| log("Unable to create Class Loader: " | log("Unable to create Class Loader: " | ||||
| @@ -300,6 +333,14 @@ public class Project { | |||||
| return loader; | return loader; | ||||
| } | } | ||||
| /** | |||||
| * Factory method to create a class loader for loading classes from | |||||
| * a given path | |||||
| * | |||||
| * @param path the path from whcih clases are to be loaded. | |||||
| * | |||||
| * @return an appropriate classloader | |||||
| */ | |||||
| public AntClassLoader createClassLoader(Path path) { | public AntClassLoader createClassLoader(Path path) { | ||||
| AntClassLoader loader = createClassLoader(); | AntClassLoader loader = createClassLoader(); | ||||
| loader.setClassPath(path); | loader.setClassPath(path); | ||||
| @@ -434,7 +475,8 @@ public class Project { | |||||
| * @since 1.5 | * @since 1.5 | ||||
| */ | */ | ||||
| public synchronized void setNewProperty(String name, String value) { | public synchronized void setNewProperty(String name, String value) { | ||||
| PropertyHelper.getPropertyHelper(this).setNewProperty( null, name, value); | |||||
| PropertyHelper.getPropertyHelper(this).setNewProperty(null, name, | |||||
| value); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -447,7 +489,8 @@ public class Project { | |||||
| * @see #setProperty(String,String) | * @see #setProperty(String,String) | ||||
| */ | */ | ||||
| public synchronized void setUserProperty(String name, String value) { | public synchronized void setUserProperty(String name, String value) { | ||||
| PropertyHelper.getPropertyHelper(this).setUserProperty( null, name, value); | |||||
| PropertyHelper.getPropertyHelper(this).setUserProperty(null, name, | |||||
| value); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -463,7 +506,7 @@ public class Project { | |||||
| * @see #setProperty(String,String) | * @see #setProperty(String,String) | ||||
| */ | */ | ||||
| public synchronized void setInheritedProperty(String name, String value) { | public synchronized void setInheritedProperty(String name, String value) { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| ph.setInheritedProperty(null, name, value); | ph.setInheritedProperty(null, name, value); | ||||
| } | } | ||||
| @@ -476,8 +519,8 @@ public class Project { | |||||
| * @param value The property value. Must not be <code>null</code>. | * @param value The property value. Must not be <code>null</code>. | ||||
| */ | */ | ||||
| private void setPropertyInternal(String name, String value) { | private void setPropertyInternal(String name, String value) { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| ph.setProperty(null, name, value, false ); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| ph.setProperty(null, name, value, false); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -490,8 +533,8 @@ public class Project { | |||||
| * or if a <code>null</code> name is provided. | * or if a <code>null</code> name is provided. | ||||
| */ | */ | ||||
| public String getProperty(String name) { | public String getProperty(String name) { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| return (String)ph.getProperty(null, name); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| return (String) ph.getProperty(null, name); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -509,9 +552,8 @@ public class Project { | |||||
| * property name, e.g. <code>${xxx</code> | * property name, e.g. <code>${xxx</code> | ||||
| */ | */ | ||||
| public String replaceProperties(String value) | public String replaceProperties(String value) | ||||
| throws BuildException | |||||
| { | |||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| throws BuildException { | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| return ph.replaceProperties(null, value, null); | return ph.replaceProperties(null, value, null); | ||||
| } | } | ||||
| @@ -525,8 +567,8 @@ public class Project { | |||||
| * or if a <code>null</code> name is provided. | * or if a <code>null</code> name is provided. | ||||
| */ | */ | ||||
| public String getUserProperty(String name) { | public String getUserProperty(String name) { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| return (String)ph.getUserProperty( null, name ); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| return (String) ph.getUserProperty(null, name); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -535,7 +577,7 @@ public class Project { | |||||
| * (including user properties). | * (including user properties). | ||||
| */ | */ | ||||
| public Hashtable getProperties() { | public Hashtable getProperties() { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| return ph.getProperties(); | return ph.getProperties(); | ||||
| } | } | ||||
| @@ -544,7 +586,7 @@ public class Project { | |||||
| * @return a hashtable containing just the user properties | * @return a hashtable containing just the user properties | ||||
| */ | */ | ||||
| public Hashtable getUserProperties() { | public Hashtable getUserProperties() { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| return ph.getUserProperties(); | return ph.getUserProperties(); | ||||
| } | } | ||||
| @@ -561,7 +603,7 @@ public class Project { | |||||
| * @since Ant 1.5 | * @since Ant 1.5 | ||||
| */ | */ | ||||
| public void copyUserProperties(Project other) { | public void copyUserProperties(Project other) { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| ph.copyUserProperties(other); | ph.copyUserProperties(other); | ||||
| } | } | ||||
| @@ -578,7 +620,7 @@ public class Project { | |||||
| * @since Ant 1.5 | * @since Ant 1.5 | ||||
| */ | */ | ||||
| public void copyInheritedProperties(Project other) { | public void copyInheritedProperties(Project other) { | ||||
| PropertyHelper ph=PropertyHelper.getPropertyHelper(this); | |||||
| PropertyHelper ph = PropertyHelper.getPropertyHelper(this); | |||||
| ph.copyInheritedProperties(other); | ph.copyInheritedProperties(other); | ||||
| } | } | ||||
| @@ -654,8 +696,8 @@ public class Project { | |||||
| * been set. | * been set. | ||||
| */ | */ | ||||
| public String getDescription() { | public String getDescription() { | ||||
| if( description== null ) { | |||||
| description=Description.getDescription(this); | |||||
| if (description == null) { | |||||
| description = Description.getDescription(this); | |||||
| } | } | ||||
| return description; | return description; | ||||
| @@ -924,7 +966,7 @@ public class Project { | |||||
| * Must not be <code>null</code>. | * Must not be <code>null</code>. | ||||
| */ | */ | ||||
| public void addDataTypeDefinition(String typeName, Class typeClass) { | public void addDataTypeDefinition(String typeName, Class typeClass) { | ||||
| synchronized(dataClassDefinitions) { | |||||
| synchronized (dataClassDefinitions) { | |||||
| Class old = (Class) dataClassDefinitions.get(typeName); | Class old = (Class) dataClassDefinitions.get(typeName); | ||||
| if (null != old) { | if (null != old) { | ||||
| if (old.equals(typeClass)) { | if (old.equals(typeClass)) { | ||||
| @@ -1043,8 +1085,8 @@ public class Project { | |||||
| * creation fails. | * creation fails. | ||||
| */ | */ | ||||
| public Task createTask(String taskType) throws BuildException { | public Task createTask(String taskType) throws BuildException { | ||||
| Task task=createNewTask(taskType); | |||||
| if(task!=null) { | |||||
| Task task = createNewTask(taskType); | |||||
| if (task != null) { | |||||
| addCreatedTask(taskType, task); | addCreatedTask(taskType, task); | ||||
| } | } | ||||
| return task; | return task; | ||||
| @@ -1132,11 +1174,11 @@ public class Project { | |||||
| if (v != null) { | if (v != null) { | ||||
| Enumeration enum = v.elements(); | Enumeration enum = v.elements(); | ||||
| while (enum.hasMoreElements()) { | while (enum.hasMoreElements()) { | ||||
| WeakishReference ref= | |||||
| WeakishReference ref = | |||||
| (WeakishReference) enum.nextElement(); | (WeakishReference) enum.nextElement(); | ||||
| Task t = (Task) ref.get(); | Task t = (Task) ref.get(); | ||||
| //being a weak ref, it may be null by this point | //being a weak ref, it may be null by this point | ||||
| if(t!=null) { | |||||
| if (t != null) { | |||||
| t.markInvalid(); | t.markInvalid(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -1240,6 +1282,48 @@ public class Project { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Read data from the default input stream. If no default has been | |||||
| * specified, System.in is used. | |||||
| * | |||||
| * @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 | |||||
| */ | |||||
| public int defaultInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| if (defaultInputStream != null) { | |||||
| return defaultInputStream.read(buffer, offset, length); | |||||
| } else { | |||||
| return System.in.read(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Demux an input request to the correct task. | |||||
| * | |||||
| * @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 | |||||
| */ | |||||
| public int demuxInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| Task task = (Task) threadTasks.get(Thread.currentThread()); | |||||
| if (task == null) { | |||||
| return defaultInput(buffer, offset, length); | |||||
| } else { | |||||
| return task.handleInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Demultiplexes flush operation so that each task receives the appropriate | * Demultiplexes flush operation so that each task receives the appropriate | ||||
| * messages. If the current thread is not currently executing a task, | * messages. If the current thread is not currently executing a task, | ||||
| @@ -1250,8 +1334,6 @@ public class Project { | |||||
| * @param line Message to handle. Should not be <code>null</code>. | * @param line Message to handle. Should not be <code>null</code>. | ||||
| * @param isError Whether the text represents an error (<code>true</code>) | * @param isError Whether the text represents an error (<code>true</code>) | ||||
| * or information (<code>false</code>). | * or information (<code>false</code>). | ||||
| * @param terminated true if this line should be terminated with an | |||||
| * end-of-line marker | |||||
| */ | */ | ||||
| public void demuxFlush(String line, boolean isError) { | public void demuxFlush(String line, boolean isError) { | ||||
| Task task = (Task) threadTasks.get(Thread.currentThread()); | Task task = (Task) threadTasks.get(Thread.currentThread()); | ||||
| @@ -1763,7 +1845,7 @@ public class Project { | |||||
| */ | */ | ||||
| public void addReference(String name, Object value) { | public void addReference(String name, Object value) { | ||||
| synchronized (references) { | synchronized (references) { | ||||
| Object old = ((AntRefTable)references).getReal(name); | |||||
| Object old = ((AntRefTable) references).getReal(name); | |||||
| if (old == value) { | if (old == value) { | ||||
| // no warning, this is not changing anything | // no warning, this is not changing anything | ||||
| return; | return; | ||||
| @@ -1777,7 +1859,7 @@ public class Project { | |||||
| try { | try { | ||||
| valueAsString = value.toString(); | valueAsString = value.toString(); | ||||
| } catch (Throwable t) { | } catch (Throwable t) { | ||||
| log("Caught exception (" + t.getClass().getName() +")" | |||||
| log("Caught exception (" + t.getClass().getName() + ")" | |||||
| + " while expanding " + name + ": " + t.getMessage(), | + " while expanding " + name + ": " + t.getMessage(), | ||||
| MSG_WARN); | MSG_WARN); | ||||
| } | } | ||||
| @@ -2051,7 +2133,7 @@ public class Project { | |||||
| Project project; | Project project; | ||||
| public AntRefTable(Project project) { | public AntRefTable(Project project) { | ||||
| super(); | super(); | ||||
| this.project=project; | |||||
| this.project = project; | |||||
| } | } | ||||
| /** Returns the unmodified original object. | /** Returns the unmodified original object. | ||||
| @@ -2061,8 +2143,8 @@ public class Project { | |||||
| * of UnknownElement ( this is similar with the JDNI | * of UnknownElement ( this is similar with the JDNI | ||||
| * refs behavior ) | * refs behavior ) | ||||
| */ | */ | ||||
| public Object getReal(Object key ) { | |||||
| return super.get( key ); | |||||
| public Object getReal(Object key) { | |||||
| return super.get(key); | |||||
| } | } | ||||
| /** Get method for the reference table. | /** Get method for the reference table. | ||||
| @@ -2078,11 +2160,11 @@ public class Project { | |||||
| */ | */ | ||||
| public Object get(Object key) { | public Object get(Object key) { | ||||
| //System.out.println("AntRefTable.get " + key); | //System.out.println("AntRefTable.get " + key); | ||||
| Object o=super.get(key); | |||||
| if( o instanceof UnknownElement ) { | |||||
| Object o = super.get(key); | |||||
| if (o instanceof UnknownElement) { | |||||
| // Make sure that | // Make sure that | ||||
| ((UnknownElement)o).maybeConfigure(); | |||||
| o=((UnknownElement)o).getTask(); | |||||
| ((UnknownElement) o).maybeConfigure(); | |||||
| o = ((UnknownElement) o).getTask(); | |||||
| } | } | ||||
| return o; | return o; | ||||
| } | } | ||||
| @@ -2091,28 +2173,28 @@ public class Project { | |||||
| private static class AntTaskTable extends LazyHashtable { | private static class AntTaskTable extends LazyHashtable { | ||||
| Project project; | Project project; | ||||
| Properties props; | Properties props; | ||||
| boolean tasks=false; | |||||
| boolean tasks = false; | |||||
| public AntTaskTable( Project p, boolean tasks ) { | |||||
| this.project=p; | |||||
| this.tasks=tasks; | |||||
| public AntTaskTable(Project p, boolean tasks) { | |||||
| this.project = p; | |||||
| this.tasks = tasks; | |||||
| } | } | ||||
| public void addDefinitions( Properties props ) { | |||||
| this.props=props; | |||||
| public void addDefinitions(Properties props) { | |||||
| this.props = props; | |||||
| } | } | ||||
| protected void initAll( ) { | |||||
| if( initAllDone ) return; | |||||
| protected void initAll() { | |||||
| if (initAllDone ) return; | |||||
| project.log("InitAll", Project.MSG_DEBUG); | project.log("InitAll", Project.MSG_DEBUG); | ||||
| if( props==null ) return; | |||||
| if (props==null ) return; | |||||
| Enumeration enum = props.propertyNames(); | Enumeration enum = props.propertyNames(); | ||||
| while (enum.hasMoreElements()) { | while (enum.hasMoreElements()) { | ||||
| String key = (String) enum.nextElement(); | String key = (String) enum.nextElement(); | ||||
| Class taskClass=getTask( key ); | Class taskClass=getTask( key ); | ||||
| if( taskClass!=null ) { | |||||
| if (taskClass!=null ) { | |||||
| // This will call a get() and a put() | // This will call a get() and a put() | ||||
| if( tasks ) | |||||
| if (tasks ) | |||||
| project.addTaskDefinition(key, taskClass); | project.addTaskDefinition(key, taskClass); | ||||
| else | else | ||||
| project.addDataTypeDefinition(key, taskClass ); | project.addDataTypeDefinition(key, taskClass ); | ||||
| @@ -2122,19 +2204,19 @@ public class Project { | |||||
| } | } | ||||
| protected Class getTask(String key) { | protected Class getTask(String key) { | ||||
| if( props==null ) return null; // for tasks loaded before init() | |||||
| if (props==null ) return null; // for tasks loaded before init() | |||||
| String value=props.getProperty(key); | String value=props.getProperty(key); | ||||
| if( value==null) { | |||||
| if (value==null) { | |||||
| //project.log( "No class name for " + key, Project.MSG_VERBOSE ); | //project.log( "No class name for " + key, Project.MSG_VERBOSE ); | ||||
| return null; | return null; | ||||
| } | } | ||||
| try { | try { | ||||
| Class taskClass=null; | Class taskClass=null; | ||||
| if( project.getCoreLoader() != null && | |||||
| if (project.getCoreLoader() != null && | |||||
| !("only".equals(project.getProperty("build.sysclasspath")))) { | !("only".equals(project.getProperty("build.sysclasspath")))) { | ||||
| try { | try { | ||||
| taskClass=project.getCoreLoader().loadClass(value); | taskClass=project.getCoreLoader().loadClass(value); | ||||
| if( taskClass != null ) return taskClass; | |||||
| if (taskClass != null ) return taskClass; | |||||
| } catch( Exception ex ) { | } catch( Exception ex ) { | ||||
| } | } | ||||
| } | } | ||||
| @@ -2153,11 +2235,11 @@ public class Project { | |||||
| // Hashtable implementation | // Hashtable implementation | ||||
| public Object get( Object key ) { | public Object get( Object key ) { | ||||
| Object orig=super.get( key ); | Object orig=super.get( key ); | ||||
| if( orig!= null ) return orig; | |||||
| if( ! (key instanceof String) ) return null; | |||||
| if (orig!= null ) return orig; | |||||
| if (! (key instanceof String) ) return null; | |||||
| project.log("Get task " + key, Project.MSG_DEBUG ); | project.log("Get task " + key, Project.MSG_DEBUG ); | ||||
| Object taskClass=getTask( (String) key); | Object taskClass=getTask( (String) key); | ||||
| if( taskClass != null) | |||||
| if (taskClass != null) | |||||
| super.put( key, taskClass ); | super.put( key, taskClass ); | ||||
| return taskClass; | return taskClass; | ||||
| } | } | ||||
| @@ -55,6 +55,7 @@ | |||||
| package org.apache.tools.ant; | package org.apache.tools.ant; | ||||
| import java.util.Enumeration; | import java.util.Enumeration; | ||||
| import java.io.IOException; | |||||
| /** | /** | ||||
| * Base class for all tasks. | * Base class for all tasks. | ||||
| @@ -312,6 +313,22 @@ public abstract class Task extends ProjectComponent { | |||||
| handleOutput(line); | handleOutput(line); | ||||
| } | } | ||||
| /** | |||||
| * Handle an input request by this task | |||||
| * | |||||
| * @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 { | |||||
| return getProject().defaultInput(buffer, offset, length); | |||||
| } | |||||
| /** | /** | ||||
| * Handles an error line by logging it with the INFO priority. | * Handles an error line by logging it with the INFO priority. | ||||
| * | * | ||||
| @@ -397,6 +414,9 @@ public abstract class Task extends ProjectComponent { | |||||
| /** | /** | ||||
| * Has this task been marked invalid? | * Has this task been marked invalid? | ||||
| * | * | ||||
| * @return true if this task is no longer valid. A new task should be | |||||
| * configured in this case. | |||||
| * | |||||
| * @since Ant 1.5 | * @since Ant 1.5 | ||||
| */ | */ | ||||
| protected final boolean isInvalid() { | protected final boolean isInvalid() { | ||||
| @@ -55,6 +55,7 @@ | |||||
| package org.apache.tools.ant; | package org.apache.tools.ant; | ||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import java.io.IOException; | |||||
| /** | /** | ||||
| * Wrapper class that holds all the information necessary to create a task | * Wrapper class that holds all the information necessary to create a task | ||||
| @@ -124,7 +125,7 @@ public class UnknownElement extends Task { | |||||
| getWrapper().setProxy(realThing); | getWrapper().setProxy(realThing); | ||||
| if (realThing instanceof Task) { | if (realThing instanceof Task) { | ||||
| Task task=(Task)realThing; | |||||
| Task task = (Task) realThing; | |||||
| task.setProject(project); | task.setProject(project); | ||||
| task.setRuntimeConfigurableWrapper(getWrapper()); | task.setRuntimeConfigurableWrapper(getWrapper()); | ||||
| @@ -135,7 +136,7 @@ public class UnknownElement extends Task { | |||||
| // For Script to work. Ugly | // For Script to work. Ugly | ||||
| // The reference is replaced by RuntimeConfigurable | // The reference is replaced by RuntimeConfigurable | ||||
| this.getOwningTarget().replaceChild(this, (Task)realThing); | |||||
| this.getOwningTarget().replaceChild(this, (Task) realThing); | |||||
| } | } | ||||
| handleChildren(realThing, getWrapper()); | handleChildren(realThing, getWrapper()); | ||||
| @@ -156,6 +157,26 @@ public class UnknownElement extends Task { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Handle an input request by this element | |||||
| * | |||||
| * @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 (realThing instanceof Task) { | |||||
| return ((Task) realThing).handleInput(buffer, offset, length); | |||||
| } else { | |||||
| return super.handleInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Handles output sent to System.out by this task or its real task. | * Handles output sent to System.out by this task or its real task. | ||||
| * | * | ||||
| @@ -214,7 +235,7 @@ public class UnknownElement extends Task { | |||||
| // the task will not be reused ( a new init() will be called ) | // the task will not be reused ( a new init() will be called ) | ||||
| // Let GC do its job | // Let GC do its job | ||||
| realThing=null; | |||||
| realThing = null; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -241,8 +262,7 @@ public class UnknownElement extends Task { | |||||
| */ | */ | ||||
| protected void handleChildren(Object parent, | protected void handleChildren(Object parent, | ||||
| RuntimeConfigurable parentWrapper) | RuntimeConfigurable parentWrapper) | ||||
| throws BuildException | |||||
| { | |||||
| throws BuildException { | |||||
| if (parent instanceof TaskAdapter) { | if (parent instanceof TaskAdapter) { | ||||
| parent = ((TaskAdapter) parent).getProxy(); | parent = ((TaskAdapter) parent).getProxy(); | ||||
| } | } | ||||
| @@ -259,15 +279,15 @@ public class UnknownElement extends Task { | |||||
| //ProjectComponentHelper helper=ProjectComponentHelper.getProjectComponentHelper(); | //ProjectComponentHelper helper=ProjectComponentHelper.getProjectComponentHelper(); | ||||
| //realChild = helper.createProjectComponent( child, getProject(), null, | //realChild = helper.createProjectComponent( child, getProject(), null, | ||||
| // child.getTag()); | // child.getTag()); | ||||
| realChild=makeTask(child, childWrapper, false); | |||||
| realChild = makeTask(child, childWrapper, false); | |||||
| if (realChild == null ) { | |||||
| if (realChild == null) { | |||||
| throw getNotFoundException("task", child.getTag()); | throw getNotFoundException("task", child.getTag()); | ||||
| } | } | ||||
| // XXX DataTypes will be wrapped or treated like normal components | // XXX DataTypes will be wrapped or treated like normal components | ||||
| if( realChild instanceof Task ) { | |||||
| Task task=(Task)realChild; | |||||
| if (realChild instanceof Task) { | |||||
| Task task = (Task) realChild; | |||||
| ((TaskContainer) parent).addTask(task); | ((TaskContainer) parent).addTask(task); | ||||
| task.setLocation(child.getLocation()); | task.setLocation(child.getLocation()); | ||||
| // UnknownElement always has an associated target | // UnknownElement always has an associated target | ||||
| @@ -277,7 +297,8 @@ public class UnknownElement extends Task { | |||||
| // What ? Add data type ? createElement ? | // What ? Add data type ? createElement ? | ||||
| } | } | ||||
| } else { | } else { | ||||
| realChild = ih.createElement(getProject(), parent, child.getTag()); | |||||
| realChild | |||||
| = ih.createElement(getProject(), parent, child.getTag()); | |||||
| } | } | ||||
| childWrapper.setProxy(realChild); | childWrapper.setProxy(realChild); | ||||
| @@ -296,6 +296,18 @@ public class Ant extends Task { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * @see Task#handleInput(byte[], int, int) | |||||
| */ | |||||
| public int handleInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| if (newProject != null) { | |||||
| return newProject.demuxInput(buffer, offset, length); | |||||
| } else { | |||||
| return super.handleInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Pass output sent to System.out to the new project. | * Pass output sent to System.out to the new project. | ||||
| * | * | ||||
| @@ -443,7 +455,8 @@ public class Ant extends Task { | |||||
| * requested. | * requested. | ||||
| */ | */ | ||||
| private void addReferences() throws BuildException { | private void addReferences() throws BuildException { | ||||
| Hashtable thisReferences = (Hashtable) getProject().getReferences().clone(); | |||||
| Hashtable thisReferences | |||||
| = (Hashtable) getProject().getReferences().clone(); | |||||
| Hashtable newReferences = newProject.getReferences(); | Hashtable newReferences = newProject.getReferences(); | ||||
| Enumeration e; | Enumeration e; | ||||
| if (references.size() > 0) { | if (references.size() > 0) { | ||||
| @@ -56,6 +56,7 @@ package org.apache.tools.ant.taskdefs; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import java.io.IOException; | |||||
| /** | /** | ||||
| * Call another target in the same project. | * Call another target in the same project. | ||||
| @@ -185,6 +186,15 @@ public class CallTarget extends Task { | |||||
| } | } | ||||
| } | } | ||||
| public int handleInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| if (callee != null) { | |||||
| return callee.handleInput(buffer, offset, length); | |||||
| } else { | |||||
| return super.handleInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Pass output sent to System.out to the new project. | * Pass output sent to System.out to the new project. | ||||
| * | * | ||||
| @@ -416,6 +416,15 @@ public class Java extends Task { | |||||
| } | } | ||||
| } | } | ||||
| public int handleInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| if (redirector.getInputStream() != null) { | |||||
| return redirector.handleInput(buffer, offset, length); | |||||
| } else { | |||||
| return super.handleInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Pass output sent to System.out to specified output file. | * Pass output sent to System.out to specified output file. | ||||
| * | * | ||||
| @@ -79,37 +79,92 @@ import org.apache.tools.ant.util.TeeOutputStream; | |||||
| * @since Ant 1.6 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public class Redirector { | public class Redirector { | ||||
| /** | |||||
| * The file receiveing standard output. Will also receive standard error | |||||
| * unless standard error is redirected or logError is true. | |||||
| */ | |||||
| private File out; | private File out; | ||||
| /** | |||||
| * The file to which standard error is being redirected | |||||
| */ | |||||
| private File error; | private File error; | ||||
| /** | |||||
| * The file from which standard input is being taken. | |||||
| */ | |||||
| private File input; | 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; | private boolean logError = false; | ||||
| /** | |||||
| * Buffer used to capture output for storage into a property | |||||
| */ | |||||
| private ByteArrayOutputStream baos = null; | private ByteArrayOutputStream baos = null; | ||||
| /** | |||||
| * Buffer used to capture error output for storage into a property | |||||
| */ | |||||
| private ByteArrayOutputStream errorBaos = null; | private ByteArrayOutputStream errorBaos = null; | ||||
| /** The name of the property into which output is to be stored */ | |||||
| private String outputProperty; | private String outputProperty; | ||||
| /** The name of the property into which error output is to be stored */ | |||||
| private String errorProperty; | private String errorProperty; | ||||
| /** String from which input is taken */ | |||||
| private String inputString; | private String inputString; | ||||
| /** Flag which indicates if error and output files are to be appended. */ | |||||
| private boolean append = false; | private boolean append = false; | ||||
| /** The task for which this redirector is working */ | |||||
| private Task managingTask; | private Task managingTask; | ||||
| /** The stream for output data */ | |||||
| private OutputStream outputStream = null; | private OutputStream outputStream = null; | ||||
| /** The stream for error output */ | |||||
| private OutputStream errorStream = null; | private OutputStream errorStream = null; | ||||
| private InputStream inputStream = null; | |||||
| /** The stream for input */ | |||||
| private InputStream inputStream = null; | |||||
| /** Stream which are used for line oriented output */ | |||||
| private PrintStream outPrintStream = null; | private PrintStream outPrintStream = null; | ||||
| /** Stream which is used for line oriented error output */ | |||||
| private PrintStream errorPrintStream = null; | 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) { | public Redirector(Task managingTask) { | ||||
| this.managingTask = managingTask; | this.managingTask = managingTask; | ||||
| } | } | ||||
| /** | /** | ||||
| * Set the input to use for the task | * Set the input to use for the task | ||||
| * | |||||
| * @param input the file from which input is read. | |||||
| */ | */ | ||||
| public void setInput(File input) { | public void setInput(File input) { | ||||
| this.input = 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) { | public void setInputString(String inputString) { | ||||
| this.inputString = inputString; | this.inputString = inputString; | ||||
| } | } | ||||
| @@ -118,6 +173,8 @@ public class Redirector { | |||||
| /** | /** | ||||
| * File the output of the process is redirected to. If error is not | * File the output of the process is redirected to. If error is not | ||||
| * redirected, it too will appear in the output | * redirected, it too will appear in the output | ||||
| * | |||||
| * @param out the file to which output stream is written | |||||
| */ | */ | ||||
| public void setOutput(File out) { | public void setOutput(File out) { | ||||
| this.out = out; | this.out = out; | ||||
| @@ -127,14 +184,18 @@ public class Redirector { | |||||
| * Controls whether error output of exec is logged. This is only useful | * Controls whether error output of exec is logged. This is only useful | ||||
| * when output is being redirected and error output is desired in the | * when output is being redirected and error output is desired in the | ||||
| * Ant log | * 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) { | public void setLogError(boolean logError) { | ||||
| this.logError = logError; | this.logError = logError; | ||||
| } | } | ||||
| /** | /** | ||||
| * File the error stream of the process is redirected to. | |||||
| * 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) { | public void setError(File error) { | ||||
| this.error = error; | this.error = error; | ||||
| @@ -143,6 +204,9 @@ public class Redirector { | |||||
| /** | /** | ||||
| * Property name whose value should be set to the output of | * Property name whose value should be set to the output of | ||||
| * the process. | * the process. | ||||
| * | |||||
| * @param outputProperty the name of the property to be set with the | |||||
| * task's output. | |||||
| */ | */ | ||||
| public void setOutputProperty(String outputProperty) { | public void setOutputProperty(String outputProperty) { | ||||
| this.outputProperty = outputProperty; | this.outputProperty = outputProperty; | ||||
| @@ -152,6 +216,8 @@ public class Redirector { | |||||
| * Whether output should be appended to or overwrite an existing file. | * Whether output should be appended to or overwrite an existing file. | ||||
| * Defaults to false. | * Defaults to false. | ||||
| * | * | ||||
| * @param append if true output and error streams are appended to their | |||||
| * respective files, if specified. | |||||
| */ | */ | ||||
| public void setAppend(boolean append) { | public void setAppend(boolean append) { | ||||
| this.append = append; | this.append = append; | ||||
| @@ -161,11 +227,21 @@ public class Redirector { | |||||
| * Property name whose value should be set to the error of | * Property name whose value should be set to the error of | ||||
| * the process. | * the process. | ||||
| * | * | ||||
| * @param errorProperty the name of the property to be set | |||||
| * with the error output. | |||||
| */ | */ | ||||
| public void setErrorProperty(String errorProperty) { | public void setErrorProperty(String errorProperty) { | ||||
| this.errorProperty = 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, | private void setPropertyFromBAOS(ByteArrayOutputStream baos, | ||||
| String propertyName) throws IOException { | String propertyName) throws IOException { | ||||
| @@ -183,6 +259,10 @@ public class Redirector { | |||||
| } | } | ||||
| /** | |||||
| * Create the input, error and output streams based on the | |||||
| * configuration options. | |||||
| */ | |||||
| public void createStreams() { | public void createStreams() { | ||||
| if (out == null && outputProperty == null) { | if (out == null && outputProperty == null) { | ||||
| outputStream = new LogOutputStream(managingTask, Project.MSG_INFO); | outputStream = new LogOutputStream(managingTask, Project.MSG_INFO); | ||||
| @@ -265,6 +345,11 @@ public class Redirector { | |||||
| /** | /** | ||||
| * Create the StreamHandler to use with our Execute instance. | * 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 { | public ExecuteStreamHandler createHandler() throws BuildException { | ||||
| createStreams(); | createStreams(); | ||||
| @@ -272,8 +357,9 @@ public class Redirector { | |||||
| } | } | ||||
| /** | /** | ||||
| * Pass output sent to System.out to specified output file. | |||||
| * Pass output sent to System.out to specified output. | |||||
| * | * | ||||
| * @param line the data to be output | |||||
| */ | */ | ||||
| protected void handleOutput(String line) { | protected void handleOutput(String line) { | ||||
| if (outPrintStream == null) { | if (outPrintStream == null) { | ||||
| @@ -282,9 +368,31 @@ public class Redirector { | |||||
| outPrintStream.println(line); | outPrintStream.println(line); | ||||
| } | } | ||||
| /** | |||||
| * 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); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Pass output sent to System.out to specified output file. | |||||
| * Process data due to a flush operation. | |||||
| * | * | ||||
| * @param line the data being flushed. | |||||
| */ | */ | ||||
| protected void handleFlush(String line) { | protected void handleFlush(String line) { | ||||
| if (outPrintStream == null) { | if (outPrintStream == null) { | ||||
| @@ -294,8 +402,9 @@ public class Redirector { | |||||
| } | } | ||||
| /** | /** | ||||
| * Pass output sent to System.err to specified output file. | |||||
| * Process error output | |||||
| * | * | ||||
| * @param line the error output data. | |||||
| */ | */ | ||||
| protected void handleErrorOutput(String line) { | protected void handleErrorOutput(String line) { | ||||
| if (errorPrintStream == null) { | if (errorPrintStream == null) { | ||||
| @@ -305,8 +414,9 @@ public class Redirector { | |||||
| } | } | ||||
| /** | /** | ||||
| * Pass output sent to System.err to specified output file. | |||||
| * Handle a flush operation on the error stream | |||||
| * | * | ||||
| * @param line the error information being flushed. | |||||
| */ | */ | ||||
| protected void handleErrorFlush(String line) { | protected void handleErrorFlush(String line) { | ||||
| if (errorPrintStream == null) { | if (errorPrintStream == null) { | ||||
| @@ -315,15 +425,45 @@ public class Redirector { | |||||
| errorPrintStream.print(line); | errorPrintStream.print(line); | ||||
| } | } | ||||
| /** | |||||
| * Get the output stream for the redirector | |||||
| * | |||||
| * @return the redirector's output stream or null if no output | |||||
| * has been configured | |||||
| */ | |||||
| public OutputStream getOutputStream() { | public OutputStream getOutputStream() { | ||||
| return outputStream; | 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() { | public OutputStream getErrorStream() { | ||||
| return errorStream; | 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 opertaion will close any streams and create any specified | |||||
| * property values. | |||||
| * | |||||
| * @throws IOException if the outptu properties cannot be read from their | |||||
| * output streams. | |||||
| */ | |||||
| public void complete() throws IOException { | public void complete() throws IOException { | ||||
| System.out.flush(); | System.out.flush(); | ||||
| System.err.flush(); | System.err.flush(); | ||||
| @@ -713,6 +713,21 @@ public class JUnitTask extends Task { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * @see Task#handleInput(byte[], int, int) | |||||
| * | |||||
| * @since Ant 1.6 | |||||
| */ | |||||
| protected int handleInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| if (runner != null) { | |||||
| return runner.handleInput(buffer, offset, length); | |||||
| } else { | |||||
| return super.handleInput(buffer, offset, length); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Pass output sent to System.out to the TestRunner so it can | * Pass output sent to System.out to the TestRunner so it can | ||||
| * collect ot for the formatters. | * collect ot for the formatters. | ||||
| @@ -410,6 +410,11 @@ public class JUnitTestRunner implements TestListener { | |||||
| } | } | ||||
| } | } | ||||
| protected int handleInput(byte[] buffer, int offset, int length) | |||||
| throws IOException { | |||||
| return -1; | |||||
| } | |||||
| protected void handleErrorOutput(String line) { | protected void handleErrorOutput(String line) { | ||||
| if (systemError != null) { | if (systemError != null) { | ||||
| systemError.println(line); | systemError.println(line); | ||||
| @@ -56,9 +56,10 @@ package org.apache.tools.ant.taskdefs; | |||||
| import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
| import org.apache.tools.ant.BuildFileTest; | import org.apache.tools.ant.BuildFileTest; | ||||
| import java.util.Random; | import java.util.Random; | ||||
| /** | /** | ||||
| * A simple task that prints to System.out and System.err and then catches | * A simple task that prints to System.out and System.err and then catches | ||||
| * the output which it then check. If the output does not match, an | |||||
| * the output which it then checks. If the output does not match, an | |||||
| * exception is thrown | * exception is thrown | ||||
| * | * | ||||
| * @since 1.5 | * @since 1.5 | ||||