Author: jglick
Date: Mon Feb 27 14:24:26 2006
New Revision: 381467

URL: http://svn.apache.org/viewcvs?rev=381467&view=rev
Log:
#38799: <junit> task should work so long as junit.jar
present in <classpath> even if not among Ant libs.

Added:
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
   (with props)
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
   (with props)
Modified:
    ant/core/trunk/WHATSNEW
    ant/core/trunk/docs/manual/OptionalTasks/junit.html
    ant/core/trunk/docs/manual/install.html
    ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
    
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
    ant/core/trunk/xdocs/faq.xml

Modified: ant/core/trunk/WHATSNEW
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/WHATSNEW?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Mon Feb 27 14:24:26 2006
@@ -1,4 +1,4 @@
-Changes from current Ant 1.6.5 version to current RCS version
+Changes from current Ant 1.6.5 version to current SVN version
 =============================================================
 
 Changes that could break older environments:
@@ -76,6 +76,8 @@
 
 Fixed bugs:
 -----------
+
+* <junit> can now work with junit.jar in its <classpath>. Bugzilla Report 
38799.
 
 * Some potential NullPointerExceptions, Bugzilla Reports 37765 and 38056
 

Modified: ant/core/trunk/docs/manual/OptionalTasks/junit.html
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/OptionalTasks/junit.html?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/OptionalTasks/junit.html (original)
+++ ant/core/trunk/docs/manual/OptionalTasks/junit.html Mon Feb 27 14:24:26 2006
@@ -19,12 +19,12 @@
 </p>
 <p>
 <strong>Note</strong>:
-You must have <code>junit.jar</code> and the class files for the
-<code>&lt;junit&gt;</code> task in the same classpath.
+You must have <code>junit.jar</code> available.
 You can do one of:
+</p>
 <ol>
 <li>
-Put both <code>junit.jar</code> and the optional tasks jar file in
+Put both <code>junit.jar</code> and <code>ant-junit.jar</code> in
 <code>ANT_HOME/lib</code>.
 </li>
 <li>
@@ -32,15 +32,23 @@
 include their locations in your <code>CLASSPATH</code> environment variable.
 </li>
 <li>
-Do neither of the above, and instead, specify their locations using
-a <code>&lt;classpath&gt;</code> element in the build file.
-
+Add both JARs to your classpath using <code>-lib</code>.
+</li>
+<li>
+Specify the locations of both JARs using
+a <code>&lt;classpath&gt;</code> element in a <code>&lt;taskdef&gt;</code> in 
the build file.
+</li>
+<li>
+Leave <code>ant-junit.jar</code> in its default location in 
<code>ANT_HOME/lib</code>
+but include <code>junit.jar</code> in the <code>&lt;classpath&gt;</code> passed
+to <code>&lt;junit&gt;</code>. <em>(since Ant 1.7)</em>
+</li>
+</ol>
+<p>
 See <a href="../../faq.html#delegating-classloader" target="_top">the
 FAQ</a> for details.
-</ol>
 </p>
 
-
 <p>Tests are defined by nested <code>test</code> or
 <code>batchtest</code> tags (see <a href="#nested">nested
 elements</a>).</p>
@@ -217,6 +225,9 @@
 element that represents a <a href="../using.html#path">PATH like
 structure</a>.</p>
 
+<p>As of Ant 1.7, this classpath may be used to refer to <code>junit.jar</code>
+as well as your tests and the tested code.
+
 <h4>jvmarg</h4>
 
 <p>If <code>fork</code> is enabled, additional parameters may be passed to
@@ -580,7 +591,7 @@
 <code>${reports.tests}</code>.</p>
 
 <hr>
-<p align="center">Copyright &copy; 2000-2005 The Apache Software Foundation. 
All rights
+<p align="center">Copyright &copy; 2000-2006 The Apache Software Foundation. 
All rights
 Reserved.</p>
 </body>
 </html>

Modified: ant/core/trunk/docs/manual/install.html
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/install.html?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/install.html (original)
+++ ant/core/trunk/docs/manual/install.html Mon Feb 27 14:24:26 2006
@@ -456,7 +456,7 @@
   </tr>
   <tr>
     <td>junit.jar</td>
-    <td>junit tasks</td>
+    <td><code>&lt;junit&gt;</code> task. May be in classpath passed to task 
rather than Ant's classpath.</td>
     <td><a href="http://www.junit.org/"; 
target="_top">http://www.junit.org/</a></td>
   </tr>
   <tr>
@@ -698,7 +698,7 @@
 
 
 <hr>
-<p align="center">Copyright &copy; 2000-2005 The Apache Software Foundation. 
All rights
+<p align="center">Copyright &copy; 2000-2006 The Apache Software Foundation. 
All rights
 Reserved.</p>
 
 </body>

Modified: ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java Mon Feb 27 
14:24:26 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright  2000-2005 The Apache Software Foundation
+ * Copyright  2000-2006 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -1488,6 +1488,10 @@
             String packageName = (String) e.nextElement();
             addSystemPackageRoot(packageName);
         }
+    }
+
+    public String toString() {
+        return "AntClassLoader[" + getClasspath() + "]";
     }
 
 }

Modified: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
 (original)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
 Mon Feb 27 14:24:26 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright  2001-2004 The Apache Software Foundation
+ * Copyright  2001-2004,2006 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -188,14 +188,14 @@
     /**
      * @since Ant 1.2
      */
-    JUnitResultFormatter createFormatter() throws BuildException {
+    JUnitTaskMirror.JUnitResultFormatterMirror createFormatter() throws 
BuildException {
         return createFormatter(null);
     }
 
     /**
      * @since Ant 1.6
      */
-    JUnitResultFormatter createFormatter(ClassLoader loader)
+    JUnitTaskMirror.JUnitResultFormatterMirror createFormatter(ClassLoader 
loader)
         throws BuildException {
 
         if (classname == null) {
@@ -210,7 +210,9 @@
                 f = Class.forName(classname, true, loader);
             }
         } catch (ClassNotFoundException e) {
-            throw new BuildException(e);
+            throw new BuildException("Using loader " + loader + " on class " + 
classname + ": " + e, e);
+        } catch (NoClassDefFoundError e) {
+            throw new BuildException("Using loader " + loader + " on class " + 
classname + ": " + e, e);
         }
 
         Object o = null;
@@ -222,12 +224,11 @@
             throw new BuildException(e);
         }
 
-        if (!(o instanceof JUnitResultFormatter)) {
+        if (!(o instanceof JUnitTaskMirror.JUnitResultFormatterMirror)) {
             throw new BuildException(classname
                 + " is not a JUnitResultFormatter");
         }
-
-        JUnitResultFormatter r = (JUnitResultFormatter) o;
+        JUnitTaskMirror.JUnitResultFormatterMirror r = 
(JUnitTaskMirror.JUnitResultFormatterMirror) o;
 
         if (useFile && outFile != null) {
             try {

Modified: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
 (original)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
 Mon Feb 27 14:24:26 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright  2001-2002,2004 The Apache Software Foundation
+ * Copyright  2001-2002,2004,2006 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
  * testrun.
  *
  */
-public interface JUnitResultFormatter extends TestListener {
+public interface JUnitResultFormatter extends TestListener, 
JUnitTaskMirror.JUnitResultFormatterMirror {
     /**
      * The whole testsuite started.
      */

Modified: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
 (original)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
 Mon Feb 27 14:24:26 2006
@@ -24,6 +24,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
@@ -34,9 +35,6 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Vector;
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestResult;
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -134,7 +132,7 @@
     private boolean summary = false;
     private boolean reloading = true;
     private String summaryValue = "";
-    private JUnitTestRunner runner = null;
+    private JUnitTaskMirror.JUnitTestRunnerMirror runner = null;
 
     private boolean newEnvironment = false;
     private Environment env = new Environment();
@@ -148,6 +146,9 @@
     private Permissions perm = null;
     private ForkMode forkMode = new ForkMode("perTest");
 
+    private boolean splitJunit = false;
+    private JUnitTaskMirror delegate;
+
     private static final int STRING_BUFFER_SIZE = 128;
     /**
      * @since Ant 1.7
@@ -632,12 +633,81 @@
      */
     public void init() {
         antRuntimeClasses = new Path(getProject());
-        addClasspathEntry("/junit/framework/TestCase.class");
+        splitJunit = !addClasspathEntry("/junit/framework/TestCase.class");
         addClasspathEntry("/org/apache/tools/ant/launch/AntMain.class");
         addClasspathEntry("/org/apache/tools/ant/Task.class");
         
addClasspathEntry("/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class");
     }
 
+    private static JUnitTaskMirror createMirror(JUnitTask task, ClassLoader 
loader) {
+        try {
+            loader.loadClass("junit.framework.Test"); // sanity check
+        } catch (ClassNotFoundException e) {
+            throw new BuildException(
+                    "The <classpath> for <junit> must include junit.jar if not 
in Ant's own classpath",
+                    e, task.getLocation());
+        }
+        try {
+            Class c = loader.loadClass(JUnitTaskMirror.class.getName() + 
"Impl");
+            if (c.getClassLoader() != loader) {
+                throw new BuildException("Overdelegating loader", 
task.getLocation());
+            }
+            Constructor cons = c.getConstructor(new Class[] {JUnitTask.class});
+            return (JUnitTaskMirror) cons.newInstance(new Object[] {task});
+        } catch (Exception e) {
+            throw new BuildException(e, task.getLocation());
+        }
+    }
+
+    private final class SplitLoader extends AntClassLoader {
+
+        public SplitLoader(ClassLoader parent, Path path) {
+            super(parent, getProject(), path, true);
+        }
+
+        // forceLoadClass is not convenient here since it would not
+        // properly deal with inner classes of these classes.
+        protected synchronized Class loadClass(String classname, boolean 
resolve)
+        throws ClassNotFoundException {
+            Class theClass = findLoadedClass(classname);
+            if (theClass != null) {
+                return theClass;
+            }
+            if (isSplit(classname)) {
+                theClass = findClass(classname);
+                if (resolve) {
+                    resolveClass(theClass);
+                }
+                return theClass;
+            } else {
+                return super.loadClass(classname, resolve);
+            }
+        }
+
+        private final String[] SPLIT_CLASSES = {
+            "BriefJUnitResultFormatter",
+            "JUnitResultFormatter",
+            "JUnitTaskMirrorImpl",
+            "JUnitTestRunner",
+            "JUnitVersionHelper",
+            "OutErrSummaryJUnitResultFormatter",
+            "PlainJUnitResultFormatter",
+            "SummaryJUnitResultFormatter",
+            "XMLJUnitResultFormatter",
+        };
+
+        private boolean isSplit(String classname) {
+            String simplename = classname.substring(classname.lastIndexOf('.') 
+ 1);
+            for (int i = 0; i < SPLIT_CLASSES.length; i++) {
+                if (simplename.equals(SPLIT_CLASSES[i]) || 
simplename.startsWith(SPLIT_CLASSES[i] + '$')) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+    }
+    
     /**
      * Runs the testcase.
      *
@@ -645,6 +715,18 @@
      * @since Ant 1.2
      */
     public void execute() throws BuildException {
+        ClassLoader myLoader = JUnitTask.class.getClassLoader();
+        ClassLoader mirrorLoader;
+        if (splitJunit) {
+            Path path = new Path(getProject());
+            path.add(antRuntimeClasses);
+            path.add(getCommandline().getClasspath());
+            mirrorLoader = new SplitLoader(myLoader, path);
+        } else {
+            mirrorLoader = myLoader;
+        }
+        delegate = createMirror(this, mirrorLoader);
+
         List testLists = new ArrayList();
 
         boolean forkPerTest = forkMode.getValue().equals(ForkMode.PER_TEST);
@@ -672,6 +754,10 @@
             }
         } finally {
             deleteClassLoader();
+            if (mirrorLoader instanceof SplitLoader) {
+                ((SplitLoader) mirrorLoader).cleanup();
+            }
+            delegate = null;
         }
     }
 
@@ -1061,18 +1147,22 @@
         try {
             log("Using System properties " + System.getProperties(),
                 Project.MSG_VERBOSE);
-            createClassLoader();
+            if (splitJunit) {
+                classLoader = (AntClassLoader) 
delegate.getClass().getClassLoader();
+            } else {
+                createClassLoader();
+            }
             if (classLoader != null) {
                 classLoader.setThreadContextLoader();
             }
-            runner = new JUnitTestRunner(test, test.getHaltonerror(),
+            runner = delegate.newJUnitTestRunner(test, test.getHaltonerror(),
                                          test.getFiltertrace(),
                                          test.getHaltonfailure(), false,
                                          true, classLoader);
             if (summary) {
 
-                SummaryJUnitResultFormatter f =
-                    new SummaryJUnitResultFormatter();
+                JUnitTaskMirror.SummaryJUnitResultFormatterMirror f =
+                    delegate.newSummaryJUnitResultFormatter();
                 f.setWithOutAndErr("withoutanderr"
                                    .equalsIgnoreCase(summaryValue));
                 f.setOutput(getDefaultOutput());
@@ -1186,7 +1276,7 @@
         if (fe.getUseFile()) {
             String base = test.getOutfile();
             if (base == null) {
-                base = JUnitTestRunner.IGNORED_FILE_NAME;
+                base = JUnitTaskMirror.JUnitTestRunnerMirror.IGNORED_FILE_NAME;
             }
             String filename = base + fe.getExtension();
             File destFile = new File(test.getTodir(), filename);
@@ -1204,9 +1294,10 @@
      * getResource doesn't contain the name of the archive.</p>
      *
      * @param resource resource that one wants to lookup
+     * @return true if something was in fact added
      * @since Ant 1.4
      */
-    protected void addClasspathEntry(String resource) {
+    protected boolean addClasspathEntry(String resource) {
         /*
          * pre Ant 1.6 this method used to call getClass().getResource
          * while Ant 1.6 will call ClassLoader.getResource().
@@ -1228,8 +1319,10 @@
         if (f != null) {
             log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG);
             antRuntimeClasses.createPath().setLocation(f);
+            return true;
         } else {
             log("Couldn\'t find " + resource, Project.MSG_DEBUG);
+            return false;
         }
     }
 
@@ -1269,7 +1362,7 @@
         for (int i = 0; i < feArray.length; i++) {
             FormatterElement fe = feArray[i];
             File outFile = getOutput(fe, test);
-            JUnitResultFormatter formatter = fe.createFormatter(classLoader);
+            JUnitTaskMirror.JUnitResultFormatterMirror formatter = 
fe.createFormatter(classLoader);
             if (outFile != null && formatter != null) {
                 try {
                     OutputStream out = new FileOutputStream(outFile);
@@ -1280,7 +1373,7 @@
             }
         }
         if (summary) {
-            SummaryJUnitResultFormatter f = new SummaryJUnitResultFormatter();
+            JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = 
delegate.newSummaryJUnitResultFormatter();
             f.setWithOutAndErr("withoutanderr".equalsIgnoreCase(summaryValue));
             addVmExit(test, f, getDefaultOutput(), message);
         }
@@ -1291,23 +1384,9 @@
      * Only used from the logVmExit method.
      * @since Ant 1.7
      */
-    private void addVmExit(JUnitTest test, JUnitResultFormatter formatter,
+    private void addVmExit(JUnitTest test, 
JUnitTaskMirror.JUnitResultFormatterMirror formatter,
                            OutputStream out, final String message) {
-        formatter.setOutput(out);
-        formatter.startTestSuite(test);
-
-        //the trick to integrating test output to the formatter, is to
-        //create a special test class that asserts an error
-        //and tell the formatter that it raised.
-        Test t = new Test() {
-            public int countTestCases() { return 1; }
-            public void run(TestResult r) {
-                throw new AssertionFailedError(message);
-            }
-        };
-        formatter.startTest(t);
-        formatter.addError(t, new AssertionFailedError(message));
-        formatter.endTestSuite(test);
+        delegate.addVmExit(test, formatter, out, message);
     }
 
     /**
@@ -1535,9 +1614,9 @@
         // everything otherwise just log a statement
         boolean fatal = result.timedOut || result.crashed;
         boolean errorOccurredHere =
-            result.exitCode == JUnitTestRunner.ERRORS || fatal;
+            result.exitCode == JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS || 
fatal;
         boolean failureOccurredHere =
-            result.exitCode != JUnitTestRunner.SUCCESS || fatal;
+            result.exitCode != JUnitTaskMirror.JUnitTestRunnerMirror.SUCCESS 
|| fatal;
         if (errorOccurredHere || failureOccurredHere) {
             if ((errorOccurredHere && test.getHaltonerror())
                 || (failureOccurredHere && test.getHaltonfailure())) {
@@ -1559,7 +1638,7 @@
     }
 
     protected class TestResultHolder {
-        public int exitCode = JUnitTestRunner.ERRORS;
+        public int exitCode = JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS;
         public boolean timedOut = false;
         public boolean crashed = false;
     }

Added: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java?rev=381467&view=auto
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
 (added)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
 Mon Feb 27 14:24:26 2006
@@ -0,0 +1,110 @@
+/*
+ * Copyright  2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.types.Permissions;
+
+/**
+ * Handles the portions of [EMAIL PROTECTED] JUnitTask} which need to directly 
access
+ * actual JUnit classes, so that junit.jar need not be on Ant's startup 
classpath.
+ * Neither JUnitTask.java nor JUnitTaskMirror.java nor their transitive static
+ * deps may import any junit.** classes!
+ * Specifically, need to not refer to
+ * - JUnitResultFormatter or its subclasses
+ * - JUnitVersionHelper
+ * - JUnitTestRunner
+ * Cf. [EMAIL PROTECTED] JUnitTask.SplitLoader#isSplit}
+ * Public only to permit access from classes in this package; do not use 
directly.
+ * 
+ * @author refactoring tricks by Jesse Glick, real code by others
+ * @since 1.7
+ * @see "bug #38799"
+ */
+public interface JUnitTaskMirror {
+    
+    void addVmExit(JUnitTest test, JUnitResultFormatterMirror formatter,
+            OutputStream out, final String message);
+    
+    JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, boolean 
haltOnError,
+            boolean filterTrace, boolean haltOnFailure, boolean showOutput,
+            boolean logTestListenerEvents, AntClassLoader classLoader);
+
+    SummaryJUnitResultFormatterMirror newSummaryJUnitResultFormatter();
+
+    public interface JUnitResultFormatterMirror {
+
+        void setOutput(OutputStream outputStream);
+
+    }
+
+    public interface SummaryJUnitResultFormatterMirror extends 
JUnitResultFormatterMirror {
+
+        void setWithOutAndErr(boolean value);
+
+    }
+
+    public interface JUnitTestRunnerMirror {
+
+        /**
+         * Used in formatter arguments as a placeholder for the basename
+         * of the output file (which gets replaced by a test specific
+         * output file name later).
+         *
+         * @since Ant 1.6.3
+         */
+        String IGNORED_FILE_NAME = "IGNORETHIS";
+
+        /**
+         * No problems with this test.
+         */
+        int SUCCESS = 0;
+    
+        /**
+         * Some tests failed.
+         */
+        int FAILURES = 1;
+
+        /**
+         * An error occurred.
+         */
+        int ERRORS = 2;
+
+        void setPermissions(Permissions perm);
+    
+        void run();
+
+        void addFormatter(JUnitResultFormatterMirror formatter);
+    
+        int getRetCode();
+    
+        void handleErrorFlush(String output);
+    
+        void handleErrorOutput(String output);
+    
+        void handleOutput(String output);
+    
+        int handleInput(byte[] buffer, int offset, int length) throws 
IOException;
+    
+        void handleFlush(String output);
+
+    }
+    
+}

Propchange: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java?rev=381467&view=auto
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
 (added)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
 Mon Feb 27 14:24:26 2006
@@ -0,0 +1,72 @@
+/*
+ * Copyright  2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import java.io.OutputStream;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestResult;
+import org.apache.tools.ant.AntClassLoader;
+
+/**
+ * Implementation of the part of the junit task which can directly refer to 
junit.* classes.
+ * Public only to permit use of reflection; do not use directly.
+ * @see JUnitTaskMirror
+ * @see "bug #38799"
+ * @since 1.7
+ */
+public final class JUnitTaskMirrorImpl implements JUnitTaskMirror {
+    
+    private final JUnitTask task;
+    
+    public JUnitTaskMirrorImpl(JUnitTask task) {
+        this.task = task;
+    }
+    
+    public void addVmExit(JUnitTest test, JUnitResultFormatterMirror 
_formatter,
+            OutputStream out, final String message) {
+        JUnitResultFormatter formatter = (JUnitResultFormatter) _formatter;
+        formatter.setOutput(out);
+        formatter.startTestSuite(test);
+        
+        //the trick to integrating test output to the formatter, is to
+        //create a special test class that asserts an error
+        //and tell the formatter that it raised.
+        Test t = new Test() {
+            public int countTestCases() { return 1; }
+            public void run(TestResult r) {
+                throw new AssertionFailedError(message);
+            }
+        };
+        formatter.startTest(t);
+        formatter.addError(t, new AssertionFailedError(message));
+        formatter.endTestSuite(test);
+    }
+
+    public JUnitTaskMirror.JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest 
test,
+            boolean haltOnError, boolean filterTrace, boolean haltOnFailure,
+            boolean showOutput, boolean logTestListenerEvents, AntClassLoader 
classLoader) {
+        return new JUnitTestRunner(test, haltOnError, filterTrace, 
haltOnFailure,
+                showOutput, logTestListenerEvents, classLoader);
+    }
+
+    public JUnitTaskMirror.SummaryJUnitResultFormatterMirror 
newSummaryJUnitResultFormatter() {
+        return new SummaryJUnitResultFormatter();
+    }
+    
+}

Propchange: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
 (original)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
 Mon Feb 27 14:24:26 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright  2000-2005 The Apache Software Foundation
+ * Copyright  2000-2006 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -62,31 +62,7 @@
  * @since Ant 1.2
  */
 
-public class JUnitTestRunner implements TestListener {
-
-    /**
-     * No problems with this test.
-     */
-    public static final int SUCCESS = 0;
-
-    /**
-     * Some tests failed.
-     */
-    public static final int FAILURES = 1;
-
-    /**
-     * An error occurred.
-     */
-    public static final int ERRORS = 2;
-
-    /**
-     * Used in formatter arguments as a placeholder for the basename
-     * of the output file (which gets replaced by a test specific
-     * output file name later).
-     *
-     * @since Ant 1.6.3
-     */
-    public static final String IGNORED_FILE_NAME = "IGNORETHIS";
+public class JUnitTestRunner implements TestListener, 
JUnitTaskMirror.JUnitTestRunnerMirror {
 
     /**
      * Holds the registered formatters.
@@ -441,7 +417,7 @@
         perm = permissions;
     }
 
-    protected void handleOutput(String output) {
+    public void handleOutput(String output) {
         if (!logTestListenerEvents && 
output.startsWith(JUnitTask.TESTLISTENER_PREFIX))
             ; // ignore
         else if (systemOut != null) {
@@ -454,24 +430,24 @@
      *
      * @since Ant 1.6
      */
-    protected int handleInput(byte[] buffer, int offset, int length)
+    public int handleInput(byte[] buffer, int offset, int length)
         throws IOException {
         return -1;
     }
 
-    protected void handleErrorOutput(String output) {
+    public void handleErrorOutput(String output) {
         if (systemError != null) {
             systemError.print(output);
         }
     }
 
-    protected void handleFlush(String output) {
+    public void handleFlush(String output) {
         if (systemOut != null) {
             systemOut.print(output);
         }
     }
 
-    protected void handleErrorFlush(String output) {
+    public void handleErrorFlush(String output) {
         if (systemError != null) {
             systemError.print(output);
         }
@@ -505,6 +481,10 @@
         formatters.addElement(f);
     }
 
+    public void addFormatter(JUnitTaskMirror.JUnitResultFormatterMirror f) {
+        formatters.addElement((JUnitResultFormatter) f);
+    }
+
     /**
      * Entry point for standalone (forked) mode.
      *
@@ -645,7 +625,7 @@
                              test.getOutfile() + fe.getExtension());
                 fe.setOutfile(destFile);
             }
-            runner.addFormatter(fe.createFormatter());
+            runner.addFormatter((JUnitResultFormatter) fe.createFormatter());
         }
     }
 

Modified: 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
 (original)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
 Mon Feb 27 14:24:26 2006
@@ -29,7 +29,7 @@
  *
  */
 
-public class SummaryJUnitResultFormatter implements JUnitResultFormatter {
+public class SummaryJUnitResultFormatter implements JUnitResultFormatter, 
JUnitTaskMirror.SummaryJUnitResultFormatterMirror {
 
     /**
      * Formatter for timings.

Modified: ant/core/trunk/xdocs/faq.xml
URL: 
http://svn.apache.org/viewcvs/ant/core/trunk/xdocs/faq.xml?rev=381467&r1=381466&r2=381467&view=diff
==============================================================================
--- ant/core/trunk/xdocs/faq.xml (original)
+++ ant/core/trunk/xdocs/faq.xml Mon Feb 27 14:24:26 2006
@@ -1386,6 +1386,10 @@
         <code>org.apache.tools.ant.taskdefs.XSLTLiaison</code>
         class.</p>
 
+        <p><em>As of Ant 1.7</em> <code>&lt;junit&gt;</code> no longer
+        requires you to have <code>junit.jar</code> in Ant's startup
+        classpath even if <code>ant-junit.jar</code> is present there.</p>
+
         <p>Ant&apos;s class loader implementation uses Java&apos;s
         delegation model, see <a
         
href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html";>http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html</a>
@@ -1776,4 +1780,4 @@
     </faq>
   </faqsection>
 
-</document>
\ No newline at end of file
+</document>



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to