diff --git a/docs/manual/CoreTasks/touch.html b/docs/manual/CoreTasks/touch.html index eb3922b87..1b7f22d57 100644 --- a/docs/manual/CoreTasks/touch.html +++ b/docs/manual/CoreTasks/touch.html @@ -12,7 +12,8 @@

Changes the modification time of a file and possibly creates it at the same time. In addition to working with a single file, this Task can also work a Fileset (which -also includes directories).

+also includes directories) +or a Filelist (since Ant 1.6).

For JDK 1.1 only the creation of new files with a modification time of now works, all other cases will emit a warning.

Parameters

@@ -26,6 +27,7 @@ of now works, all other cases will emit a warning.

file the name of the file unless a nested fileset element + or a nested filelist element has been specified. @@ -67,4 +69,3 @@ Reserved.

- diff --git a/src/etc/testcases/taskdefs/touch.xml b/src/etc/testcases/taskdefs/touch.xml index 010aff651..8f97ddf1d 100644 --- a/src/etc/testcases/taskdefs/touch.xml +++ b/src/etc/testcases/taskdefs/touch.xml @@ -12,4 +12,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/Touch.java b/src/main/org/apache/tools/ant/taskdefs/Touch.java index 55c7bd000..d7e41c23e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Touch.java +++ b/src/main/org/apache/tools/ant/taskdefs/Touch.java @@ -65,11 +65,13 @@ 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; +import org.apache.tools.ant.types.FileList; import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.JavaEnvUtils; /** - * Touch a file and/or fileset(s); corresponds to the Unix touch command. + * Touch a file and/or fileset(s) and/or filelist(s); + * corresponds to the Unix touch command. * *

If the file to touch doesn't exist, an empty one is * created.

@@ -91,6 +93,7 @@ public class Touch extends Task { private long millis = -1; private String dateTime; private Vector filesets = new Vector(); + private Vector filelists = new Vector(); private FileUtils fileUtils; public Touch() { @@ -131,15 +134,22 @@ public class Touch extends Task { filesets.addElement(set); } + /** + * Add a filelist to touch + */ + public void addFilelist(FileList list) { + filelists.addElement(list); + } + /** * Execute the touch operation. */ public void execute() throws BuildException { long savedMillis = millis; - if (file == null && filesets.size() == 0) { + if (file == null && filesets.size() == 0 && filelists.size() == 0) { throw - new BuildException("Specify at least one source - a file or " + new BuildException("Specify at least one source - a file, filelist or " + "a fileset."); } @@ -195,26 +205,9 @@ public class Touch extends Task { } /** - * Does the actual work. Entry point for Untar and Expand as well. + * Does the actual work; assumes everything has been checked by now. */ protected void touch() throws BuildException { - if (file != null) { - if (!file.exists()) { - log("Creating " + file, Project.MSG_INFO); - try { - fileUtils.createNewFile(file); - } catch (IOException ioe) { - throw new BuildException("Could not create " + file, ioe, - getLocation()); - } - } - } - - if (millis >= 0 && JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { - log("modification time of files cannot be set in JDK 1.1", - Project.MSG_WARN); - return; - } boolean resetMillis = false; if (millis < 0) { @@ -244,21 +237,43 @@ public class Touch extends Task { } } + // deal with the filelists + for (int i = 0; i < filelists.size(); i++) { + FileList fl = (FileList) filelists.elementAt(i); + File fromDir = fl.getDir(getProject()); + + String[] srcFiles = fl.getFiles(getProject()); + + for (int j = 0; j < srcFiles.length; j++) { + touch(new File(fromDir, srcFiles[j])); + } + } + if (resetMillis) { millis = -1; } } + /** + * touch a single file with the current timestamp (this.millis) + * @param file file to touch + * @throws BuildException + */ protected void touch(File file) throws BuildException { + if (!file.exists()) { + log("Creating " + file, Project.MSG_INFO); + try { + fileUtils.createNewFile(file); + } catch (IOException ioe) { + throw new BuildException("Could not create " + file, ioe, + getLocation()); + } + } + if (!file.canWrite()) { throw new BuildException("Can not change modification date of " + "read-only file " + file); } - - if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { - return; - } - fileUtils.setFileLastModified(file, millis); } diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index af3894ace..f5c8bf475 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -116,6 +116,10 @@ public class FileUtils { */ public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000; + /** + * the granularity of timestamps under Unix + */ + public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; // stolen from FilePathToURI of the Xerces-J team static { @@ -1401,7 +1405,7 @@ public class FileUtils { if (Os.isFamily("dos")) { return FAT_FILE_TIMESTAMP_GRANULARITY; } else { - return 0; + return UNIX_FILE_TIMESTAMP_GRANULARITY; } } } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/TouchTest.java b/src/testcases/org/apache/tools/ant/taskdefs/TouchTest.java index 4668221fe..d91a17ef2 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/TouchTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/TouchTest.java @@ -55,9 +55,15 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.BuildFileTest; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.util.FileUtils; + +import java.io.File; public class TouchTest extends BuildFileTest { + private static String touchfile="src/etc/testcases/taskdefs/touchtest"; + public TouchTest(String name) { super(name); } @@ -69,13 +75,23 @@ public class TouchTest extends BuildFileTest { public void tearDown() { executeTarget("cleanup"); } - + + public long getTargetTime() { + + File file = new File(touchfile); + if(!file.exists()) { + throw new BuildException("failed to touch file "+touchfile); + } + return file.lastModified(); + } + /** * No real test, simply checks whether the dateformat without * seconds is accepted - by erroring out otherwise. */ public void testNoSeconds() { executeTarget("noSeconds"); + long time = getTargetTime(); } /** @@ -84,5 +100,74 @@ public class TouchTest extends BuildFileTest { */ public void testSeconds() { executeTarget("seconds"); + long time=getTargetTime(); + } + /** + * verify that the millis test sets things up + */ + public void testMillis() { + touchFile("testMillis", 1234567); + } + + /** + * verify that the default value defaults to now + */ + public void testNow() { + long now=System.currentTimeMillis(); + executeTarget("testNow"); + long time = getTargetTime(); + assertTimesNearlyMatch(time,now,5000); + } + /** + * verify that the millis test sets things up + */ + public void test1970() { + touchFile("test1970", 0); + } + + /** + * test the file list + */ + public void testFilelist() { + touchFile("testFilelist", 100000); + } + + /** + * test the file set + */ + public void testFileset() { + touchFile("testFileset", 200000); + } + + /** + * run a target to touch the test file; verify the timestamp is as expected + * @param targetName + * @param timestamp + */ + private void touchFile(String targetName, long timestamp) { + executeTarget(targetName); + long time = getTargetTime(); + assertTimesNearlyMatch(timestamp,time); + } + + /** + * assert that two times are within the current FS granularity; + * @param timestamp + * @param time + */ + public void assertTimesNearlyMatch(long timestamp,long time) { + long granularity= FileUtils.newFileUtils().getFileTimestampGranularity(); + assertTimesNearlyMatch(timestamp, time, granularity); + } + + /** + * assert that two times are within a specified range + * @param timestamp + * @param time + * @param range + */ + private void assertTimesNearlyMatch(long timestamp, long time, long range) { + assertTrue("Time "+timestamp+" is not within "+range+" ms of "+time, + Math.abs(time-timestamp)<=range); } }