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); | |||
} | |||
} |