diff --git a/src/main/org/apache/tools/ant/DemuxOutputStream.java b/src/main/org/apache/tools/ant/DemuxOutputStream.java
new file mode 100644
index 000000000..8568e7ff1
--- /dev/null
+++ b/src/main/org/apache/tools/ant/DemuxOutputStream.java
@@ -0,0 +1,151 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 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
+ * processLine
+ */
+ protected void processBuffer() {
+ String output = getBuffer().toString();
+ project.demuxOutput(output, isErrorStream);
+ resetBuffer();
+ }
+
+ /**
+ * Writes all remaining
+ */
+ public void close() throws IOException {
+ flush();
+ }
+
+ /**
+ * Writes all remaining
+ */
+ public void flush() throws IOException {
+ if (getBuffer().size() > 0) {
+ processBuffer();
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java
index d8e186fae..37a239c9f 100644
--- a/src/main/org/apache/tools/ant/Main.java
+++ b/src/main/org/apache/tools/ant/Main.java
@@ -267,7 +267,14 @@ public class Main {
System.out.println("Only one logger class may be specified.");
return;
}
- loggerClassname = args[++i];
+ try {
+ loggerClassname = args[++i];
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe) {
+ System.out.println("You must specify a classname when " +
+ "using the -logger argument");
+ return;
+ }
} else if (arg.equals("-emacs")) {
emacsMode = true;
} else if (arg.equals("-projecthelp")) {
@@ -403,43 +410,54 @@ public class Main {
try {
addBuildListeners(project);
- project.fireBuildStarted();
- project.init();
- project.setUserProperty("ant.version", getAntVersion());
-
- // set user-define properties
- Enumeration e = definedProps.keys();
- while (e.hasMoreElements()) {
- String arg = (String)e.nextElement();
- String value = (String)definedProps.get(arg);
- project.setUserProperty(arg, value);
- }
-
- project.setUserProperty("ant.file" , buildFile.getAbsolutePath() );
-
- // first use the ProjectHelper to create the project object
- // from the given build file.
+ PrintStream err = System.err;
+ PrintStream out = System.out;
+
try {
- Class.forName("javax.xml.parsers.SAXParserFactory");
- ProjectHelper.configureProject(project, buildFile);
- } catch (NoClassDefFoundError ncdfe) {
- throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", ncdfe);
- } catch (ClassNotFoundException cnfe) {
- throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", cnfe);
- } catch (NullPointerException npe) {
- throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", npe);
+ System.setOut(new PrintStream(new DemuxOutputStream(project, false)));
+ System.setErr(new PrintStream(new DemuxOutputStream(project, true)));
+ project.fireBuildStarted();
+ project.init();
+ project.setUserProperty("ant.version", getAntVersion());
+
+ // set user-define properties
+ Enumeration e = definedProps.keys();
+ while (e.hasMoreElements()) {
+ String arg = (String)e.nextElement();
+ String value = (String)definedProps.get(arg);
+ project.setUserProperty(arg, value);
+ }
+
+ project.setUserProperty("ant.file" , buildFile.getAbsolutePath() );
+
+ // first use the ProjectHelper to create the project object
+ // from the given build file.
+ try {
+ Class.forName("javax.xml.parsers.SAXParserFactory");
+ ProjectHelper.configureProject(project, buildFile);
+ } catch (NoClassDefFoundError ncdfe) {
+ throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", ncdfe);
+ } catch (ClassNotFoundException cnfe) {
+ throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", cnfe);
+ } catch (NullPointerException npe) {
+ throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", npe);
+ }
+
+ // make sure that we have a target to execute
+ if (targets.size() == 0) {
+ targets.addElement(project.getDefaultTarget());
+ }
+
+ if (!projectHelp) {
+ project.executeTargets(targets);
+ }
}
-
- // make sure that we have a target to execute
- if (targets.size() == 0) {
- targets.addElement(project.getDefaultTarget());
+ finally {
+ System.setOut(out);
+ System.setErr(err);
}
-
if (projectHelp) {
- printTargets(project);
- } else {
- // actually do some work
- project.executeTargets(targets);
+ printTargets(project);
}
}
catch(RuntimeException exc) {
diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java
index fc2aff151..30d37583d 100644
--- a/src/main/org/apache/tools/ant/Project.java
+++ b/src/main/org/apache/tools/ant/Project.java
@@ -113,6 +113,9 @@ public class Project {
/** The system classloader - may be null */
private ClassLoader systemLoader = null;
+
+ /** Records the latest task on a thread */
+ private Hashtable threadTasks = new Hashtable();
static {
@@ -525,6 +528,21 @@ public class Project {
}
}
+ public void demuxOutput(String line, boolean isError) {
+ Task task = (Task)threadTasks.get(Thread.currentThread());
+ if (task == null) {
+ fireMessageLogged(this, line, isError ? MSG_ERR : MSG_INFO);
+ }
+ else {
+ if (isError) {
+ task.handleOutput(line);
+ }
+ else {
+ task.handleErrorOutput(line);
+ }
+ }
+ }
+
public void executeTarget(String targetName) throws BuildException {
// sanity check ourselves, if we've been asked to build nothing
@@ -547,7 +565,7 @@ public class Project {
do {
curtarget = (Target) sortedTargets.elementAt(curidx++);
- runTarget(curtarget);
+ curtarget.performTasks();
} while (!curtarget.getName().equals(targetName));
}
@@ -903,23 +921,6 @@ public class Project {
s.equalsIgnoreCase("yes"));
}
- // Given a string defining a target name, and a Hashtable
- // containing the "name to Target" mapping, pick out the
- // Target and execute it.
- public void runTarget(Target target)
- throws BuildException {
-
- try {
- fireTargetStarted(target);
- target.execute();
- fireTargetFinished(target, null);
- }
- catch(RuntimeException exc) {
- fireTargetFinished(target, exc);
- throw exc;
- }
- }
-
/**
* Topologically sort a set of Targets.
* @param root is the (String) name of the root Target. The sort is
@@ -1084,6 +1085,8 @@ public class Project {
}
protected void fireTaskStarted(Task task) {
+ // register this as the current task on the current thread.
+ threadTasks.put(Thread.currentThread(), task);
BuildEvent event = new BuildEvent(task);
for (int i = 0; i < listeners.size(); i++) {
BuildListener listener = (BuildListener) listeners.elementAt(i);
@@ -1092,6 +1095,9 @@ public class Project {
}
protected void fireTaskFinished(Task task, Throwable exception) {
+ threadTasks.remove(Thread.currentThread());
+ System.out.flush();
+ System.err.flush();
BuildEvent event = new BuildEvent(task);
for (int i = 0; i < listeners.size(); i++) {
BuildListener listener = (BuildListener) listeners.elementAt(i);
diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java
index 62bfb2b50..6e87e0b57 100644
--- a/src/main/org/apache/tools/ant/ProjectHelper.java
+++ b/src/main/org/apache/tools/ant/ProjectHelper.java
@@ -348,11 +348,11 @@ public class ProjectHelper {
}
private void handleTaskdef(String name, AttributeList attrs) throws SAXParseException {
- (new TaskHandler(this, null)).init(name, attrs);
+ (new TaskHandler(this, null, null)).init(name, attrs);
}
private void handleProperty(String name, AttributeList attrs) throws SAXParseException {
- (new TaskHandler(this, null)).init(name, attrs);
+ (new TaskHandler(this, null, null)).init(name, attrs);
}
private void handleTarget(String tag, AttributeList attrs) throws SAXParseException {
@@ -433,7 +433,7 @@ public class ProjectHelper {
if (project.getDataTypeDefinitions().get(name) != null) {
new DataTypeHandler(this, target).init(name, attrs);
} else {
- new TaskHandler(this, target).init(name, attrs);
+ new TaskHandler(this, target, target).init(name, attrs);
}
}
}
@@ -443,12 +443,13 @@ public class ProjectHelper {
*/
private class TaskHandler extends AbstractHandler {
private Target target;
+ private TaskContainer container;
private Task task;
private RuntimeConfigurable wrapper = null;
- public TaskHandler(DocumentHandler parentHandler, Target target) {
+ public TaskHandler(DocumentHandler parentHandler, TaskContainer container, Target target) {
super(parentHandler);
-
+ this.container = container;
this.target = target;
}
@@ -471,7 +472,7 @@ public class ProjectHelper {
// Top level tasks don't have associated targets
if (target != null) {
task.setOwningTarget(target);
- target.addTask(task);
+ container.addTask(task);
task.init();
wrapper = task.getRuntimeConfigurableWrapper();
wrapper.setAttributes(attrs);
@@ -500,7 +501,13 @@ public class ProjectHelper {
}
public void startElement(String name, AttributeList attrs) throws SAXParseException {
- new NestedElementHandler(this, task, wrapper).init(name, attrs);
+ if (task instanceof TaskContainer) {
+ // task can contain other tasks - no other nested elements possible
+ new TaskHandler(this, (TaskContainer)task, target).init(name, attrs);
+ }
+ else {
+ new NestedElementHandler(this, task, wrapper, target).init(name, attrs);
+ }
}
}
@@ -508,35 +515,38 @@ public class ProjectHelper {
* Handler for all nested properties.
*/
private class NestedElementHandler extends AbstractHandler {
- private Object target;
+ private Object parent;
private Object child;
private RuntimeConfigurable parentWrapper;
private RuntimeConfigurable childWrapper = null;
+ private Target target;
public NestedElementHandler(DocumentHandler parentHandler,
- Object target,
- RuntimeConfigurable parentWrapper) {
+ Object parent,
+ RuntimeConfigurable parentWrapper,
+ Target target) {
super(parentHandler);
- if (target instanceof TaskAdapter) {
- this.target = ((TaskAdapter) target).getProxy();
+ if (parent instanceof TaskAdapter) {
+ this.parent = ((TaskAdapter) parent).getProxy();
} else {
- this.target = target;
+ this.parent = parent;
}
this.parentWrapper = parentWrapper;
+ this.target = target;
}
public void init(String propType, AttributeList attrs) throws SAXParseException {
- Class targetClass = target.getClass();
+ Class parentClass = parent.getClass();
IntrospectionHelper ih =
- IntrospectionHelper.getHelper(targetClass);
+ IntrospectionHelper.getHelper(parentClass);
try {
- if (target instanceof UnknownElement) {
+ if (parent instanceof UnknownElement) {
child = new UnknownElement(propType.toLowerCase());
- ((UnknownElement) target).addChild((UnknownElement) child);
+ ((UnknownElement) parent).addChild((UnknownElement) child);
} else {
- child = ih.createElement(project, target, propType.toLowerCase());
+ child = ih.createElement(project, parent, propType.toLowerCase());
}
configureId(child, attrs);
@@ -566,7 +576,14 @@ public class ProjectHelper {
}
public void startElement(String name, AttributeList attrs) throws SAXParseException {
- new NestedElementHandler(this, child, childWrapper).init(name, attrs);
+ if (child instanceof TaskContainer) {
+ // taskcontainer nested element can contain other tasks - no other
+ // nested elements possible
+ new TaskHandler(this, (TaskContainer)child, target).init(name, attrs);
+ }
+ else {
+ new NestedElementHandler(this, child, childWrapper, target).init(name, attrs);
+ }
}
}
@@ -616,7 +633,7 @@ public class ProjectHelper {
}
public void startElement(String name, AttributeList attrs) throws SAXParseException {
- new NestedElementHandler(this, element, wrapper).init(name, attrs);
+ new NestedElementHandler(this, element, wrapper, target).init(name, attrs);
}
}
diff --git a/src/main/org/apache/tools/ant/Target.java b/src/main/org/apache/tools/ant/Target.java
index 35d884c2b..36a28ffd4 100644
--- a/src/main/org/apache/tools/ant/Target.java
+++ b/src/main/org/apache/tools/ant/Target.java
@@ -62,7 +62,7 @@ import java.util.*;
* @author James Davidson duncan@x180.com
*/
-public class Target {
+public class Target implements TaskContainer {
private String name;
private String ifCondition = "";
@@ -161,23 +161,7 @@ public class Target {
Object o = enum.nextElement();
if (o instanceof Task) {
Task task = (Task) o;
-
- try {
- project.fireTaskStarted(task);
- task.maybeConfigure();
- task.execute();
- project.fireTaskFinished(task, null);
- }
- catch(RuntimeException exc) {
- if (exc instanceof BuildException) {
- BuildException be = (BuildException) exc;
- if (be.getLocation() == Location.UNKNOWN_LOCATION) {
- be.setLocation(task.getLocation());
- }
- }
- project.fireTaskFinished(task, exc);
- throw exc;
- }
+ task.perform();
} else {
RuntimeConfigurable r = (RuntimeConfigurable) o;
r.maybeConfigure(project);
@@ -192,6 +176,18 @@ public class Target {
}
}
+ public final void performTasks() {
+ try {
+ project.fireTargetStarted(this);
+ execute();
+ project.fireTargetFinished(this, null);
+ }
+ catch(RuntimeException exc) {
+ project.fireTargetFinished(this, exc);
+ throw exc;
+ }
+ }
+
void replaceTask(UnknownElement el, Task t) {
int index = -1;
while ((index = children.indexOf(el)) >= 0) {
diff --git a/src/main/org/apache/tools/ant/Task.java b/src/main/org/apache/tools/ant/Task.java
index 9e4b1f122..11d348865 100644
--- a/src/main/org/apache/tools/ant/Task.java
+++ b/src/main/org/apache/tools/ant/Task.java
@@ -220,5 +220,36 @@ public abstract class Task {
wrapper.maybeConfigure(project);
}
}
+
+ protected void handleOutput(String line) {
+ log(line, Project.MSG_INFO);
+ }
+
+ protected void handleErrorOutput(String line) {
+ log(line, Project.MSG_ERR);
+ }
+
+
+ /**
+ * Perform this task
+ */
+ public final void perform() {
+ try {
+ project.fireTaskStarted(this);
+ maybeConfigure();
+ execute();
+ project.fireTaskFinished(this, null);
+ }
+ catch(RuntimeException exc) {
+ if (exc instanceof BuildException) {
+ BuildException be = (BuildException) exc;
+ if (be.getLocation() == Location.UNKNOWN_LOCATION) {
+ be.setLocation(getLocation());
+ }
+ }
+ project.fireTaskFinished(this, exc);
+ throw exc;
+ }
+ }
}
diff --git a/src/main/org/apache/tools/ant/TaskContainer.java b/src/main/org/apache/tools/ant/TaskContainer.java
new file mode 100644
index 000000000..87ca7dadd
--- /dev/null
+++ b/src/main/org/apache/tools/ant/TaskContainer.java
@@ -0,0 +1,70 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 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
+ *
+ * @author Thomas Christen chr@active.ch + * @author Conor MacNeill + */ +public class Parallel extends Task + implements TaskContainer { + + /** Collection holding the nested tasks */ + private Vector nestedTasks = new Vector(); + + + /** + * Add a nested task to execute parallel (asynchron). + *
+ * @param nestedTask Nested task to be executed in parallel + */ + public void addTask(Task nestedTask) throws BuildException { + nestedTasks.addElement(nestedTask); + } + + /** + * Block execution until the specified time or for a + * specified amount of milliseconds and if defined, + * execute the wait status. + */ + public void execute() throws BuildException { + TaskThread[] threads = new TaskThread[nestedTasks.size()]; + int threadNumber = 0; + for (Enumeration e = nestedTasks.elements(); e.hasMoreElements(); threadNumber++) { + Task nestedTask = (Task)e.nextElement(); + threads[threadNumber] = new TaskThread(threadNumber, nestedTask); + } + + // now start all threads + for (int i = 0; i < threads.length; ++i) { + threads[i].start(); + } + + // now join to all the threads + for (int i = 0; i < threads.length; ++i) { + try { + threads[i].join(); + } + catch (InterruptedException ie) { + // who would interrupt me at a time like this? + } + } + + // now did any of the threads throw an exception + StringBuffer exceptionMessage = new StringBuffer(); + String lSep = System.getProperty("line.separator"); + int numExceptions = 0; + Throwable firstException = null; + Location firstLocation = Location.UNKNOWN_LOCATION;; + for (int i = 0; i < threads.length; ++i) { + Throwable t = threads[i].getException(); + if (t != null) { + numExceptions++; + if (firstException == null) { + firstException = t; + } + if (t instanceof BuildException && + firstLocation == Location.UNKNOWN_LOCATION) { + firstLocation = ((BuildException)t).getLocation(); + } + exceptionMessage.append(lSep); + exceptionMessage.append(t.getMessage()); + } + } + + if (numExceptions == 1) { + if (firstException instanceof BuildException) { + throw (BuildException)firstException; + } + else { + throw new BuildException(firstException); + } + } + else if (numExceptions > 1) { + throw new BuildException(exceptionMessage.toString(), firstLocation); + } + } + + class TaskThread extends Thread { + private Throwable exception; + private Task task; + private int taskNumber; + + /** + * Construct a new TaskThread
+ *
+ * @param task the Task to be executed in a seperate thread
+ */
+ TaskThread(int taskNumber, Task task) {
+ this.task = task;
+ this.taskNumber = taskNumber;
+ }
+
+ /**
+ * Executes the task within a thread and takes care about
+ * Exceptions raised within the task.
+ */
+ public void run() {
+ try {
+ task.perform();
+ }
+ catch (Throwable t) {
+ exception = t;
+ }
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/Sequential.java b/src/main/org/apache/tools/ant/taskdefs/Sequential.java
new file mode 100644
index 000000000..cb663f4a7
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/Sequential.java
@@ -0,0 +1,92 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 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
+ *
+ * @author Thomas Christen chr@active.ch + */ +public class Sequential extends Task + implements TaskContainer { + + /** Optional Vector holding the nested tasks */ + private Vector nestedTasks = new Vector(); + + /** + * Add a nested task to Sequential. + *
+ * @param nestedTask Nested task to execute Sequential + *
+ */
+ public void addTask(Task nestedTask) {
+ nestedTasks.addElement(nestedTask);
+ }
+
+ /**
+ * Execute all nestedTasks.
+ */
+ public void execute() throws BuildException {
+ for (Enumeration e = nestedTasks.elements(); e.hasMoreElements();) {
+ Task nestedTask = (Task)e.nextElement();
+ nestedTask.perform();
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java
index d0724511e..34641bf72 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java
@@ -83,15 +83,8 @@ public class Javac13 extends DefaultCompilerAdapter {
attributes.log("Using modern compiler", Project.MSG_VERBOSE);
Commandline cmd = setupJavacCommand();
- PrintStream err = System.err;
- PrintStream out = System.out;
-
- PrintStream logstr =
- new PrintStream(new LogOutputStream(attributes, Project.MSG_WARN));
// Use reflection to be able to build on all JDKs >= 1.1:
try {
- System.setOut(logstr);
- System.setErr(logstr);
Class c = Class.forName ("com.sun.tools.javac.Main");
Object compiler = c.newInstance ();
Method compile = c.getMethod ("compile",
@@ -105,10 +98,6 @@ public class Javac13 extends DefaultCompilerAdapter {
} else {
throw new BuildException("Error starting modern compiler", ex, location);
}
- } finally {
- System.setErr(err);
- System.setOut(out);
- logstr.close();
}
}
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
index 1a2453597..979219625 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -49,6 +49,8 @@ typedef=org.apache.tools.ant.taskdefs.Typedef
sleep=org.apache.tools.ant.taskdefs.Sleep
pathconvert=org.apache.tools.ant.taskdefs.PathConvert
ear=org.apache.tools.ant.taskdefs.Ear
+parallel=org.apache.tools.ant.taskdefs.Parallel
+sequential=org.apache.tools.ant.taskdefs.Sequential
# optional tasks
script=org.apache.tools.ant.taskdefs.optional.Script
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java
index f8834ec41..ee32e580a 100755
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java
@@ -308,19 +308,12 @@ public class Javah extends Task {
throw new BuildException("Compile failed");
}
*/
- PrintStream err = System.err;
- PrintStream out = System.out;
-
- PrintStream logstr =
- new PrintStream(new LogOutputStream(this, Project.MSG_WARN));
try {
// Javac uses logstr to change the output stream and calls
// the constructor's invoke method to create a compiler instance
// dynamically. However, javah has a different interface and this
// makes it harder, so here's a simple alternative.
//------------------------------------------------------------------
- System.setOut(logstr);
- System.setErr(logstr);
com.sun.tools.javah.Main main = new com.sun.tools.javah.Main( cmd.getArguments() );
main.run();
}
@@ -335,10 +328,6 @@ public class Javah extends Task {
} else {
throw new BuildException("Error starting javah: ", ex, location);
}
- } finally {
- System.setErr(err);
- System.setOut(out);
- logstr.close();
}
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
index 483ab368d..b8872eec1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
@@ -155,7 +155,8 @@ public class JUnitTask extends Task {
private Integer timeout = null;
private boolean summary = false;
private String summaryValue = "";
-
+ private JUnitTestRunner runner = null;
+
/**
* Tells this task to halt when there is an error in a test.
* this property is applied on all BatchTest (batchtest) and JUnitTest (test)
@@ -509,6 +510,25 @@ public class JUnitTask extends Task {
// whole build. IMHO this method should be avoided and it would be best
// to remove it in future versions. TBD. (SBa)
+
+ protected void handleOutput(String line) {
+ if (runner != null) {
+ runner.handleOutput(line);
+ }
+ else {
+ super.handleOutput(line);
+ }
+ }
+
+ protected void handleErrorOutput(String line) {
+ if (runner != null) {
+ runner.handleErrorOutput(line);
+ }
+ else {
+ super.handleErrorOutput(line);
+ }
+ }
+
/**
* Execute inside VM.
*/
@@ -535,7 +555,7 @@ public class JUnitTask extends Task {
// will cause trouble in JDK 1.1 if omitted
cl.addSystemPackageRoot("org.apache.tools.ant");
}
- JUnitTestRunner runner = new JUnitTestRunner(test, test.getHaltonerror(), test.getHaltonfailure(), cl);
+ runner = new JUnitTestRunner(test, test.getHaltonerror(), test.getHaltonfailure(), cl);
if (summary) {
log("Running " + test.getName(), Project.MSG_INFO);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
index fd0f52c31..3021a7172 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
@@ -138,6 +138,12 @@ public class JUnitTestRunner implements TestListener {
*/
private JUnitTest junitTest;
+ /** output written during the test */
+ private PrintStream systemError;
+
+ /** Error output during the test */
+ private PrintStream systemOut;
+
/**
* Constructor for fork=true or when the user hasn't specified a
* classpath.
@@ -212,22 +218,19 @@ public class JUnitTestRunner implements TestListener {
} else {
- PrintStream oldErr = System.err;
- PrintStream oldOut = System.out;
-
ByteArrayOutputStream errStrm = new ByteArrayOutputStream();
- System.setErr(new PrintStream(errStrm));
+ systemError = new PrintStream(errStrm);
ByteArrayOutputStream outStrm = new ByteArrayOutputStream();
- System.setOut(new PrintStream(outStrm));
+ systemOut = new PrintStream(outStrm);
try {
suite.run(res);
} finally {
- System.err.close();
- System.out.close();
- System.setErr(oldErr);
- System.setOut(oldOut);
+ systemError.close();
+ systemError = null;
+ systemOut.close();
+ systemOut = null;
sendOutAndErr(new String(outStrm.toByteArray()),
new String(errStrm.toByteArray()));
@@ -299,6 +302,18 @@ public class JUnitTestRunner implements TestListener {
}
}
+ protected void handleOutput(String line) {
+ if (systemOut != null) {
+ systemOut.println(line);
+ }
+ }
+
+ protected void handleErrorOutput(String line) {
+ if (systemError != null) {
+ systemError.println(line);
+ }
+ }
+
private void sendOutAndErr(String out, String err) {
for (int i=0; i