--- Touch.java.orig	Wed Jan  3 07:18:31 2001
+++ Touch.java	Tue Mar 13 02:49:16 2001
@@ -55,7 +55,12 @@
 package org.apache.tools.ant.taskdefs;
 
 import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.*;
+import org.apache.tools.ant.util.*;
 
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -67,131 +72,244 @@
 import java.util.Locale;
 
 /**
- * Touch a file - corresponds to the Unix touch command.
+ * Touch a file and/or fileset(s) -- corresponds to the Unix touch command.
  *
  * <p>If the file to touch doesn't exist, an empty one is
- * created. Setting the modification time of files is not supported in
- * JDK 1.1.
+ * created. </p>
+ *
+ * <p>Note: Setting the modification time of files is not supported in
+ * JDK 1.1.</p>
+ *
+ * <p> This implementation is based on the Copy task. </p>
  *
  * @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> 
+ * @author <a href="mailto:mj@servidium.com">Michael J. Sikorsky</a>
+ * @author <a href="mailto:shaw@servidium.com">Robert Shaw</a>
  */
-public class Touch extends Task {
+public class Touch extends Task 
+{
+   // Attributes of the Touch task.
+   protected File file = null;     // required
+   protected Vector filesets = new Vector();
+   protected long millis = -1;
+   protected String dateTime;
+   protected int verbosity = Project.MSG_VERBOSE;
+
+   // Holds the files & directories to Touch.
+   protected Vector filesToTouch = new Vector();
+
+   // Holds onto the "setLastModified" method -- we do this such that
+   // Ant may run on JDK1.1
+   protected static Method setLastModified = null;
+   protected static Object lockReflection = new Object();
+
+   /**
+    * Sets a single source file to touch.  If the file does not exist
+    * an  empty file will be created.
+    */
+   public void setFile(File file) {
+      this.file = file;
+   }
+
+   /**
+    * Milliseconds since 01/01/1970 00:00 am.
+    */
+   public void setMillis(long millis) {
+      this.millis = millis;
+   }
+
+   /**
+    * Date in the format MM/DD/YYYY HH:MM AM_PM.
+    */
+   public void setDatetime(String dateTime) {
+      this.dateTime = dateTime;
+   }
+
+   /**
+    * Used to force listing of all names of touched files.
+    */
+   public void setVerbose(boolean verbose) {
+      if (verbose) {
+         this.verbosity = Project.MSG_INFO;
+      } else {
+         this.verbosity = Project.MSG_VERBOSE;
+      } 
+   } 
+
+   /**
+    * Adds a set of files (nested fileset attribute).
+    */
+   public void addFileset(FileSet set) {
+      filesets.addElement(set);
+   }
+
+   /**
+    * Execute the touch operation.
+    */
+   public void execute() throws BuildException {
+      // make sure we don't have an illegal set of options
+      validateAttributes();   
+
+      // deal with the single file case
+      if (file != null)  {
+         filesToTouch.add(file);
 
-    private File file;              // required
-    private long millis = -1;
-    private String dateTime;
-
-    private static Method setLastModified = null;
-    private static Object lockReflection = new Object();
-
-    /**
-     * The name of the file to touch.
-     */
-    public void setFile(File file) {
-        this.file = file;
-    }
+         if ( !file.exists()) {
+            // No file, so lets create it.
+            log("Creating "+file, Project.MSG_INFO);
+            try {
+               FileOutputStream fos = new FileOutputStream(file);
+               fos.write(new byte[0]);
+               fos.close();
+            } catch (IOException ioe) {
+               throw new BuildException("Could not create "+file, ioe, 
+                                        location);
+            }
+         }
+      }
 
-    /**
-     * Milliseconds since 01/01/1970 00:00 am.
-     */
-    public void setMillis(long millis) {
-        this.millis = millis;
-    }
+      // deal with the filesets
+      for (int i=0; i < filesets.size(); i++) {
+         FileSet fs = (FileSet) filesets.elementAt(i);
+         DirectoryScanner ds = fs.getDirectoryScanner(project);
+         File fromDir = fs.getDir(project);
+
+         String[] srcFiles = ds.getIncludedFiles();
+         String[] srcDirs = ds.getIncludedDirectories();
+
+         for( int j=0; j < srcFiles.length ; j++ )
+         {
+            filesToTouch.add(new File(fromDir,srcFiles[j]));
+         }
+         
+         for( int j=0; j < srcDirs.length ; j++ )
+         {
+            filesToTouch.add(new File(fromDir,srcDirs[j]));
+         }
+         
+         // add the "fromDir" i.e. the "srcDir" for processing.
+         filesToTouch.add(fromDir);
+      }
+
+      // do all the touch operations now...
+      doTouchOperations();
 
-    /**
-     * Date in the format MM/DD/YYYY HH:MM AM_PM.
-     */
-    public void setDatetime(String dateTime) {
-        this.dateTime = dateTime;
     }
 
-    /**
-     * Do the work.
-     *
-     * @exception BuildException Thrown in unrecoverable error.
-     */
-    public void execute() throws BuildException {
-        if (file.exists() && project.getJavaVersion() == Project.JAVA_1_1) {
-            log("Cannot change the modification time of "
-                + file + " in JDK 1.1",
-                Project.MSG_WARN);
-            return;
-        }
-        
-        if (dateTime != null) {
-            DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
-                                                           DateFormat.SHORT,
-                                                           Locale.US);
-            try {
-                setMillis(df.parse(dateTime).getTime());
-            } catch (ParseException pe) {
-                throw new BuildException(pe.getMessage(), pe, location);
+//************************************************************************
+//  protected and private methods
+//************************************************************************
+
+   /**
+    * Ensure we have a consistent and legal set of attributes, and set
+    * any internal flags necessary based on different combinations 
+    * of attributes.
+    */
+   protected void validateAttributes() throws BuildException {
+      if (file == null && filesets.size() == 0) {
+         throw 
+         new BuildException("Specify at least one source - a file or a fileset.");
+      }
+
+      if (file != null && file.exists() && file.isDirectory()) {
+         throw new BuildException("Use a fileset to touch directories.");
+      }
+   }
+
+   /**
+    * Iterates through the files & directories and dispatches to the
+    * touch() method to do the actual touching.
+    */
+   protected void doTouchOperations() {
+      if (project.getJavaVersion() == Project.JAVA_1_1) {
+         log("Cannot change the modification time of "
+             + file + " in JDK 1.1",
+             Project.MSG_WARN);
+         return;
+      }
+
+      if (dateTime != null) {
+         DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
+                                                        DateFormat.SHORT,
+                                                        Locale.US);
+         try {
+            setMillis(df.parse(dateTime).getTime());
+         } catch (ParseException pe) {
+            throw new BuildException(pe.getMessage(), pe, location);
+         }
+      }
+      
+      // Process Files & Directories from the filesToTouch vector.
+      if (filesToTouch.size() > 0) 
+      {
+         log("Touching " + filesToTouch.size() + 
+             " file" + (filesToTouch.size() == 1 ? "" : "s") + 
+             ".");
+
+         Enumeration files = filesToTouch.elements();
+         while (files.hasMoreElements()) 
+         {
+            File fromFile = (File) files.nextElement();
+            try 
+            {
+               log("Touching " + fromFile.getAbsolutePath() + ".", verbosity);    
+               touch(fromFile);
+            } 
+            catch (Exception ioe) 
+            {
+               String msg = "Failed to touch " + fromFile + " due to " + 
+                            ioe.getMessage();
+               throw new BuildException(msg, ioe, location);
             }
-        }
+         }
+      }
+   }
+
+   /**
+    * Does the actual "touching" work.
+    */
+   void touch(File file) throws BuildException  {
+      if (setLastModified == null) {
+         synchronized (lockReflection) {
+            if (setLastModified == null) {
+               try {
+                  setLastModified = 
+                     java.io.File.class.getMethod("setLastModified", 
+                                                  new Class[] {Long.TYPE});
+               } catch (NoSuchMethodException nse) {
+                  throw new BuildException("File.setlastModified not "+
+                                           "in JDK > 1.1?",
+                                           nse, location);
+               }
+            }
+         }
+      }
+      
+      Long[] times = new Long[1];
+      if (millis < 0) {
+         times[0] = new Long(System.currentTimeMillis());
+      } else {
+         times[0] = new Long(millis);
+      }
+      
+      try {
+         log("Setting modification time for "+file, 
+             Project.MSG_VERBOSE);
+         
+         setLastModified.invoke(file, times);
+      } catch (InvocationTargetException ite) {
+         Throwable nested = ite.getTargetException();
+         throw new BuildException("Exception setting the modification time of "
+                                  + file, nested, location);
+      } catch (Throwable other) {
+         throw new BuildException("Exception setting the modification time of "
+                                  + file, other, location);
+      }
+   }
+}
+
 
-        if (millis >= 0 && project.getJavaVersion() == Project.JAVA_1_1) {
-            log(file + " will be created but its modification time cannot be set in JDK 1.1",
-                Project.MSG_WARN);
-        }
 
-        touch();
-    }
 
-    /**
-     * Does the actual work. Entry point for Untar and Expand as well.
-     */
-    void touch() throws BuildException {
-        if (!file.exists()) {
-            log("Creating "+file, Project.MSG_INFO);
-            try {
-                FileOutputStream fos = new FileOutputStream(file);
-                fos.write(new byte[0]);
-                fos.close();
-            } catch (IOException ioe) {
-                throw new BuildException("Could not create "+file, ioe, 
-                                         location);
-            }
-        }
 
-        if (project.getJavaVersion() == Project.JAVA_1_1) {
-            return;
-        }
-
-        if (setLastModified == null) {
-            synchronized (lockReflection) {
-                if (setLastModified == null) {
-                    try {
-                        setLastModified = 
-                            java.io.File.class.getMethod("setLastModified", 
-                                                         new Class[] {Long.TYPE});
-                    } catch (NoSuchMethodException nse) {
-                        throw new BuildException("File.setlastModified not in JDK > 1.1?",
-                                                 nse, location);
-                    }
-                }
-            }
-        }
-        
-        Long[] times = new Long[1];
-        if (millis < 0) {
-            times[0] = new Long(System.currentTimeMillis());
-        } else {
-            times[0] = new Long(millis);
-        }
-
-        try {
-            log("Setting modification time for "+file, 
-                Project.MSG_VERBOSE);
-
-            setLastModified.invoke(file, times);
-        } catch (InvocationTargetException ite) {
-            Throwable nested = ite.getTargetException();
-            throw new BuildException("Exception setting the modification time of "
-                                     + file, nested, location);
-        } catch (Throwable other) {
-            throw new BuildException("Exception setting the modification time of "
-                                     + file, other, location);
-        }
-    }
 
-}

