diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java
new file mode 100644
index 000000000..588bafc53
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java
@@ -0,0 +1,127 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import java.lang.reflect.Method;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * A set of helpers functions to deal with JUnit.
+ *
+ * @author Stephane Bailliez
+ */
+public final class JUnitHelper {
+
+ private static final String SUITE_METHODNAME = "suite";
+
+ /**
+ * This method parse the output of the method toString()
+ * from the TestCase class. The format returned is:
+ * name(classname)
+ * @return an array with the elements in the order name, classname.
+ */
+ public static String[] parseTestString(String testname){
+ int p1 = testname.indexOf('(');
+ int p2 = testname.indexOf(')', p1);
+ return new String[]{
+ testname.substring(0, p1),
+ testname.substring(p1 + 1, p2) };
+ }
+
+ /**
+ * Returns the Test corresponding to to the given class name
+ * @param classname the classname of the test we want to extract.
+ * @throws Exception a generic exception
+ */
+ public static Test getTest(ClassLoader loader, String classname) throws Exception {
+ Class clazz = null;
+ if (loader == null) {
+ clazz = Class.forName(classname);
+ } else {
+ loader.loadClass(classname);
+ }
+ return getTest(clazz);
+ }
+
+
+ /**
+ * Extract a test from a given class
+ * @param clazz the class to extract a test from.
+ * @throws Exception a generic exception
+ */
+ public static Test getTest(Class clazz) {
+ try {
+ Object obj = clazz.newInstance();
+ if (obj instanceof TestSuite){
+ return (TestSuite) obj;
+ }
+ } catch (Exception e){
+ }
+ try {
+ // check if there is a suite method
+ Method suiteMethod = clazz.getMethod(SUITE_METHODNAME, new Class[0]);
+ return (Test) suiteMethod.invoke(null, new Class[0]);
+ } catch (Exception e) {
+ }
+ // try to extract a test suite automatically
+ // this will generate warnings if the class is no suitable Test
+ try {
+ return new TestSuite(clazz);
+ } catch (Exception e){
+ }
+ return null;
+ }
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestRunListener.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestRunListener.java
new file mode 100644
index 000000000..297d43dd1
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestRunListener.java
@@ -0,0 +1,120 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import java.util.Properties;
+
+
+/**
+ * A test sequence listener listening for a batch test run.
+ *
+ *
+ * This code is based on the code from Erich Gamma made for the
+ * JUnit plugin for Eclipse. {@link http://www.eclipse.org} and is merged
+ * with code originating from Ant 1.4.x.
+ *
+ *
+ * @author Stephane Bailliez
+ */
+public interface TestRunListener {
+
+ /** Some tests failed. */
+ public final static int STATUS_FAILURE = 1;
+
+ /** An error occured. */
+ public final static int STATUS_ERROR = 2;
+
+ /**
+ * A test has started.
+ * @param a testname made of the testname and testcase classname.
+ * in the following format: <testname>(<testcase>)
+ */
+ public void testStarted(String testname);
+
+ /**
+ * A test ended.
+ * @param a testname made of the testname and testcase classname.
+ * in the following format: <testname>(<testcase>)
+ */
+ public void testEnded(String testname);
+
+ /**
+ * A test has failed.
+ * @param status failure or error status code.
+ * @param a testname made of the testname and testcase classname.
+ * in the following format: <testname>(<testcase>)
+ * @param trace the error/failure stacktrace.
+ * @todo change this to a testFailure / testError ?
+ */
+ public void testFailed(int status, String testname, String trace);
+
+ /** test logged this line on stdout */
+ public void testStdOutLine(String testname, String line);
+
+ /** test logged this line on sterr */
+ public void testStdErrLine(String testname, String line);
+
+ /** these system properties are used on the remote client */
+ public void testRunSystemProperties(Properties props);
+
+ /** starting a sequence of testcount tests. */
+ public void testRunStarted(int testcount);
+
+ /** ending gracefully the sequence after elapsedtime ms. */
+ public void testRunEnded(long elapsedtime);
+
+ /** stopping the sequence after elapsedtime ms. */
+ public void testRunStopped(long elapsedtime);
+
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/WatchdogTest.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/WatchdogTest.java
new file mode 100644
index 000000000..7a0587acd
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/WatchdogTest.java
@@ -0,0 +1,115 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 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", "Jakarta-Regexp", 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
+ * .
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import junit.extensions.TestDecorator;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+/**
+ * A Test decorator that allows to cancel a test if it exceeds
+ * a certain time. It can be used globally or individually over
+ * each testcase.
+ *
+ * @author Stephane Bailliez
+ */
+public class WatchdogTest extends TestDecorator {
+
+ /** the time out delay in msecs */
+ protected long timeOut;
+
+ /**
+ * Create a new watchdog.
+ * @param test the test to watch for
+ * @param msecs the time out delay in msecs.
+ */
+ public WatchdogTest(Test test, long msecs) {
+ super(test);
+ timeOut = msecs;
+ }
+
+ public void run(TestResult result) {
+ Thread worker = createWorker(result);
+ worker.start();
+
+ try {
+ // wait at most the timeOut time.
+ worker.join(timeOut);
+
+ // if the thread is still alive, it must be killed.
+ if (worker.isAlive()) {
+ worker.interrupt();
+ result.addFailure(getTest(),
+ new AssertionFailedError("Timed out after " + timeOut + "ms"));
+ }
+ } catch (InterruptedException e) {
+ worker.interrupt();
+ result.addError(getTest(), e);
+ result.stop();
+ }
+ }
+
+ /** create a new worker thread */
+ protected Thread createWorker(final TestResult result) {
+ Thread worker = new Thread("JUnit Test Worker") {
+ public void run() {
+ getTest().run(result);
+ }
+ };
+ return worker;
+ }
+
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/BaseFormatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/BaseFormatter.java
new file mode 100644
index 000000000..74b89b1de
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/BaseFormatter.java
@@ -0,0 +1,160 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Properties;
+
+/**
+ * Provide a common set of attributes and methods to factorize
+ *
+ * @author Stephane Bailliez
+ */
+public abstract class BaseFormatter implements Formatter {
+
+ protected OutputStream out;
+
+ protected PrintWriter writer;
+
+ protected int errorCount;
+
+ protected int failureCount;
+
+ protected int runCount;
+
+ protected Properties props;
+
+ public void setOutput(OutputStream value) {
+ out = value;
+ try {
+ writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF8")), true);
+ } catch (IOException e){
+ // should not happen
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ super.finalize();
+ close();
+ }
+
+ public void setSystemOutput(String out) {
+ }
+
+ public void setSystemError(String err) {
+ }
+
+ public void testStdOutLine(String testname, String line) {
+ }
+
+ public void testStdErrLine(String testname, String line) {
+ }
+
+ public void testRunSystemProperties(Properties props) {
+ }
+
+ public void testStarted(String testname) {
+ }
+
+ public void testEnded(String testname) {
+ }
+
+ public void testFailed(int status, String testname, String trace) {
+ if (status == STATUS_ERROR) {
+ errorCount++;
+ } else if (status == STATUS_FAILURE) {
+ failureCount++;
+ }
+ }
+
+ public void testRunStarted(int testcount) {
+ runCount = testcount;
+ }
+
+ public void testRunEnded(long elapsedtime) {
+ finished(elapsedtime);
+ }
+
+ public void testRunStopped(long elapsedtime) {
+ finished(elapsedtime);
+ }
+
+ protected void finished(long elapsedtime) {
+ close();
+ }
+
+ /** helper method to flush and close all streams */
+ protected void close() {
+ try {
+ if (writer != null) {
+ writer.flush();
+ writer = null;
+ }
+ } finally {
+ // make sure we're not closing System.out or System.err...
+ if (out != null && out != System.err && out != System.out) {
+ try {
+ out.close();
+ out = null;
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/BriefFormatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/BriefFormatter.java
new file mode 100644
index 000000000..602a9d841
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/BriefFormatter.java
@@ -0,0 +1,80 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+
+/**
+ * Display additional messages from a SummaryFormatter
+ * for failures and errors.
+ *
+ * @author Stephane Bailliez
+ */
+public class BriefFormatter extends SummaryFormatter {
+
+ public void testFailed(int status, String testname, String trace) {
+ writer.print("TestCase: ");
+ writer.print(testname);
+ if (status == STATUS_ERROR) {
+ writer.print("\tCaused an ERROR");
+ } else if (status == STATUS_FAILURE) {
+ writer.write("\tFAILED");
+ }
+ writer.println();
+ writer.print(trace);
+ writer.println();
+ writer.println();
+ super.testFailed(status, testname, trace);
+ }
+
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/DefaultTestRunListener.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/DefaultTestRunListener.java
new file mode 100644
index 000000000..5bb2ffca9
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/DefaultTestRunListener.java
@@ -0,0 +1,94 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.util.Properties;
+
+import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
+
+/**
+ *
+ * @author Stephane Bailliez
+ */
+public class DefaultTestRunListener implements TestRunListener {
+
+ public void testStarted(String testname) {
+ System.out.println("Started " + testname);
+ }
+
+ public void testEnded(String testname) {
+ System.out.println("Ended " + testname);
+ }
+
+ public void testFailed(int status, String testname, String trace) {
+ System.out.println(testname + " failed with status " + status);
+ System.out.println(trace);
+ }
+
+ public void testRunSystemProperties(Properties props) {
+ System.out.println("properties: " + props);
+ }
+
+ public void testRunStarted(int testcount) {
+ System.out.println("testsuite: " + testcount);
+ }
+
+ public void testRunEnded(long elapsedtime) {
+ System.out.println("testsuite ended after: " + elapsedtime);
+ }
+
+ public void testRunStopped(long elapsedtime) {
+ System.out.println("testsuite stopped after: " + elapsedtime);
+ }
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/FilterFormatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/FilterFormatter.java
new file mode 100644
index 000000000..514f055b1
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/FilterFormatter.java
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.io.OutputStream;
+import java.util.Properties;
+
+/**
+ * A base class that can be used to filter data.
+ *
+ * @author Stephane Bailliez
+ */
+public abstract class FilterFormatter implements Formatter {
+
+ protected Formatter formatter;
+
+ protected FilterFormatter(Formatter value){
+ formatter = value;
+ }
+
+ public void setOutput(OutputStream out) {
+ formatter.setOutput(out);
+ }
+
+ public void testStarted(String testname) {
+ formatter.testStarted(testname);
+ }
+
+ public void setSystemOutput(String out) {
+ formatter.setSystemOutput(out);
+ }
+
+ public void testEnded(String testname) {
+ formatter.testEnded(testname);
+ }
+
+ public void setSystemError(String err) {
+ formatter.setSystemError(err);
+ }
+
+ public void testFailed(int status, String testname, String trace) {
+ formatter.testFailed(status, testname, trace);
+ }
+
+ public void testRunSystemProperties(Properties props) {
+ formatter.testRunSystemProperties(props);
+ }
+
+ public void testRunStarted(int testcount) {
+ formatter.testRunStarted(testcount);
+ }
+
+ public void testRunEnded(long elapsedtime) {
+ formatter.testRunEnded(elapsedtime);
+ }
+
+ public void testRunStopped(long elapsedtime) {
+ formatter.testRunEnded(elapsedtime);
+ }
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/FilterStackFormatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/FilterStackFormatter.java
new file mode 100644
index 000000000..d12fd9ffa
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/FilterStackFormatter.java
@@ -0,0 +1,132 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.io.StringWriter;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.BufferedReader;
+import java.util.StringTokenizer;
+
+import org.apache.tools.ant.util.StringUtils;
+
+/**
+ * Filtered Formatter that strips out unwanted stack frames from the full
+ * stack trace, for instance it will filter the lines containing the
+ * following matches:
+ *
+ * junit.framework.TestCase
+ * junit.framework.TestResult
+ * junit.framework.TestSuite
+ * junit.framework.Assert.
+ * junit.swingui.TestRunner
+ * junit.awtui.TestRunner
+ * junit.textui.TestRunner
+ * java.lang.reflect.Method.invoke(
+ * org.apache.tools.ant.
+ *
+ * Removing all the above will help to make stacktrace more readable.
+ *
+ * @author Stephane Bailliez
+ */
+public class FilterStackFormatter extends FilterFormatter {
+
+ /** the set of matches to look for in a stack trace */
+ private final static String[] DEFAULT_TRACE_FILTERS = new String[] {
+ "junit.framework.TestCase",
+ "junit.framework.TestResult",
+ "junit.framework.TestSuite",
+ "junit.framework.Assert.", // don't filter AssertionFailure
+ "junit.swingui.TestRunner",
+ "junit.awtui.TestRunner",
+ "junit.textui.TestRunner",
+ "java.lang.reflect.Method.invoke(",
+ "org.apache.tools.ant."
+ };
+
+ /**
+ * Creates a new FilterStackFormatter
+ * @param formatter the formatter to be filtered.
+ */
+ public FilterStackFormatter(Formatter formatter){
+ super(formatter);
+ }
+
+ public void testFailed(int status, String testname, String trace) {
+ StringTokenizer st = new StringTokenizer(trace,"\r\n");
+ StringBuffer buf = new StringBuffer(trace.length());
+ while ( st.hasMoreTokens() ){
+ String line = st.nextToken();
+ if ( accept(line) ){
+ buf.append(line).append(StringUtils.LINE_SEP);
+ }
+ }
+ super.testFailed(status, testname, buf.toString());
+ }
+
+ /**
+ * Check whether or not the line should be accepted.
+ * @param the line to be check for acceptance.
+ * @return true if the line is accepted, false if not.
+ */
+ protected boolean accept(String line){
+ for (int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++) {
+ if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/Formatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/Formatter.java
new file mode 100644
index 000000000..b01cd6efa
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/Formatter.java
@@ -0,0 +1,80 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.io.OutputStream;
+
+import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
+
+/**
+ *
+ * @author Stephane Bailliez
+ */
+public interface Formatter extends TestRunListener {
+ /**
+ * Sets the stream the formatter is supposed to write its results to.
+ */
+ public void setOutput( OutputStream out );
+
+ /**
+ * This is what the test has written to System.out
+ */
+ public void setSystemOutput( String out );
+
+ /**
+ * This is what the test has written to System.err
+ */
+ public void setSystemError( String err );
+
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/SummaryFormatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/SummaryFormatter.java
new file mode 100644
index 000000000..8978e6f3f
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/SummaryFormatter.java
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.text.MessageFormat;
+
+/**
+ * Display a summary message at the end of a testsuite stating
+ * runs, failures, errors, and elapsed time.
+ *
+ * @author Stephane Bailliez
+ */
+public class SummaryFormatter extends BaseFormatter {
+
+ protected MessageFormat mf = new MessageFormat(
+ "Tests run: {0, number, integer}" +
+ ", Failures: {1, number, integer}" +
+ ", Errors: {2, number, integer}" +
+ ", Time elapsed: {3, number, integer} sec");
+
+ protected void finished(long elapsedtime) {
+ writer.print("Testsuite: ");
+ writer.println();
+ String line = mf.format(new Object[]{
+ new Integer(runCount),
+ new Integer(failureCount),
+ new Integer(errorCount),
+ new Long(elapsedtime / 1000)
+ });
+ writer.print(line);
+ writer.println();
+ writer.println();
+ close();
+ }
+
+}
diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/XMLFormatter.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/XMLFormatter.java
new file mode 100644
index 000000000..2b595b7fe
--- /dev/null
+++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/formatter/XMLFormatter.java
@@ -0,0 +1,223 @@
+/*
+ * 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
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.junit.formatter;
+
+import java.util.Hashtable;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
+
+/**
+ *
+ * @author Stephane Bailliez
+ */
+public class XMLFormatter extends BaseFormatter {
+
+ /** the testsuites element for the aggregate document */
+ public final static String TESTSUITES = "testsuites";
+
+ /** the testsuite element */
+ public final static String TESTSUITE = "testsuite";
+
+ /** the testcase element */
+ public final static String TESTCASE = "testcase";
+
+ /** the error element */
+ public final static String ERROR = "error";
+
+ /** the failure element */
+ public final static String FAILURE = "failure";
+
+ /** the system-err element */
+ public final static String SYSTEM_ERR = "system-err";
+
+ /** the system-out element */
+ public final static String SYSTEM_OUT = "system-out";
+
+ /** package attribute for the aggregate document */
+ public final static String ATTR_PACKAGE = "package";
+
+ /** name attribute for property, testcase and testsuite elements */
+ public final static String ATTR_NAME = "name";
+
+ /** time attribute for testcase and testsuite elements */
+ public final static String ATTR_TIME = "time";
+
+ /** errors attribute for testsuite elements */
+ public final static String ATTR_ERRORS = "errors";
+
+ /** failures attribute for testsuite elements */
+ public final static String ATTR_FAILURES = "failures";
+
+ /** tests attribute for testsuite elements */
+ public final static String ATTR_TESTS = "tests";
+
+ /** type attribute for failure and error elements */
+ public final static String ATTR_TYPE = "type";
+
+ /** message attribute for failure elements */
+ public final static String ATTR_MESSAGE = "message";
+
+ /** the properties element */
+ public final static String PROPERTIES = "properties";
+
+ /** the property element */
+ public final static String PROPERTY = "property";
+
+ /** value attribute for property elements */
+ public final static String ATTR_VALUE = "value";
+
+ /** The XML document. */
+ private Document doc;
+
+ /** The wrapper for the whole testsuite. */
+ private Element rootElement;
+
+ /** Element for the current test. */
+ private Hashtable testElements = new Hashtable();
+
+ /** Timing helper. */
+ private Hashtable testStarts = new Hashtable();
+
+ public void testStarted(String testname) {
+ //@fixme, eh, a testname only can obviouslly be a duplicate...
+ testStarts.put(testname, new Long(System.currentTimeMillis()));
+ Element currentTest = doc.createElement(TESTCASE);
+ currentTest.setAttribute(ATTR_NAME, testname);
+ rootElement.appendChild(currentTest);
+ testElements.put(testname, currentTest);
+ super.testStarted(testname);
+ }
+
+ public void testEnded(String testname) {
+ Element currentTest = (Element) testElements.get(testname);
+ // with a TestSetup, startTest and endTest are not called.
+ if (currentTest == null){
+ testStarted(testname);
+ currentTest = (Element) testElements.get(testname);
+ }
+ Long l = (Long) testStarts.get(testname);
+ float time = ((System.currentTimeMillis()-l.longValue()) / 1000.0f);
+ currentTest.setAttribute(ATTR_TIME, Float.toString(time));
+ super.testEnded(testname);
+ // remove the test objects
+ testStarts.remove(testname);
+ testElements.remove(testname);
+ }
+
+ public void testFailed(int status, String testname, String trace) {
+ if (testname != null) {
+ testEnded(testname);
+ }
+ String type = status == STATUS_FAILURE ? FAILURE : ERROR;
+ Element nested = doc.createElement(type);
+ Element currentTest = null;
+ if (testname != null) {
+ currentTest = (Element) testElements.get(testname);
+ } else {
+ currentTest = rootElement;
+ }
+
+ currentTest.appendChild(nested);
+
+ String[] args = parseFirstLine(trace);
+ if (args[1] != null && args[1].length() > 0) {
+ nested.setAttribute(ATTR_MESSAGE, args[1]);
+ }
+ nested.setAttribute(ATTR_TYPE, args[0]);
+ Text text = doc.createTextNode(trace);
+ nested.appendChild(text);
+ super.testFailed(status, testname, trace);
+ }
+
+ public void testRunStarted(int testcount) {
+ super.testRunStarted(testcount);
+ }
+
+ public void testRunEnded(long elapsedtime) {
+ super.testRunEnded(elapsedtime);
+ }
+
+ public void testRunStopped(long elapsedtime) {
+ super.testRunStopped(elapsedtime);
+ }
+
+ private static DocumentBuilder getDocumentBuilder() {
+ try {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch(Exception exc) {
+ throw new ExceptionInInitializerError(exc);
+ }
+ }
+
+ protected static String[] parseFirstLine(String trace){
+ int pos = trace.indexOf('\n');
+ if (pos == -1){
+ return new String[]{ trace, ""};
+ }
+ String line = trace.substring(0, pos);
+ pos = line.indexOf(':');
+ if (pos != -1){
+ String classname = line.substring(0, pos).trim();
+ String message = line.substring(pos + 1).trim();
+ return new String[]{ classname, message };
+ }
+ return new String[]{ trace, ""};
+ }
+}