Summary
Add verbiage to the specifications of the java.io classes File, FileInputStream, FileOutputStream, and RandomAccessFile with respect to the handling of symbolic links.
Problem
The java.io classes File, FileInputStream, FileOutputStream, and RandomAccessFile do not provide any information on how symbolic links passed to their constructors and methods are handled.
Solution
Add some text to the specifications of the indicated classes stating how symbolic links are handled and referring to the java.nio.file package documentation.
Specification
--- a/src/java.base/share/classes/java/io/File.java
+++ b/src/java.base/share/classes/java/io/File.java
@@ -79,6 +79,10 @@
* {@code user.dir}, and is typically the directory in which the Java
* virtual machine was invoked.
*
+ * <p> Unless otherwise noted, {@linkplain java.nio.file##links symbolic links}
+ * are automatically redirected to the <i>target</i> of the link, whether they
+ * are provided by a pathname string or via a {@code File} object.
+ *
* <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
* the {@link #getParent} method of this class and consists of the pathname's
* prefix and each name in the pathname's name sequence except for the last.
@@ -904,8 +908,16 @@ public boolean isFile() {
* Tests whether the file named by this abstract pathname is a hidden
* file. The exact definition of <em>hidden</em> is system-dependent. On
* UNIX systems, a file is considered to be hidden if its name begins with
- * a period character ({@code '.'}). On Microsoft Windows systems, a file is
- * considered to be hidden if it has been marked as such in the filesystem.
+ * a period character ({@code '.'}). On Microsoft Windows systems, a file
+ * is considered to be hidden if it has been marked as such in the
+ * filesystem.
+ *
+ *
+ * @implNote
+ * If the file is a symbolic link, then on UNIX system it is considered to
+ * be hidden if the name of the link itself, not that of its target, begins
+ * with a period character. On Windows systems, a symbolic link is
+ * considered hidden if its target is so marked in the filesystem.
*
* @return {@code true} if and only if the file denoted by this
* abstract pathname is hidden according to the conventions of the
@@ -1048,7 +1060,8 @@ public boolean createNewFile() throws IOException {
/**
* Deletes the file or directory denoted by this abstract pathname. If
* this pathname denotes a directory, then the directory must be empty in
- * order to be deleted.
+ * order to be deleted. If this pathname denotes a symbolic link, then the
+ * link itself, not its target, will be deleted.
*
* <p> Note that the {@link java.nio.file.Files} class defines the {@link
* java.nio.file.Files#delete(Path) delete} method to throw an {@link IOException}
@@ -1078,6 +1091,8 @@ public boolean delete() {
/**
* Requests that the file or directory denoted by this abstract
* pathname be deleted when the virtual machine terminates.
+ * If this pathname denotes a symbolic link, then the
+ * link itself, not its target, will be deleted.
* Files (or directories) are deleted in the reverse order that
* they are registered. Invoking this method to delete a file or
* directory that is already registered for deletion has no effect.
@@ -1421,7 +1436,9 @@ public boolean mkdirs() {
}
/**
- * Renames the file denoted by this abstract pathname.
+ * Renames the file denoted by this abstract pathname. If this pathname
+ * denotes a symbolic link, then the link itself, not its target, will be
+ * renamed.
*
* <p> Many aspects of the behavior of this method are inherently
* platform-dependent: The rename operation might not be able to move a
--- a/src/java.base/share/classes/java/io/FileInputStream.java
+++ b/src/java.base/share/classes/java/io/FileInputStream.java
@@ -85,7 +85,9 @@ public class FileInputStream extends InputStream
* Creates a {@code FileInputStream} by
* opening a connection to an actual file,
* the file named by the path name {@code name}
- * in the file system. A new {@code FileDescriptor}
+ * in the file system. {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
+ * A new {@code FileDescriptor}
* object is created to represent this file
* connection.
* <p>
@@ -117,6 +119,8 @@ public FileInputStream(String name) throws FileNotFoundException {
* opening a connection to an actual file,
* the file named by the {@code File}
* object {@code file} in the file system.
+ * {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
* A new {@code FileDescriptor} object
* is created to represent this file connection.
* <p>
--- a/src/java.base/share/classes/java/io/FileOutputStream.java
+++ b/src/java.base/share/classes/java/io/FileOutputStream.java
@@ -97,7 +97,10 @@ public class FileOutputStream extends OutputStream
/**
* Creates a file output stream to write to the file with the
- * specified name. A new {@code FileDescriptor} object is
+ * specified name. If the file exists, it is truncated, otherwise a
+ * new file is created. {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
+ * A new {@code FileDescriptor} object is
* created to represent this file connection.
* <p>
* First, if there is a security manager, its {@code checkWrite}
@@ -126,8 +129,11 @@ public FileOutputStream(String name) throws FileNotFoundException {
/**
* Creates a file output stream to write to the file with the specified
- * name. If the second argument is {@code true}, then
- * bytes will be written to the end of the file rather than the beginning.
+ * name. If the file exists, it is truncated unless the second
+ * argument is {@code true}, in which case bytes will be written to the
+ * end of the file rather than the beginning. If the file does not exist,
+ * it is created. {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
* A new {@code FileDescriptor} object is created to represent this
* file connection.
* <p>
@@ -158,9 +164,12 @@ public FileOutputStream(String name, boolean append)
/**
* Creates a file output stream to write to the file represented by
- * the specified {@code File} object. A new
- * {@code FileDescriptor} object is created to represent this
- * file connection.
+ * the specified {@code File} object.
+ * If the file exists, it is truncated, otherwise a
+ * new file is created. {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
+ * A new {@code FileDescriptor} object is
+ * created to represent this file connection.
* <p>
* First, if there is a security manager, its {@code checkWrite}
* method is called with the path represented by the {@code file}
@@ -187,10 +196,14 @@ public FileOutputStream(File file) throws FileNotFoundException {
/**
* Creates a file output stream to write to the file represented by
- * the specified {@code File} object. If the second argument is
- * {@code true}, then bytes will be written to the end of the file
- * rather than the beginning. A new {@code FileDescriptor} object is
- * created to represent this file connection.
+ * the specified {@code File} object.
+ * If the file exists, it is truncated unless the second
+ * argument is {@code true}, in which case bytes will be written to the
+ * end of the file rather than the beginning. If the file does not exist,
+ * it is created. {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
+ * A new {@code FileDescriptor} object is created to represent this
+ * file connection.
* <p>
* First, if there is a security manager, its {@code checkWrite}
* method is called with the path represented by the {@code file}
--- a/src/java.base/share/classes/java/io/RandomAccessFile.java
+++ b/src/java.base/share/classes/java/io/RandomAccessFile.java
@@ -101,8 +101,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Creates a random access file stream to read from, and optionally
- * to write to, a file with the specified pathname. A new
- * {@link FileDescriptor} object is created to represent the
+ * to write to, a file with the specified pathname. If the file exists
+ * it is opened; if it does not exist and write mode is specified, a
+ * new file is created.
+ * {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
+ * A new {@link FileDescriptor} object is created to represent the
* connection to the file.
*
* <p> The {@code mode} argument specifies the access mode with which the
@@ -146,9 +150,14 @@ public RandomAccessFile(String pathname, String mode)
}
/**
- * Creates a random access file stream to read from, and optionally to
- * write to, the file specified by the {@link File} argument. A new {@link
- * FileDescriptor} object is created to represent this file connection.
+ * Creates a random access file stream to read from, and optionally
+ * to write to, the file specified by the {@link File} argument. If
+ * the file exists it is opened; if it does not exist and write mode
+ * is specified, a new file is created.
+ * {@linkplain java.nio.file##links Symbolic links}
+ * are automatically redirected to the <i>target</i> of the link.
+ * A new {@link FileDescriptor} object is created to represent the
+ * connection to the file.
*
* <p>The <a id="mode">{@code mode}</a> argument specifies the access mode
* in which the file is to be opened. The permitted values and their
- csr of
-
JDK-8339574 Behavior of File.is{Directory,File,Hidden} is not documented with respect to symlinks
- Resolved