JDK-6314708 : File should provide methods to access created and last-access times
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2005-08-23
  • Updated: 2010-04-02
  • Resolved: 2009-02-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Duplicate :  
Description
A DESCRIPTION OF THE FIX :
  Bug Description : java.io.File can provide access to created and last-access times.
Subset of Releases affected : 1.5.0, Mustang b41.
Platforms affected : Windows, Solaris, Linux
Test case : See Test case section.
Diff baseline : Mustang b41
Diff :
--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\share\classes\java\io\File.java	2005-08-04 21:55:42.000000000 +0200
+++ ..\src\share\classes\java\io\File.java	2005-08-09 02:46:30.256833600 +0200
@@ -3,6 +3,8 @@
  *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 package java.io;
@@ -798,6 +800,54 @@


The fix and test case are too large to include here.  Refer to the attached file
508675.txt.
A DESCRIPTION OF THE FIX :
  Bug Description : java.io.File can provide access to created and last-access times.
Subset of Releases affected : 1.5.0, Mustang b41.
Platforms affected : Windows, Solaris, Linux
Test case : See Test case section.
Diff baseline : Mustang b41
Diff :
--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\share\classes\java\io\File.java	2005-08-04 21:55:42.000000000 +0200
+++ ..\src\share\classes\java\io\File.java	2005-08-09 02:46:30.256833600 +0200
@@ -3,6 +3,8 @@
  *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 package java.io;
@@ -798,6 +800,54 @@
 
     /**
      * Returns the time that the file denoted by this abstract pathname was
+     * created.
+     *
+     * @return  A <code>long</code> value representing the time the file was
+     *          created, measured in milliseconds since the epoch
+     *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
+     *          file does not exist or if an I/O error occurs
+     *
+     * @throws  SecurityException
+     *          If a security manager exists and its <code>{@link
+     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
+     *          method denies read access to the file
+     *
+     * @since 6.0
+     */
+    public long created() {
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    security.checkRead(path);
+	}
+	return fs.getCreatedTime(this);
+    }
+
+    /**
+     * Returns the time that the file denoted by this abstract pathname was
+     * last accessed.
+     *
+     * @return  A <code>long</code> value representing the time the file was
+     *          last accessed, measured in milliseconds since the epoch
+     *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
+     *          file does not exist or if an I/O error occurs
+     *
+     * @throws  SecurityException
+     *          If a security manager exists and its <code>{@link
+     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
+     *          method denies read access to the file
+     *
+     * @since 6.0
+     */
+    public long lastAccessed() {
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    security.checkRead(path);
+	}
+	return fs.getLastAccessedTime(this);
+    }
+
+    /**
+     * Returns the time that the file denoted by this abstract pathname was
      * last modified.
      *
      * @return  A <code>long</code> value representing the time the file was
@@ -1216,6 +1266,78 @@
     }
 
     /**
+     * Sets the created time of the file or directory named by this
+     * abstract pathname.
+     *
+     * <p> All platforms support file-creation times to the nearest second,
+     * but some provide more precision.  The argument will be truncated to fit
+     * the supported precision.  If the operation succeeds and no intervening
+     * operations on the file take place, then the next invocation of the
+     * <code>{@link #created}</code> method will return the (possibly
+     * truncated) <code>time</code> argument that was passed to this method.
+     * <p>
+     * <b>Note:</b> this method is not available on UNIX systems.
+     *
+     * @param  time  The new created time, measured in milliseconds since
+     *               the epoch (00:00:00 GMT, January 1, 1970)
+     *
+     * @return <code>true</code> if and only if the operation succeeded;
+     *          <code>false</code> otherwise
+     *
+     * @throws  IllegalArgumentException  If the argument is negative
+     *
+     * @throws  SecurityException
+     *          If a security manager exists and its <code>{@link
+     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
+     *          method denies write access to the named file
+     *
+     * @since 6.0
+     */
+    public boolean setCreated(long time) {
+	if (time < 0) throw new IllegalArgumentException("Negative time");
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    security.checkWrite(path);
+	}
+	return fs.setCreatedTime(this, time);
+    }
+
+    /**
+     * Sets the last-accessed time of the file or directory named by this
+     * abstract pathname.
+     *
+     * <p> All platforms support file-access times to the nearest second,
+     * but some provide more precision.  The argument will be truncated to fit
+     * the supported precision.  If the operation succeeds and no intervening
+     * operations on the file take place, then the next invocation of the
+     * <code>{@link #lastAccessed}</code> method will return the (possibly
+     * truncated) <code>time</code> argument that was passed to this method.
+     *
+     * @param  time  The new last-accessed time, measured in milliseconds since
+     *               the epoch (00:00:00 GMT, January 1, 1970)
+     *
+     * @return <code>true</code> if and only if the operation succeeded;
+     *          <code>false</code> otherwise
+     *
+     * @throws  IllegalArgumentException  If the argument is negative
+     *
+     * @throws  SecurityException
+     *          If a security manager exists and its <code>{@link
+     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
+     *          method denies write access to the named file
+     *
+     * @since 6.0
+     */
+    public boolean setLastAccessed(long time) {
+	if (time < 0) throw new IllegalArgumentException("Negative time");
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    security.checkWrite(path);
+	}
+	return fs.setLastAccessedTime(this, time);
+    }
+
+    /**
      * Sets the last-modified time of the file or directory named by this
      * abstract pathname.
      *


--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\share\classes\java\io\FileSystem.java	2005-08-04 21:55:42.000000000 +0200
+++ ..\src\share\classes\java\io\FileSystem.java	2005-08-09 02:38:14.914566400 +0200
@@ -3,6 +3,8 @@
  *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 package java.io;
@@ -111,6 +113,20 @@
 
     /**
      * Return the time at which the file or directory denoted by the given
+     * abstract pathname was created, or zero if it does not exist or
+     * some other I/O error occurs.
+     */
+    public abstract long getCreatedTime(File f);
+
+    /**
+     * Return the time at which the file or directory denoted by the given
+     * abstract pathname was last accessed, or zero if it does not exist or
+     * some other I/O error occurs.
+     */
+    public abstract long getLastAccessedTime(File f);
+
+    /**
+     * Return the time at which the file or directory denoted by the given
      * abstract pathname was last modified, or zero if it does not exist or
      * some other I/O error occurs.
      */
@@ -169,6 +185,20 @@
     public abstract boolean rename(File f1, File f2);
 
     /**
+     * Set the created time of the file or directory denoted by the
+     * given abstract pathname, returning <code>true</code> if and only if the
+     * operation succeeds.
+     */
+    public abstract boolean setCreatedTime(File f, long time);
+
+    /**
+     * Set the last-accessed time of the file or directory denoted by the
+     * given abstract pathname, returning <code>true</code> if and only if the
+     * operation succeeds.
+     */
+    public abstract boolean setLastAccessedTime(File f, long time);
+
+    /**
      * Set the last-modified time of the file or directory denoted by the
      * given abstract pathname, returning <code>true</code> if and only if the
      * operation succeeds.


--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\windows\classes\java\io\Win32FileSystem.java	2005-08-04 21:56:52.000000000 +0200
+++ ..\src\windows\classes\java\io\Win32FileSystem.java	2005-08-09 02:36:24.255446400 +0200
@@ -3,6 +3,8 @@
  *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 package java.io;
@@ -485,6 +487,9 @@
 
     public native int getBooleanAttributes(File f);
     public native boolean checkAccess(File f, boolean write);
+
+    public native long getCreatedTime(File f);
+    public native long getLastAccessedTime(File f);
     public native long getLastModifiedTime(File f);
     public native long getLength(File f);
 
@@ -518,6 +523,9 @@
         return rename0(f1, f2);
     }
     protected native boolean rename0(File f1, File f2);
+
+    public native boolean setCreatedTime(File f, long time);
+    public native boolean setLastAccessedTime(File f, long time);
     public native boolean setLastModifiedTime(File f, long time);
     public native boolean setReadOnly(File f);
 

--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\windows\classes\java\io\WinNTFileSystem.java	2005-08-04 21:56:52.000000000 +0200
+++ ..\src\windows\classes\java\io\WinNTFileSystem.java	2005-08-09 02:36:21.571587200 +0200
@@ -1,10 +1,10 @@
 /*
+ * @(#)WinNTFileSystem.java	1.9 04/03/20
+ *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
-/*
- * @(#)WinNTFileSystem.java	1.9 04/03/20
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 package java.io;
@@ -28,6 +28,8 @@
 
     public native int getBooleanAttributes(File f);
     public native boolean checkAccess(File f, boolean write);
+    public native long getCreatedTime(File f);
+    public native long getLastAccessedTime(File f);
     public native long getLastModifiedTime(File f);
     public native long getLength(File f);
 
@@ -41,6 +43,8 @@
     public native String[] list(File f);
     public native boolean createDirectory(File f);
     protected native boolean rename0(File f1, File f2);
+    public native boolean setCreatedTime(File f, long time);
+    public native boolean setLastAccessedTime(File f, long time);
     public native boolean setLastModifiedTime(File f, long time);
     public native boolean setReadOnly(File f);
     protected native String getDriveDirectory(int drive);


--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\solaris\classes\java\io\UnixFileSystem.java	2005-08-04 21:56:46.000000000 +0200
+++ ..\src\solaris\classes\java\io\UnixFileSystem.java	2005-08-09 02:37:57.219121600 +0200
@@ -3,6 +3,8 @@
  *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 package java.io;
@@ -232,6 +234,9 @@
     }
 
     public native boolean checkAccess(File f, boolean write);
+
+    public native long getCreatedTime(File f);
+    public native long getLastAccessedTime(File f);
     public native long getLastModifiedTime(File f);
     public native long getLength(File f);
 
@@ -265,6 +270,12 @@
         return rename0(f1, f2);
     }
     private native boolean rename0(File f1, File f2);
+
+    //public native boolean setCreatedTime(File f, long time); // TODO by UNIX experts
+    public boolean setCreatedTime(File f, long time) {
+      return false; // Not available for UNIX systems ? (Ulf Zibis)
+    }
+    public native boolean setLastAccessedTime(File f, long time);
     public native boolean setLastModifiedTime(File f, long time);
     public native boolean setReadOnly(File f);
 

--- G:\jdk6.0 ea ausgepackt\src-b41\j2se\src\windows\native\java\io\Win32FileSystem_md.c	2005-08-02 20:28:36.000000000 +0200
+++ ..\src\windows\native\java\io\Win32FileSystem_md.c	2005-08-09 02:51:55.594646400 +0200
@@ -3,6 +3,8 @@
  *
  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ * Contributors: Ulf Zibis, Germany, mailto:###@###.###
  */
 
 #include <assert.h>
@@ -134,24 +136,62 @@
 }
 
 
+jlong
+javaTime(FILETIME t)
+{
+    LARGE_INTEGER time;
+	time.LowPart = (DWORD) t.dwLowDateTime;
+	time.HighPart = (LONG) t.dwHighDateTime;
+	return (jlong) time.QuadPart / 10000 - 11644473600000;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_Win32FileSystem_getCreatedTime(JNIEnv *env, jobject this,
+						 jobject file)
+{
+    jlong rv = 0;
+    WITH_NATIVE_PATH(env, file, ids.path, path) {
+		/* Win95, Win98, WinME */
+		WIN32_FIND_DATA fd;
+		HANDLE h = FindFirstFile(path, &fd);
+		if (h != INVALID_HANDLE_VALUE) {
+			FindClose(h);
+			rv = javaTime(fd.ftCreationTime);
+		}
+    } END_NATIVE_PATH(env, path);
+    return rv;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_Win32FileSystem_getLastAccessedTime(JNIEnv *env, jobject this,
+						 jobject file)
+{
+    jlong rv = 0;
+    WITH_NATIVE_PATH(env, file, ids.path, path) {
+		/* Win95, Win98, WinME */
+		WIN32_FIND_DATA fd;
+		HANDLE h = FindFirstFile(path, &fd);
+		if (h != INVALID_HANDLE_VALUE) {
+			FindClose(h);
+			rv = javaTime(fd.ftLastAccessTime);
+		}
+    } END_NATIVE_PATH(env, path);
+    return rv;
+}
+
 JNIEXPORT jlong JNICALL
 Java_java_io_Win32FileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
 						 jobject file)
 {
     jlong rv = 0;
     WITH_NATIVE_PATH(env, file, ids.path, path) {
-    /* Win95, Win98, WinME */
-    WIN32_FIND_DATA fd;
-    jlong temp = 0;
-    LARGE_INTEGER modTime;
-    HANDLE h = FindFirstFile(path, &fd);
-    if (h != INVALID_HANDLE_VALUE) {
-        FindClose(h);
-        modTime.LowPart = (DWORD) fd.ftLastWriteTime.dwLowDateTime;
-        modTime.HighPart = (LONG) fd.ftLastWriteTime.dwHighDateTime;
-        rv = modTime.QuadPart / 10000;
-        rv -= 11644473600000;
-    }
+		/* Win95, Win98, WinME */
+		WIN32_FIND_DATA fd;
+		HANDLE h = FindFirstFile(path, &fd);
+		if (h != INVALID_HANDLE_VALUE) {
+			FindClose(h);
+			rv = javaTime(fd.ftLastWriteTime);
+		}
     } END_NATIVE_PATH(env, path);
     return rv;
 }
@@ -328,6 +368,61 @@
 }
 
 
+HANDLE
+createSetFileTimeHandle()
+{
+    return CreateFileW(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+		           FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
+}
+
+FILETIME
+j2FileTime(jlong time)
+{
+	FILETIME t;
+	((LARGE_INTEGER)time).QuadPart = (time + 11644473600000L) * 10000L;
+	t.dwLowDateTime = (DWORD)((LARGE_INTEGER)time).LowPart;
+	t.dwHighDateTime = (DWORD)((LARGE_INTEGER)time).HighPart;
+	return t;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_Win32FileSystem_setCreatedTime(JNIEnv *env, jobject this,
+						 jobject file, jlong time)
+{
+    jboolean rv = JNI_FALSE;
+
+    WITH_NATIVE_PATH(env, file, ids.path, path) {
+		HANDLE h = createSetFileTimeHandle();
+		if (h != INVALID_HANDLE_VALUE) {
+			FILETIME t = j2FileTime(time);
+			if (SetFileTime(h, &t, NULL, NULL))
+				rv = JNI_TRUE;
+			CloseHandle(h);
+		}
+    } END_NATIVE_PATH(env, path);
+
+    return rv;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_Win32FileSystem_setLastAccessedTime(JNIEnv *env, jobject this,
+						 jobject file, jlong time)
+{
+    jboolean rv = JNI_FALSE;
+
+    WITH_NATIVE_PATH(env, file, ids.path, path) {
+		HANDLE h = createSetFileTimeHandle();
+		if (h != INVALID_HANDLE_VALUE) {
+			FILETIME t = j2FileTime(time);
+			if (SetFileTime(h, NULL, &t, NULL))
+				rv = JNI_TRUE;
+			CloseHandle(h);
+		}
+    } END_NATIVE_PATH(env, path);
+
+    return rv;
+}
+
 JNIEXPORT jboolean JNICALL
 Java_java_io_Win32FileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
 						 jobject file, jlong time)
@@ -335,20 +430,13 @@
     jboolean rv = JNI_FALSE;
 
     WITH_NATIVE_PATH(env, file, ids.path, path) {
-	HANDLE h;
-	h = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
-		       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
-	if (h != INVALID_HANDLE_VALUE) {
-	    LARGE_INTEGER modTime;
-	    FILETIME t;
-	    modTime.QuadPart = (time + 11644473600000L) * 10000L;
-	    t.dwLowDateTime = (DWORD)modTime.LowPart;
-	    t.dwHighDateTime = (DWORD)modTime.HighPart;
-	    if (SetFileTime(h, NULL, NULL, &t)) {
-		rv = JNI_TRUE;
-	    }
-

Comments
EVALUATION This feature has been addressed by the new file system API defined by JSR-203.
16-02-2009

EVALUATION Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=12037&forumID=1463
15-03-2006

EVALUATION The submitter has provided a fine patch to add this functionality to java.io.File. It is good to see contributions to address missing functionality like this. However there is a bigger issue here and that is the need to define a new file system interface to overcome the many limitations of java.io.File. This interface will be defined by JSR-203 (http://jcp.org/en/jsr/detail?id=203). Among the goals of this JSR will be to provide an interface for efficient access to file attributes. It is important that we do not extend java.io.File in Mustang in areas that will be covered by this JSR. The only exception to this is a small number of critical methods to set access permissions and get free space/usage information. JSR-203 will be starting up shortly and will target Dolphin (Java SE 7.0).
23-08-2005