intent is to move all date tests to this single place, to eliminate inconsistencies. The only place I use it is signjar, which, by virtue of the fact there is no signjar test, means I know it wont break the tests. Also, cleaned up the reflection hacks for 1.1. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276381 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1531,11 +1531,6 @@ public class Project { | |||||
*/ | */ | ||||
public void setFileLastModified(File file, long time) | public void setFileLastModified(File file, long time) | ||||
throws BuildException { | throws BuildException { | ||||
if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { | |||||
log("Cannot change the modification time of " + file | |||||
+ " in JDK 1.1", Project.MSG_WARN); | |||||
return; | |||||
} | |||||
fileUtils.setFileLastModified(file, time); | fileUtils.setFileLastModified(file, time); | ||||
log("Setting modification time for " + file, MSG_VERBOSE); | log("Setting modification time for " + file, MSG_VERBOSE); | ||||
} | } | ||||
@@ -28,6 +28,7 @@ import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
import org.apache.tools.ant.types.FileSet; | import org.apache.tools.ant.types.FileSet; | ||||
import org.apache.tools.ant.util.JavaEnvUtils; | import org.apache.tools.ant.util.JavaEnvUtils; | ||||
import org.apache.tools.ant.util.FileUtils; | |||||
/** | /** | ||||
* Signs jar or zip files with the javasign command line tool. The | * Signs jar or zip files with the javasign command line tool. The | ||||
@@ -321,7 +322,7 @@ public class SignJar extends Task { | |||||
if (jarFile.equals(signedjarFile)) { | if (jarFile.equals(signedjarFile)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (signedjarFile.lastModified() > jarFile.lastModified()) { | |||||
if (FileUtils.newFileUtils().isUpToDate(jarFile,signedjarFile)) { | |||||
return true; | return true; | ||||
} | } | ||||
} else { | } else { | ||||
@@ -333,6 +334,12 @@ public class SignJar extends Task { | |||||
return false; | return false; | ||||
} | } | ||||
/** | |||||
* test for a file being signed, by looking for a signature in the META-INF | |||||
* directory | |||||
* @param file | |||||
* @return | |||||
*/ | |||||
protected boolean isSigned(File file) { | protected boolean isSigned(File file) { | ||||
final String SIG_START = "META-INF/"; | final String SIG_START = "META-INF/"; | ||||
final String SIG_END = ".SF"; | final String SIG_END = ".SF"; | ||||
@@ -57,9 +57,9 @@ import org.apache.tools.ant.launch.Locator; | |||||
*/ | */ | ||||
public class FileUtils { | public class FileUtils { | ||||
private static Random rand = new Random(System.currentTimeMillis()); | |||||
private static Object lockReflection = new Object(); | |||||
private static java.lang.reflect.Method setLastModified = null; | |||||
//get some non-crypto-grade randomness from various places. | |||||
private static Random rand = new Random(System.currentTimeMillis() | |||||
+Runtime.getRuntime().freeMemory()); | |||||
private boolean onNetWare = Os.isFamily("netware"); | private boolean onNetWare = Os.isFamily("netware"); | ||||
@@ -78,6 +78,7 @@ public class FileUtils { | |||||
*/ | */ | ||||
public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; | public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; | ||||
// stolen from FilePathToURI of the Xerces-J team | // stolen from FilePathToURI of the Xerces-J team | ||||
static { | static { | ||||
for (int i = 0; i <= 0x20; i++) { | for (int i = 0; i <= 0x20; i++) { | ||||
@@ -648,65 +649,27 @@ public class FileUtils { | |||||
} | } | ||||
if (preserveLastModified) { | if (preserveLastModified) { | ||||
setFileLastModified(destFile, sourceFile.lastModified()); | |||||
destFile.setLastModified(sourceFile.lastModified()); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/** | |||||
* see whether we have a setLastModified method in File and return it. | |||||
* | |||||
* @return a method to setLastModified. | |||||
*/ | |||||
protected final Method getSetLastModified() { | |||||
if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { | |||||
return 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); | |||||
} | |||||
} | |||||
} | |||||
return setLastModified; | |||||
} | |||||
/** | /** | ||||
* Calls File.setLastModified(long time) in a Java 1.1 compatible way. | |||||
* 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 file the file whose modified time is to be set | ||||
* @param time the time to which the last 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. | |||||
* @throws BuildException if the time cannot be set. | * @throws BuildException if the time cannot be set. | ||||
*/ | */ | ||||
public void setFileLastModified(File file, long time) | public void setFileLastModified(File file, long time) | ||||
throws BuildException { | throws BuildException { | ||||
if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { | |||||
return; | |||||
} | |||||
Long[] times = new Long[1]; | |||||
if (time < 0) { | if (time < 0) { | ||||
times[0] = new Long(System.currentTimeMillis()); | |||||
} else { | |||||
times[0] = new Long(time); | |||||
} | |||||
try { | |||||
getSetLastModified().invoke(file, times); | |||||
} catch (java.lang.reflect.InvocationTargetException ite) { | |||||
Throwable nested = ite.getTargetException(); | |||||
throw new BuildException("Exception setting the modification time " | |||||
+ "of " + file, nested); | |||||
} catch (Throwable other) { | |||||
throw new BuildException("Exception setting the modification time " | |||||
+ "of " + file, other); | |||||
time=System.currentTimeMillis(); | |||||
} | } | ||||
file.setLastModified(time); | |||||
} | } | ||||
/** | /** | ||||
@@ -1357,5 +1320,40 @@ public class FileUtils { | |||||
return UNIX_FILE_TIMESTAMP_GRANULARITY; | return UNIX_FILE_TIMESTAMP_GRANULARITY; | ||||
} | } | ||||
} | } | ||||
/** | |||||
* 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, taking the | |||||
* granularity into account | |||||
* @since Ant1.7 | |||||
*/ | |||||
public boolean isUpToDate(File source,File dest,long granularity) { | |||||
//do a check for the destination file existing | |||||
if(!dest.exists()) { | |||||
//if it does not, then the file is not up to date. | |||||
return false; | |||||
} | |||||
long sourceTime=source.lastModified(); | |||||
long destTime=dest.lastModified(); | |||||
return destTime>=sourceTime+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 Ant1.7 | |||||
*/ | |||||
public boolean isUpToDate(File source, File dest) { | |||||
return isUpToDate(source, dest, getFileTimestampGranularity()); | |||||
} | |||||
} | } | ||||
@@ -50,6 +50,16 @@ public class FileUtilsTest extends TestCase { | |||||
} | } | ||||
} | } | ||||
/** | |||||
* test modification. | |||||
* Since Ant1.7, the method being tested no longer uses | |||||
* reflection to provide backwards support to Java1.1, so this | |||||
* test is not so critical. But it does explore file system | |||||
* behaviour and will help catch any regression in Java itself, | |||||
* so is worth retaining. | |||||
* @see FileUtils#setFileLastModified(java.io.File, long) | |||||
* @throws IOException | |||||
*/ | |||||
public void testSetLastModified() throws IOException { | public void testSetLastModified() throws IOException { | ||||
removeThis = new File("dummy"); | removeThis = new File("dummy"); | ||||
FileOutputStream fos = new FileOutputStream(removeThis); | FileOutputStream fos = new FileOutputStream(removeThis); | ||||
@@ -64,20 +74,14 @@ public class FileUtilsTest extends TestCase { | |||||
* granularity (should be > 2s to account for Windows FAT). | * granularity (should be > 2s to account for Windows FAT). | ||||
*/ | */ | ||||
try { | try { | ||||
Thread.currentThread().sleep(5000); | |||||
Thread.sleep(5000); | |||||
} catch (InterruptedException ie) { | } catch (InterruptedException ie) { | ||||
fail(ie.getMessage()); | fail(ie.getMessage()); | ||||
} | } | ||||
fu.setFileLastModified(removeThis, -1); | fu.setFileLastModified(removeThis, -1); | ||||
long secondModTime = removeThis.lastModified(); | long secondModTime = removeThis.lastModified(); | ||||
try { | |||||
Class.forName("java.lang.ThreadLocal"); | |||||
assertTrue(secondModTime > modTime); | |||||
} catch (ClassNotFoundException e) { | |||||
// JDK 1.1 | |||||
assertEquals(modTime, secondModTime); | |||||
} | |||||
assertTrue(secondModTime > modTime); | |||||
// number of milliseconds in a day | // number of milliseconds in a day | ||||
@@ -87,19 +91,13 @@ public class FileUtilsTest extends TestCase { | |||||
// it did not work on a computer running JDK 1.4.1_02 + Windows 2000 | // it did not work on a computer running JDK 1.4.1_02 + Windows 2000 | ||||
fu.setFileLastModified(removeThis, secondModTime + millisperday); | fu.setFileLastModified(removeThis, secondModTime + millisperday); | ||||
long thirdModTime = removeThis.lastModified(); | long thirdModTime = removeThis.lastModified(); | ||||
try { | |||||
Class.forName("java.lang.ThreadLocal"); | |||||
/* | |||||
* I would love to compare this with 123456, but depending on | |||||
* the filesystems granularity it can take an arbitrary value. | |||||
* | |||||
* Just assert the time has changed. | |||||
*/ | |||||
assertTrue(thirdModTime != secondModTime); | |||||
} catch (ClassNotFoundException e) { | |||||
// JDK 1.1 | |||||
assertEquals(modTime, thirdModTime); | |||||
} | |||||
/* | |||||
* I would love to compare this with 123456, but depending on | |||||
* the filesystems granularity it can take an arbitrary value. | |||||
* | |||||
* Just assert the time has changed. | |||||
*/ | |||||
assertTrue(thirdModTime != secondModTime); | |||||
} | } | ||||
public void testResolveFile() { | public void testResolveFile() { | ||||