PR: 23526 Submitted by: gudnabrsam@yahoo.com git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275869 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -12,7 +12,8 @@ | |||
| <p>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 <a href="../CoreTypes/fileset.html">Fileset</a> (which | |||
| also includes directories).</p> | |||
| also includes directories) | |||
| or a <a href="../CoreTypes/filelist.html">Filelist</a> (since Ant 1.6).</p> | |||
| <p>For JDK 1.1 only the creation of new files with a modification time | |||
| of now works, all other cases will emit a warning.</p> | |||
| <h3>Parameters</h3> | |||
| @@ -26,6 +27,7 @@ of now works, all other cases will emit a warning.</p> | |||
| <td valign="top">file</td> | |||
| <td valign="top">the name of the file</td> | |||
| <td valign="top" align="center">unless a nested fileset element | |||
| or a nested filelist element | |||
| has been specified.</td> | |||
| </tr> | |||
| <tr> | |||
| @@ -67,4 +69,3 @@ Reserved.</p> | |||
| </body> | |||
| </html> | |||
| @@ -12,4 +12,30 @@ | |||
| <target name="seconds"> | |||
| <touch file="touchtest" datetime="2003/06/24 2:20:12 pm"/> | |||
| </target> | |||
| <target name="testNow"> | |||
| <touch file="touchtest" /> | |||
| </target> | |||
| <target name="testMillis"> | |||
| <touch file="touchtest" millis="1234567" /> | |||
| </target> | |||
| <target name="test1970"> | |||
| <touch file="touchtest" millis="0" /> | |||
| </target> | |||
| <target name="testFilelist"> | |||
| <touch millis="100000" > | |||
| <filelist dir="." files="touchtest"/> | |||
| </touch> | |||
| </target> | |||
| <target name="testFileset" depends="testNow"> | |||
| <touch millis="200000" > | |||
| <fileset dir="." includes="touchtest"/> | |||
| </touch> | |||
| </target> | |||
| </project> | |||
| @@ -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. | |||
| * | |||
| * <p>If the file to touch doesn't exist, an empty one is | |||
| * created. </p> | |||
| @@ -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); | |||
| } | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||