Ok, this is what I've managed to bash together this morning:

- NioFileUtils (uses Java1.4 NIO libraries, altered the TRANSFER_SIZE as suggested to 32000, currently no way to override that (yet)) - Java6FileUtils (currently has no implementation, but could be used in future for implementing Java6 features (file permisions etc)) - FileUtils (refactored to imlement interface, still needs to have all comments refactored into @see -> interface)
- FileUtilsAdapter (interface of FileUtils)
- FileUtilsFactory (uses runtime class-loading to select correct version, also allows for selection of impl via system property or ant property (project.getProperty), as suggested, caches the instance of the FileUtilsAdapter on first use. This assumes that during a build a user won't want to swap out FilUtils implementations.)
- build.xml (contains the selector code for [Nio|Java6]FileUtils)

Current problems:
I cannot get the current code to select the implementation based on the property I'm specifying - (I'm using .ant.properties and I've also tried -D style props). Any hint as to how this mechanism works in general would be appreciated. Code is just in util package, it would be nicer in it's own separate package - open to suggestions on this. Not sure that the selector in the build is working - after bootstrap + build, the ant-nodeps.jar doesn't contain the Nio or the Java6FileUtils - should they be here?

Patch attached for consideration and comments.

Btw, swapping to NIO does help the AppFuse build to get past the copying - it now fails on HtmlUnit - which we can't do much about. So (anecdotally anyway), NIO seems to use less memory than traditional IO.

Thanks
Kev
Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/MagicNames.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/MagicNames.java   
    (revision 395527)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/MagicNames.java   
    (working copy)
@@ -127,6 +127,14 @@
      * Value: [EMAIL PROTECTED]
      */
     public static final String REGEXP_IMPL = "ant.regexp.regexpimpl";
+    
+    /**
+     * property for file utils implementation.
+     * default to classic/original
+     * @since Ant 1.7
+     * Value: [EMAIL PROTECTED]
+     */
+    public static final String FILEUTILS_IMPL = "ant.util.fileutilsimpl";
 
     /**
      * property that provides the default value for javac's and

Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
    (revision 395527)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
    (working copy)
@@ -28,25 +28,28 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.Project;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
-import org.apache.tools.ant.types.Mapper;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.FilterSet;
-import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.FilterSetCollection;
+import org.apache.tools.ant.types.Mapper;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.ResourceFactory;
 import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.FileNameMapper;
+import org.apache.tools.ant.util.FileUtilsAdapter;
+import org.apache.tools.ant.util.FileUtilsFactory;
+import org.apache.tools.ant.util.FlatFileNameMapper;
 import org.apache.tools.ant.util.IdentityMapper;
 import org.apache.tools.ant.util.ResourceUtils;
 import org.apache.tools.ant.util.SourceFileScanner;
-import org.apache.tools.ant.util.FlatFileNameMapper;
 
 /**
  * Copies a file or directory to a new file
@@ -85,7 +88,7 @@
     protected Hashtable completeDirMap = new Hashtable();
 
     protected Mapper mapperElement = null;
-    protected FileUtils fileUtils;
+    protected FileUtilsAdapter fileUtils;
     private Vector filterChains = new Vector();
     private Vector filterSets = new Vector();
     private String inputEncoding = null;
@@ -96,7 +99,7 @@
      * Copy task constructor.
      */
     public Copy() {
-        fileUtils = FileUtils.getFileUtils();
+        fileUtils = FileUtilsFactory.getFileUtils();
         granularity = fileUtils.getFileTimestampGranularity();
     }
 
@@ -105,7 +108,7 @@
      * @return the fileutils object.
      */
     protected FileUtils getFileUtils() {
-        return fileUtils;
+        return FileUtils.getFileUtils();
     }
 
     /**
@@ -758,25 +761,36 @@
      */
     protected void doFileOperations() {
         if (fileCopyMap.size() > 0) {
-            log("Copying " + fileCopyMap.size()
-                + " file" + (fileCopyMap.size() == 1 ? "" : "s")
-                + " to " + destDir.getAbsolutePath());
+            StringBuffer sb = new StringBuffer("Copying ")
+                .append(fileCopyMap.size())
+                .append(" file")
+                .append((fileCopyMap.size() == 1 ? "" : "s"))
+                .append(" to ")
+                .append(destDir.getAbsolutePath());
+            log(sb.toString());
 
             Enumeration e = fileCopyMap.keys();
+            String toFile;
             while (e.hasMoreElements()) {
                 String fromFile = (String) e.nextElement();
+                // use a StringBuffer to try to reduce memory consumption on 
large numbers of files
+                if (verbosity >= Project.MSG_DEBUG) {
+                    sb = new StringBuffer("Copying 
").append(fromFile).append(" to ");
+                }
+                
                 String[] toFiles = (String[]) fileCopyMap.get(fromFile);
 
                 for (int i = 0; i < toFiles.length; i++) {
-                    String toFile = toFiles[i];
+                    toFile = toFiles[i];
 
                     if (fromFile.equals(toFile)) {
                         log("Skipping self-copy of " + fromFile, verbosity);
                         continue;
                     }
                     try {
-                        log("Copying " + fromFile + " to " + toFile, 
verbosity);
-
+                        if (verbosity >= Project.MSG_DEBUG) {
+                            log(sb.append(toFile).toString(), verbosity);
+                        }
                         FilterSetCollection executionFilters =
                             new FilterSetCollection();
                         if (filtering) {

Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtils.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtils.java
   (revision 395527)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtils.java
   (working copy)
@@ -46,7 +46,7 @@
  * their last modification time.
  *
  */
-public class FileUtils {
+public class FileUtils implements FileUtilsAdapter {
 
     private static final FileUtils PRIMARY_INSTANCE = new FileUtils();
 
@@ -61,26 +61,7 @@
 
     static final int BUF_SIZE = 8192;
 
-
     /**
-     * The granularity of timestamps under FAT.
-     */
-    public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000;
-
-    /**
-     * The granularity of timestamps under Unix.
-     */
-    public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000;
-
-    /**
-     * The granularity of timestamps under the NT File System.
-     * NTFS has a granularity of 100 nanoseconds, which is less
-     * than 1 millisecond, so we round this up to 1 millisecond.
-     */
-    public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1;
-
-
-    /**
      * Factory method.
      *
      * @return a new instance of FileUtils.
Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/NioFileUtils.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/NioFileUtils.java
        (revision 0)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/NioFileUtils.java
        (revision 0)
@@ -0,0 +1,232 @@
+/*
+ * 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.util;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.nio.channels.FileChannel;
+import java.util.Vector;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.filters.util.ChainReaderHelper;
+import org.apache.tools.ant.types.FilterSetCollection;
+
+/**
+ * @author jbleijen
+ */
+public class NioFileUtils extends FileUtils {
+
+    private static final int TRANSFER_SIZE = 32000;
+
+    /**
+     * Empty constructor.
+     */
+    protected NioFileUtils() {
+        super();
+    }
+
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * filter chains must be used, if source files may overwrite
+     * newer destination files and the last modified time of
+     * <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param filterChains filterChains to apply during the copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param inputEncoding the encoding used to read the files.
+     * @param outputEncoding the encoding used to write the files.
+     * @param project the project instance.
+     *
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.6
+     */
+    public void copyFile(File sourceFile, File destFile,
+                         FilterSetCollection filters, Vector filterChains,
+                         boolean overwrite, boolean preserveLastModified,
+                         String inputEncoding, String outputEncoding,
+                         Project project)
+        throws IOException {
+
+        if (overwrite || !destFile.exists()
+            || destFile.lastModified() < sourceFile.lastModified()) {
+
+            if (destFile.exists() && destFile.isFile()) {
+                destFile.delete();
+            }
+            // ensure that parent dir of dest file exists!
+            // not using getParentFile method to stay 1.1 compat
+            File parent = destFile.getParentFile();
+            if (parent != null && !parent.exists()) {
+                parent.mkdirs();
+            }
+            final boolean filterSetsAvailable = (filters != null
+                                                 && filters.hasFilters());
+            final boolean filterChainsAvailable = (filterChains != null
+                                                   && filterChains.size() > 0);
+            if (filterSetsAvailable) {
+                BufferedReader in = null;
+                BufferedWriter out = null;
+                try {
+                    if (inputEncoding == null) {
+                        in = new BufferedReader(new FileReader(sourceFile));
+                    } else {
+                        InputStreamReader isr
+                            = new InputStreamReader(new 
FileInputStream(sourceFile),
+                                                    inputEncoding);
+                        in = new BufferedReader(isr);
+                    }
+                    if (outputEncoding == null) {
+                        out = new BufferedWriter(new FileWriter(destFile));
+                    } else {
+                        OutputStreamWriter osw
+                            = new OutputStreamWriter(new 
FileOutputStream(destFile),
+                                                     outputEncoding);
+                        out = new BufferedWriter(osw);
+                    }
+                    if (filterChainsAvailable) {
+                        ChainReaderHelper crh = new ChainReaderHelper();
+                        crh.setBufferSize(BUF_SIZE);
+                        crh.setPrimaryReader(in);
+                        crh.setFilterChains(filterChains);
+                        crh.setProject(project);
+                        Reader rdr = crh.getAssembledReader();
+                        in = new BufferedReader(rdr);
+                    }
+                    LineTokenizer lineTokenizer = new LineTokenizer();
+                    lineTokenizer.setIncludeDelims(true);
+                    String newline = null;
+                    String line = lineTokenizer.getToken(in);
+                    while (line != null) {
+                        if (line.length() == 0) {
+                            // this should not happen, because the lines are
+                            // returned with the end of line delimiter
+                            out.newLine();
+                        } else {
+                            newline = filters.replaceTokens(line);
+                            out.write(newline);
+                        }
+                        line = lineTokenizer.getToken(in);
+                    }
+                } finally {
+                    close(out);
+                    close(in);
+                }
+            } else if (filterChainsAvailable
+                       || (inputEncoding != null
+                           && !inputEncoding.equals(outputEncoding))
+                       || (inputEncoding == null && outputEncoding != null)) {
+                BufferedReader in = null;
+                BufferedWriter out = null;
+                 try {
+                     if (inputEncoding == null) {
+                         in = new BufferedReader(new FileReader(sourceFile));
+                     } else {
+                         in =
+                             new BufferedReader(
+                                 new InputStreamReader(
+                                     new FileInputStream(sourceFile),
+                                     inputEncoding));
+                     }
+                     if (outputEncoding == null) {
+                         out = new BufferedWriter(new FileWriter(destFile));
+                     } else {
+                         out =
+                             new BufferedWriter(
+                                 new OutputStreamWriter(
+                                     new FileOutputStream(destFile),
+                                     outputEncoding));
+                     }
+                     if (filterChainsAvailable) {
+                         ChainReaderHelper crh = new ChainReaderHelper();
+                         crh.setBufferSize(BUF_SIZE);
+                         crh.setPrimaryReader(in);
+                         crh.setFilterChains(filterChains);
+                         crh.setProject(project);
+                         Reader rdr = crh.getAssembledReader();
+                         in = new BufferedReader(rdr);
+                     }
+                     char[] buffer = new char[BUF_SIZE];
+                     while (true) {
+                         int nRead = in.read(buffer, 0, buffer.length);
+                         if (nRead == -1) {
+                             break;
+                         }
+                         out.write(buffer, 0, nRead);
+                      }
+                 } finally {
+                     close(out);
+                     close(in);
+                 }
+            } else {
+                FileInputStream in = null;
+                FileOutputStream out = null;
+                FileChannel srcChannel = null;
+                FileChannel destChannel = null;
+
+                try {
+                    // we can use direct copy with nio
+                    in = new FileInputStream(sourceFile);
+                    out = new FileOutputStream(destFile);
+                        
+                    srcChannel = in.getChannel();
+                    destChannel = out.getChannel();
+                    
+                    long position = 0;
+                    long count = srcChannel.size();
+                    while( position < count ) {
+                      position += srcChannel.transferTo(position, 
TRANSFER_SIZE, destChannel);
+                    }
+               } finally {
+                    if (srcChannel != null)
+                       srcChannel.close();
+                    if (destChannel != null)
+                        destChannel.close();
+                    if (out != null)
+                        out.close();
+                    if (in != null)
+                        in.close();
+                }
+
+            }
+            if (preserveLastModified) {
+                setFileLastModified(destFile, sourceFile.lastModified());
+            }
+        }
+    }
+}
\ No newline at end of file
Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtilsFactory.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtilsFactory.java
    (revision 0)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtilsFactory.java
    (revision 0)
@@ -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.util;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.Project;
+
+public class FileUtilsFactory {
+
+    private static final String CLASSIC = 
"org.apache.tools.ant.util.FileUtils";
+    private static final String NIO = "org.apache.tools.ant.util.NioFileUtils";
+    private static final String JAVA6 = 
"org.apache.tools.ant.util.Java6FileUtils";
+    
+    private static FileUtilsAdapter instance = null;
+    
+    /* private shouldn't instantiate a factory */
+    private FileUtilsFactory() {}
+    
+    /***
+     * Create a new FileUtilsAdapter instance.
+     * @return the fileutils adapter
+     * @throws BuildException on error
+     */
+    public static FileUtilsAdapter getFileUtils() {
+        return (instance == null) ? newFileUtils(null) : instance;
+    }
+    
+    /***
+     * Create a new FileUtilsAdapter instance.
+     * @param p Project
+     * @return the fileutils adapter
+     * @throws BuildException on error
+     */
+    public static FileUtilsAdapter getFileUtils(final Project p) {
+        return (instance == null) ? newFileUtils(p) : instance;
+    }
+    
+    /***
+     * Create a new fileutils instance.
+     *
+     * @param p Project whose ant.util.fileutilsimpl property will be used.
+     * @return the fileutils adapter
+     * @throws BuildException on error
+     */
+    public static FileUtilsAdapter newFileUtils(final Project p) throws 
BuildException {
+        String systemDefault = null;
+        if (p == null) {
+            systemDefault = System.getProperty(MagicNames.FILEUTILS_IMPL);
+        } else {
+            systemDefault = p.getProperty(MagicNames.FILEUTILS_IMPL);
+        }
+        
+        if (systemDefault != null) {
+            return createInstance(systemDefault);
+        }
+        
+        /* none specified in project, or in System properties
+         * so try best available until we get a match
+         */
+        try {
+            return createInstance(JAVA6);
+        } catch (BuildException e) {
+            // ignore
+        }
+
+        try {
+            return createInstance(NIO);
+        } catch (BuildException e) {
+            // ignore
+        }
+        
+        try {
+            return createInstance(CLASSIC);
+        } catch (BuildException e) {
+            // ignore
+        }
+        
+        //shouldn't reach here
+        throw new BuildException("No FileUtils implementation found");
+    }
+    
+    /**
+     * Create an instance of an implementation from a classname.
+     *
+     * @param className a <code>String</code> value
+     * @return a <code>FileUtilsAdapter</code> value
+     * @exception BuildException if an error occurs
+     */
+    protected static FileUtilsAdapter createInstance(final String className) 
throws BuildException {
+        instance = (FileUtilsAdapter) ClasspathUtils.newInstance(className,
+                FileUtilsFactory.class.getClassLoader(), 
FileUtilsAdapter.class);
+        return instance;
+    }
+}
Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtilsAdapter.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtilsAdapter.java
    (revision 0)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/FileUtilsAdapter.java
    (revision 0)
@@ -0,0 +1,714 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Vector;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.FilterSetCollection;
+
+/**
+ * An interface for the different types of FileUtils (classic, Nio, Java6+)
+ *
+ */
+public interface FileUtilsAdapter {
+    
+    /**
+     * The granularity of timestamps under FAT.
+     */
+    public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000;
+
+    /**
+     * The granularity of timestamps under Unix.
+     */
+    public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000;
+
+    /**
+     * The granularity of timestamps under the NT File System.
+     * NTFS has a granularity of 100 nanoseconds, which is less
+     * than 1 millisecond, so we round this up to 1 millisecond.
+     */
+    public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1;
+    
+    /**
+     * Get the URL for a file taking into account # characters.
+     *
+     * @param file the file whose URL representation is required.
+     * @return The FileURL value.
+     * @throws MalformedURLException if the URL representation cannot be
+     *      formed.
+     */
+    public URL getFileURL(File file) throws MalformedURLException;
+    
+    /**
+     * Convenience method to copy a file from a source to a destination.
+     * No filtering is performed.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(String sourceFile, String destFile)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a destination
+     * specifying if token filtering must be used.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(String sourceFile, String destFile,
+                         FilterSetCollection filters)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used and if
+     * source files may overwrite newer destination files.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(String sourceFile, String destFile, 
FilterSetCollection filters,
+                         boolean overwrite) throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * source files may overwrite newer destination files and the
+     * last modified time of <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(String sourceFile, String destFile, 
FilterSetCollection filters,
+                         boolean overwrite, boolean preserveLastModified)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * source files may overwrite newer destination files and the
+     * last modified time of <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param encoding the encoding used to read and write the files.
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.5
+     */
+    public void copyFile(String sourceFile, String destFile,
+                         FilterSetCollection filters, boolean overwrite,
+                         boolean preserveLastModified, String encoding)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * filter chains must be used, if source files may overwrite
+     * newer destination files and the last modified time of
+     * <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param filterChains filterChains to apply during the copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param encoding the encoding used to read and write the files.
+     * @param project the project instance.
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.5
+     */
+    public void copyFile(String sourceFile, String destFile,
+                         FilterSetCollection filters, Vector filterChains,
+                         boolean overwrite, boolean preserveLastModified,
+                         String encoding, Project project)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * filter chains must be used, if source files may overwrite
+     * newer destination files and the last modified time of
+     * <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile Name of file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile Name of file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param filterChains filterChains to apply during the copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param inputEncoding the encoding used to read the files.
+     * @param outputEncoding the encoding used to write the files.
+     * @param project the project instance.
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.6
+     */
+    public void copyFile(String sourceFile, String destFile,
+                         FilterSetCollection filters, Vector filterChains,
+                         boolean overwrite, boolean preserveLastModified,
+                         String inputEncoding, String outputEncoding,
+                         Project project)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a destination.
+     * No filtering is performed.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(File sourceFile, File destFile) throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a destination
+     * specifying if token filtering must be used.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(File sourceFile, File destFile, FilterSetCollection 
filters)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used and if
+     * source files may overwrite newer destination files.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(File sourceFile, File destFile, FilterSetCollection 
filters,
+                         boolean overwrite) throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * source files may overwrite newer destination files and the
+     * last modified time of <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     *
+     * @throws IOException if the copying fails.
+     */
+    public void copyFile(File sourceFile, File destFile, FilterSetCollection 
filters,
+                         boolean overwrite, boolean preserveLastModified)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * source files may overwrite newer destination files, the last
+     * modified time of <code>destFile</code> file should be made
+     * equal to the last modified time of <code>sourceFile</code> and
+     * which character encoding to assume.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param encoding the encoding used to read and write the files.
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.5
+     */
+    public void copyFile(File sourceFile, File destFile,
+                         FilterSetCollection filters, boolean overwrite,
+                         boolean preserveLastModified, String encoding)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * filter chains must be used, if source files may overwrite
+     * newer destination files and the last modified time of
+     * <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param filterChains filterChains to apply during the copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param encoding the encoding used to read and write the files.
+     * @param project the project instance.
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.5
+     */
+    public void copyFile(File sourceFile, File destFile,
+                         FilterSetCollection filters, Vector filterChains,
+                         boolean overwrite, boolean preserveLastModified,
+                         String encoding, Project project)
+        throws IOException;
+    
+    /**
+     * Convenience method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * filter chains must be used, if source files may overwrite
+     * newer destination files and the last modified time of
+     * <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @param sourceFile the file to copy from.
+     *                   Must not be <code>null</code>.
+     * @param destFile the file to copy to.
+     *                 Must not be <code>null</code>.
+     * @param filters the collection of filters to apply to this copy.
+     * @param filterChains filterChains to apply during the copy.
+     * @param overwrite Whether or not the destination file should be
+     *                  overwritten if it already exists.
+     * @param preserveLastModified Whether or not the last modified time of
+     *                             the resulting file should be set to that
+     *                             of the source file.
+     * @param inputEncoding the encoding used to read the files.
+     * @param outputEncoding the encoding used to write the files.
+     * @param project the project instance.
+     *
+     *
+     * @throws IOException if the copying fails.
+     *
+     * @since Ant 1.6
+     */
+    public void copyFile(File sourceFile, File destFile,
+                         FilterSetCollection filters, Vector filterChains,
+                         boolean overwrite, boolean preserveLastModified,
+                         String inputEncoding, String outputEncoding,
+                         Project project)
+        throws IOException;
+    
+    /**
+     * Calls File.setLastModified(long time). Originally written to
+     * to dynamically bind to that call on Java1.2+.
+     *
+     * @param file the file whose modified time is to be set
+     * @param time the time to which the last modified time is to be set.
+     *             if this is -1, the current time is used.
+     */
+    public void setFileLastModified(File file, long time);
+    
+    /**
+     * Interpret the filename as a file relative to the given file
+     * unless the filename already represents an absolute filename.
+     * Differs from <code>new File(file, filename)</code> in that
+     * the resulting File's path will always be a normalized,
+     * absolute pathname.  Also, if it is determined that
+     * <code>filename</code> is context-relative, <code>file</code>
+     * will be discarded and the reference will be resolved using
+     * available context/state information about the filesystem.
+     *
+     * @param file the "reference" file for relative paths. This
+     * instance must be an absolute file and must not contain
+     * &quot;./&quot; or &quot;../&quot; sequences (same for \ instead
+     * of /).  If it is null, this call is equivalent to
+     * <code>new java.io.File(filename).getAbsoluteFile()</code>.
+     *
+     * @param filename a file name.
+     *
+     * @return an absolute file.
+     * @throws java.lang.NullPointerException if filename is null.
+     */
+    public File resolveFile(File file, String filename);
+                
+    /**
+     * &quot;Normalize&quot; the given absolute path.
+     *
+     * <p>This includes:
+     * <ul>
+     *   <li>Uppercase the drive letter if there is one.</li>
+     *   <li>Remove redundant slashes after the drive spec.</li>
+     *   <li>Resolve all ./, .\, ../ and ..\ sequences.</li>
+     *   <li>DOS style paths that start with a drive letter will have
+     *     \ as the separator.</li>
+     * </ul>
+     * Unlike <code>File#getCanonicalPath()</code> this method
+     * specifically does not resolve symbolic links.
+     *
+     * @param path the path to be normalized.
+     * @return the normalized version of the path.
+     *
+     * @throws java.lang.NullPointerException if path is null.
+     */
+    public File normalize(final String path);
+    
+    /**
+     * Dissect the specified absolute path.
+     * @param path the path to dissect.
+     * @return String[] {root, remaining path}.
+     * @throws java.lang.NullPointerException if path is null.
+     * @since Ant 1.7
+     */
+    public String[] dissect(String path);
+    
+    /**
+     * Returns a VMS String representation of a <code>File</code> object.
+     * This is useful since the JVM by default internally converts VMS paths
+     * to Unix style.
+     * The returned String is always an absolute path.
+     *
+     * @param f The <code>File</code> to get the VMS path for.
+     * @return The absolute VMS path to <code>f</code>.
+     */
+    public String toVMSPath(File f);
+    
+    /**
+     * Create a temporary file in a given directory.
+     *
+     * <p>The file denoted by the returned abstract pathname did not
+     * exist before this method was invoked, any subsequent invocation
+     * of this method will yield a different file name.</p>
+     * <p>
+     * The filename is prefixNNNNNsuffix where NNNN is a random number.
+     * </p>
+     * <p>This method is different from File.createTempFile() of JDK 1.2
+     * as it doesn't create the file itself.  It uses the location pointed
+     * to by java.io.tmpdir when the parentDir attribute is null.</p>
+     *
+     * @param prefix prefix before the random number.
+     * @param suffix file extension; include the '.'.
+     * @param parentDir Directory to create the temporary file in;
+     * java.io.tmpdir used if not specified.
+     *
+     * @return a File reference to the new temporary file.
+     * @since Ant 1.5
+     */
+    public File createTempFile(String prefix, String suffix, File parentDir);
+    
+    /**
+     * Compares the contents of two files.
+     *
+     * @param f1 the file whose content is to be compared.
+     * @param f2 the other file whose content is to be compared.
+     *
+     * @return true if the content of the files is the same.
+     *
+     * @throws IOException if the files cannot be read.
+     */
+    public boolean contentEquals(File f1, File f2) throws IOException;
+    
+    /**
+     * Compares the contents of two files.
+     *
+     * @param f1 the file whose content is to be compared.
+     * @param f2 the other file whose content is to be compared.
+     * @param textfile true if the file is to be treated as a text file and
+     *        differences in kind of line break are to be ignored.
+     *
+     * @return true if the content of the files is the same.
+     *
+     * @throws IOException if the files cannot be read.
+     * @since Ant 1.6.3
+     */
+    public boolean contentEquals(File f1, File f2, boolean textfile) throws 
IOException;
+    
+    /**
+     * This was originally an emulation of [EMAIL PROTECTED] 
File#getParentFile} for JDK 1.1,
+     * but it is now implemented using that method (Ant 1.6.3 onwards).
+     * @param f the file whose parent is required.
+     * @return the given file's parent, or null if the file does not have a
+     *         parent.
+     * @since 1.10
+     * @deprecated Just use [EMAIL PROTECTED] File#getParentFile} directly.
+     */
+    public File getParentFile(File f);
+    
+    /**
+     * This was originally an emulation of File.createNewFile for JDK 1.1,
+     * but it is now implemented using that method (Ant 1.6.3 onwards).
+     *
+     * <p>This method has historically <strong>not</strong> guaranteed that the
+     * operation was atomic. In its current implementation it is.
+     *
+     * @param f the file to be created.
+     * @return true if the file did not exist already.
+     * @throws IOException on error.
+     * @since Ant 1.5
+     */
+    public boolean createNewFile(File f) throws IOException;
+    
+    /**
+     * Create a new file, optionally creating parent directories.
+     *
+     * @param f the file to be created.
+     * @param mkdirs <code>boolean</code> whether to create parent directories.
+     * @return true if the file did not exist already.
+     * @throws IOException on error.
+     * @since Ant 1.6.3
+     */
+    public boolean createNewFile(File f, boolean mkdirs) throws IOException;
+    
+    /**
+     * Checks whether a given file is a symbolic link.
+     *
+     * <p>It doesn't really test for symbolic links but whether the
+     * canonical and absolute paths of the file are identical--this
+     * may lead to false positives on some platforms.</p>
+     *
+     * @param parent the parent directory of the file to test
+     * @param name the name of the file to test.
+     *
+     * @return true if the file is a symbolic link.
+     * @throws IOException on error.
+     * @since Ant 1.5
+     */
+    public boolean isSymbolicLink(File parent, String name)
+        throws IOException;
+    
+    /**
+     * Removes a leading path from a second path.
+     *
+     * @param leading The leading path, must not be null, must be absolute.
+     * @param path The path to remove from, must not be null, must be absolute.
+     *
+     * @return path's normalized absolute if it doesn't start with
+     * leading; path's path with leading's path removed otherwise.
+     *
+     * @since Ant 1.5
+     */
+    public String removeLeadingPath(File leading, File path);
+    
+    /**
+     * Learn whether one path "leads" another.
+     * @param leading The leading path, must not be null, must be absolute.
+     * @param path The path to remove from, must not be null, must be absolute.
+     * @return true if path starts with leading; false otherwise.
+     * @since Ant 1.7
+     */
+    public boolean isLeadingPath(File leading, File path);
+    
+    /**
+     * Constructs a <code>file:</code> URI that represents the
+     * external form of the given pathname.
+     *
+     * <p>Will be an absolute URI if the given path is absolute.</p>
+     *
+     * <p>This code encodes non ASCII characters too.</p>
+     *
+     * <p>The coding of the output is the same as what 
File.toURI().toASCIIString() produces</p>
+     *
+     * @see <a href="http://www.w3.org/TR/xml11/#dt-sysid";>dt-sysid</a>
+     * which makes some mention of how
+     * characters not supported by URI Reference syntax should be escaped.
+     *
+     * @param path the path in the local file system.
+     * @return the URI version of the local path.
+     * @since Ant 1.6
+     */
+    public String toURI(String path);
+    
+    /**
+     * Constructs a file path from a <code>file:</code> URI.
+     *
+     * <p>Will be an absolute path if the given URI is absolute.</p>
+     *
+     * <p>Swallows '%' that are not followed by two characters,
+     * doesn't deal with non-ASCII characters.</p>
+     *
+     * @param uri the URI designating a file in the local filesystem.
+     * @return the local file system path for the file.
+     * @since Ant 1.6
+     */
+    public String fromURI(String uri);
+    
+    /**
+     * Compares two filenames.
+     *
+     * <p>Unlike java.io.File#equals this method will try to compare
+     * the absolute paths and &quot;normalize&quot; the filenames
+     * before comparing them.</p>
+     *
+     * @param f1 the file whose name is to be compared.
+     * @param f2 the other file whose name is to be compared.
+     *
+     * @return true if the file are for the same file.
+     *
+     * @since Ant 1.5.3
+     */
+    public boolean fileNameEquals(File f1, File f2);
+    
+    /**
+     * Renames a file, even if that involves crossing file system boundaries.
+     *
+     * <p>This will remove <code>to</code> (if it exists), ensure that
+     * <code>to</code>'s parent directory exists and move
+     * <code>from</code>, which involves deleting <code>from</code> as
+     * well.</p>
+     *
+     * @param from the file to move.
+     * @param to the new file name.
+     *
+     * @throws IOException if anything bad happens during this
+     * process.  Note that <code>to</code> may have been deleted
+     * already when this happens.
+     *
+     * @since Ant 1.6
+     */
+    public void rename(File from, File to) throws IOException;
+    
+    /**
+     * Get the granularity of file timestamps.
+     * The choice is made based on OS, which is incorrect--it should really be
+     * by filesystem. We do not have an easy way to probe for file systems,
+     * however, so this heuristic gives us a decent default.
+     * @return the difference, in milliseconds, which two file timestamps must 
have
+     * in order for the two files to be considered to have different 
timestamps.
+     */
+    public long getFileTimestampGranularity();
+    
+    /**
+     * Returns true if the source is older than the dest.
+     * If the dest file does not exist, then the test returns false; it is
+     * implicitly not up do date.
+     * @param source source file (should be the older).
+     * @param dest dest file (should be the newer).
+     * @param granularity an offset added to the source time.
+     * @return true if the source is older than the dest after accounting
+     *              for granularity.
+     * @since Ant 1.6.3
+     */
+    public boolean isUpToDate(File source, File dest, long granularity);
+    
+    /**
+     * Returns true if the source is older than the dest.
+     * @param source source file (should be the older).
+     * @param dest dest file (should be the newer).
+     * @return true if the source is older than the dest, taking the 
granularity into account.
+     * @since Ant 1.6.3
+     */
+    public boolean isUpToDate(File source, File dest);
+    
+    /**
+     * Compare two timestamps for being up to date using
+     * the specified granularity.
+     *
+     * @param sourceTime timestamp of source file.
+     * @param destTime timestamp of dest file.
+     * @param granularity os/filesys granularity.
+     * @return true if the dest file is considered up to date.
+     */
+    public boolean isUpToDate(long sourceTime, long destTime, long 
granularity);
+    
+    /**
+     * Compare two timestamps for being up to date using the
+     * current granularity.
+     *
+     * @param sourceTime  timestamp of source file.
+     * @param destTime    timestamp of dest file.
+     * @return true if the dest file is considered up to date.
+     */
+    public boolean isUpToDate(long sourceTime, long destTime);   
+}
Index: 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/Java6FileUtils.java
===================================================================
--- 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/Java6FileUtils.java
      (revision 0)
+++ 
D:/java_projects/ant-core-trunk/src/main/org/apache/tools/ant/util/Java6FileUtils.java
      (revision 0)
@@ -0,0 +1,22 @@
+/*
+ * 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.util;
+
+public class Java6FileUtils extends NioFileUtils {
+
+}
Index: D:/java_projects/ant-core-trunk/build.xml
===================================================================
--- D:/java_projects/ant-core-trunk/build.xml   (revision 395527)
+++ D:/java_projects/ant-core-trunk/build.xml   (working copy)
@@ -161,6 +161,7 @@
     <or>
       <filename name="${regexp.package}/Jdk14Regexp*"/>
       <filename name="${ant.package}/types/AssertionsTest.java"/>
+      <filename name="${util.package}/NioFileUtils.java"/>
     </or>
   </selector>
 
@@ -170,6 +171,12 @@
       <filename name="${util.package}/java15/*"/>
     </or>
   </selector>
+       
+  <selector id="needs.jdk1.6+">
+    <or>
+      <filename name="${util.package}/Java6FileUtils.java"/>
+    </or>
+  </selector>
 
   <!-- Kaffe has some JDK 1.5 features including java.lang.Readable,
        but not all of them -->
@@ -676,6 +683,7 @@
             <selector refid="needs.jdk1.3+" unless="jdk1.3+"/>
             <selector refid="needs.jdk1.4+" unless="jdk1.4+"/>
             <selector refid="needs.jdk1.5+" unless="jdk1.5+"/>
+               <selector refid="needs.jdk1.6+" unless="jdk1.6+"/>
             <selector refid="not.in.kaffe" if="kaffe"/>
             <selector refid="needs.sun.uue" unless="sunuue.present"/>
             <selector refid="needs.sun.b64" unless="base64.present"/>

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

Reply via email to