ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anto...@apache.org
Subject svn commit: r1045279 [9/12] - in /ant/core/branches/ANT_SITE: ./ docs/ docs/antlibs/ docs/antlibs/antunit/ docs/antlibs/compress/ docs/antlibs/dotnet/ docs/antlibs/props/ docs/antlibs/svn/ docs/manual/ docs/manual/CoreTasks/ docs/manual/CoreTypes/ docs...
Date Mon, 13 Dec 2010 18:34:09 GMT
Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java Mon Dec 13 18:34:00 2010
@@ -50,6 +50,7 @@ public abstract class Mailer {
     // CheckStyle:VisibilityModifier ON
     private boolean ignoreInvalidRecipients = false;
     private boolean starttls = false;
+    private boolean portExplicitlySpecified = false;
 
     /**
      * Set the mail server.
@@ -70,6 +71,22 @@ public abstract class Mailer {
     }
 
     /**
+     * Whether the port has been explicitly specified by the user. 
+     * @since Ant 1.8.2
+     */
+    public void setPortExplicitlySpecified(boolean explicit) {
+        portExplicitlySpecified = explicit;
+    }
+
+    /**
+     * Whether the port has been explicitly specified by the user. 
+     * @since Ant 1.8.2
+     */
+    protected boolean isPortExplicitlySpecified() {
+        return portExplicitlySpecified;
+    }
+
+    /**
      * Set the user for smtp auth.
      *
      * @param user the username.

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Message.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Message.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Message.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/Message.java Mon Dec 13 18:34:00 2010
@@ -26,7 +26,6 @@ import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 
 import org.apache.tools.ant.ProjectComponent;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Class representing an email message.

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java Mon Dec 13 18:34:00 2010
@@ -157,6 +157,10 @@ public class MimeMailer extends Mailer {
                 // SMTP provider
                 props.put("mail.smtp.socketFactory.class", SSL_FACTORY);
                 props.put("mail.smtp.socketFactory.fallback", "false");
+                if (isPortExplicitlySpecified()) {
+                    props.put("mail.smtp.socketFactory.port",
+                              String.valueOf(port));
+                }
             }
             if (user != null || password != null) {
                 props.put("mail.smtp.auth", "true");

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java Mon Dec 13 18:34:00 2010
@@ -31,7 +31,6 @@ import java.io.Reader;
 import java.io.Writer;
 import java.util.Iterator;
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.FileSet;
@@ -43,6 +42,7 @@ import org.apache.tools.ant.types.resour
 import org.apache.tools.ant.types.resources.Union;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.regexp.Regexp;
+import org.apache.tools.ant.util.regexp.RegexpUtil;
 
 /**
  * Performs regular expression string replacements in a text
@@ -513,23 +513,7 @@ public class ReplaceRegExp extends Task 
                                      + "time.");
         }
 
-        int options = 0;
-
-        if (flags.indexOf('g') != -1) {
-            options |= Regexp.REPLACE_ALL;
-        }
-
-        if (flags.indexOf('i') != -1) {
-            options |= Regexp.MATCH_CASE_INSENSITIVE;
-        }
-
-        if (flags.indexOf('m') != -1) {
-            options |= Regexp.MATCH_MULTILINE;
-        }
-
-        if (flags.indexOf('s') != -1) {
-            options |= Regexp.MATCH_SINGLELINE;
-        }
+        int options = RegexpUtil.asOptions(flags);
 
         if (file != null && file.exists()) {
             try {

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java Mon Dec 13 18:34:00 2010
@@ -24,6 +24,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.util.Enumeration;
+import java.util.Map;
 import java.util.Vector;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -44,10 +45,9 @@ import org.apache.tools.ant.types.Path;
  */
 public class Rpm extends Task {
 
-    private static final String PATH1 = "PATH=";
-    private static final String PATH2 = "Path=";
-    private static final String PATH3 = "path=";
-    private static final int PATH_LEN = PATH1.length();
+    private static final String PATH1 = "PATH";
+    private static final String PATH2 = "Path";
+    private static final String PATH3 = "path";
 
     /**
      * the spec file
@@ -317,13 +317,12 @@ public class Rpm extends Task {
      * @since 1.6
      */
     protected String guessRpmBuildCommand() {
-        Vector env = Execute.getProcEnvironment();
-        String path = null;
-        for (Enumeration e = env.elements(); e.hasMoreElements();) {
-            String var = (String) e.nextElement();
-            if (var.startsWith(PATH1) || var.startsWith(PATH2) || var.startsWith(PATH3)) {
-                path = var.substring(PATH_LEN);
-                break;
+        Map/*<String, String>*/ env = Execute.getEnvironmentVariables();
+        String path = (String) env.get(PATH1);
+        if (path == null) {
+            path = (String) env.get(PATH2);
+            if (path == null) {
+                path = (String) env.get(PATH3);
             }
         }
 

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java Mon Dec 13 18:34:00 2010
@@ -42,6 +42,8 @@ public class JavahAdapterFactory {
     public static String getDefault() {
         if (JavaEnvUtils.isKaffe()) {
             return Kaffeh.IMPLEMENTATION_NAME;
+        } else if (JavaEnvUtils.isGij()) {
+            return Gcjh.IMPLEMENTATION_NAME;
         }
         return SunJavah.IMPLEMENTATION_NAME;
     }
@@ -82,6 +84,9 @@ public class JavahAdapterFactory {
         if ((JavaEnvUtils.isKaffe() && choice == null)
             || Kaffeh.IMPLEMENTATION_NAME.equals(choice)) {
             return new Kaffeh();
+        } else if ((JavaEnvUtils.isGij() && choice == null)
+            || Gcjh.IMPLEMENTATION_NAME.equals(choice)) {
+            return new Gcjh();
         } else if (SunJavah.IMPLEMENTATION_NAME.equals(choice)) {
             return new SunJavah();
         } else if (choice != null) {

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java Mon Dec 13 18:34:00 2010
@@ -24,8 +24,8 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.util.Map;
 import java.util.Vector;
-import java.util.Enumeration;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
@@ -593,16 +593,11 @@ public class JDependTask extends Task {
         }
 
         if (includeRuntime) {
-            Vector v = Execute.getProcEnvironment();
-            Enumeration e = v.elements();
-            while (e.hasMoreElements()) {
-                String s = (String) e.nextElement();
-                if (s.startsWith("CLASSPATH=")) {
-                    commandline.createClasspath(getProject()).createPath()
-                        .append(new Path(getProject(),
-                                         s.substring("CLASSPATH=".length()
-                                                     )));
-                }
+            Map/*<String, String>*/ env = Execute.getEnvironmentVariables();
+            String cp = (String) env.get("CLASSPATH");
+            if (cp != null) {
+                commandline.createClasspath(getProject()).createPath()
+                    .append(new Path(getProject(), cp));
             }
             log("Implicitly adding " + runtimeClasses + " to CLASSPATH",
                 Project.MSG_VERBOSE);

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java Mon Dec 13 18:34:00 2010
@@ -23,6 +23,7 @@ package org.apache.tools.ant.taskdefs.op
  */
 public class Constants {
 
+    static final String METHOD_NAMES = "methods=";
     static final String HALT_ON_ERROR = "haltOnError=";
     static final String HALT_ON_FAILURE = "haltOnFailure=";
     static final String FILTERTRACE = "filtertrace=";

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java Mon Dec 13 18:34:00 2010
@@ -249,7 +249,9 @@ public class FailureRecorder extends Pro
             File sourceFile = new File((getLocationName() + ".java"));
             verbose("Write collector class to '" + sourceFile.getAbsolutePath() + "'");
 
-            sourceFile.delete();
+            if (sourceFile.exists() && !sourceFile.delete()) {
+                throw new IOException("could not delete " + sourceFile);
+            }
             writer = new BufferedWriter(new FileWriter(sourceFile));
 
             createClassHeader();
@@ -334,13 +336,13 @@ public class FailureRecorder extends Pro
     /**
      * TestInfos holds information about a given test for later use.
      */
-    public class TestInfos implements Comparable {
+    public static class TestInfos implements Comparable {
 
         /** The class name of the test. */
-        private String className;
+        private final String className;
 
         /** The method name of the testcase. */
-        private String methodName;
+        private final String methodName;
 
         /**
          * This constructor extracts the needed information from the given test.
@@ -348,8 +350,8 @@ public class FailureRecorder extends Pro
          */
         public TestInfos(Test test) {
             className = test.getClass().getName();
-            methodName = test.toString();
-            methodName = methodName.substring(0, methodName.indexOf('('));
+            String _methodName = test.toString();
+            methodName = _methodName.substring(0, _methodName.indexOf('('));
         }
 
         /**
@@ -378,6 +380,12 @@ public class FailureRecorder extends Pro
                 return -1;
             }
         }
+        public boolean equals(Object obj) {
+            return obj instanceof TestInfos && toString().equals(obj.toString());
+        }
+        public int hashCode() {
+            return toString().hashCode();
+        }
     }
 
     // ===== BuildListener =====

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java Mon Dec 13 18:34:00 2010
@@ -23,6 +23,7 @@ import java.io.FileOutputStream;
 import java.io.OutputStream;
 import java.io.BufferedOutputStream;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import org.apache.tools.ant.BuildException;
@@ -326,8 +327,10 @@ public class FormatterElement {
                 // there is already a project reference so dont overwrite this
                 needToSetProjectReference = false;
             }
-        } catch (Exception e) {
+        } catch (NoSuchFieldException e) {
             // no field present, so no previous reference exists
+        } catch (IllegalAccessException e) {
+            throw new BuildException(e);
         }
 
         if (needToSetProjectReference) {
@@ -335,8 +338,12 @@ public class FormatterElement {
             try {
                 setter = r.getClass().getMethod("setProject", new Class[] {Project.class});
                 setter.invoke(r, new Object[] {project});
-            } catch (Exception e) {
+            } catch (NoSuchMethodException e) {
                 // no setProject to invoke; just ignore
+            } catch (IllegalAccessException e) {
+                throw new BuildException(e);
+            } catch (InvocationTargetException e) {
+                throw new BuildException(e);
             }
         }
 

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java Mon Dec 13 18:34:00 2010
@@ -29,6 +29,8 @@ import java.io.OutputStream;
 import java.io.PrintStream;
 import java.lang.reflect.Constructor;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
@@ -130,7 +132,7 @@ public class JUnitTask extends Task {
 
     private static final String LINE_SEP
         = System.getProperty("line.separator");
-    private static final String CLASSPATH = "CLASSPATH=";
+    private static final String CLASSPATH = "CLASSPATH";
     private CommandlineJava commandline;
     private Vector tests = new Vector();
     private Vector batchTests = new Vector();
@@ -163,6 +165,7 @@ public class JUnitTask extends Task {
     private ForkMode forkMode = new ForkMode("perTest");
 
     private boolean splitJunit = false;
+    private boolean enableTestListenerEvents = false;
     private JUnitTaskMirror delegate;
     private ClassLoader mirrorLoader;
 
@@ -184,6 +187,12 @@ public class JUnitTask extends Task {
     public static final String TESTLISTENER_PREFIX =
         "junit.framework.TestListener: ";
 
+    /**
+     * Name of magic property that enables test listener events.
+     */
+    public static final String ENABLE_TESTLISTENER_EVENTS =
+        "ant.junit.enabletestlistenerevents";
+
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     /**
@@ -652,8 +661,6 @@ public class JUnitTask extends Task {
      * @since Ant 1.2
      */
     public JUnitTask() throws Exception {
-        getCommandline()
-            .setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
     }
 
     /**
@@ -673,6 +680,32 @@ public class JUnitTask extends Task {
     }
 
     /**
+     * Whether test listener events shall be generated.
+     *
+     * <p>Defaults to false.</p>
+     * 
+     * <p>This value will be overridden by the magic property
+     * ant.junit.enabletestlistenerevents if it has been set.</p>
+     *
+     * @since Ant 1.8.2
+     */
+    public void setEnableTestListenerEvents(boolean b) {
+        enableTestListenerEvents = b;
+    }
+
+    /**
+     * Whether test listener events shall be generated.
+     * @since Ant 1.8.2
+     */
+    public boolean getEnableTestListenerEvents() {
+        String e = getProject().getProperty(ENABLE_TESTLISTENER_EVENTS);
+        if (e != null) {
+            return Project.toBoolean(e);
+        }
+        return enableTestListenerEvents;
+    }
+
+    /**
      * Adds the jars or directories containing Ant, this task and
      * JUnit to the classpath - this should make the forked JVM work
      * without having to specify them directly.
@@ -716,18 +749,20 @@ public class JUnitTask extends Task {
      * @since Ant 1.7.1
      */
     protected void setupJUnitDelegate() {
-        ClassLoader myLoader = JUnitTask.class.getClassLoader();
+        final ClassLoader myLoader = JUnitTask.class.getClassLoader();
         if (splitJunit) {
-            Path path = new Path(getProject());
+            final Path path = new Path(getProject());
             path.add(antRuntimeClasses);
             Path extra = getCommandline().getClasspath();
             if (extra != null) {
                 path.add(extra);
             }
-            mirrorLoader =
-                new SplitClassLoader(myLoader, path, getProject(),
+            mirrorLoader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    return new SplitClassLoader(myLoader, path, getProject(),
                                      new String[] {
                                          "BriefJUnitResultFormatter",
+                                         "JUnit4TestMethodAdapter",
                                          "JUnitResultFormatter",
                                          "JUnitTaskMirrorImpl",
                                          "JUnitTestRunner",
@@ -738,6 +773,8 @@ public class JUnitTask extends Task {
                                          "TearDownOnVmCrash",
                                          "XMLJUnitResultFormatter",
                                      });
+                }
+            });
         } else {
             mirrorLoader = myLoader;
         }
@@ -751,6 +788,8 @@ public class JUnitTask extends Task {
      * @since Ant 1.2
      */
     public void execute() throws BuildException {
+        checkMethodLists();
+
         setupJUnitDelegate();
 
         List testLists = new ArrayList();
@@ -851,6 +890,9 @@ public class JUnitTask extends Task {
             while (iter.hasNext()) {
                 test = (JUnitTest) iter.next();
                 printDual(writer, logWriter, test.getName());
+                if (test.getMethods() != null) {
+                    printDual(writer, logWriter, ":" + test.getMethodsString().replace(',', '+'));
+                }
                 if (test.getTodir() == null) {
                     printDual(writer, logWriter,
                               "," + getProject().resolveFile("."));
@@ -878,10 +920,10 @@ public class JUnitTask extends Task {
             log(e.toString(), Project.MSG_ERR);
             throw new BuildException(e);
         } finally {
-            FILE_UTILS.close(writer);
+            FileUtils.close(writer);
 
             try {
-                casesFile.delete();
+                FILE_UTILS.tryHardToDelete(casesFile);
             } catch (Exception e) {
                 log(e.toString(), Project.MSG_ERR);
             }
@@ -919,9 +961,11 @@ public class JUnitTask extends Task {
         } catch (CloneNotSupportedException e) {
             throw new BuildException("This shouldn't happen", e, getLocation());
         }
-        cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
         if (casesFile == null) {
             cmd.createArgument().setValue(test.getName());
+            if (test.getMethods() != null) {
+                cmd.createArgument().setValue(Constants.METHOD_NAMES + test.getMethodsString());
+            }
         } else {
             log("Running multiple tests in the same VM", Project.MSG_VERBOSE);
             cmd.createArgument().setValue(Constants.TESTSFILE + casesFile);
@@ -942,8 +986,9 @@ public class JUnitTask extends Task {
         cmd.createArgument().setValue(Constants.LOG_FAILED_TESTS
                                       + String.valueOf(logFailedTests));
 
-        cmd.createArgument().setValue(
-            Constants.LOGTESTLISTENEREVENTS + "true"); // #31885
+        // #31885
+        cmd.createArgument().setValue(Constants.LOGTESTLISTENEREVENTS
+                                      + String.valueOf(getEnableTestListenerEvents()));
 
         StringBuffer formatterArg = new StringBuffer(STRING_BUFFER_SIZE);
         final FormatterElement[] feArray = mergeFormatters(test);
@@ -979,7 +1024,7 @@ public class JUnitTask extends Task {
             props.store(outstream, "Ant JUnitTask generated properties file");
             outstream.close();
         } catch (java.io.IOException e) {
-            propsFile.delete();
+            FILE_UTILS.tryHardToDelete(propsFile);
             throw new BuildException("Error creating temporary properties "
                                      + "file.", e, getLocation());
         }
@@ -1034,7 +1079,7 @@ public class JUnitTask extends Task {
             } finally {
                 FileUtils.close(br);
                 if (vmWatcher.exists()) {
-                    vmWatcher.delete();
+                    FILE_UTILS.tryHardToDelete(vmWatcher);
                 }
             }
 
@@ -1053,9 +1098,10 @@ public class JUnitTask extends Task {
                 logVmCrash(feArray, test, vmCrashString);
             }
 
-            if (!propsFile.delete()) {
+            if (!FILE_UTILS.tryHardToDelete(propsFile)) {
                 throw new BuildException("Could not delete temporary "
-                                         + "properties file.");
+                                         + "properties file '"
+                                         + propsFile.getAbsolutePath() + "'.");
             }
         }
 
@@ -1068,16 +1114,11 @@ public class JUnitTask extends Task {
      */
     private void checkIncludeAntRuntime(CommandlineJava cmd) {
         if (includeAntRuntime) {
-            Vector v = Execute.getProcEnvironment();
-            Enumeration e = v.elements();
-            while (e.hasMoreElements()) {
-                String s = (String) e.nextElement();
-                if (s.startsWith(CLASSPATH)) {
-                    cmd.createClasspath(getProject()).createPath()
-                        .append(new Path(getProject(),
-                                         s.substring(CLASSPATH.length()
-                                                     )));
-                }
+            Map/*<String, String>*/ env = Execute.getEnvironmentVariables();
+            String cp = (String) env.get(CLASSPATH);
+            if (cp != null) {
+                cmd.createClasspath(getProject()).createPath()
+                    .append(new Path(getProject(), cp));
             }
             log("Implicitly adding " + antRuntimeClasses + " to CLASSPATH",
                 Project.MSG_VERBOSE);
@@ -1135,7 +1176,7 @@ public class JUnitTask extends Task {
                 for (Enumeration e = loader.getResources(projectResourceName);
                      e.hasMoreElements();) {
                     URL current = (URL) e.nextElement();
-                    if (previous != null && !current.equals(previous)) {
+                    if (previous != null && !urlEquals(current, previous)) {
                         log("WARNING: multiple versions of ant detected "
                             + "in path for junit "
                             + LINE_SEP + "         " + previous
@@ -1156,6 +1197,30 @@ public class JUnitTask extends Task {
     }
 
     /**
+     * Compares URLs for equality but takes case-sensitivity into
+     * account when comparing file URLs and ignores the jar specific
+     * part of the URL if present.
+     */
+    private static boolean urlEquals(URL u1, URL u2) {
+        String url1 = maybeStripJarAndClass(u1);
+        String url2 = maybeStripJarAndClass(u2);
+        if (url1.startsWith("file:") && url2.startsWith("file:")) {
+            return new File(FILE_UTILS.fromURI(url1))
+                .equals(new File(FILE_UTILS.fromURI(url2)));
+        }
+        return url1.equals(url2);
+    }
+
+    private static String maybeStripJarAndClass(URL u) {
+        String s = u.toString();
+        if (s.startsWith("jar:")) {
+            int pling = s.indexOf('!');
+            s = s.substring(4, pling == -1 ? s.length() : pling);
+        }
+        return s;
+    }
+
+    /**
      * Create a temporary file to pass the properties to a new process.
      * Will auto-delete on (graceful) exit.
      * The file will be in the project basedir unless tmpDir declares
@@ -1173,7 +1238,7 @@ public class JUnitTask extends Task {
 
     /**
      * Pass output sent to System.out to the TestRunner so it can
-     * collect ot for the formatters.
+     * collect it for the formatters.
      *
      * @param output output coming from System.out
      * @since Ant 1.5
@@ -1321,10 +1386,11 @@ public class JUnitTask extends Task {
             if (classLoader != null) {
                 classLoader.setThreadContextLoader();
             }
-            runner = delegate.newJUnitTestRunner(test, test.getHaltonerror(),
+            runner = delegate.newJUnitTestRunner(test, test.getMethods(), test.getHaltonerror(),
                                          test.getFiltertrace(),
                                          test.getHaltonfailure(), false,
-                                         true, classLoader);
+                                         getEnableTestListenerEvents(),
+                                         classLoader);
             if (summary) {
 
                 JUnitTaskMirror.SummaryJUnitResultFormatterMirror f =
@@ -1407,6 +1473,29 @@ public class JUnitTask extends Task {
     }
 
     /**
+     * Verifies all <code>test</code> elements having the <code>methods</code>
+     * attribute specified and having the <code>if</code>-condition resolved
+     * to true, that the value of the <code>methods</code> attribute is valid.
+     * @exception BuildException if some of the tests matching the described
+     *                           conditions has invalid value of the
+     *                           <code>methods</code> attribute
+     * @since 1.8.2
+     */
+    private void checkMethodLists() throws BuildException {
+        if (tests.isEmpty()) {
+            return;
+        }
+
+        Enumeration testsEnum = tests.elements();
+        while (testsEnum.hasMoreElements()) {
+            JUnitTest test = (JUnitTest) testsEnum.nextElement();
+            if (test.hasMethodsSpecified() && test.shouldRun(getProject())) {
+                test.resolveMethods();
+            }
+        }
+    }
+
+    /**
      * return an enumeration listing each test, then each batchtest
      * @return enumeration
      * @since Ant 1.3
@@ -1666,6 +1755,7 @@ public class JUnitTask extends Task {
     protected CommandlineJava getCommandline() {
         if (commandline == null) {
             commandline = new CommandlineJava();
+            commandline.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
         }
         return commandline;
     }
@@ -1883,7 +1973,7 @@ public class JUnitTask extends Task {
     /**
      * A value class that contains the result of a test.
      */
-    protected class TestResultHolder {
+    protected static class TestResultHolder {
         // CheckStyle:VisibilityModifier OFF - bc
         /** the exit code of the test. */
         public int exitCode = JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS;
@@ -1962,7 +2052,7 @@ public class JUnitTask extends Task {
      */
     private static JUnitTest createDummyTestForBatchTest(JUnitTest test) {
         JUnitTest t = (JUnitTest) test.clone();
-        int index = test.getName().indexOf(".");
+        int index = test.getName().lastIndexOf('.');
         // make sure test looks as if it was in the same "package" as
         // the last test of the batch
         String pack = index > 0 ? test.getName().substring(0, index + 1) : "";

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java Mon Dec 13 18:34:00 2010
@@ -55,6 +55,7 @@ public interface JUnitTaskMirror {
     /**
      * Create a new test runner for a test.
      * @param test the test to run.
+     * @param methods names of the test methods to be run.
      * @param haltOnError if true halt the tests if an error occurs.
      * @param filterTrace if true filter the stack traces.
      * @param haltOnFailure if true halt the test if a failure occurs.
@@ -63,7 +64,7 @@ public interface JUnitTaskMirror {
      * @param classLoader      the classloader to use to create the runner.
      * @return the test runner.
      */
-    JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, boolean haltOnError,
+    JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, String[] methods, boolean haltOnError,
             boolean filterTrace, boolean haltOnFailure, boolean showOutput,
             boolean logTestListenerEvents, AntClassLoader classLoader);
 

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java Mon Dec 13 18:34:00 2010
@@ -60,9 +60,10 @@ public final class JUnitTaskMirrorImpl i
 
     /** {@inheritDoc}. */
     public JUnitTaskMirror.JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test,
+            String[] methods,
             boolean haltOnError, boolean filterTrace, boolean haltOnFailure,
             boolean showOutput, boolean logTestListenerEvents, AntClassLoader classLoader) {
-        return new JUnitTestRunner(test, haltOnError, filterTrace, haltOnFailure,
+        return new JUnitTestRunner(test, methods, haltOnError, filterTrace, haltOnFailure,
                 showOutput, logTestListenerEvents, classLoader);
     }
 

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java Mon Dec 13 18:34:00 2010
@@ -22,6 +22,7 @@ import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Properties;
 import java.util.Vector;
+import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.PropertyHelper;
 
@@ -41,6 +42,19 @@ public class JUnitTest extends BaseTest 
     /** the name of the test case */
     private String name = null;
 
+    /**
+     * whether the list of test methods has been specified
+     * @see #setMethods(java.lang.String)
+     * @see #setMethods(java.lang.String[])
+     */
+    private boolean methodsSpecified = false;
+
+    /** comma-separated list of names of test methods to execute */
+    private String methodsList = null;
+
+    /** the names of test methods to execute */
+    private String[] methods = null;
+    
     /** the name of the result file */
     private String outfile = null;
 
@@ -73,11 +87,52 @@ public class JUnitTest extends BaseTest 
      * @param filtertrace if true filter stack traces.
      */
     public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure,
-                     boolean filtertrace) {
+            boolean filtertrace) {
+        this(name, haltOnError, haltOnFailure, filtertrace, null);
+    }    
+    
+    /**
+     * Constructor with options.
+     * @param name the name of the test.
+     * @param haltOnError if true halt the tests if there is an error.
+     * @param haltOnFailure if true halt the tests if there is a failure.
+     * @param filtertrace if true filter stack traces.
+     * @param methods if non-null run only these test methods
+     * @since 1.8.2
+     */
+    public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure,
+                     boolean filtertrace, String[] methods) {
         this.name  = name;
         this.haltOnError = haltOnError;
         this.haltOnFail = haltOnFailure;
         this.filtertrace = filtertrace;
+        this.methodsSpecified = methods != null;
+        this.methods = methodsSpecified ? (String[]) methods.clone() : null;
+    }
+
+    /**
+     * Sets names of individual test methods to be executed.
+     * @param value comma-separated list of names of individual test methods
+     *              to be executed,
+     *              or <code>null</code> if all test methods should be executed
+     * @since 1.8.2
+     */
+    public void setMethods(String value) {
+        methodsList = value;
+        methodsSpecified = (value != null);
+        methods = null;
+    }
+
+    /**
+     * Sets names of individual test methods to be executed.
+     * @param value non-empty array of names of test methods to be executed
+     * @see #setMethods(String)
+     * @since 1.8.2
+     */
+    void setMethods(String[] value) {
+        methods = value;
+        methodsSpecified = (value != null);
+        methodsList = null;
     }
 
     /**
@@ -97,6 +152,189 @@ public class JUnitTest extends BaseTest 
     }
 
     /**
+     * Informs whether a list of test methods has been specified in this test.
+     * @return <code>true</code> if test methods to be executed have been
+     *         specified, <code>false</code> otherwise
+     * @see #setMethods(java.lang.String)
+     * @see #setMethods(java.lang.String[])
+     * @since 1.8.2
+     */
+    boolean hasMethodsSpecified() {
+        return methodsSpecified;
+    }
+
+    /**
+     * Get names of individual test methods to be executed.
+     *
+     * @return array of names of the individual test methods to be executed,
+     *         or <code>null</code> if all test methods in the suite
+     *         defined by the test class will be executed
+     * @since 1.8.2
+     */
+    String[] getMethods() {
+        if (methodsSpecified && (methods == null)) {
+            resolveMethods();
+        }
+        return methods;
+    }
+
+    /**
+     * Gets a comma-separated list of names of methods that are to be executed
+     * by this test.
+     * @return the comma-separated list of test method names, or an empty
+     *         string of no method is to be executed, or <code>null</code>
+     *         if no method is specified
+     * @since 1.8.2
+     */
+    String getMethodsString() {
+        if ((methodsList == null) && methodsSpecified) {
+            if (methods.length == 0) {
+                methodsList = "";
+            } else if (methods.length == 1) {
+                methodsList = methods[0];
+            } else {
+                StringBuffer buf = new StringBuffer(methods.length * 16);
+                buf.append(methods[0]);
+                for (int i = 1; i < methods.length; i++) {
+                    buf.append(',').append(methods[i]);
+                }
+                methodsList = buf.toString();
+            }
+        }
+        return methodsList;
+    }
+
+    /**
+     * Computes the value of the {@link #methods} field from the value
+     * of the {@link #methodsList} field, if it has not been computed yet.
+     * @exception BuildException if the value of the {@link #methodsList} field
+     *                           was invalid
+     * @since 1.8.2
+     */
+    void resolveMethods() {
+        if ((methods == null) && methodsSpecified) {
+            try {
+                methods = parseTestMethodNamesList(methodsList);
+            } catch (IllegalArgumentException ex) {
+                throw new BuildException(
+                        "Invalid specification of test methods: \""
+                            + methodsList
+                            + "\"; expected: comma-separated list of valid Java identifiers",
+                        ex);
+            }
+        }
+    }
+
+    /**
+     * Parses a comma-separated list of method names and check their validity.
+     * @param methodNames comma-separated list of method names to be parsed
+     * @return array of individual test method names
+     * @exception  java.lang.IllegalArgumentException
+     *             if the given string is <code>null</code> or if it is not
+     *             a comma-separated list of valid Java identifiers;
+     *             an empty string is acceptable and is handled as an empty
+     *             list
+     * @since 1.8.2
+     */
+    public static String[] parseTestMethodNamesList(String methodNames)
+                                            throws IllegalArgumentException {
+        if (methodNames == null) {
+            throw new IllegalArgumentException("methodNames is <null>");
+        }
+
+        methodNames = methodNames.trim();
+
+        int length = methodNames.length();
+        if (length == 0) {
+            return new String[0];
+        }
+
+        /* strip the trailing comma, if any */
+        if (methodNames.charAt(length - 1) == ',') {
+            methodNames = methodNames.substring(0, length - 1).trim();
+            length = methodNames.length();
+            if (length == 0) {
+                throw new IllegalArgumentException("Empty method name");
+            }
+        }
+
+        final char[] chars = methodNames.toCharArray();
+        /* easy detection of one particular case of illegal string: */
+        if (chars[0] == ',') {
+            throw new IllegalArgumentException("Empty method name");
+        }
+        /* count number of method names: */
+        int wordCount = 1;
+        for (int i = 1; i < chars.length; i++) {
+            if (chars[i] == ',') {
+                wordCount++;
+            }
+        }
+        /* prepare the resulting array: */
+        String[] result = new String[wordCount];
+        /* parse the string: */
+        final int stateBeforeWord = 1;
+        final int stateInsideWord = 2;
+        final int stateAfterWord = 3;
+        //
+        int state = stateBeforeWord;
+        int wordStartIndex = -1;
+        int wordIndex = 0;
+        for (int i = 0; i < chars.length; i++) {
+            char c = chars[i];
+            switch (state) {
+                case stateBeforeWord:
+                    if (c == ',') {
+                        throw new IllegalArgumentException("Empty method name");
+                    } else if (c == ' ') {
+                        // remain in the same state
+                    } else if (Character.isJavaIdentifierStart(c)) {
+                        wordStartIndex = i;
+                        state = stateInsideWord;
+                    } else {
+                        throw new IllegalArgumentException("Illegal start of method name: " + c);
+                    }
+                    break;
+                case stateInsideWord:
+                    if (c == ',') {
+                        result[wordIndex++] = methodNames.substring(wordStartIndex, i);
+                        state = stateBeforeWord;
+                    } else if (c == ' ') {
+                        result[wordIndex++] = methodNames.substring(wordStartIndex, i);
+                        state = stateAfterWord;
+                    } else if (Character.isJavaIdentifierPart(c)) {
+                        // remain in the same state
+                    } else {
+                        throw new IllegalArgumentException("Illegal character in method name: " + c);
+                    }
+                    break;
+                case stateAfterWord:
+                    if (c == ',') {
+                        state = stateBeforeWord;
+                    } else if (c == ' ') {
+                        // remain in the same state
+                    } else {
+                        throw new IllegalArgumentException("Space in method name");
+                    }
+                    break;
+                default:
+                    // this should never happen
+            }
+        }
+        switch (state) {
+            case stateBeforeWord:
+            case stateAfterWord:
+                break;
+            case stateInsideWord:
+                result[wordIndex++] = methodNames.substring(wordStartIndex, chars.length);
+                break;
+            default:
+                // this should never happen
+        }
+        return result;
+    }
+
+    /**
      * Get the name of the test class.
      * @return the name of the test.
      */

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java Mon Dec 13 18:34:00 2010
@@ -163,6 +163,9 @@ public class JUnitTestRunner implements 
      */
     private static String crashFile = null;
 
+    /** Names of test methods to execute */
+    private String[] methods = null;
+    
     /**
      * Constructor for fork=true or when the user hasn't specified a
      * classpath.
@@ -205,7 +208,26 @@ public class JUnitTestRunner implements 
     public JUnitTestRunner(JUnitTest test, boolean haltOnError,
                            boolean filtertrace, boolean haltOnFailure,
                            boolean showOutput, boolean logTestListenerEvents) {
-        this(test, haltOnError, filtertrace, haltOnFailure, showOutput,
+        this(test, null, haltOnError, filtertrace, haltOnFailure, showOutput,
+             logTestListenerEvents, null);
+    }
+
+    /**
+     * Constructor for fork=true or when the user hasn't specified a
+     * classpath.
+     * @param test the test to run.
+     * @param methods names of methods of the test to be executed.
+     * @param haltOnError whether to stop the run if an error is found.
+     * @param filtertrace whether to filter junit.*.* stack frames out of exceptions
+     * @param haltOnFailure whether to stop the run if failure is found.
+     * @param showOutput    whether to send output to System.out/.err as well as formatters.
+     * @param logTestListenerEvents whether to print TestListener events.
+     * @since 1.8.2
+     */
+    public JUnitTestRunner(JUnitTest test, String[] methods, boolean haltOnError,
+                           boolean filtertrace, boolean haltOnFailure,
+                           boolean showOutput, boolean logTestListenerEvents) {
+        this(test, methods, haltOnError, filtertrace, haltOnFailure, showOutput,
              logTestListenerEvents, null);
     }
 
@@ -254,12 +276,26 @@ public class JUnitTestRunner implements 
                            boolean filtertrace, boolean haltOnFailure,
                            boolean showOutput, boolean logTestListenerEvents,
                            ClassLoader loader) {
-        JUnitTestRunner.filtertrace = filtertrace;
+        this(test, null, haltOnError, filtertrace, haltOnFailure, showOutput, 
+             logTestListenerEvents, loader);
+    }
+
+
+    /**
+     * Constructor to use when the user has specified a classpath.
+     * @since 1.8.2
+     */
+    public JUnitTestRunner(JUnitTest test, String[] methods, boolean haltOnError,
+                           boolean filtertrace, boolean haltOnFailure,
+                           boolean showOutput, boolean logTestListenerEvents,
+                           ClassLoader loader) {
+        JUnitTestRunner.filtertrace = filtertrace; // XXX clumsy, should use instance field somehow
         this.junitTest = test;
         this.haltOnError = haltOnError;
         this.haltOnFailure = haltOnFailure;
         this.showOutput = showOutput;
         this.logTestListenerEvents = logTestListenerEvents;
+        this.methods = methods != null ? (String[]) methods.clone() : null;
         this.loader = loader;
     }
 
@@ -340,9 +376,12 @@ public class JUnitTestRunner implements 
                                               loader);
                 }
 
+                final boolean testMethodsSpecified = (methods != null);
+
                 // check for a static suite method first, even when using
                 // JUnit 4
                 Method suiteMethod = null;
+                if (!testMethodsSpecified) {
                 try {
                     // check if there is a suite method
                     suiteMethod = testClass.getMethod("suite", new Class[0]);
@@ -350,6 +389,7 @@ public class JUnitTestRunner implements 
                     // no appropriate suite method found. We don't report any
                     // error here since it might be perfectly normal.
                 }
+                }
 
                 if (suiteMethod != null) {
                     // if there is a suite method available, then try
@@ -359,7 +399,23 @@ public class JUnitTestRunner implements 
 
                 } else {
                     Class junit4TestAdapterClass = null;
+                    boolean useSingleMethodAdapter = false;
 
+                    if (junit.framework.TestCase.class.isAssignableFrom(testClass)) {
+                        // Do not use JUnit 4 API for running JUnit 3.x
+                        // tests - it is not able to run individual test
+                        // methods.
+                        //
+                        // Technical details:
+                        // org.junit.runner.Request.method(Class, String).getRunner()
+                        // would return a runner which always executes all
+                        // test methods. The reason is that the Runner would be
+                        // an instance of class
+                        // org.junit.internal.runners.OldTestClassRunner
+                        // that does not implement interface Filterable - so it
+                        // is unable to filter out test methods not matching
+                        // the requested name.
+                    } else {
                     // Check for JDK 5 first. Will *not* help on JDK 1.4
                     // if only junit-4.0.jar in CP because in that case
                     // linkage of whole task will already have failed! But
@@ -373,29 +429,69 @@ public class JUnitTestRunner implements 
                         if (loader == null) {
                             junit4TestAdapterClass =
                                 Class.forName(JUNIT_4_TEST_ADAPTER);
+                            if (testMethodsSpecified) {
+                                /*
+                                 * We cannot try to load the JUnit4TestAdapter
+                                 * before trying to load JUnit4TestMethodAdapter
+                                 * because it might fail with
+                                 * NoClassDefFoundException, instead of plain
+                                 * ClassNotFoundException.
+                                 */
+                                junit4TestAdapterClass = Class.forName(
+                                    "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter");
+                                useSingleMethodAdapter = true;
+                            }
                         } else {
                             junit4TestAdapterClass =
                                 Class.forName(JUNIT_4_TEST_ADAPTER,
                                               true, loader);
+                            if (testMethodsSpecified) {
+                                junit4TestAdapterClass =
+                                    Class.forName(
+                                        "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter",
+                                        true, loader);
+                                useSingleMethodAdapter = true;
+                            }
                         }
                     } catch (ClassNotFoundException e) {
                         // OK, fall back to JUnit 3.
                     }
+                    }
                     junit4 = junit4TestAdapterClass != null;
 
                     if (junit4) {
                         // Let's use it!
+                        Class[] formalParams;
+                        Object[] actualParams;
+                        if (useSingleMethodAdapter) {
+                            formalParams = new Class[] {Class.class, String[].class};
+                            actualParams = new Object[] {testClass, methods};
+                        } else {
+                            formalParams = new Class[] {Class.class};
+                            actualParams = new Object[] {testClass};
+                        }
                         suite =
                             (Test) junit4TestAdapterClass
-                            .getConstructor(new Class[] {Class.class}).
-                            newInstance(new Object[] {testClass});
+                            .getConstructor(formalParams).
+                            newInstance(actualParams);
                     } else {
                         // Use JUnit 3.
 
                         // try to extract a test suite automatically this
                         // will generate warnings if the class is no
                         // suitable Test
-                        suite = new TestSuite(testClass);
+                        if (!testMethodsSpecified) {
+                            suite = new TestSuite(testClass);
+                        } else if (methods.length == 1) {
+                            suite = TestSuite.createTest(testClass, methods[0]);
+                        } else {
+                            TestSuite testSuite = new TestSuite(testClass.getName());
+                            for (int i = 0; i < methods.length; i++) {
+                                testSuite.addTest(
+                                    TestSuite.createTest(testClass, methods[i]));
+                            }
+                            suite = testSuite;
+                        }
                     }
 
                 }
@@ -670,11 +766,16 @@ public class JUnitTestRunner implements 
      * <tr><td>logtestlistenerevents</td><td>log TestListener events to
      * System.out.</td><td>false</td></tr>
      *
+     * <tr><td>methods</td><td>Comma-separated list of names of individual
+     * test methods to execute.
+     * </td><td>null</td></tr>
+     *
      * </table>
      * @param args the command line arguments.
      * @throws IOException on error.
      */
     public static void main(String[] args) throws IOException {
+        String[] methods = null;
         boolean haltError = false;
         boolean haltFail = false;
         boolean stackfilter = true;
@@ -696,7 +797,15 @@ public class JUnitTestRunner implements 
         }
 
         for (int i = 1; i < args.length; i++) {
-            if (args[i].startsWith(Constants.HALT_ON_ERROR)) {
+            if (args[i].startsWith(Constants.METHOD_NAMES)) {
+                try {
+                    String methodsList = args[i].substring(Constants.METHOD_NAMES.length());
+                    methods = JUnitTest.parseTestMethodNamesList(methodsList);
+                } catch (IllegalArgumentException ex) {
+                    System.err.println("Invalid specification of test method names: " + args[i]);
+                    System.exit(ERRORS);
+                }
+            } else if (args[i].startsWith(Constants.HALT_ON_ERROR)) {
                 haltError = Project.toBoolean(args[i].substring(Constants.HALT_ON_ERROR.length()));
             } else if (args[i].startsWith(Constants.HALT_ON_FAILURE)) {
                 haltFail = Project.toBoolean(args[i].substring(Constants.HALT_ON_FAILURE.length()));
@@ -744,18 +853,30 @@ public class JUnitTestRunner implements 
                 java.io.BufferedReader reader =
                     new java.io.BufferedReader(new java.io.FileReader(args[0]));
                 String testCaseName;
+                String[] testMethodNames;
                 int code = 0;
                 boolean errorOccurred = false;
                 boolean failureOccurred = false;
                 String line = null;
                 while ((line = reader.readLine()) != null) {
                     StringTokenizer st = new StringTokenizer(line, ",");
-                    testCaseName = st.nextToken();
+                    String testListSpec = st.nextToken();
+                    int colonIndex = testListSpec.indexOf(':');
+                    if (colonIndex == -1) {
+                        testCaseName = testListSpec;
+                        testMethodNames = null;
+                    } else {
+                        testCaseName = testListSpec.substring(0, colonIndex);
+                        testMethodNames = JUnitTest.parseTestMethodNamesList(
+                                                    testListSpec
+                                                    .substring(colonIndex + 1)
+                                                    .replace('+', ','));
+                    }
                     JUnitTest t = new JUnitTest(testCaseName);
                     t.setTodir(new File(st.nextToken()));
                     t.setOutfile(st.nextToken());
                     t.setProperties(props);
-                    code = launch(t, haltError, stackfilter, haltFail,
+                    code = launch(t, testMethodNames, haltError, stackfilter, haltFail,
                                   showOut, outputToFormat,
                                   logTestListenerEvents);
                     errorOccurred = (code == ERRORS);
@@ -783,7 +904,7 @@ public class JUnitTestRunner implements 
             JUnitTest t = new JUnitTest(args[0]);
             t.setProperties(props);
             returnCode = launch(
-                t, haltError, stackfilter, haltFail,
+                t, methods, haltError, stackfilter, haltFail,
                 showOut, outputToFormat, logTestListenerEvents);
         }
 
@@ -917,12 +1038,12 @@ public class JUnitTestRunner implements 
     /**
      * @since Ant 1.6.2
      */
-    private static int launch(JUnitTest t, boolean haltError,
+    private static int launch(JUnitTest t, String[] methods, boolean haltError,
                               boolean stackfilter, boolean haltFail,
                               boolean showOut, boolean outputToFormat,
                               boolean logTestListenerEvents) {
         JUnitTestRunner runner =
-            new JUnitTestRunner(t, haltError, stackfilter, haltFail, showOut,
+            new JUnitTestRunner(t, methods, haltError, stackfilter, haltFail, showOut,
                                 logTestListenerEvents, null);
         runner.forked = true;
         runner.outputToFormatters = outputToFormat;

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java Mon Dec 13 18:34:00 2010
@@ -279,6 +279,8 @@ public class XMLResultAggregator extends
             } catch (IOException e) {
                 log("Error while accessing file " + file + ": "
                     + e.getMessage(), Project.MSG_ERR);
+                log("Error while accessing file " + file + ": "
+                    + e.getMessage(), e, Project.MSG_VERBOSE);
             }
         }
         return rootElement;

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java Mon Dec 13 18:34:00 2010
@@ -834,7 +834,7 @@ public class FTP extends Task implements
                         } else if (!result) {
                             return;
                         }
-                        this.curpwd = this.curpwd + remoteFileSep
+                        this.curpwd = getCurpwdPlusFileSep()
                             + currentPathElement;
                     } catch (IOException ioe) {
                         throw new BuildException("could not change working dir to "
@@ -895,7 +895,7 @@ public class FTP extends Task implements
              * @return absolute path as string
              */
             public String getAbsolutePath() {
-                return curpwd + remoteFileSep + ftpFile.getName();
+                return getCurpwdPlusFileSep() + ftpFile.getName();
             }
             /**
              * find out the relative path assuming that the path used to construct
@@ -1037,6 +1037,17 @@ public class FTP extends Task implements
                 return curpwd;
             }
             /**
+             * returns the path of the directory containing the AntFTPFile.
+             * of the full path of the file itself in case of AntFTPRootFile
+             * and appends the remote file separator if necessary.
+             * @return parent directory of the AntFTPFile
+             * @since Ant 1.8.2
+             */
+            public String getCurpwdPlusFileSep() {
+                return curpwd.endsWith(remoteFileSep) ? curpwd
+                    : curpwd + remoteFileSep;
+            }
+            /**
              * find out if a symbolic link is encountered in the relative path of this file
              * from rootPath.
              * @return <code>true</code> if a symbolic link is encountered in the relative path.
@@ -2091,7 +2102,7 @@ public class FTP extends Task implements
             myReply = ftp.getReplyStrings();
 
             for (int x = 0; x < myReply.length; x++) {
-                if (myReply[x].indexOf("200") == -1) {
+                if (myReply[x] != null && myReply[x].indexOf("200") == -1) {
                     log(myReply[x], Project.MSG_WARN);
                 }
             }

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java Mon Dec 13 18:34:00 2010
@@ -19,8 +19,6 @@ package org.apache.tools.ant.taskdefs.op
 
 import java.io.File;
 import java.lang.reflect.Constructor;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.Locale;
 import java.util.Vector;
 

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java Mon Dec 13 18:34:00 2010
@@ -736,7 +736,7 @@ public class FTPTaskMirrorImpl implement
                         } else if (!result) {
                             return;
                         }
-                        this.curpwd = this.curpwd + task.getSeparator()
+                        this.curpwd = getCurpwdPlusFileSep()
                             + currentPathElement;
                     } catch (IOException ioe) {
                         throw new BuildException("could not change working dir to "
@@ -797,7 +797,7 @@ public class FTPTaskMirrorImpl implement
              * @return absolute path as string
              */
             public String getAbsolutePath() {
-                return curpwd + task.getSeparator() + ftpFile.getName();
+                return getCurpwdPlusFileSep() + ftpFile.getName();
             }
             /**
              * find out the relative path assuming that the path used to construct
@@ -943,6 +943,17 @@ public class FTPTaskMirrorImpl implement
                 return curpwd;
             }
             /**
+             * returns the path of the directory containing the AntFTPFile.
+             * of the full path of the file itself in case of AntFTPRootFile
+             * and appends the remote file separator if necessary.
+             * @return parent directory of the AntFTPFile
+             * @since Ant 1.8.2
+             */
+            public String getCurpwdPlusFileSep() {
+                String sep = task.getSeparator();
+                return curpwd.endsWith(sep) ? curpwd : curpwd + sep;
+            }
+            /**
              * find out if a symbolic link is encountered in the relative path of this file
              * from rootPath.
              * @return <code>true</code> if a symbolic link is encountered in the relative path.

Propchange: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Mon Dec 13 18:34:00 2010
@@ -0,0 +1,2 @@
+/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java:945039
+/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java:939803-1045116

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java Mon Dec 13 18:34:00 2010
@@ -282,7 +282,6 @@ public class ScpFromMessage extends Abst
 
     private void setLastModified(File localFile) throws JSchException {
         SftpATTRS fileAttributes = null;
-        String remotePath = null;
         ChannelSftp channel = openSftpChannel();
         channel.connect();
         try {

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java Mon Dec 13 18:34:00 2010
@@ -29,24 +29,25 @@
 
 package org.apache.tools.ant.taskdefs.optional.unix;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
 
-import java.util.Vector;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.Properties;
+import java.util.Vector;
 
-import org.apache.tools.ant.Project;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.dispatch.DispatchTask;
 import org.apache.tools.ant.dispatch.DispatchUtils;
 import org.apache.tools.ant.taskdefs.Execute;
@@ -560,8 +561,10 @@ public class Symlink extends DispatchTas
                 File inc = new File(dir, incs[j]);
                 File pf = inc.getParentFile();
                 Properties lnks = new Properties();
+                InputStream is = null;
                 try {
-                    lnks.load(new BufferedInputStream(new FileInputStream(inc)));
+                    is = new BufferedInputStream(new FileInputStream(inc));
+                    lnks.load(is);
                     pf = pf.getCanonicalFile();
                 } catch (FileNotFoundException fnfe) {
                     handleError("Unable to find " + incs[j] + "; skipping it.");
@@ -570,6 +573,8 @@ public class Symlink extends DispatchTas
                     handleError("Unable to open " + incs[j]
                                 + " or its parent dir; skipping it.");
                     continue;
+                } finally {
+                    FileUtils.close(is);
                 }
                 lnks.list(new PrintStream(
                     new LogOutputStream(this, Project.MSG_INFO)));

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/AbstractFileSet.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/AbstractFileSet.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/AbstractFileSet.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/AbstractFileSet.java Mon Dec 13 18:34:00 2010
@@ -444,6 +444,15 @@ public abstract class AbstractFileSet ex
      }
 
     /**
+     * Gets whether an error is/shold be thrown if the base directory
+     * does not exist.
+     * @since Ant 1.8.2
+     */
+     public boolean getErrorOnMissingDir() {
+         return errorOnMissingDir;
+     }
+
+    /**
      * Returns the directory scanner needed to access the files to process.
      * @return a <code>DirectoryScanner</code> instance.
      */

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/Path.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/Path.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/Path.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/Path.java Mon Dec 13 18:34:00 2010
@@ -342,6 +342,12 @@ public class Path extends DataType imple
             }
             if (f.exists()) {
                 setLocation(f);
+            } else if (f.getParentFile() != null && f.getParentFile().exists()
+                       && containsWildcards(f.getName())) {
+                setLocation(f);
+                log("adding " + f + " which contains wildcards and may not"
+                    + " do what you intend it to do depending on your OS or"
+                    + " version of Java", Project.MSG_VERBOSE);
             } else {
                 log("dropping " + f + " from path as it doesn't exist",
                     Project.MSG_VERBOSE);
@@ -759,4 +765,14 @@ public class Path extends DataType imple
         }
         return preserveBC.booleanValue();
     }
+
+    /**
+     * Does the given file name contain wildcards?
+     * @since Ant 1.8.2
+     */
+    private static boolean containsWildcards(String path) {
+        return path != null
+            && (path.indexOf("*") > -1 || path.indexOf("?") > -1);
+    }
+
 }

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/ZipScanner.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/ZipScanner.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/ZipScanner.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/ZipScanner.java Mon Dec 13 18:34:00 2010
@@ -25,7 +25,6 @@ import java.util.Map;
 import java.util.zip.ZipException;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.types.resources.ZipResource;
 import org.apache.tools.ant.types.resources.FileProvider;
 import org.apache.tools.zip.ZipEntry;

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/defaults.properties
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/defaults.properties?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/defaults.properties (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/defaults.properties Mon Dec 13 18:34:00 2010
@@ -46,6 +46,7 @@ compositemapper=org.apache.tools.ant.uti
 chainedmapper=org.apache.tools.ant.util.ChainedMapper
 filtermapper=org.apache.tools.ant.types.mappers.FilterMapper
 firstmatchmapper=org.apache.tools.ant.util.FirstMatchMapper
+cutdirsmapper=org.apache.tools.ant.types.mappers.CutDirsMapper
 
 #this condition is in here because it is the sole
 #condition defined in Ant1.6

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java Mon Dec 13 18:34:00 2010
@@ -17,16 +17,8 @@
  */
 package org.apache.tools.ant.types.resources;
 
-import java.io.File;
-import java.util.Stack;
-import java.util.Iterator;
 import java.util.Collection;
-
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.DataType;
-import org.apache.tools.ant.types.Resource;
-import org.apache.tools.ant.types.ResourceCollection;
+import java.util.Iterator;
 
 /**
  * Base class for a ResourceCollection that wraps a single nested
@@ -34,165 +26,24 @@ import org.apache.tools.ant.types.Resour
  * @since Ant 1.7
  */
 public abstract class BaseResourceCollectionWrapper
-    extends DataType implements ResourceCollection, Cloneable {
-    private static final String ONE_NESTED_MESSAGE
-        = " expects exactly one nested resource collection.";
+    extends AbstractResourceCollectionWrapper {
 
-    private ResourceCollection rc;
     private Collection coll = null;
-    private boolean cache = true;
-
-    /**
-     * Set whether to cache collections.
-     * @param b boolean cache flag.
-     */
-    public synchronized void setCache(boolean b) {
-        cache = b;
-    }
 
-    /**
-     * Learn whether to cache collections. Default is <code>true</code>.
-     * @return boolean cache flag.
-     */
-    public synchronized boolean isCache() {
-        return cache;
+    protected Iterator createIterator() {
+        return cacheCollection().iterator();
     }
 
-    /**
-     * Add a ResourceCollection to the container.
-     * @param c the ResourceCollection to add.
-     * @throws BuildException on error.
-     */
-    public synchronized void add(ResourceCollection c) throws BuildException {
-        if (isReference()) {
-            throw noChildrenAllowed();
-        }
-        if (c == null) {
-            return;
-        }
-        if (rc != null) {
-            throw oneNested();
-        }
-        rc = c;
-        if (Project.getProject(rc) == null) {
-            Project p = getProject();
-            if (p != null) {
-                p.setProjectReference(rc);
-            }
-        }
-        setChecked(false);
-    }
-
-    /**
-     * Fulfill the ResourceCollection contract.
-     * @return an Iterator of Resources.
-     */
-    public final synchronized Iterator iterator() {
-        if (isReference()) {
-            return ((BaseResourceCollectionWrapper) getCheckedRef()).iterator();
-        }
-        dieOnCircularReference();
-        return new FailFast(this, cacheCollection().iterator());
-    }
-
-    /**
-     * Fulfill the ResourceCollection contract.
-     * @return number of elements as int.
-     */
-    public synchronized int size() {
-        if (isReference()) {
-            return ((BaseResourceCollectionWrapper) getCheckedRef()).size();
-        }
-        dieOnCircularReference();
+	protected int getSize() {
         return cacheCollection().size();
     }
 
     /**
-     * Fulfill the ResourceCollection contract.
-     * @return whether this is a filesystem-only resource collection.
-     */
-    public synchronized boolean isFilesystemOnly() {
-        if (isReference()) {
-            return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly();
-        }
-        dieOnCircularReference();
-
-        if (rc == null || rc.isFilesystemOnly()) {
-            return true;
-        }
-        /* now check each Resource in case the child only
-           lets through files from any children IT may have: */
-        for (Iterator i = cacheCollection().iterator(); i.hasNext();) {
-            Resource r = (Resource) i.next();
-            if (r.as(FileProvider.class) == null) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Overrides the version of DataType to recurse on all DataType
-     * child elements that may have been added.
-     * @param stk the stack of data types to use (recursively).
-     * @param p   the project to use to dereference the references.
-     * @throws BuildException on error.
-     */
-    protected synchronized void dieOnCircularReference(Stack stk, Project p)
-        throws BuildException {
-        if (isChecked()) {
-            return;
-        }
-        if (isReference()) {
-            super.dieOnCircularReference(stk, p);
-        } else {
-            if (rc instanceof DataType) {
-                pushAndInvokeCircularReferenceCheck((DataType) rc, stk, p);
-            }
-            setChecked(true);
-        }
-    }
-
-    /**
-     * Get the nested ResourceCollection.
-     * @return a ResourceCollection.
-     * @throws BuildException if no nested ResourceCollection has been provided.
-     */
-    protected final synchronized ResourceCollection getResourceCollection() {
-        dieOnCircularReference();
-        if (rc == null) {
-            throw oneNested();
-        }
-        return rc;
-    }
-
-    /**
      * Template method for subclasses to return a Collection of Resources.
      * @return Collection.
      */
     protected abstract Collection getCollection();
 
-    /**
-     * Format this BaseResourceCollectionWrapper as a String.
-     * @return a descriptive <code>String</code>.
-     */
-    public synchronized String toString() {
-        if (isReference()) {
-            return getCheckedRef().toString();
-        }
-        if (cacheCollection().size() == 0) {
-            return "";
-        }
-        StringBuffer sb = new StringBuffer();
-        for (Iterator i = coll.iterator(); i.hasNext();) {
-            if (sb.length() > 0) {
-                sb.append(File.pathSeparatorChar);
-            }
-            sb.append(i.next());
-        }
-        return sb.toString();
-    }
-
     private synchronized Collection cacheCollection() {
         if (coll == null || !isCache()) {
             coll = getCollection();
@@ -200,8 +51,4 @@ public abstract class BaseResourceCollec
         return coll;
     }
 
-    private BuildException oneNested() {
-        return new BuildException(super.toString() + ONE_NESTED_MESSAGE);
-    }
-
 }

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/FileResource.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/FileResource.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/FileResource.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/FileResource.java Mon Dec 13 18:34:00 2010
@@ -345,7 +345,9 @@ public class FileResource extends Resour
             ((FileResource) getCheckedRef()).touch(modTime);
             return;
         }
-        getNotNullFile().setLastModified(modTime);
+        if (!getNotNullFile().setLastModified(modTime)) {
+            log("Failed to change file modification time", Project.MSG_WARN);
+        }
     }
 
     /**

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Resources.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Resources.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Resources.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Resources.java Mon Dec 13 18:34:00 2010
@@ -208,6 +208,7 @@ public class Resources extends DataType 
         if (isReference()) {
             return getCheckedRef().toString();
         }
+        validate();
         if (coll == null || coll.isEmpty()) {
             return "";
         }

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Restrict.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Restrict.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Restrict.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/Restrict.java Mon Dec 13 18:34:00 2010
@@ -17,8 +17,6 @@
  */
 package org.apache.tools.ant.types.resources;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.Stack;
 
@@ -37,23 +35,17 @@ import org.apache.tools.ant.types.resour
 public class Restrict
     extends ResourceSelectorContainer implements ResourceCollection {
 
-    private BaseResourceCollectionWrapper w = new BaseResourceCollectionWrapper() {
+    private LazyResourceCollectionWrapper w = new  LazyResourceCollectionWrapper() {
         /**
          * Restrict the nested ResourceCollection based on the nested selectors.
-         * @return a Collection of Resources.
          */
-        protected Collection getCollection() {
-            ArrayList result = new ArrayList();
-outer:      for (Iterator ri = w.getResourceCollection().iterator(); ri.hasNext();) {
-                Resource r = (Resource) ri.next();
-                for (Iterator i = getSelectors(); i.hasNext();) {
-                    if (!((ResourceSelector) (i.next())).isSelected(r)) {
-                        continue outer;
-                    }
+        protected boolean filterResource(Resource r) {
+            for (Iterator i = getSelectors(); i.hasNext();) {
+                if (!((ResourceSelector) (i.next())).isSelected(r)) {
+                    return true;
                 }
-                result.add(r);
             }
-            return result;
+            return false;
         }
     };
 

Modified: ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/selectors/Name.java
URL: http://svn.apache.org/viewvc/ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/selectors/Name.java?rev=1045279&r1=1045278&r2=1045279&view=diff
==============================================================================
--- ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/selectors/Name.java (original)
+++ ant/core/branches/ANT_SITE/src/main/org/apache/tools/ant/types/resources/selectors/Name.java Mon Dec 13 18:34:00 2010
@@ -22,6 +22,7 @@ import org.apache.tools.ant.types.Regula
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.selectors.SelectorUtils;
 import org.apache.tools.ant.util.regexp.Regexp;
+import org.apache.tools.ant.util.regexp.RegexpUtil;
 
 /**
  * Name ResourceSelector.
@@ -137,11 +138,7 @@ public class Name implements ResourceSel
                 reg.setPattern(regex);
                 expression = reg.getRegexp(project);
             }
-            int options = Regexp.MATCH_DEFAULT;
-            if (!cs) {
-                options |= Regexp.MATCH_CASE_INSENSITIVE;
-            }
-            return expression.matches(modify(name), options);
+            return expression.matches(modify(name), RegexpUtil.asOptions(cs));
         }
     }
 



Mime
View raw message