7006126: (fs) Updates to file system API (1/2011)
Reviewed-by: chegar, sherman
This commit is contained in:
parent
254ad140f3
commit
2f37110eca
@ -443,7 +443,6 @@ JAVA_JAVA_java = \
|
||||
java/io/FileReader.java \
|
||||
java/io/PipedReader.java \
|
||||
java/io/StringReader.java \
|
||||
java/io/TempFileHelper.java \
|
||||
java/io/Writer.java \
|
||||
java/io/BufferedWriter.java \
|
||||
java/io/PrintWriter.java \
|
||||
|
@ -81,12 +81,12 @@ FILES_src = \
|
||||
java/nio/file/ClosedDirectoryStreamException.java \
|
||||
java/nio/file/ClosedFileSystemException.java \
|
||||
java/nio/file/ClosedWatchServiceException.java \
|
||||
java/nio/file/CopyMoveHelper.java \
|
||||
java/nio/file/CopyOption.java \
|
||||
java/nio/file/DirectoryIteratorException.java \
|
||||
java/nio/file/DirectoryNotEmptyException.java \
|
||||
java/nio/file/DirectoryStream.java \
|
||||
java/nio/file/FileAlreadyExistsException.java \
|
||||
java/nio/file/FileRef.java \
|
||||
java/nio/file/FileStore.java \
|
||||
java/nio/file/FileSystem.java \
|
||||
java/nio/file/FileSystemAlreadyExistsException.java \
|
||||
@ -116,6 +116,7 @@ FILES_src = \
|
||||
java/nio/file/StandardCopyOption.java \
|
||||
java/nio/file/StandardOpenOption.java \
|
||||
java/nio/file/StandardWatchEventKind.java \
|
||||
java/nio/file/TempFileHelper.java \
|
||||
java/nio/file/WatchEvent.java \
|
||||
java/nio/file/WatchKey.java \
|
||||
java/nio/file/WatchService.java \
|
||||
@ -127,7 +128,6 @@ FILES_src = \
|
||||
java/nio/file/attribute/AclEntryType.java \
|
||||
java/nio/file/attribute/AclFileAttributeView.java \
|
||||
java/nio/file/attribute/AttributeView.java \
|
||||
java/nio/file/attribute/Attributes.java \
|
||||
java/nio/file/attribute/BasicFileAttributeView.java \
|
||||
java/nio/file/attribute/BasicFileAttributes.java \
|
||||
java/nio/file/attribute/DosFileAttributeView.java \
|
||||
@ -136,8 +136,6 @@ FILES_src = \
|
||||
java/nio/file/attribute/FileAttributeView.java \
|
||||
java/nio/file/attribute/FileOwnerAttributeView.java \
|
||||
java/nio/file/attribute/FileStoreAttributeView.java \
|
||||
java/nio/file/attribute/FileStoreSpaceAttributeView.java \
|
||||
java/nio/file/attribute/FileStoreSpaceAttributes.java \
|
||||
java/nio/file/attribute/FileTime.java \
|
||||
java/nio/file/attribute/GroupPrincipal.java \
|
||||
java/nio/file/attribute/UserDefinedFileAttributeView.java \
|
||||
@ -246,6 +244,7 @@ FILES_src = \
|
||||
sun/nio/fs/AbstractAclFileAttributeView.java \
|
||||
sun/nio/fs/AbstractBasicFileAttributeView.java \
|
||||
sun/nio/fs/AbstractFileTypeDetector.java \
|
||||
sun/nio/fs/AbstractFileSystemProvider.java \
|
||||
sun/nio/fs/AbstractPath.java \
|
||||
sun/nio/fs/AbstractPoller.java \
|
||||
sun/nio/fs/AbstractUserDefinedFileAttributeView.java \
|
||||
|
@ -31,7 +31,7 @@ BUILDDIR = ..
|
||||
PRODUCT = demos
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
SUBDIRS = jni nio
|
||||
SUBDIRS = jni
|
||||
SUBDIRS_desktop = applets jfc
|
||||
SUBDIRS_management = management
|
||||
SUBDIRS_misc = scripting
|
||||
|
@ -54,6 +54,7 @@ package java.io;
|
||||
*
|
||||
* @see FileReader
|
||||
* @see InputStreamReader
|
||||
* @see java.nio.file.Files#newBufferedReader
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since JDK1.1
|
||||
@ -374,6 +375,8 @@ public class BufferedReader extends Reader {
|
||||
* stream has been reached
|
||||
*
|
||||
* @exception IOException If an I/O error occurs
|
||||
*
|
||||
* @see java.nio.file.Files#readAllLines
|
||||
*/
|
||||
public String readLine() throws IOException {
|
||||
return readLine(false);
|
||||
|
@ -57,6 +57,7 @@ package java.io;
|
||||
* @see PrintWriter
|
||||
* @see FileWriter
|
||||
* @see OutputStreamWriter
|
||||
* @see java.nio.file.Files#newBufferedWriter
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since JDK1.1
|
||||
|
@ -35,8 +35,7 @@ import java.util.ArrayList;
|
||||
import java.security.AccessController;
|
||||
import java.security.SecureRandom;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.FileSystems;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
@ -139,9 +138,10 @@ import sun.security.action.GetPropertyAction;
|
||||
* many of the limitations of the {@code java.io.File} class.
|
||||
* The {@link #toPath toPath} method may be used to obtain a {@link
|
||||
* Path} that uses the abstract path represented by a {@code File} object to
|
||||
* locate a file. The resulting {@code Path} provides more efficient and
|
||||
* extensive access to file attributes, additional file operations, and I/O
|
||||
* exceptions to help diagnose errors when an operation on a file fails.
|
||||
* locate a file. The resulting {@code Path} may be used with the {@link
|
||||
* java.nio.file.Files} class to provide more efficient and extensive access to
|
||||
* additional file operations, file attributes, and I/O exceptions to help
|
||||
* diagnose errors when an operation on a file fails.
|
||||
*
|
||||
* @author unascribed
|
||||
* @since JDK1.0
|
||||
@ -778,6 +778,12 @@ public class File
|
||||
* Tests whether the file denoted by this abstract pathname is a
|
||||
* directory.
|
||||
*
|
||||
* <p> Where it is required to distinguish an I/O exception from the case
|
||||
* that the file is not a directory, or where several attributes of the
|
||||
* same file are required at the same time, then the {@link
|
||||
* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
|
||||
* Files.readAttributes} method may be used.
|
||||
*
|
||||
* @return <code>true</code> if and only if the file denoted by this
|
||||
* abstract pathname exists <em>and</em> is a directory;
|
||||
* <code>false</code> otherwise
|
||||
@ -786,8 +792,6 @@ public class File
|
||||
* If a security manager exists and its <code>{@link
|
||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||
* method denies read access to the file
|
||||
*
|
||||
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||
*/
|
||||
public boolean isDirectory() {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
@ -804,6 +808,12 @@ public class File
|
||||
* addition, satisfies other system-dependent criteria. Any non-directory
|
||||
* file created by a Java application is guaranteed to be a normal file.
|
||||
*
|
||||
* <p> Where it is required to distinguish an I/O exception from the case
|
||||
* that the file is not a normal file, or where several attributes of the
|
||||
* same file are required at the same time, then the {@link
|
||||
* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
|
||||
* Files.readAttributes} method may be used.
|
||||
*
|
||||
* @return <code>true</code> if and only if the file denoted by this
|
||||
* abstract pathname exists <em>and</em> is a normal file;
|
||||
* <code>false</code> otherwise
|
||||
@ -812,8 +822,6 @@ public class File
|
||||
* If a security manager exists and its <code>{@link
|
||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||
* method denies read access to the file
|
||||
*
|
||||
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||
*/
|
||||
public boolean isFile() {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
@ -853,6 +861,13 @@ public class File
|
||||
* Returns the time that the file denoted by this abstract pathname was
|
||||
* last modified.
|
||||
*
|
||||
* <p> Where it is required to distinguish an I/O exception from the case
|
||||
* where {@code 0L} is returned, or where several attributes of the
|
||||
* same file are required at the same time, or where the time of last
|
||||
* access or the creation time are required, then the {@link
|
||||
* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
|
||||
* Files.readAttributes} method may be used.
|
||||
*
|
||||
* @return A <code>long</code> value representing the time the file was
|
||||
* last modified, measured in milliseconds since the epoch
|
||||
* (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
|
||||
@ -862,8 +877,6 @@ public class File
|
||||
* If a security manager exists and its <code>{@link
|
||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||
* method denies read access to the file
|
||||
*
|
||||
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||
*/
|
||||
public long lastModified() {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
@ -877,6 +890,12 @@ public class File
|
||||
* Returns the length of the file denoted by this abstract pathname.
|
||||
* The return value is unspecified if this pathname denotes a directory.
|
||||
*
|
||||
* <p> Where it is required to distinguish an I/O exception from the case
|
||||
* that {@code 0L} is returned, or where several attributes of the same file
|
||||
* are required at the same time, then the {@link
|
||||
* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
|
||||
* Files.readAttributes} method may be used.
|
||||
*
|
||||
* @return The length, in bytes, of the file denoted by this abstract
|
||||
* pathname, or <code>0L</code> if the file does not exist. Some
|
||||
* operating systems may return <code>0L</code> for pathnames
|
||||
@ -886,8 +905,6 @@ public class File
|
||||
* If a security manager exists and its <code>{@link
|
||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||
* method denies read access to the file
|
||||
*
|
||||
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||
*/
|
||||
public long length() {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
@ -937,11 +954,10 @@ public class File
|
||||
* this pathname denotes a directory, then the directory must be empty in
|
||||
* order to be deleted.
|
||||
*
|
||||
* <p> Note that the {@link Path} class defines the {@link Path#delete
|
||||
* delete} method to throw an {@link IOException} when a file cannot be
|
||||
* deleted. This is useful for error reporting and to diagnose why a file
|
||||
* cannot be deleted. The {@link #toPath toPath} method may be used to
|
||||
* obtain a {@code Path} representing this abstract pathname.
|
||||
* <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}
|
||||
* when a file cannot be deleted. This is useful for error reporting and to
|
||||
* diagnose why a file cannot be deleted.
|
||||
*
|
||||
* @return <code>true</code> if and only if the file or directory is
|
||||
* successfully deleted; <code>false</code> otherwise
|
||||
@ -1009,12 +1025,11 @@ public class File
|
||||
* will appear in any specific order; they are not, in particular,
|
||||
* guaranteed to appear in alphabetical order.
|
||||
*
|
||||
* <p> Note that the {@link Path} class defines the {@link
|
||||
* Path#newDirectoryStream newDirectoryStream} method to open a directory
|
||||
* and iterate over the names of the files in the directory. This may use
|
||||
* less resources when working with very large directories. The {@link
|
||||
* #toPath toPath} method may be used to obtain a {@code Path} representing
|
||||
* this abstract pathname.
|
||||
* <p> Note that the {@link java.nio.file.Files} class defines the {@link
|
||||
* java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to
|
||||
* open a directory and iterate over the names of the files in the directory.
|
||||
* This may use less resources when working with very large directories, and
|
||||
* may be more responsive when working with remote directories.
|
||||
*
|
||||
* @return An array of strings naming the files and directories in the
|
||||
* directory denoted by this abstract pathname. The array will be
|
||||
@ -1061,6 +1076,8 @@ public class File
|
||||
* If a security manager exists and its {@link
|
||||
* SecurityManager#checkRead(String)} method denies read access to
|
||||
* the directory
|
||||
*
|
||||
* @see java.nio.file.Files#newDirectoryStream(Path,String)
|
||||
*/
|
||||
public String[] list(FilenameFilter filter) {
|
||||
String names[] = list();
|
||||
@ -1095,12 +1112,11 @@ public class File
|
||||
* will appear in any specific order; they are not, in particular,
|
||||
* guaranteed to appear in alphabetical order.
|
||||
*
|
||||
* <p> Note that the {@link Path} class defines the {@link
|
||||
* Path#newDirectoryStream newDirectoryStream} method to open a directory
|
||||
* and iterate over the names of the files in the directory. This may use
|
||||
* less resources when working with very large directories. The {@link
|
||||
* #toPath toPath} method may be used to obtain a {@code Path} representing
|
||||
* this abstract pathname.
|
||||
* <p> Note that the {@link java.nio.file.Files} class defines the {@link
|
||||
* java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method
|
||||
* to open a directory and iterate over the names of the files in the
|
||||
* directory. This may use less resources when working with very large
|
||||
* directories.
|
||||
*
|
||||
* @return An array of abstract pathnames denoting the files and
|
||||
* directories in the directory denoted by this abstract pathname.
|
||||
@ -1154,6 +1170,7 @@ public class File
|
||||
* the directory
|
||||
*
|
||||
* @since 1.2
|
||||
* @see java.nio.file.Files#newDirectoryStream(Path,String)
|
||||
*/
|
||||
public File[] listFiles(FilenameFilter filter) {
|
||||
String ss[] = list();
|
||||
@ -1191,6 +1208,7 @@ public class File
|
||||
* the directory
|
||||
*
|
||||
* @since 1.2
|
||||
* @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)
|
||||
*/
|
||||
public File[] listFiles(FileFilter filter) {
|
||||
String ss[] = list();
|
||||
@ -1207,12 +1225,6 @@ public class File
|
||||
/**
|
||||
* Creates the directory named by this abstract pathname.
|
||||
*
|
||||
* <p> Note that the {@link Path} class defines the {@link Path#createDirectory
|
||||
* createDirectory} method to throw an {@link IOException} when a directory
|
||||
* cannot be created. This is useful for error reporting and to diagnose why
|
||||
* a directory cannot be created. The {@link #toPath toPath} method may be
|
||||
* used to obtain a {@code Path} representing this abstract pathname.
|
||||
*
|
||||
* @return <code>true</code> if and only if the directory was
|
||||
* created; <code>false</code> otherwise
|
||||
*
|
||||
@ -1278,10 +1290,9 @@ public class File
|
||||
* already exists. The return value should always be checked to make sure
|
||||
* that the rename operation was successful.
|
||||
*
|
||||
* <p> Note that the {@link Path} class defines the {@link Path#moveTo
|
||||
* moveTo} method to move or rename a file in a platform independent manner.
|
||||
* The {@link #toPath toPath} method may be used to obtain a {@code Path}
|
||||
* representing this abstract pathname.
|
||||
* <p> Note that the {@link java.nio.file.Files} class defines the {@link
|
||||
* java.nio.file.Files#move move} method to move or rename a file in a
|
||||
* platform independent manner.
|
||||
*
|
||||
* @param dest The new abstract pathname for the named file
|
||||
*
|
||||
@ -1369,10 +1380,9 @@ public class File
|
||||
* Sets the owner's or everybody's write permission for this abstract
|
||||
* pathname.
|
||||
*
|
||||
* <p> The {@link java.nio.file.attribute.Attributes Attributes} class
|
||||
* defines methods that operate on file attributes including file
|
||||
* permissions. This may be used when finer manipulation of file permissions
|
||||
* is required.
|
||||
* <p> The {@link java.nio.file.Files} class defines methods that operate on
|
||||
* file attributes including file permissions. This may be used when finer
|
||||
* manipulation of file permissions is required.
|
||||
*
|
||||
* @param writable
|
||||
* If <code>true</code>, sets the access permission to allow write
|
||||
@ -1437,10 +1447,9 @@ public class File
|
||||
* Sets the owner's or everybody's read permission for this abstract
|
||||
* pathname.
|
||||
*
|
||||
* <p> The {@link java.nio.file.attribute.Attributes Attributes} class
|
||||
* defines methods that operate on file attributes including file
|
||||
* permissions. This may be used when finer manipulation of file permissions
|
||||
* is required.
|
||||
* <p> The {@link java.nio.file.Files} class defines methods that operate on
|
||||
* file attributes including file permissions. This may be used when finer
|
||||
* manipulation of file permissions is required.
|
||||
*
|
||||
* @param readable
|
||||
* If <code>true</code>, sets the access permission to allow read
|
||||
@ -1511,10 +1520,9 @@ public class File
|
||||
* Sets the owner's or everybody's execute permission for this abstract
|
||||
* pathname.
|
||||
*
|
||||
* <p> The {@link java.nio.file.attribute.Attributes Attributes} class
|
||||
* defines methods that operate on file attributes including file
|
||||
* permissions. This may be used when finer manipulation of file permissions
|
||||
* is required.
|
||||
* <p> The {@link java.nio.file.Files} class defines methods that operate on
|
||||
* file attributes including file permissions. This may be used when finer
|
||||
* manipulation of file permissions is required.
|
||||
*
|
||||
* @param executable
|
||||
* If <code>true</code>, sets the access permission to allow execute
|
||||
@ -1646,6 +1654,7 @@ public class File
|
||||
* filesystem roots.
|
||||
*
|
||||
* @since 1.2
|
||||
* @see java.nio.file.FileStore
|
||||
*/
|
||||
public static File[] listRoots() {
|
||||
return fs.listRoots();
|
||||
@ -1753,7 +1762,7 @@ public class File
|
||||
|
||||
/* -- Temporary files -- */
|
||||
|
||||
static class TempDirectory {
|
||||
private static class TempDirectory {
|
||||
private TempDirectory() { }
|
||||
|
||||
// temporary directory location
|
||||
@ -1880,11 +1889,12 @@ public class File
|
||||
* java.lang.String, java.io.File)
|
||||
* createTempFile(prefix, suffix, null)}</code>.
|
||||
*
|
||||
* <p> The {@link #createTemporaryFile(String,String,FileAttribute[])} method
|
||||
* provides an alternative method to create an empty file in the
|
||||
* temporary-file directory. Files created by that method may have more
|
||||
* restrictive access permissions to files created by this method and so
|
||||
* may be more suited to security-sensitive applications.
|
||||
* <p> The {@link
|
||||
* java.nio.file.Files#createTempFile(String,String,java.nio.file.attribute.FileAttribute[])
|
||||
* Files.createTempFile} method provides an alternative method to create an
|
||||
* empty file in the temporary-file directory. Files created by that method
|
||||
* may have more restrictive access permissions to files created by this
|
||||
* method and so may be more suited to security-sensitive applications.
|
||||
*
|
||||
* @param prefix The prefix string to be used in generating the file's
|
||||
* name; must be at least three characters long
|
||||
@ -1907,6 +1917,7 @@ public class File
|
||||
* method does not allow a file to be created
|
||||
*
|
||||
* @since 1.2
|
||||
* @see java.nio.file.Files#createTempDirectory(String,FileAttribute[])
|
||||
*/
|
||||
public static File createTempFile(String prefix, String suffix)
|
||||
throws IOException
|
||||
@ -1914,61 +1925,6 @@ public class File
|
||||
return createTempFile(prefix, suffix, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty file in the default temporary-file directory, using
|
||||
* the given prefix and suffix to generate its name.
|
||||
*
|
||||
* <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
|
||||
* attributes} to set atomically when creating the file. Each attribute is
|
||||
* identified by its {@link FileAttribute#name name}. If more than one attribute
|
||||
* of the same name is included in the array then all but the last occurrence
|
||||
* is ignored.
|
||||
*
|
||||
* <p> Where the {@code attrs} parameter does not specify <i>access
|
||||
* permissions</i> to set atomically when creating the file, then the
|
||||
* resulting file may have more restrictive access permissions than files
|
||||
* created by the {@link #createTempFile(java.lang.String, java.lang.String)}
|
||||
* method.
|
||||
*
|
||||
* @param prefix
|
||||
* The prefix string to be used in generating the file's
|
||||
* name; must be at least three characters long
|
||||
* @param suffix
|
||||
* The suffix string to be used in generating the file's
|
||||
* name; may be {@code null}, in which case the suffix
|
||||
* {@code ".tmp"} will be used
|
||||
* @param attrs
|
||||
* An optional list of file attributes to set atomically when creating
|
||||
* the file
|
||||
*
|
||||
* @return An abstract pathname denoting a newly-created empty file
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the {@code prefix} argument contains fewer than three
|
||||
* characters
|
||||
* @throws UnsupportedOperationException
|
||||
* If the array contains an attribute that cannot be set atomically
|
||||
* when creating the file
|
||||
* @throws IOException
|
||||
* If a file could not be created
|
||||
* @throws SecurityException
|
||||
* If a security manager exists and its <code>{@link
|
||||
* java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
|
||||
* method does not allow a file to be created.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public static File createTemporaryFile(String prefix,
|
||||
String suffix,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
if (prefix.length() < 3)
|
||||
throw new IllegalArgumentException("Prefix string too short");
|
||||
suffix = (suffix == null) ? ".tmp" : suffix;
|
||||
return TempFileHelper.createFile(prefix, suffix, attrs);
|
||||
}
|
||||
|
||||
/* -- Basic infrastructure -- */
|
||||
|
||||
/**
|
||||
@ -2104,6 +2060,7 @@ public class File
|
||||
* path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})
|
||||
*
|
||||
* @since 1.7
|
||||
* @see Path#toFile
|
||||
*/
|
||||
public Path toPath() {
|
||||
Path result = filePath;
|
||||
@ -2111,12 +2068,7 @@ public class File
|
||||
synchronized (this) {
|
||||
result = filePath;
|
||||
if (result == null) {
|
||||
if (path.length() == 0) {
|
||||
// assume default file system treats "." as current directory
|
||||
result = Paths.get(".");
|
||||
} else {
|
||||
result = Paths.get(path);
|
||||
}
|
||||
result = FileSystems.getDefault().getPath(path);
|
||||
filePath = result;
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import sun.nio.ch.FileChannelImpl;
|
||||
* @see java.io.File
|
||||
* @see java.io.FileDescriptor
|
||||
* @see java.io.FileOutputStream
|
||||
* @see java.nio.file.Files#newInputStream
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public
|
||||
|
@ -46,6 +46,7 @@ import sun.nio.ch.FileChannelImpl;
|
||||
* @see java.io.File
|
||||
* @see java.io.FileDescriptor
|
||||
* @see java.io.FileInputStream
|
||||
* @see java.nio.file.Files#newOutputStream
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public
|
||||
|
@ -72,7 +72,7 @@ import sun.security.util.SecurityConstants;
|
||||
* <DT> readlink
|
||||
* <DD> read link permission. Allows the target of a
|
||||
* <a href="../nio/file/package-summary.html#links">symbolic link</a>
|
||||
* to be read by invoking the {@link java.nio.file.Path#readSymbolicLink
|
||||
* to be read by invoking the {@link java.nio.file.Files#readSymbolicLink
|
||||
* readSymbolicLink } method.
|
||||
* </DL>
|
||||
* <P>
|
||||
|
@ -54,5 +54,3 @@
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -248,7 +248,7 @@ public abstract class FileChannel
|
||||
* FileSystemProvider#newFileChannel newFileChannel} method on the
|
||||
* provider that created the {@code Path}.
|
||||
*
|
||||
* @param file
|
||||
* @param path
|
||||
* The path of the file to open or create
|
||||
* @param options
|
||||
* Options specifying how the file is opened
|
||||
@ -261,7 +261,7 @@ public abstract class FileChannel
|
||||
* @throws IllegalArgumentException
|
||||
* If the set contains an invalid combination of options
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code file} is associated with a provider that does not
|
||||
* If the {@code path} is associated with a provider that does not
|
||||
* support creating file channels, or an unsupported open option is
|
||||
* specified, or the array contains an attribute that cannot be set
|
||||
* atomically when creating the file
|
||||
@ -278,13 +278,13 @@ public abstract class FileChannel
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public static FileChannel open(Path file,
|
||||
public static FileChannel open(Path path,
|
||||
Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
FileSystemProvider provider = file.getFileSystem().provider();
|
||||
return provider.newFileChannel(file, options, attrs);
|
||||
FileSystemProvider provider = path.getFileSystem().provider();
|
||||
return provider.newFileChannel(path, options, attrs);
|
||||
}
|
||||
|
||||
private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
|
||||
@ -295,10 +295,12 @@ public abstract class FileChannel
|
||||
* <p> An invocation of this method behaves in exactly the same way as the
|
||||
* invocation
|
||||
* <pre>
|
||||
* fc.{@link #open(Path,Set,FileAttribute[]) open}(file, options, new FileAttribute<?>[0]);
|
||||
* fc.{@link #open(Path,Set,FileAttribute[]) open}(file, opts, new FileAttribute<?>[0]);
|
||||
* </pre>
|
||||
* where {@code opts} is a set of the options specified in the {@code
|
||||
* options} array.
|
||||
*
|
||||
* @param file
|
||||
* @param path
|
||||
* The path of the file to open or create
|
||||
* @param options
|
||||
* Options specifying how the file is opened
|
||||
@ -308,7 +310,7 @@ public abstract class FileChannel
|
||||
* @throws IllegalArgumentException
|
||||
* If the set contains an invalid combination of options
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code file} is associated with a provider that does not
|
||||
* If the {@code path} is associated with a provider that does not
|
||||
* support creating file channels, or an unsupported open option is
|
||||
* specified
|
||||
* @throws IOException
|
||||
@ -324,12 +326,12 @@ public abstract class FileChannel
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public static FileChannel open(Path file, OpenOption... options)
|
||||
public static FileChannel open(Path path, OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
Set<OpenOption> set = new HashSet<OpenOption>(options.length);
|
||||
Collections.addAll(set, options);
|
||||
return open(file, set, NO_ATTRIBUTES);
|
||||
return open(path, set, NO_ATTRIBUTES);
|
||||
}
|
||||
|
||||
// -- Channel operations --
|
||||
|
@ -47,7 +47,7 @@ import java.io.IOException;
|
||||
* so that method invocations on the implementation class can be chained.
|
||||
*
|
||||
* @since 1.7
|
||||
* @see java.nio.file.Path#newByteChannel
|
||||
* @see java.nio.file.Files#newByteChannel
|
||||
*/
|
||||
|
||||
public interface SeekableByteChannel
|
||||
|
@ -29,8 +29,6 @@ package java.nio.file;
|
||||
* Defines access modes used to test the accessibility of a file.
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Path#checkAccess
|
||||
*/
|
||||
|
||||
public enum AccessMode {
|
||||
|
158
jdk/src/share/classes/java/nio/file/CopyMoveHelper.java
Normal file
158
jdk/src/share/classes/java/nio/file/CopyMoveHelper.java
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.nio.file;
|
||||
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Helper class to support copying or moving files when the source and target
|
||||
* are associated with different providers.
|
||||
*/
|
||||
|
||||
class CopyMoveHelper {
|
||||
private CopyMoveHelper() { }
|
||||
|
||||
/**
|
||||
* Parses the arguments for a file copy operation.
|
||||
*/
|
||||
private static class CopyOptions {
|
||||
boolean replaceExisting = false;
|
||||
boolean copyAttributes = false;
|
||||
boolean followLinks = true;
|
||||
|
||||
private CopyOptions() { }
|
||||
|
||||
static CopyOptions parse(CopyOption... options) {
|
||||
CopyOptions result = new CopyOptions();
|
||||
for (CopyOption option: options) {
|
||||
if (option == StandardCopyOption.REPLACE_EXISTING) {
|
||||
result.replaceExisting = true;
|
||||
continue;
|
||||
}
|
||||
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||||
result.followLinks = false;
|
||||
continue;
|
||||
}
|
||||
if (option == StandardCopyOption.COPY_ATTRIBUTES) {
|
||||
result.copyAttributes = true;
|
||||
continue;
|
||||
}
|
||||
if (option == null)
|
||||
throw new NullPointerException();
|
||||
throw new UnsupportedOperationException("'" + option +
|
||||
"' is not a recognized copy option");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given array of options for moving a file to options suitable
|
||||
* for copying the file when a move is implemented as copy + delete.
|
||||
*/
|
||||
private static CopyOption[] convertMoveToCopyOptions(CopyOption... options)
|
||||
throws AtomicMoveNotSupportedException
|
||||
{
|
||||
int len = options.length;
|
||||
CopyOption[] newOptions = new CopyOption[len+2];
|
||||
for (int i=0; i<len; i++) {
|
||||
CopyOption option = options[i];
|
||||
if (option == StandardCopyOption.ATOMIC_MOVE) {
|
||||
throw new AtomicMoveNotSupportedException(null, null,
|
||||
"Atomic move between providers is not supported");
|
||||
}
|
||||
newOptions[i] = option;
|
||||
}
|
||||
newOptions[len] = LinkOption.NOFOLLOW_LINKS;
|
||||
newOptions[len+1] = StandardCopyOption.COPY_ATTRIBUTES;
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple copy for use when source and target are associated with different
|
||||
* providers
|
||||
*/
|
||||
static void copyToForeignTarget(Path source, Path target,
|
||||
CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
CopyOptions opts = CopyOptions.parse(options);
|
||||
LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] :
|
||||
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
|
||||
|
||||
// attributes of source file
|
||||
BasicFileAttributes attrs = Files.readAttributes(source,
|
||||
BasicFileAttributes.class,
|
||||
linkOptions);
|
||||
if (attrs.isSymbolicLink())
|
||||
throw new IOException("Copying of symbolic links not supported");
|
||||
|
||||
// delete target if it exists and REPLACE_EXISTING is specified
|
||||
if (opts.replaceExisting) {
|
||||
Files.deleteIfExists(target);
|
||||
} else if (Files.exists(target))
|
||||
throw new FileAlreadyExistsException(target.toString());
|
||||
|
||||
// create directory or copy file
|
||||
if (attrs.isDirectory()) {
|
||||
Files.createDirectory(target);
|
||||
} else {
|
||||
try (InputStream in = Files.newInputStream(source)) {
|
||||
Files.copy(in, target);
|
||||
}
|
||||
}
|
||||
|
||||
// copy basic attributes to target
|
||||
if (opts.copyAttributes) {
|
||||
BasicFileAttributeView view =
|
||||
Files.getFileAttributeView(target, BasicFileAttributeView.class, linkOptions);
|
||||
try {
|
||||
view.setTimes(attrs.lastModifiedTime(),
|
||||
attrs.lastAccessTime(),
|
||||
attrs.creationTime());
|
||||
} catch (IOException x) {
|
||||
// rollback
|
||||
try {
|
||||
Files.delete(target);
|
||||
} catch (IOException ignore) { }
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple move implements as copy+delete for use when source and target are
|
||||
* associated with different providers
|
||||
*/
|
||||
static void moveToForeignTarget(Path source, Path target,
|
||||
CopyOption... options) throws IOException
|
||||
{
|
||||
copyToForeignTarget(source, target, convertMoveToCopyOptions(options));
|
||||
Files.delete(source);
|
||||
}
|
||||
}
|
@ -28,8 +28,12 @@ package java.nio.file;
|
||||
/**
|
||||
* An object that configures how to copy or move a file.
|
||||
*
|
||||
* <p> Objects of this type may be used with the {@link Path#copyTo copyTo} and
|
||||
* {@link Path#moveTo moveTo} methods to configure how a file is copied or moved.
|
||||
* <p> Objects of this type may be used with the {@link
|
||||
* Files#copy(Path,Path,CopyOption[]) Files.copy(Path,Path,CopyOption...)},
|
||||
* {@link Files#copy(java.io.InputStream,Path,CopyOption[])
|
||||
* Files.copy(InputStream,Path,CopyOption...)} and {@link Files#move
|
||||
* Files.move(Path,Path,CopyOption...)} methods to configure how a file is
|
||||
* copied or moved.
|
||||
*
|
||||
* <p> The {@link StandardCopyOption} enumeration type defines the
|
||||
* <i>standard</i> options.
|
||||
|
@ -54,7 +54,7 @@ import java.io.IOException;
|
||||
* construct to ensure that the stream is closed:
|
||||
* <pre>
|
||||
* Path dir = ...
|
||||
* try (DirectoryStream<Path> stream = dir.newDirectoryStream()) {
|
||||
* try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
|
||||
* for (Path entry: stream) {
|
||||
* ...
|
||||
* }
|
||||
@ -97,8 +97,8 @@ import java.io.IOException;
|
||||
* both the for-each and try-with-resources constructs.
|
||||
* <pre>
|
||||
* List<Path> listSourceFiles(Path dir) throws IOException {
|
||||
* List<Path> result = new ArrayList<Path>();
|
||||
* try (DirectoryStream<Path> stream = dir.newDirectoryStream("*.{c,h,cpp,hpp,java}")) {
|
||||
* List<Path> result = new ArrayList<>();
|
||||
* try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
|
||||
* for (Path entry: stream) {
|
||||
* result.add(entry);
|
||||
* }
|
||||
@ -113,7 +113,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Path#newDirectoryStream
|
||||
* @see Files#newDirectoryStream(Path)
|
||||
*/
|
||||
|
||||
public interface DirectoryStream<T>
|
||||
@ -122,9 +122,9 @@ public interface DirectoryStream<T>
|
||||
/**
|
||||
* An interface that is implemented by objects that decide if a directory
|
||||
* entry should be accepted or filtered. A {@code Filter} is passed as the
|
||||
* parameter to the {@link Path#newDirectoryStream(DirectoryStream.Filter)
|
||||
* newDirectoryStream} method when opening a directory to iterate over the
|
||||
* entries in the directory.
|
||||
* parameter to the {@link Files#newDirectoryStream(Path,DirectoryStream.Filter)}
|
||||
* method when opening a directory to iterate over the entries in the
|
||||
* directory.
|
||||
*
|
||||
* @param <T> the type of the directory entry
|
||||
*
|
||||
|
@ -1,322 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.nio.file;
|
||||
|
||||
import java.nio.file.attribute.*;
|
||||
import java.util.Map;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A reference to a file.
|
||||
*
|
||||
* <p> A {@code FileRef} is an object that locates a file and defines methods to
|
||||
* open the file for reading or writing. It also provides access to associated
|
||||
* metadata or file attributes.
|
||||
*
|
||||
* @since 1.7
|
||||
* @see java.nio.file.attribute.Attributes
|
||||
* @see java.io.File#toPath
|
||||
*/
|
||||
|
||||
public interface FileRef {
|
||||
|
||||
/**
|
||||
* Opens the file referenced by this object, returning an input stream to
|
||||
* read from the file. The stream will not be buffered, and is not required
|
||||
* to support the {@link InputStream#mark mark} or {@link InputStream#reset
|
||||
* reset} methods. The stream will be safe for access by multiple concurrent
|
||||
* threads. Reading commences at the beginning of the file.
|
||||
*
|
||||
* <p> The {@code options} parameter determines how the file is opened.
|
||||
* If no options are present then it is equivalent to opening the file with
|
||||
* the {@link StandardOpenOption#READ READ} option. In addition to the {@code
|
||||
* READ} option, an implementation may also support additional implementation
|
||||
* specific options.
|
||||
*
|
||||
* @return an input stream to read bytes from the file
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if an invalid combination of options is specified
|
||||
* @throws UnsupportedOperationException
|
||||
* if an unsupported option is specified
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file.
|
||||
*/
|
||||
InputStream newInputStream(OpenOption... options) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens or creates the file located by this object for writing, returning
|
||||
* an output stream to write bytes to the file.
|
||||
*
|
||||
* <p> The {@code options} parameter determines how the file is opened.
|
||||
* If no options are present then this method creates a new file for writing
|
||||
* or truncates an existing file. In addition to the {@link StandardOpenOption
|
||||
* standard} options, an implementation may also support additional
|
||||
* implementation specific options.
|
||||
*
|
||||
* <p> The resulting stream will not be buffered. The stream will be safe
|
||||
* for access by multiple concurrent threads.
|
||||
*
|
||||
* @param options
|
||||
* options specifying how the file is opened
|
||||
*
|
||||
* @return a new output stream
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code options} contains an invalid combination of options
|
||||
* @throws UnsupportedOperationException
|
||||
* if an unsupported option is specified
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method is invoked to check write access to the file.
|
||||
*/
|
||||
OutputStream newOutputStream(OpenOption... options) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a file attribute view of a given type.
|
||||
*
|
||||
* <p> A file attribute view provides a read-only or updatable view of a
|
||||
* set of file attributes. This method is intended to be used where the file
|
||||
* attribute view defines type-safe methods to read or update the file
|
||||
* attributes. The {@code type} parameter is the type of the attribute view
|
||||
* required and the method returns an instance of that type if supported.
|
||||
* The {@link BasicFileAttributeView} type supports access to the basic
|
||||
* attributes of a file. Invoking this method to select a file attribute
|
||||
* view of that type will always return an instance of that class.
|
||||
*
|
||||
* <p> The {@code options} array may be used to indicate how symbolic links
|
||||
* are handled by the resulting file attribute view for the case that the
|
||||
* file is a symbolic link. By default, symbolic links are followed. If the
|
||||
* option {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} is present then
|
||||
* symbolic links are not followed. This option is ignored by implementations
|
||||
* that do not support symbolic links.
|
||||
*
|
||||
* @param type
|
||||
* the {@code Class} object corresponding to the file attribute view
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
*
|
||||
* @return a file attribute view of the specified type, or {@code null} if
|
||||
* the attribute view type is not available
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If options contains an unsupported option. This exception is
|
||||
* specified to allow the {@code LinkOption} enum be extended
|
||||
* in future releases.
|
||||
*
|
||||
* @see Attributes#readBasicFileAttributes
|
||||
*/
|
||||
<V extends FileAttributeView> V getFileAttributeView(Class<V> type,
|
||||
LinkOption... options);
|
||||
|
||||
/**
|
||||
* Sets the value of a file attribute.
|
||||
*
|
||||
* <p> The {@code attribute} parameter identifies the attribute to be set
|
||||
* and takes the form:
|
||||
* <blockquote>
|
||||
* [<i>view-name</i><b>:</b>]<i>attribute-name</i>
|
||||
* </blockquote>
|
||||
* where square brackets [...] delineate an optional component and the
|
||||
* character {@code ':'} stands for itself.
|
||||
*
|
||||
* <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link
|
||||
* FileAttributeView} that identifies a set of file attributes. If not
|
||||
* specified then it defaults to {@code "basic"}, the name of the file
|
||||
* attribute view that identifies the basic set of file attributes common to
|
||||
* many file systems. <i>attribute-name</i> is the name of the attribute
|
||||
* within the set.
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we want to set the DOS "hidden" attribute:
|
||||
* <pre>
|
||||
* file.setAttribute("dos:hidden", true);
|
||||
* </pre>
|
||||
*
|
||||
* @param attribute
|
||||
* the attribute to set
|
||||
* @param value
|
||||
* the attribute value
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the attribute view is not available or it does not support
|
||||
* updating the attribute
|
||||
* @throws IllegalArgumentException
|
||||
* if the attribute value is of the correct type but has an
|
||||
* inappropriate value
|
||||
* @throws ClassCastException
|
||||
* If the attribute value is not of the expected type or is a
|
||||
* collection containing elements that are not of the expected
|
||||
* type
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the file. If this method is invoked
|
||||
* to set security sensitive attributes then the security manager
|
||||
* may be invoked to check for additional permissions.
|
||||
*/
|
||||
void setAttribute(String attribute, Object value, LinkOption... options)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Reads the value of a file attribute.
|
||||
*
|
||||
* <p> The {@code attribute} parameter identifies the attribute to be read
|
||||
* and takes the form:
|
||||
* <blockquote>
|
||||
* [<i>view-name</i><b>:</b>]<i>attribute-name</i>
|
||||
* </blockquote>
|
||||
* where square brackets [...] delineate an optional component and the
|
||||
* character {@code ':'} stands for itself.
|
||||
*
|
||||
* <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link
|
||||
* FileAttributeView} that identifies a set of file attributes. If not
|
||||
* specified then it defaults to {@code "basic"}, the name of the file
|
||||
* attribute view that identifies the basic set of file attributes common to
|
||||
* many file systems. <i>attribute-name</i> is the name of the attribute.
|
||||
*
|
||||
* <p> The {@code options} array may be used to indicate how symbolic links
|
||||
* are handled for the case that the file is a symbolic link. By default,
|
||||
* symbolic links are followed and the file attribute of the final target
|
||||
* of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS
|
||||
* NOFOLLOW_LINKS} is present then symbolic links are not followed and so
|
||||
* the method returns the file attribute of the symbolic link.
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we require the user ID of the file owner on a system that
|
||||
* supports a "{@code unix}" view:
|
||||
* <pre>
|
||||
* int uid = (Integer)file.getAttribute("unix:uid");
|
||||
* </pre>
|
||||
*
|
||||
* @param attribute
|
||||
* the attribute to read
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
* @return the attribute value or {@code null} if the attribute view
|
||||
* is not available or it does not support reading the attribute
|
||||
*
|
||||
* reading the attribute
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, its {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method denies read access to the file. If this method is invoked
|
||||
* to read security sensitive attributes then the security manager
|
||||
* may be invoked to check for additional permissions.
|
||||
*/
|
||||
Object getAttribute(String attribute, LinkOption... options) throws IOException;
|
||||
|
||||
/**
|
||||
* Reads a set of file attributes as a bulk operation.
|
||||
*
|
||||
* <p> The {@code attributes} parameter identifies the attributes to be read
|
||||
* and takes the form:
|
||||
* <blockquote>
|
||||
* [<i>view-name</i><b>:</b>]<i>attribute-list</i>
|
||||
* </blockquote>
|
||||
* where square brackets [...] delineate an optional component and the
|
||||
* character {@code ':'} stands for itself.
|
||||
*
|
||||
* <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link
|
||||
* FileAttributeView} that identifies a set of file attributes. If not
|
||||
* specified then it defaults to {@code "basic"}, the name of the file
|
||||
* attribute view that identifies the basic set of file attributes common to
|
||||
* many file systems.
|
||||
*
|
||||
* <p> The <i>attribute-list</i> component is a comma separated list of
|
||||
* zero or more names of attributes to read. If the list contains the value
|
||||
* {@code "*"} then all attributes are read. Attributes that are not supported
|
||||
* are ignored and will not be present in the returned map. It is
|
||||
* implementation specific if all attributes are read as an atomic operation
|
||||
* with respect to other file system operations.
|
||||
*
|
||||
* <p> The following examples demonstrate possible values for the {@code
|
||||
* attributes} parameter:
|
||||
*
|
||||
* <blockquote>
|
||||
* <table border="0">
|
||||
* <tr>
|
||||
* <td> {@code "*"} </td>
|
||||
* <td> Read all {@link BasicFileAttributes basic-file-attributes}. </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@code "size,lastModifiedTime,lastAccessTime"} </td>
|
||||
* <td> Reads the file size, last modified time, and last access time
|
||||
* attributes. </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@code "posix:*"} </td>
|
||||
* <td> Read all {@link PosixFileAttributes POSIX-file-attributes}.. </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@code "posix:permissions,owner,size"} </td>
|
||||
* <td> Reads the POSX file permissions, owner, and file size. </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* <p> The {@code options} array may be used to indicate how symbolic links
|
||||
* are handled for the case that the file is a symbolic link. By default,
|
||||
* symbolic links are followed and the file attribute of the final target
|
||||
* of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS
|
||||
* NOFOLLOW_LINKS} is present then symbolic links are not followed and so
|
||||
* the method returns the file attribute of the symbolic link.
|
||||
*
|
||||
* @param attributes
|
||||
* The attributes to read
|
||||
* @param options
|
||||
* Options indicating how symbolic links are handled
|
||||
*
|
||||
* @return A map of the attributes returned; may be empty. The map's keys
|
||||
* are the attribute names, its values are the attribute values
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, its {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method denies read access to the file. If this method is invoked
|
||||
* to read security sensitive attributes then the security manager
|
||||
* may be invoke to check for additional permissions.
|
||||
*/
|
||||
Map<String,?> readAttributes(String attributes, LinkOption... options)
|
||||
throws IOException;
|
||||
}
|
@ -32,16 +32,13 @@ import java.io.IOException;
|
||||
* Storage for files. A {@code FileStore} represents a storage pool, device,
|
||||
* partition, volume, concrete file system or other implementation specific means
|
||||
* of file storage. The {@code FileStore} for where a file is stored is obtained
|
||||
* by invoking the {@link Path#getFileStore getFileStore} method, or all file
|
||||
* by invoking the {@link Files#getFileStore getFileStore} method, or all file
|
||||
* stores can be enumerated by invoking the {@link FileSystem#getFileStores
|
||||
* getFileStores} method.
|
||||
*
|
||||
* <p> In addition to the methods defined by this class, a file store may support
|
||||
* one or more {@link FileStoreAttributeView FileStoreAttributeView} classes
|
||||
* that provide a read-only or updatable view of a set of file store attributes.
|
||||
* File stores associated with the default provider support the {@link
|
||||
* FileStoreSpaceAttributeView} to read the space related attributes of the
|
||||
* file store.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
@ -86,6 +83,51 @@ public abstract class FileStore {
|
||||
*/
|
||||
public abstract boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of the file store.
|
||||
*
|
||||
* @return the size of the file store, in bytes
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public abstract long getTotalSpace() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the number of bytes available to this Java virtual machine on the
|
||||
* file store.
|
||||
*
|
||||
* <p> The returned number of available bytes is a hint, but not a
|
||||
* guarantee, that it is possible to use most or any of these bytes. The
|
||||
* number of usable bytes is most likely to be accurate immediately
|
||||
* after the space attributes are obtained. It is likely to be made inaccurate
|
||||
* by any external I/O operations including those made on the system outside
|
||||
* of this Java virtual machine.
|
||||
*
|
||||
* @return the number of bytes available
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public abstract long getUsableSpace() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the number of unallocated bytes in the file store.
|
||||
*
|
||||
* <p> The returned number of unallocated bytes is a hint, but not a
|
||||
* guarantee, that it is possible to use most or any of these bytes. The
|
||||
* number of unallocated bytes is most likely to be accurate immediately
|
||||
* after the space attributes are obtained. It is likely to be
|
||||
* made inaccurate by any external I/O operations including those made on
|
||||
* the system outside of this virtual machine.
|
||||
*
|
||||
* @return the number of unallocated bytes
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public abstract long getUnallocatedSpace() throws IOException;
|
||||
|
||||
/**
|
||||
* Tells whether or not this file store supports the file attributes
|
||||
* identified by the given file attribute view.
|
||||
@ -131,12 +173,6 @@ public abstract class FileStore {
|
||||
* The {@code type} parameter is the type of the attribute view required and
|
||||
* the method returns an instance of that type if supported.
|
||||
*
|
||||
* <p> For {@code FileStore} objects created by the default provider, then
|
||||
* the file stores support the {@link FileStoreSpaceAttributeView} that
|
||||
* provides access to space attributes. In that case invoking this method
|
||||
* with a parameter value of {@code FileStoreSpaceAttributeView.class} will
|
||||
* always return an instance of that class.
|
||||
*
|
||||
* @param type
|
||||
* the {@code Class} object corresponding to the attribute view
|
||||
*
|
||||
@ -160,10 +196,6 @@ public abstract class FileStore {
|
||||
* a {@link FileStore AttributeView} that identifies a set of file attributes.
|
||||
* <i>attribute-name</i> is the name of the attribute.
|
||||
*
|
||||
* <p> For {@code FileStore} objects created by the default provider, then
|
||||
* the file stores support the {@link FileStoreSpaceAttributeView} that
|
||||
* provides access to space attributes.
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we want to know if ZFS compression is enabled (assuming the "zfs"
|
||||
* view is supported):
|
||||
|
@ -38,8 +38,8 @@ import java.io.IOException;
|
||||
* <p> The default file system, obtained by invoking the {@link FileSystems#getDefault
|
||||
* FileSystems.getDefault} method, provides access to the file system that is
|
||||
* accessible to the Java virtual machine. The {@link FileSystems} class defines
|
||||
* methods to create file systems that provide access to other types of file
|
||||
* systems.
|
||||
* methods to create file systems that provide access to other types of (custom)
|
||||
* file systems.
|
||||
*
|
||||
* <p> A file system is the factory for several types of objects:
|
||||
*
|
||||
@ -214,10 +214,9 @@ public abstract class FileSystem
|
||||
* Suppose we want to print the space usage for all file stores:
|
||||
* <pre>
|
||||
* for (FileStore store: FileSystems.getDefault().getFileStores()) {
|
||||
* FileStoreSpaceAttributes attrs = Attributes.readFileStoreSpaceAttributes(store);
|
||||
* long total = attrs.totalSpace() / 1024;
|
||||
* long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / 1024;
|
||||
* long avail = attrs.usableSpace() / 1024;
|
||||
* long total = store.getTotalSpace() / 1024;
|
||||
* long used = (store.getTotalSpace() - store.getUnallocatedSpace()) / 1024;
|
||||
* long avail = store.getUsableSpace() / 1024;
|
||||
* System.out.format("%-20s %12d %12d %12d%n", store, total, used, avail);
|
||||
* }
|
||||
* </pre>
|
||||
@ -244,7 +243,20 @@ public abstract class FileSystem
|
||||
public abstract Set<String> supportedFileAttributeViews();
|
||||
|
||||
/**
|
||||
* Converts a path string to a {@code Path}.
|
||||
* Converts a path string, or a sequence of strings that when joined form
|
||||
* a path string, to a {@code Path}. If {@code more} does not specify any
|
||||
* elements then the value of the {@code first} parameter is the path string
|
||||
* to convert. If {@code more} specifies one or more elements then each
|
||||
* non-empty string, including {@code first}, is considered to be a sequence
|
||||
* of name elements (see {@link Path}) and is joined to form a path string.
|
||||
* The details as to how the Strings are joined is provider specific but
|
||||
* typically they will be joined using the {@link #getSeparator
|
||||
* name-separator} as the separator. For example, if the name separator is
|
||||
* "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the
|
||||
* path string {@code "/foo/bar/gus"} is converted to a {@code Path}.
|
||||
* A {@code Path} representing an empty path is returned if {@code first}
|
||||
* is the empty string and {@code more} does not contain any non-empty
|
||||
* strings.
|
||||
*
|
||||
* <p> The parsing and conversion to a path object is inherently
|
||||
* implementation dependent. In the simplest case, the path string is rejected,
|
||||
@ -270,18 +282,17 @@ public abstract class FileSystem
|
||||
* index} value indicating the first position in the {@code path} parameter
|
||||
* that caused the path string to be rejected.
|
||||
*
|
||||
* <p> Invoking this method with an empty path string throws
|
||||
* {@code InvalidPathException}.
|
||||
* @param first
|
||||
* the path string or initial part of the path string
|
||||
* @param more
|
||||
* additional strings to be joined to form the path string
|
||||
*
|
||||
* @param path
|
||||
* The path string
|
||||
*
|
||||
* @return A {@code Path} object
|
||||
* @return the resulting {@code Path}
|
||||
*
|
||||
* @throws InvalidPathException
|
||||
* If the path string cannot be converted
|
||||
*/
|
||||
public abstract Path getPath(String path);
|
||||
public abstract Path getPath(String first, String... more);
|
||||
|
||||
/**
|
||||
* Returns a {@code PathMatcher} that performs match operations on the
|
||||
@ -290,9 +301,9 @@ public abstract class FileSystem
|
||||
*
|
||||
* The {@code syntaxAndPattern} parameter identifies the syntax and the
|
||||
* pattern and takes the form:
|
||||
* <blockquote>
|
||||
* <blockquote><pre>
|
||||
* <i>syntax</i><b>:</b><i>pattern</i>
|
||||
* </blockquote>
|
||||
* </pre></blockquote>
|
||||
* where {@code ':'} stands for itself.
|
||||
*
|
||||
* <p> A {@code FileSystem} implementation supports the "{@code glob}" and
|
||||
@ -409,7 +420,7 @@ public abstract class FileSystem
|
||||
* @throws UnsupportedOperationException
|
||||
* If the pattern syntax is not known to the implementation
|
||||
*
|
||||
* @see Path#newDirectoryStream(String)
|
||||
* @see Files#newDirectoryStream(Path,String)
|
||||
*/
|
||||
public abstract PathMatcher getPathMatcher(String syntaxAndPattern);
|
||||
|
||||
@ -421,10 +432,8 @@ public abstract class FileSystem
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we want to make "joe" the owner of a file:
|
||||
* <pre>
|
||||
* Path file = ...
|
||||
* UserPrincipal joe = file.getFileSystem().getUserPrincipalLookupService()
|
||||
* .lookupPrincipalByName("joe");
|
||||
* Attributes.setOwner(file, joe);
|
||||
* UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService();
|
||||
* Files.setOwner(path, lookupService.lookupPrincipalByName("joe"));
|
||||
* </pre>
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
|
@ -164,8 +164,8 @@ public final class FileSystems {
|
||||
* to the first provider instance. The third provider class is instantiated
|
||||
* by invoking it with a reference to the second instance, and so on. The
|
||||
* last provider to be instantiated becomes the default provider; its {@code
|
||||
* getFileSystem} method is invoked with the URI {@code "file:///"} to create
|
||||
* the default file system.
|
||||
* getFileSystem} method is invoked with the URI {@code "file:///"} to
|
||||
* get a reference to the default file system.
|
||||
*
|
||||
* <p> Subsequent invocations of this method return the file system that was
|
||||
* returned by the first invocation.
|
||||
@ -238,7 +238,7 @@ public final class FileSystems {
|
||||
* Suppose there is a provider identified by the scheme {@code "memory"}
|
||||
* installed:
|
||||
* <pre>
|
||||
* Map<String,String> env = new HashMap<String,String>();
|
||||
* Map<String,String> env = new HashMap<>();
|
||||
* env.put("capacity", "16G");
|
||||
* env.put("blockSize", "4k");
|
||||
* FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env);
|
||||
@ -343,33 +343,25 @@ public final class FileSystems {
|
||||
*
|
||||
* <p> This method makes use of specialized providers that create pseudo file
|
||||
* systems where the contents of one or more files is treated as a file
|
||||
* system. The {@code file} parameter is a reference to an existing file
|
||||
* and the {@code env} parameter is a map of provider specific properties to
|
||||
* configure the file system.
|
||||
* system.
|
||||
*
|
||||
* <p> This method iterates over the {@link FileSystemProvider#installedProviders()
|
||||
* installed} providers. It invokes, in turn, each provider's {@link
|
||||
* FileSystemProvider#newFileSystem(FileRef,Map) newFileSystem(FileRef,Map)} method.
|
||||
* If a provider returns a file system then the iteration terminates
|
||||
* and the file system is returned. If none of the installed providers return
|
||||
* a {@code FileSystem} then an attempt is made to locate the provider using
|
||||
* the given class loader. If a provider returns a file system then the lookup
|
||||
* terminates and the file system is returned.
|
||||
* FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method
|
||||
* with an empty map. If a provider returns a file system then the iteration
|
||||
* terminates and the file system is returned. If none of the installed
|
||||
* providers return a {@code FileSystem} then an attempt is made to locate
|
||||
* the provider using the given class loader. If a provider returns a file
|
||||
* system then the lookup terminates and the file system is returned.
|
||||
*
|
||||
* @param file
|
||||
* a reference to a file
|
||||
* @param env
|
||||
* a map of provider specific properties to configure the file system;
|
||||
* may be empty
|
||||
* @param path
|
||||
* the path to the file
|
||||
* @param loader
|
||||
* the class loader to locate the provider or {@code null} to only
|
||||
* attempt to locate an installed provider
|
||||
*
|
||||
* @return a new file system
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code env} parameter does not contain properties required
|
||||
* by the provider, or a property value is invalid
|
||||
* @throws ProviderNotFoundException
|
||||
* if a provider supporting this file type cannot be located
|
||||
* @throws ServiceConfigurationError
|
||||
@ -380,18 +372,18 @@ public final class FileSystems {
|
||||
* if a security manager is installed and it denies an unspecified
|
||||
* permission
|
||||
*/
|
||||
public static FileSystem newFileSystem(FileRef file,
|
||||
Map<String,?> env,
|
||||
public static FileSystem newFileSystem(Path path,
|
||||
ClassLoader loader)
|
||||
throws IOException
|
||||
{
|
||||
if (file == null)
|
||||
if (path == null)
|
||||
throw new NullPointerException();
|
||||
Map<String,?> env = Collections.emptyMap();
|
||||
|
||||
// check installed providers
|
||||
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
|
||||
try {
|
||||
return provider.newFileSystem(file, env);
|
||||
return provider.newFileSystem(path, env);
|
||||
} catch (UnsupportedOperationException uoe) {
|
||||
}
|
||||
}
|
||||
@ -402,7 +394,7 @@ public final class FileSystems {
|
||||
.load(FileSystemProvider.class, loader);
|
||||
for (FileSystemProvider provider: sl) {
|
||||
try {
|
||||
return provider.newFileSystem(file, env);
|
||||
return provider.newFileSystem(path, env);
|
||||
} catch (UnsupportedOperationException uoe) {
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,8 @@ class FileTreeWalker {
|
||||
FileVisitResult result = walk(start,
|
||||
0,
|
||||
new ArrayList<AncestorDirectory>());
|
||||
Objects.nonNull(result, "FileVisitor returned null");
|
||||
if (result == null)
|
||||
throw new NullPointerException("FileVisitor returned null");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,12 +103,13 @@ class FileTreeWalker {
|
||||
if (attrs == null) {
|
||||
try {
|
||||
try {
|
||||
attrs = Attributes.readBasicFileAttributes(file, linkOptions);
|
||||
attrs = Files.readAttributes(file, BasicFileAttributes.class, linkOptions);
|
||||
} catch (IOException x1) {
|
||||
if (followLinks) {
|
||||
try {
|
||||
attrs = Attributes
|
||||
.readBasicFileAttributes(file, LinkOption.NOFOLLOW_LINKS);
|
||||
attrs = Files.readAttributes(file,
|
||||
BasicFileAttributes.class,
|
||||
LinkOption.NOFOLLOW_LINKS);
|
||||
} catch (IOException x2) {
|
||||
exc = x2;
|
||||
}
|
||||
@ -151,7 +153,7 @@ class FileTreeWalker {
|
||||
} else {
|
||||
boolean isSameFile = false;
|
||||
try {
|
||||
isSameFile = file.isSameFile(ancestor.file());
|
||||
isSameFile = Files.isSameFile(file, ancestor.file());
|
||||
} catch (IOException x) {
|
||||
// ignore
|
||||
} catch (SecurityException x) {
|
||||
@ -175,7 +177,7 @@ class FileTreeWalker {
|
||||
|
||||
// open the directory
|
||||
try {
|
||||
stream = file.newDirectoryStream();
|
||||
stream = Files.newDirectoryStream(file);
|
||||
} catch (IOException x) {
|
||||
return visitor.visitFileFailed(file, x);
|
||||
} catch (SecurityException x) {
|
||||
@ -212,7 +214,11 @@ class FileTreeWalker {
|
||||
} finally {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException x) { }
|
||||
} catch (IOException e) {
|
||||
// IOException will be notified to postVisitDirectory
|
||||
if (ioe == null)
|
||||
ioe = e;
|
||||
}
|
||||
}
|
||||
|
||||
// invoke postVisitDirectory last
|
||||
|
@ -30,8 +30,8 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A visitor of files. An implementation of this interface is provided to the
|
||||
* {@link Files#walkFileTree walkFileTree} utility method to visit each file
|
||||
* in a tree.
|
||||
* {@link Files#walkFileTree Files.walkFileTree} methods to visit each file in
|
||||
* a file tree.
|
||||
*
|
||||
* <p> <b>Usage Examples:</b>
|
||||
* Suppose we want to delete a file tree. In that case, each directory should
|
||||
@ -43,19 +43,20 @@ import java.io.IOException;
|
||||
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||
* throws IOException
|
||||
* {
|
||||
* file.delete();
|
||||
* Files.delete(file);
|
||||
* return FileVisitResult.CONTINUE;
|
||||
* }
|
||||
* @Override
|
||||
* public FileVisitResult postVisitDirectory(Path dir, IOException e)
|
||||
* throws IOException
|
||||
* {
|
||||
* if (e != null) {
|
||||
* if (e == null) {
|
||||
* Files.delete(dir);
|
||||
* return FileVisitResult.CONTINUE;
|
||||
* } else {
|
||||
* // directory iteration failed
|
||||
* throw e;
|
||||
* }
|
||||
* dir.delete();
|
||||
* return FileVisitResult.CONTINUE;
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
@ -72,10 +73,12 @@ import java.io.IOException;
|
||||
* public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
|
||||
* throws IOException
|
||||
* {
|
||||
* Path targetdir = target.resolve(source.relativize(dir));
|
||||
* try {
|
||||
* dir.copyTo(target.resolve(source.relativize(dir)));
|
||||
* Files.copy(dir, targetdir);
|
||||
* } catch (FileAlreadyExistsException e) {
|
||||
* // ignore
|
||||
* if (!Files.isDirectory(targetdir))
|
||||
* throw e;
|
||||
* }
|
||||
* return CONTINUE;
|
||||
* }
|
||||
@ -83,7 +86,7 @@ import java.io.IOException;
|
||||
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||
* throws IOException
|
||||
* {
|
||||
* file.copyTo(target.resolve(source.relativize(file)));
|
||||
* Files.copy(file, target.resolve(source.relativize(file)));
|
||||
* return CONTINUE;
|
||||
* }
|
||||
* });
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,8 +35,8 @@ public enum LinkOption implements OpenOption, CopyOption {
|
||||
/**
|
||||
* Do not follow symbolic links.
|
||||
*
|
||||
* @see FileRef#getFileAttributeView(Class,LinkOption[])
|
||||
* @see Path#copyTo
|
||||
* @see Files#getFileAttributeView(Path,Class,LinkOption[])
|
||||
* @see Files#copy
|
||||
* @see SecureDirectoryStream#newByteChannel
|
||||
*/
|
||||
NOFOLLOW_LINKS;
|
||||
|
@ -59,8 +59,8 @@ import java.security.BasicPermission;
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Path#createLink
|
||||
* @see Path#createSymbolicLink
|
||||
* @see Files#createLink
|
||||
* @see Files#createSymbolicLink
|
||||
*/
|
||||
public final class LinkPermission extends BasicPermission {
|
||||
static final long serialVersionUID = -1441492453772213220L;
|
||||
|
@ -29,8 +29,8 @@ package java.nio.file;
|
||||
* An object that configures how to open or create a file.
|
||||
*
|
||||
* <p> Objects of this type are used by methods such as {@link
|
||||
* Path#newOutputStream(OpenOption[]) newOutputStream}, {@link
|
||||
* Path#newByteChannel newByteChannel}, {@link
|
||||
* Files#newOutputStream(Path,OpenOption[]) newOutputStream}, {@link
|
||||
* Files#newByteChannel newByteChannel}, {@link
|
||||
* java.nio.channels.FileChannel#open FileChannel.open}, and {@link
|
||||
* java.nio.channels.AsynchronousFileChannel#open AsynchronousFileChannel.open}
|
||||
* when opening or creating a file.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,7 @@ package java.nio.file;
|
||||
* @since 1.7
|
||||
*
|
||||
* @see FileSystem#getPathMatcher
|
||||
* @see Path#newDirectoryStream(String)
|
||||
* @see Files#newDirectoryStream(Path,String)
|
||||
*/
|
||||
|
||||
public interface PathMatcher {
|
||||
|
@ -39,14 +39,27 @@ public final class Paths {
|
||||
private Paths() { }
|
||||
|
||||
/**
|
||||
* Constructs a {@code Path} by converting the given path string.
|
||||
* Converts a path string, or a sequence of strings that when joined form
|
||||
* a path string, to a {@code Path}. If {@code more} does not specify any
|
||||
* elements then the value of the {@code first} parameter is the path string
|
||||
* to convert. If {@code more} specifies one or more elements then each
|
||||
* non-empty string, including {@code first}, is considered to be a sequence
|
||||
* of name elements (see {@link Path}) and is joined to form a path string.
|
||||
* The details as to how the Strings are joined is provider specific but
|
||||
* typically they will be joined using the {@link FileSystem#getSeparator
|
||||
* name-separator} as the separator. For example, if the name separator is
|
||||
* "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the
|
||||
* path string {@code "/foo/bar/gus"} is converted to a {@code Path}.
|
||||
* A {@code Path} representing an empty path is returned if {@code first}
|
||||
* is the empty string and {@code more} does not contain any non-empty
|
||||
* strings.
|
||||
*
|
||||
* <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
|
||||
* getPath} method of the {@link FileSystems#getDefault default} {@link
|
||||
* FileSystem}.
|
||||
*
|
||||
* <p> Note that while this method is very convenient, using it will
|
||||
* imply an assumed reference to the default FileSystem and limit the
|
||||
* <p> Note that while this method is very convenient, using it will imply
|
||||
* an assumed reference to the default {@code FileSystem} and limit the
|
||||
* utility of the calling code. Hence it should not be used in library code
|
||||
* intended for flexible reuse. A more flexible alternative is to use an
|
||||
* existing {@code Path} instance as an anchor, such as:
|
||||
@ -55,8 +68,10 @@ public final class Paths {
|
||||
* Path path = dir.resolve("file");
|
||||
* </pre>
|
||||
*
|
||||
* @param path
|
||||
* the path string to convert
|
||||
* @param first
|
||||
* the path string or initial part of the path string
|
||||
* @param more
|
||||
* additional strings to be joined to form the path string
|
||||
*
|
||||
* @return the resulting {@code Path}
|
||||
*
|
||||
@ -65,8 +80,8 @@ public final class Paths {
|
||||
*
|
||||
* @see FileSystem#getPath
|
||||
*/
|
||||
public static Path get(String path) {
|
||||
return FileSystems.getDefault().getPath(path);
|
||||
public static Path get(String first, String... more) {
|
||||
return FileSystems.getDefault().getPath(first, more);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +43,7 @@ import java.io.IOException;
|
||||
*
|
||||
* <p> A {@code SecureDirectoryStream} requires corresponding support from the
|
||||
* underlying operating system. Where an implementation supports this features
|
||||
* then the {@code DirectoryStream} returned by the {@link Path#newDirectoryStream
|
||||
* then the {@code DirectoryStream} returned by the {@link Files#newDirectoryStream
|
||||
* newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
|
||||
* be cast to that type in order to invoke the methods defined by this interface.
|
||||
*
|
||||
@ -56,20 +56,15 @@ import java.io.IOException;
|
||||
* @since 1.7
|
||||
*/
|
||||
|
||||
public abstract class SecureDirectoryStream<T>
|
||||
implements DirectoryStream<T>
|
||||
public interface SecureDirectoryStream<T>
|
||||
extends DirectoryStream<T>
|
||||
{
|
||||
/**
|
||||
* Initialize a new instance of this class.
|
||||
*/
|
||||
protected SecureDirectoryStream() { }
|
||||
|
||||
/**
|
||||
* Opens the directory identified by the given path, returning a {@code
|
||||
* SecureDirectoryStream} to iterate over the entries in the directory.
|
||||
*
|
||||
* <p> This method works in exactly the manner specified by the {@link
|
||||
* Path#newDirectoryStream() newDirectoryStream} method for the case that
|
||||
* Files#newDirectoryStream(Path) newDirectoryStream} method for the case that
|
||||
* the {@code path} parameter is an {@link Path#isAbsolute absolute} path.
|
||||
* When the parameter is a relative path then the directory to open is
|
||||
* relative to this open directory. The {@link
|
||||
@ -99,8 +94,7 @@ public abstract class SecureDirectoryStream<T>
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the directory.
|
||||
*/
|
||||
public abstract SecureDirectoryStream<T> newDirectoryStream(T path,
|
||||
LinkOption... options)
|
||||
SecureDirectoryStream<T> newDirectoryStream(T path, LinkOption... options)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
@ -108,11 +102,11 @@ public abstract class SecureDirectoryStream<T>
|
||||
* channel to access the file.
|
||||
*
|
||||
* <p> This method works in exactly the manner specified by the {@link
|
||||
* Path#newByteChannel Path.newByteChannel} method for the
|
||||
* Files#newByteChannel Files.newByteChannel} method for the
|
||||
* case that the {@code path} parameter is an {@link Path#isAbsolute absolute}
|
||||
* path. When the parameter is a relative path then the file to open or
|
||||
* create is relative to this open directory. In addition to the options
|
||||
* defined by the {@code Path.newByteChannel} method, the {@link
|
||||
* defined by the {@code Files.newByteChannel} method, the {@link
|
||||
* LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} option may be used to
|
||||
* ensure that this method fails if the file is a symbolic link.
|
||||
*
|
||||
@ -149,15 +143,15 @@ public abstract class SecureDirectoryStream<T>
|
||||
* checkWrite} method is invoked to check write access to the path
|
||||
* if the file is opened for writing.
|
||||
*/
|
||||
public abstract SeekableByteChannel newByteChannel(T path,
|
||||
Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
SeekableByteChannel newByteChannel(T path,
|
||||
Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Deletes a file.
|
||||
*
|
||||
* <p> Unlike the {@link Path#delete delete()} method, this method does
|
||||
* <p> Unlike the {@link Files#delete delete()} method, this method does
|
||||
* not first examine the file to determine if the file is a directory.
|
||||
* Whether a directory is deleted by this method is system dependent and
|
||||
* therefore not specified. If the file is a symbolic link, then the link
|
||||
@ -179,12 +173,12 @@ public abstract class SecureDirectoryStream<T>
|
||||
* installed, the {@link SecurityManager#checkDelete(String) checkDelete}
|
||||
* method is invoked to check delete access to the file
|
||||
*/
|
||||
public abstract void deleteFile(T path) throws IOException;
|
||||
void deleteFile(T path) throws IOException;
|
||||
|
||||
/**
|
||||
* Deletes a directory.
|
||||
*
|
||||
* <p> Unlike the {@link Path#delete delete()} method, this method
|
||||
* <p> Unlike the {@link Files#delete delete()} method, this method
|
||||
* does not first examine the file to determine if the file is a directory.
|
||||
* Whether non-directories are deleted by this method is system dependent and
|
||||
* therefore not specified. When the parameter is a relative path then the
|
||||
@ -207,12 +201,12 @@ public abstract class SecureDirectoryStream<T>
|
||||
* installed, the {@link SecurityManager#checkDelete(String) checkDelete}
|
||||
* method is invoked to check delete access to the directory
|
||||
*/
|
||||
public abstract void deleteDirectory(T path) throws IOException;
|
||||
void deleteDirectory(T path) throws IOException;
|
||||
|
||||
/**
|
||||
* Move a file from this directory to another directory.
|
||||
*
|
||||
* <p> This method works in a similar manner to {@link Path#moveTo moveTo}
|
||||
* <p> This method works in a similar manner to {@link Files#move move}
|
||||
* method when the {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} option
|
||||
* is specified. That is, this method moves a file as an atomic file system
|
||||
* operation. If the {@code srcpath} parameter is an {@link Path#isAbsolute
|
||||
@ -247,7 +241,7 @@ public abstract class SecureDirectoryStream<T>
|
||||
* method is invoked to check write access to both the source and
|
||||
* target file.
|
||||
*/
|
||||
public abstract void move(T srcpath, SecureDirectoryStream<T> targetdir, T targetpath)
|
||||
void move(T srcpath, SecureDirectoryStream<T> targetdir, T targetpath)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
@ -273,7 +267,7 @@ public abstract class SecureDirectoryStream<T>
|
||||
* this directory stream, or {@code null} if the attribute view
|
||||
* type is not available
|
||||
*/
|
||||
public abstract <V extends FileAttributeView> V getFileAttributeView(Class<V> type);
|
||||
<V extends FileAttributeView> V getFileAttributeView(Class<V> type);
|
||||
|
||||
/**
|
||||
* Returns a new file attribute view to access the file attributes of a file
|
||||
@ -306,7 +300,7 @@ public abstract class SecureDirectoryStream<T>
|
||||
* type is not available
|
||||
*
|
||||
*/
|
||||
public abstract <V extends FileAttributeView> V getFileAttributeView(T path,
|
||||
Class<V> type,
|
||||
LinkOption... options);
|
||||
<V extends FileAttributeView> V getFileAttributeView(T path,
|
||||
Class<V> type,
|
||||
LinkOption... options);
|
||||
}
|
||||
|
@ -23,54 +23,82 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.io;
|
||||
package java.nio.file;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.util.Set;
|
||||
import java.util.EnumSet;
|
||||
import java.security.SecureRandom;
|
||||
import static java.security.AccessController.*;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import static java.nio.file.attribute.PosixFilePermission.*;
|
||||
import java.util.Set;
|
||||
import java.util.EnumSet;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to support creation of temporary files and directory with
|
||||
* Helper class to support creation of temporary files and directories with
|
||||
* initial attributes.
|
||||
*/
|
||||
|
||||
class TempFileHelper {
|
||||
private TempFileHelper() { }
|
||||
|
||||
// temporary directory location
|
||||
private static final Path tmpdir =
|
||||
Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir")));
|
||||
|
||||
private static final boolean isPosix =
|
||||
FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
|
||||
|
||||
// file name generation, same as java.io.File for now
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
private static Path generatePath(String prefix, String suffix, Path dir) {
|
||||
long n = random.nextLong();
|
||||
n = (n == Long.MIN_VALUE) ? 0 : Math.abs(n);
|
||||
Path name = dir.getFileSystem().getPath(prefix + Long.toString(n) + suffix);
|
||||
// the generated name should be a simple file name
|
||||
if (name.getParent() != null)
|
||||
throw new IllegalArgumentException("Invalid prefix or suffix");
|
||||
return dir.resolve(name);
|
||||
}
|
||||
|
||||
// default file and directory permissions (lazily initialized)
|
||||
private static class PermissionsHolder {
|
||||
static final boolean hasPosixPermissions = FileSystems.getDefault()
|
||||
.supportedFileAttributeViews().contains("posix");
|
||||
private static class PosixPermissions {
|
||||
static final FileAttribute<Set<PosixFilePermission>> filePermissions =
|
||||
PosixFilePermissions.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE));
|
||||
static final FileAttribute<Set<PosixFilePermission>> directoryPermissions =
|
||||
static final FileAttribute<Set<PosixFilePermission>> dirPermissions =
|
||||
PosixFilePermissions.asFileAttribute(EnumSet
|
||||
.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file or directory in the temporary directory.
|
||||
* Creates a file or directory in in the given given directory (or in the
|
||||
* temporary directory if dir is {@code null}).
|
||||
*/
|
||||
private static File create(String prefix,
|
||||
private static Path create(Path dir,
|
||||
String prefix,
|
||||
String suffix,
|
||||
FileAttribute[] attrs,
|
||||
boolean isDirectory)
|
||||
boolean createDirectory,
|
||||
FileAttribute[] attrs)
|
||||
throws IOException
|
||||
{
|
||||
if (prefix == null)
|
||||
prefix = "";
|
||||
if (suffix == null)
|
||||
suffix = (createDirectory) ? "" : ".tmp";
|
||||
if (dir == null)
|
||||
dir = tmpdir;
|
||||
|
||||
// in POSIX environments use default file and directory permissions
|
||||
// if initial permissions not given by caller.
|
||||
if (PermissionsHolder.hasPosixPermissions) {
|
||||
if (isPosix && (dir.getFileSystem() == FileSystems.getDefault())) {
|
||||
if (attrs.length == 0) {
|
||||
// no attributes so use default permissions
|
||||
attrs = new FileAttribute<?>[1];
|
||||
attrs[0] = (isDirectory) ? PermissionsHolder.directoryPermissions :
|
||||
PermissionsHolder.filePermissions;
|
||||
attrs[0] = (createDirectory) ? PosixPermissions.dirPermissions :
|
||||
PosixPermissions.filePermissions;
|
||||
} else {
|
||||
// check if posix permissions given; if not use default
|
||||
boolean hasPermissions = false;
|
||||
@ -84,9 +112,9 @@ class TempFileHelper {
|
||||
FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length+1];
|
||||
System.arraycopy(attrs, 0, copy, 0, attrs.length);
|
||||
attrs = copy;
|
||||
attrs[attrs.length-1] = (isDirectory) ?
|
||||
PermissionsHolder.directoryPermissions :
|
||||
PermissionsHolder.filePermissions;
|
||||
attrs[attrs.length-1] = (createDirectory) ?
|
||||
PosixPermissions.dirPermissions :
|
||||
PosixPermissions.filePermissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,24 +122,25 @@ class TempFileHelper {
|
||||
// loop generating random names until file or directory can be created
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
for (;;) {
|
||||
File tmpdir = File.TempDirectory.location();
|
||||
File f = File.TempDirectory.generateFile(prefix, suffix, tmpdir);
|
||||
Path f;
|
||||
try {
|
||||
if (isDirectory) {
|
||||
f.toPath().createDirectory(attrs);
|
||||
} else {
|
||||
f.toPath().createFile(attrs);
|
||||
}
|
||||
return f;
|
||||
f = generatePath(prefix, suffix, dir);
|
||||
} catch (InvalidPathException e) {
|
||||
// don't reveal temporary directory location
|
||||
if (sm != null)
|
||||
throw new IllegalArgumentException("Invalid prefix or suffix");
|
||||
throw e;
|
||||
}
|
||||
try {
|
||||
if (createDirectory) {
|
||||
return Files.createDirectory(f, attrs);
|
||||
} else {
|
||||
return Files.createFile(f, attrs);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// don't reveal temporary directory location
|
||||
if (sm != null)
|
||||
throw new SecurityException("Unable to create temporary file");
|
||||
if (dir == tmpdir && sm != null)
|
||||
throw new SecurityException("Unable to create temporary file or directory");
|
||||
throw e;
|
||||
} catch (FileAlreadyExistsException e) {
|
||||
// ignore
|
||||
@ -120,20 +149,27 @@ class TempFileHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file in the temporary directory.
|
||||
* Creates a temporary file in the given directory, or in in the
|
||||
* temporary directory if dir is {@code null}.
|
||||
*/
|
||||
static File createFile(String prefix, String suffix, FileAttribute[] attrs)
|
||||
static Path createTempFile(Path dir,
|
||||
String prefix,
|
||||
String suffix,
|
||||
FileAttribute[] attrs)
|
||||
throws IOException
|
||||
{
|
||||
return create(prefix, suffix, attrs, false);
|
||||
return create(dir, prefix, suffix, false, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a directory in the temporary directory.
|
||||
* Creates a temporary directory in the given directory, or in in the
|
||||
* temporary directory if dir is {@code null}.
|
||||
*/
|
||||
static File createDirectory(String prefix, FileAttribute[] attrs)
|
||||
static Path createTempDirectory(Path dir,
|
||||
String prefix,
|
||||
FileAttribute[] attrs)
|
||||
throws IOException
|
||||
{
|
||||
return create(prefix, "", attrs, true);
|
||||
return create(dir, prefix, null, true, attrs);
|
||||
}
|
||||
}
|
@ -44,7 +44,7 @@ package java.nio.file;
|
||||
* @since 1.7
|
||||
*/
|
||||
|
||||
public abstract class WatchEvent<T> {
|
||||
public interface WatchEvent<T> {
|
||||
|
||||
/**
|
||||
* An event kind, for the purposes of identification.
|
||||
@ -64,11 +64,6 @@ public abstract class WatchEvent<T> {
|
||||
Class<T> type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected WatchEvent() { }
|
||||
|
||||
/**
|
||||
* An event modifier that qualifies how a {@link Watchable} is registered
|
||||
* with a {@link WatchService}.
|
||||
@ -90,7 +85,7 @@ public abstract class WatchEvent<T> {
|
||||
*
|
||||
* @return the event kind
|
||||
*/
|
||||
public abstract Kind<T> kind();
|
||||
Kind<T> kind();
|
||||
|
||||
/**
|
||||
* Returns the event count. If the event count is greater than {@code 1}
|
||||
@ -98,7 +93,7 @@ public abstract class WatchEvent<T> {
|
||||
*
|
||||
* @return the event count
|
||||
*/
|
||||
public abstract int count();
|
||||
int count();
|
||||
|
||||
/**
|
||||
* Returns the context for the event.
|
||||
@ -112,5 +107,5 @@ public abstract class WatchEvent<T> {
|
||||
*
|
||||
* @return the event context; may be {@code null}
|
||||
*/
|
||||
public abstract T context();
|
||||
T context();
|
||||
}
|
||||
|
@ -81,11 +81,7 @@ import java.util.List;
|
||||
* @since 1.7
|
||||
*/
|
||||
|
||||
public abstract class WatchKey {
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected WatchKey() { }
|
||||
public interface WatchKey {
|
||||
|
||||
/**
|
||||
* Tells whether or not this watch key is valid.
|
||||
@ -95,7 +91,7 @@ public abstract class WatchKey {
|
||||
*
|
||||
* @return {@code true} if, and only if, this watch key is valid
|
||||
*/
|
||||
public abstract boolean isValid();
|
||||
boolean isValid();
|
||||
|
||||
/**
|
||||
* Retrieves and removes all pending events for this watch key, returning
|
||||
@ -105,7 +101,7 @@ public abstract class WatchKey {
|
||||
*
|
||||
* @return the list of the events retrieved; may be empty
|
||||
*/
|
||||
public abstract List<WatchEvent<?>> pollEvents();
|
||||
List<WatchEvent<?>> pollEvents();
|
||||
|
||||
/**
|
||||
* Resets this watch key.
|
||||
@ -121,7 +117,7 @@ public abstract class WatchKey {
|
||||
* {@code false} if the watch key could not be reset because it is
|
||||
* no longer {@link #isValid valid}
|
||||
*/
|
||||
public abstract boolean reset();
|
||||
boolean reset();
|
||||
|
||||
/**
|
||||
* Cancels the registration with the watch service. Upon return the watch key
|
||||
@ -134,5 +130,21 @@ public abstract class WatchKey {
|
||||
* <p> If this watch key has already been cancelled then invoking this
|
||||
* method has no effect. Once cancelled, a watch key remains forever invalid.
|
||||
*/
|
||||
public abstract void cancel();
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Returns the object for which this watch key was created. This method will
|
||||
* continue to return the object even after the key is cancelled.
|
||||
*
|
||||
* <p> As the {@code WatchService} is intended to map directly on to the
|
||||
* native file event notification facility (where available) then many of
|
||||
* details on how registered objects are watched is highly implementation
|
||||
* specific. When watching a directory for changes for example, and the
|
||||
* directory is moved or renamed in the file system, there is no guarantee
|
||||
* that the watch key will be cancelled and so the object returned by this
|
||||
* method may no longer be a valid path to the directory.
|
||||
*
|
||||
* @return the object for which this watch key was created
|
||||
*/
|
||||
//T watchable();
|
||||
}
|
||||
|
@ -103,13 +103,9 @@ import java.util.concurrent.TimeUnit;
|
||||
* @see FileSystem#newWatchService
|
||||
*/
|
||||
|
||||
public abstract class WatchService
|
||||
implements Closeable
|
||||
public interface WatchService
|
||||
extends Closeable
|
||||
{
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected WatchService() { }
|
||||
|
||||
/**
|
||||
* Closes this watch service.
|
||||
@ -129,7 +125,7 @@ public abstract class WatchService
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
@Override
|
||||
public abstract void close() throws IOException;
|
||||
void close() throws IOException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the next watch key, or {@code null} if none are
|
||||
@ -140,7 +136,7 @@ public abstract class WatchService
|
||||
* @throws ClosedWatchServiceException
|
||||
* if this watch service is closed
|
||||
*/
|
||||
public abstract WatchKey poll();
|
||||
WatchKey poll();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the next watch key, waiting if necessary up to the
|
||||
@ -160,7 +156,7 @@ public abstract class WatchService
|
||||
* @throws InterruptedException
|
||||
* if interrupted while waiting
|
||||
*/
|
||||
public abstract WatchKey poll(long timeout, TimeUnit unit)
|
||||
WatchKey poll(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
@ -174,5 +170,5 @@ public abstract class WatchService
|
||||
* @throws InterruptedException
|
||||
* if interrupted while waiting
|
||||
*/
|
||||
public abstract WatchKey take() throws InterruptedException;
|
||||
WatchKey take() throws InterruptedException;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ public final class AclEntry {
|
||||
*/
|
||||
public Builder setPermissions(Set<AclEntryPermission> perms) {
|
||||
// copy and check for erroneous elements
|
||||
perms = new HashSet<AclEntryPermission>(perms);
|
||||
perms = EnumSet.copyOf(perms);
|
||||
checkSet(perms, AclEntryPermission.class);
|
||||
this.perms = perms;
|
||||
return this;
|
||||
@ -190,8 +190,7 @@ public final class AclEntry {
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder setPermissions(AclEntryPermission... perms) {
|
||||
Set<AclEntryPermission> set =
|
||||
new HashSet<AclEntryPermission>(perms.length);
|
||||
Set<AclEntryPermission> set = EnumSet.noneOf(AclEntryPermission.class);
|
||||
// copy and check for null elements
|
||||
for (AclEntryPermission p: perms) {
|
||||
if (p == null)
|
||||
@ -214,7 +213,7 @@ public final class AclEntry {
|
||||
*/
|
||||
public Builder setFlags(Set<AclEntryFlag> flags) {
|
||||
// copy and check for erroneous elements
|
||||
flags = new HashSet<AclEntryFlag>(flags);
|
||||
flags = EnumSet.copyOf(flags);
|
||||
checkSet(flags, AclEntryFlag.class);
|
||||
this.flags = flags;
|
||||
return this;
|
||||
@ -228,7 +227,7 @@ public final class AclEntry {
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder setFlags(AclEntryFlag... flags) {
|
||||
Set<AclEntryFlag> set = new HashSet<AclEntryFlag>(flags.length);
|
||||
Set<AclEntryFlag> set = EnumSet.noneOf(AclEntryFlag.class);
|
||||
// copy and check for null elements
|
||||
for (AclEntryFlag f: flags) {
|
||||
if (f == null)
|
||||
|
@ -65,7 +65,7 @@ import java.io.IOException;
|
||||
* UserPrincipalLookupService} may be used to obtain a {@link UserPrincipal}
|
||||
* to represent these special identities by invoking the {@link
|
||||
* UserPrincipalLookupService#lookupPrincipalByName lookupPrincipalByName}
|
||||
* method.
|
||||
* method. </p>
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we wish to add an entry to an existing ACL to grant "joe" access:
|
||||
@ -75,7 +75,7 @@ import java.io.IOException;
|
||||
* .lookupPrincipalByName("joe");
|
||||
*
|
||||
* // get view
|
||||
* AclFileAttributeView view = file.getFileAttributeView(AclFileAttributeView.class);
|
||||
* AclFileAttributeView view = Files.getFileAttributeView(file, AclFileAttributeView.class);
|
||||
*
|
||||
* // create ACE to give "joe" read access
|
||||
* AclEntry entry = AclEntry.newBuilder()
|
||||
@ -110,11 +110,11 @@ import java.io.IOException;
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* <p> The {@link FileRef#getAttribute getAttribute} method may be used to read
|
||||
* <p> The {@link Files#getAttribute getAttribute} method may be used to read
|
||||
* the ACL or owner attributes as if by invoking the {@link #getAcl getAcl} or
|
||||
* {@link #getOwner getOwner} methods.
|
||||
*
|
||||
* <p> The {@link FileRef#setAttribute setAttribute} method may be used to
|
||||
* <p> The {@link Files#setAttribute setAttribute} method may be used to
|
||||
* update the ACL or owner attributes as if by invoking the {@link #setAcl setAcl}
|
||||
* or {@link #setOwner setOwner} methods.
|
||||
*
|
||||
@ -122,8 +122,8 @@ import java.io.IOException;
|
||||
*
|
||||
* <p> Implementations supporting this attribute view may also support setting
|
||||
* the initial ACL when creating a file or directory. The initial ACL
|
||||
* may be provided to methods such as {@link Path#createFile createFile} or {@link
|
||||
* Path#createDirectory createDirectory} as an {@link FileAttribute} with {@link
|
||||
* may be provided to methods such as {@link Files#createFile createFile} or {@link
|
||||
* Files#createDirectory createDirectory} as an {@link FileAttribute} with {@link
|
||||
* FileAttribute#name name} {@code "acl:acl"} and a {@link FileAttribute#value
|
||||
* value} that is the list of {@code AclEntry} objects.
|
||||
*
|
||||
@ -135,8 +135,6 @@ import java.io.IOException;
|
||||
* translation.
|
||||
*
|
||||
* @since 1.7
|
||||
* @see Attributes#getAcl
|
||||
* @see Attributes#setAcl
|
||||
*/
|
||||
|
||||
public interface AclFileAttributeView
|
||||
|
@ -1,460 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.nio.file.attribute;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class consists exclusively of static methods that operate on or return
|
||||
* the attributes of files or file stores. These methods provide for convenient
|
||||
* use of the {@link AttributeView attribute-views} defined in this package.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
|
||||
public final class Attributes {
|
||||
private Attributes() { }
|
||||
|
||||
/**
|
||||
* Reads the basic file attributes of a file.
|
||||
*
|
||||
* <p> The {@code options} array may be used to indicate how symbolic links
|
||||
* are handled for the case that the file is a symbolic link. By default,
|
||||
* symbolic links are followed and the file attributes of the final target
|
||||
* of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS
|
||||
* NOFOLLOW_LINKS} is present then symbolic links are not followed and so
|
||||
* the method returns the file attributes of the symbolic link itself.
|
||||
* This option should be used where there is a need to determine if a
|
||||
* file is a symbolic link:
|
||||
* <pre>
|
||||
* boolean isSymbolicLink = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS).isSymbolicLink();
|
||||
* </pre>
|
||||
*
|
||||
* <p> It is implementation specific if all file attributes are read as an
|
||||
* atomic operation with respect to other file system operations.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param options
|
||||
* Options indicating how symbolic links are handled
|
||||
*
|
||||
* @return The basic file attributes
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, the security manager's {@link
|
||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
||||
* to check read access to file
|
||||
*
|
||||
* @see BasicFileAttributeView#readAttributes
|
||||
*/
|
||||
public static BasicFileAttributes readBasicFileAttributes(FileRef file,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
return file.getFileAttributeView(BasicFileAttributeView.class, options)
|
||||
.readAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the POSIX file attributes of a file.
|
||||
*
|
||||
* <p> The {@code file} parameter locates a file that supports the {@link
|
||||
* PosixFileAttributeView}. This file attribute view provides access to a
|
||||
* subset of the file attributes commonly associated with files on file
|
||||
* systems used by operating systems that implement the Portable Operating
|
||||
* System Interface (POSIX) family of standards. It is implementation
|
||||
* specific if all file attributes are read as an atomic operation with
|
||||
* respect to other file system operations.
|
||||
*
|
||||
* <p> The {@code options} array may be used to indicate how symbolic links
|
||||
* are handled for the case that the file is a symbolic link. By default,
|
||||
* symbolic links are followed and the file attributes of the final target
|
||||
* of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS
|
||||
* NOFOLLOW_LINKS} is present then symbolic links are not followed and so
|
||||
* the method returns the file attributes of the symbolic link itself.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param options
|
||||
* Options indicating how symbolic links are handled
|
||||
*
|
||||
* @return The POSIX file attributes
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code PosixFileAttributeView} is not available
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
|
||||
* or its {@link SecurityManager#checkRead(String) checkRead} method
|
||||
* denies read access to the file.
|
||||
*
|
||||
* @see PosixFileAttributeView#readAttributes
|
||||
*/
|
||||
public static PosixFileAttributes readPosixFileAttributes(FileRef file,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
PosixFileAttributeView view =
|
||||
file.getFileAttributeView(PosixFileAttributeView.class, options);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
return view.readAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the DOS file attributes of a file.
|
||||
*
|
||||
* <p> The {@code file} parameter locates a file that supports the {@link
|
||||
* DosFileAttributeView}. This file attribute view provides access to
|
||||
* legacy "DOS" attributes supported by the file systems such as File
|
||||
* Allocation Table (FAT), commonly used in <em>consumer devices</em>. It is
|
||||
* implementation specific if all file attributes are read as an atomic
|
||||
* operation with respect to other file system operations.
|
||||
*
|
||||
* <p> The {@code options} array may be used to indicate how symbolic links
|
||||
* are handled for the case that the file is a symbolic link. By default,
|
||||
* symbolic links are followed and the file attributes of the final target
|
||||
* of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS
|
||||
* NOFOLLOW_LINKS} is present then symbolic links are not followed and so
|
||||
* the method returns the file attributes of the symbolic link itself.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param options
|
||||
* Options indicating how symbolic links are handled
|
||||
*
|
||||
* @return The DOS file attributes
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code DosFileAttributeView} is not available
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, the security manager's {@link
|
||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
||||
* to check read access to file
|
||||
*
|
||||
* @see DosFileAttributeView#readAttributes
|
||||
*/
|
||||
public static DosFileAttributes readDosFileAttributes(FileRef file,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
DosFileAttributeView view =
|
||||
file.getFileAttributeView(DosFileAttributeView.class, options);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
return view.readAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner of a file.
|
||||
*
|
||||
* <p> The {@code file} parameter locates a file that supports the {@link
|
||||
* FileOwnerAttributeView}. This file attribute view provides access to
|
||||
* a file attribute that is the owner of the file.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
*
|
||||
* @return A user principal representing the owner of the file
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code FileOwnerAttributeView} is not available
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
|
||||
* or its {@link SecurityManager#checkRead(String) checkRead} method
|
||||
* denies read access to the file.
|
||||
*
|
||||
* @see FileOwnerAttributeView#getOwner
|
||||
*/
|
||||
public static UserPrincipal getOwner(FileRef file) throws IOException {
|
||||
FileOwnerAttributeView view =
|
||||
file.getFileAttributeView(FileOwnerAttributeView.class);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
return view.getOwner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the file owner.
|
||||
*
|
||||
* <p> The {@code file} parameter locates a file that supports the {@link
|
||||
* FileOwnerAttributeView}. This file attribute view provides access to
|
||||
* a file attribute that is the owner of the file.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param owner
|
||||
* The new file owner
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code FileOwnerAttributeView} is not available
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the file.
|
||||
*
|
||||
* @see FileOwnerAttributeView#setOwner
|
||||
*/
|
||||
public static void setOwner(FileRef file, UserPrincipal owner)
|
||||
throws IOException
|
||||
{
|
||||
FileOwnerAttributeView view =
|
||||
file.getFileAttributeView(FileOwnerAttributeView.class);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
view.setOwner(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a file's Access Control List (ACL).
|
||||
*
|
||||
* <p> The {@code file} parameter locates a file that supports the {@link
|
||||
* AclFileAttributeView}. This file attribute view provides access to ACLs
|
||||
* based on the ACL model specified in
|
||||
* <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC 3530</i></a>.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
*
|
||||
* @return An ordered list of {@link AclEntry entries} representing the
|
||||
* ACL. The returned list is modifiable.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code AclAttributeView} is not available
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
|
||||
* or its {@link SecurityManager#checkRead(String) checkRead} method
|
||||
* denies read access to the file.
|
||||
*
|
||||
* @see AclFileAttributeView#getAcl
|
||||
*/
|
||||
public static List<AclEntry> getAcl(FileRef file) throws IOException {
|
||||
AclFileAttributeView view =
|
||||
file.getFileAttributeView(AclFileAttributeView.class);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
return view.getAcl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a file's Access Control List (ACL).
|
||||
*
|
||||
* <p> The {@code file} parameter locates a file that supports the {@link
|
||||
* AclFileAttributeView}. This file attribute view provides access to ACLs
|
||||
* based on the ACL model specified in
|
||||
* <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC 3530</i></a>.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param acl
|
||||
* The new file ACL
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the {@code AclFileAttributeView} is not available
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the file.
|
||||
*
|
||||
* @see AclFileAttributeView#setAcl
|
||||
*/
|
||||
public static void setAcl(FileRef file, List<AclEntry> acl)
|
||||
throws IOException
|
||||
{
|
||||
AclFileAttributeView view =
|
||||
file.getFileAttributeView(AclFileAttributeView.class);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
view.setAcl(acl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a file's last modified time attribute. The file time is converted
|
||||
* to the epoch and precision supported by the file system. Converting from
|
||||
* finer to coarser granularities result in precision loss. The behavior of
|
||||
* this method when attempting to set a timestamp to a value that is outside
|
||||
* the range supported by the underlying file store is not defined. It may
|
||||
* or not fail by throwing an {@code IOException}.
|
||||
*
|
||||
* <p> If the file system does not support a last modified time attribute
|
||||
* then this method has no effect.
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we want to set the last modified time to the current time:
|
||||
* <pre>
|
||||
* FileTime now = FileTime.fromMillis(System.currentTimeMillis());
|
||||
* Attributes.setLastModifiedTime(file, now);
|
||||
* </pre>
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param lastModifiedTime
|
||||
* The new last modified time
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, the security manager's {@link
|
||||
* SecurityManager#checkWrite(String) checkWrite} method is invoked
|
||||
* to check write access to file
|
||||
*
|
||||
* @see BasicFileAttributeView#setTimes
|
||||
*/
|
||||
public static void setLastModifiedTime(FileRef file,
|
||||
FileTime lastModifiedTime)
|
||||
throws IOException
|
||||
{
|
||||
if (lastModifiedTime == null)
|
||||
throw new NullPointerException("'lastModifiedTime' is null");
|
||||
file.getFileAttributeView(BasicFileAttributeView.class)
|
||||
.setTimes(lastModifiedTime, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a file's last access time attribute. The file time is converted
|
||||
* to the epoch and precision supported by the file system. Converting from
|
||||
* finer to coarser granularities result in precision loss. The behavior of
|
||||
* this method when attempting to set a timestamp to a value that is outside
|
||||
* the range supported by the underlying file store is not defined. It may
|
||||
* or not fail by throwing an {@code IOException}.
|
||||
*
|
||||
* <p> If the file system does not support a last access time attribute then
|
||||
* this method has no effect.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param lastAccessTime
|
||||
* The new last access time
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, the security manager's {@link
|
||||
* SecurityManager#checkWrite(String) checkWrite} method is invoked
|
||||
* to check write access to file
|
||||
*
|
||||
* @see BasicFileAttributeView#setTimes
|
||||
*/
|
||||
public static void setLastAccessTime(FileRef file,
|
||||
FileTime lastAccessTime)
|
||||
throws IOException
|
||||
{
|
||||
if (lastAccessTime == null)
|
||||
throw new NullPointerException("'lastAccessTime' is null");
|
||||
file.getFileAttributeView(BasicFileAttributeView.class)
|
||||
.setTimes(null, lastAccessTime, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a file's POSIX permissions.
|
||||
*
|
||||
* <p> The {@code file} parameter is a reference to an existing file. It
|
||||
* supports the {@link PosixFileAttributeView} that provides access to file
|
||||
* attributes commonly associated with files on file systems used by
|
||||
* operating systems that implement the Portable Operating System Interface
|
||||
* (POSIX) family of standards.
|
||||
*
|
||||
* @param file
|
||||
* A file reference that locates the file
|
||||
* @param perms
|
||||
* The new set of permissions
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If {@code PosixFileAttributeView} is not available
|
||||
* @throws ClassCastException
|
||||
* If the sets contains elements that are not of type {@code
|
||||
* PosixFilePermission}
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the file.
|
||||
*
|
||||
* @see PosixFileAttributeView#setPermissions
|
||||
*/
|
||||
public static void setPosixFilePermissions(FileRef file,
|
||||
Set<PosixFilePermission> perms)
|
||||
throws IOException
|
||||
{
|
||||
PosixFileAttributeView view =
|
||||
file.getFileAttributeView(PosixFileAttributeView.class);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
view.setPermissions(perms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the space attributes of a file store.
|
||||
*
|
||||
* <p> The {@code store} parameter is a file store that supports the
|
||||
* {@link FileStoreSpaceAttributeView} providing access to the space related
|
||||
* attributes of the file store. It is implementation specific if all attributes
|
||||
* are read as an atomic operation with respect to other file system operations.
|
||||
*
|
||||
* @param store
|
||||
* The file store
|
||||
*
|
||||
* @return The file store space attributes
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the file store space attribute view is not supported
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see FileStoreSpaceAttributeView#readAttributes()
|
||||
*/
|
||||
public static FileStoreSpaceAttributes readFileStoreSpaceAttributes(FileStore store)
|
||||
throws IOException
|
||||
{
|
||||
FileStoreSpaceAttributeView view =
|
||||
store.getFileStoreAttributeView(FileStoreSpaceAttributeView.class);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException();
|
||||
return view.readAttributes();
|
||||
}
|
||||
}
|
@ -85,16 +85,15 @@ import java.io.IOException;
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* <p> The {@link java.nio.file.FileRef#getAttribute getAttribute} method may be
|
||||
* <p> The {@link java.nio.file.Files#getAttribute getAttribute} method may be
|
||||
* used to read any of these attributes as if by invoking the {@link
|
||||
* #readAttributes() readAttributes()} method.
|
||||
*
|
||||
* <p> The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be
|
||||
* <p> The {@link java.nio.file.Files#setAttribute setAttribute} method may be
|
||||
* used to update the file's last modified time, last access time or create time
|
||||
* attributes as if by invoking the {@link #setTimes setTimes} method.
|
||||
*
|
||||
* @since 1.7
|
||||
* @see Attributes
|
||||
*/
|
||||
|
||||
public interface BasicFileAttributeView
|
||||
@ -131,9 +130,10 @@ public interface BasicFileAttributeView
|
||||
* <p> This method updates the file's timestamp attributes. The values are
|
||||
* converted to the epoch and precision supported by the file system.
|
||||
* Converting from finer to coarser granularities result in precision loss.
|
||||
* The behavior of this method when attempting to set a timestamp to a value
|
||||
* that is outside the range supported by the underlying file store is not
|
||||
* defined. It may or not fail by throwing an {@code IOException}.
|
||||
* The behavior of this method when attempting to set a timestamp that is
|
||||
* not supported or to a value that is outside the range supported by the
|
||||
* underlying file store is not defined. It may or not fail by throwing an
|
||||
* {@code IOException}.
|
||||
*
|
||||
* <p> If any of the {@code lastModifiedTime}, {@code lastAccessTime},
|
||||
* or {@code createTime} parameters has the value {@code null} then the
|
||||
@ -146,6 +146,14 @@ public interface BasicFileAttributeView
|
||||
* lastAccessTime} and {@code createTime} parameters are {@code null} then
|
||||
* this method has no effect.
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we want to change a file's creation time.
|
||||
* <pre>
|
||||
* Path path = ...
|
||||
* FileTime time = ...
|
||||
* Files.getFileAttributeView(path, BasicFileAttributeView.class).setTimes(null, null, time);
|
||||
* </pre>
|
||||
*
|
||||
* @param lastModifiedTime
|
||||
* the new last modified time, or {@code null} to not change the
|
||||
* value
|
||||
@ -160,6 +168,8 @@ public interface BasicFileAttributeView
|
||||
* In the case of the default provider, a security manager is
|
||||
* installed, its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method is invoked to check write access to the file
|
||||
*
|
||||
* @see java.nio.file.Files#setLastModifiedTime
|
||||
*/
|
||||
void setTimes(FileTime lastModifiedTime,
|
||||
FileTime lastAccessTime,
|
||||
|
@ -34,8 +34,8 @@ package java.nio.file.attribute;
|
||||
*
|
||||
* <p> <b>Usage Example:</b>
|
||||
* <pre>
|
||||
* FileRef file = ...
|
||||
* BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
|
||||
* Path file = ...
|
||||
* BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
|
||||
* </pre>
|
||||
*
|
||||
* @since 1.7
|
||||
@ -48,25 +48,40 @@ public interface BasicFileAttributes {
|
||||
/**
|
||||
* Returns the time of last modification.
|
||||
*
|
||||
* <p> If the file system implementation does not support a time stamp
|
||||
* to indicate the time of last modification then this method returns an
|
||||
* implementation specific default value, typically a {@code FileTime}
|
||||
* representing the epoch (1970-01-01T00:00:00Z).
|
||||
*
|
||||
* @return a {@code FileTime} representing the time the file was last
|
||||
* modified or {@code null} if the attribute is not supported.
|
||||
* modified
|
||||
*/
|
||||
FileTime lastModifiedTime();
|
||||
|
||||
/**
|
||||
* Returns the time of last access if supported.
|
||||
* Returns the time of last access.
|
||||
*
|
||||
* @return a {@code FileTime} representing the time of last access or
|
||||
* {@code null} if the attribute is not supported.
|
||||
* <p> If the file system implementation does not support a time stamp
|
||||
* to indicate the time of last access then this method returns
|
||||
* an implementation specific default value, typically the {@link
|
||||
* #lastModifiedTime() last-modified-time} or a {@code FileTime}
|
||||
* representing the epoch (1970-01-01T00:00:00Z).
|
||||
*
|
||||
* @return a {@code FileTime} representing the time of last access
|
||||
*/
|
||||
FileTime lastAccessTime();
|
||||
|
||||
/**
|
||||
* Returns the creation time if supported. The creation time is the time
|
||||
* that the file was created.
|
||||
* Returns the creation time. The creation time is the time that the file
|
||||
* was created.
|
||||
*
|
||||
* @return a {@code FileTime} representing the time the file was created
|
||||
* or {@code null} if the attribute is not supported.
|
||||
* <p> If the file system implementation does not support a time stamp
|
||||
* to indicate the time when the file was created then this method returns
|
||||
* an implementation specific default value, typically the {@link
|
||||
* #lastModifiedTime() last-modified-time} or a {@code FileTime}
|
||||
* representing the epoch (1970-01-01T00:00:00Z).
|
||||
*
|
||||
* @return a {@code FileTime} representing the time the file was created
|
||||
*/
|
||||
FileTime creationTime();
|
||||
|
||||
@ -120,7 +135,7 @@ public interface BasicFileAttributes {
|
||||
*
|
||||
* <p> File keys returned by this method can be compared for equality and are
|
||||
* suitable for use in collections. If the file system and files remain static,
|
||||
* and two files are the {@link java.nio.file.Path#isSameFile same} with
|
||||
* and two files are the {@link java.nio.file.Files#isSameFile same} with
|
||||
* non-{@code null} file keys, then their file keys are equal.
|
||||
*
|
||||
* @see java.nio.file.Files#walkFileTree
|
||||
|
@ -65,12 +65,12 @@ import java.io.IOException;
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* <p> The {@link java.nio.file.FileRef#getAttribute getAttribute} method may
|
||||
* <p> The {@link java.nio.file.Files#getAttribute getAttribute} method may
|
||||
* be used to read any of these attributes, or any of the attributes defined by
|
||||
* {@link BasicFileAttributeView} as if by invoking the {@link #readAttributes
|
||||
* readAttributes()} method.
|
||||
*
|
||||
* <p> The {@link java.nio.file.FileRef#setAttribute setAttribute} method may
|
||||
* <p> The {@link java.nio.file.Files#setAttribute setAttribute} method may
|
||||
* be used to update the file's last modified time, last access time or create
|
||||
* time attributes as defined by {@link BasicFileAttributeView}. It may also be
|
||||
* used to update the DOS attributes as if by invoking the {@link #setReadOnly
|
||||
|
@ -29,13 +29,13 @@ package java.nio.file.attribute;
|
||||
* File attributes associated with a file in a file system that supports
|
||||
* legacy "DOS" attributes.
|
||||
*
|
||||
* <p> The DOS attributes of a file are retrieved using a {@link
|
||||
* DosFileAttributeView} by invoking its {@link DosFileAttributeView#readAttributes
|
||||
* readAttributes} method.
|
||||
* <p> <b>Usage Example:</b>
|
||||
* <pre>
|
||||
* Path file = ...
|
||||
* DosFileAttributes attrs = Files.readAttributes(file, DosFileAttributes.class);
|
||||
* </pre>
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Attributes#readDosFileAttributes
|
||||
*/
|
||||
|
||||
public interface DosFileAttributes
|
||||
|
@ -28,8 +28,8 @@ package java.nio.file.attribute;
|
||||
/**
|
||||
* An object that encapsulates the value of a file attribute that can be set
|
||||
* atomically when creating a new file or directory by invoking the {@link
|
||||
* java.nio.file.Path#createFile createFile} or {@link
|
||||
* java.nio.file.Path#createDirectory createDirectory} methods.
|
||||
* java.nio.file.Files#createFile createFile} or {@link
|
||||
* java.nio.file.Files#createDirectory createDirectory} methods.
|
||||
*
|
||||
* @param <T> The type of the file attribute value
|
||||
*
|
||||
|
@ -33,7 +33,7 @@ package java.nio.file.attribute;
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see java.nio.file.FileRef#getFileAttributeView(Class,java.nio.file.LinkOption[])
|
||||
* @see java.nio.file.Files#getFileAttributeView(Path,Class,java.nio.file.LinkOption[])
|
||||
*/
|
||||
|
||||
public interface FileAttributeView
|
||||
|
@ -37,8 +37,8 @@ import java.io.IOException;
|
||||
* <p> The {@link #getOwner getOwner} or {@link #setOwner setOwner} methods may
|
||||
* be used to read or update the owner of the file.
|
||||
*
|
||||
* <p> The {@link java.nio.file.FileRef#getAttribute getAttribute} and
|
||||
* {@link java.nio.file.FileRef#setAttribute setAttribute} methods may also be
|
||||
* <p> The {@link java.nio.file.Files#getAttribute getAttribute} and
|
||||
* {@link java.nio.file.Files#setAttribute setAttribute} methods may also be
|
||||
* used to read or update the owner. In that case, the owner attribute is
|
||||
* identified by the name {@code "owner"}, and the value of the attribute is
|
||||
* a {@link UserPrincipal}.
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.nio.file.attribute;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A file store attribute view that supports reading of space attributes.
|
||||
*
|
||||
* <p> Where dynamic access to file attributes is required, the attributes
|
||||
* supported by this attribute view have the following names and types:
|
||||
* <blockquote>
|
||||
* <table border="1" cellpadding="8">
|
||||
* <tr>
|
||||
* <th> Name </th>
|
||||
* <th> Type </th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> "totalSpace" </td>
|
||||
* <td> {@link Long} </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> "usableSpace" </td>
|
||||
* <td> {@link Long} </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> "unallocatedSpace" </td>
|
||||
* <td> {@link Long} </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
* <p> The {@link java.nio.file.FileStore#getAttribute getAttribute} method may
|
||||
* be used to read any of these attributes.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
|
||||
public interface FileStoreSpaceAttributeView
|
||||
extends FileStoreAttributeView
|
||||
{
|
||||
/**
|
||||
* Returns the name of the attribute view. Attribute views of this type
|
||||
* have the name {@code "space"}.
|
||||
*/
|
||||
@Override
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Reads the disk space attributes as a bulk operation.
|
||||
*
|
||||
* <p> It is file system specific if all attributes are read as an
|
||||
* atomic operation with respect to other file system operations.
|
||||
*
|
||||
* @return The disk space attributes
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
FileStoreSpaceAttributes readAttributes() throws IOException;
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.nio.file.attribute;
|
||||
|
||||
/**
|
||||
* Space related attributes of a file store.
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Attributes#readFileStoreSpaceAttributes
|
||||
*/
|
||||
|
||||
public interface FileStoreSpaceAttributes {
|
||||
/**
|
||||
* Returns the size, in bytes, of the file store.
|
||||
*/
|
||||
long totalSpace();
|
||||
|
||||
/**
|
||||
* Returns the number of bytes available to this Java virtual machine on the
|
||||
* file store.
|
||||
*
|
||||
* <p> The returned number of available bytes is a hint, but not a
|
||||
* guarantee, that it is possible to use most or any of these bytes. The
|
||||
* number of usable bytes is most likely to be accurate immediately
|
||||
* after the space attributes are obtained. It is likely to be made inaccurate
|
||||
* by any external I/O operations including those made on the system outside
|
||||
* of this Java virtual machine.
|
||||
*/
|
||||
long usableSpace();
|
||||
|
||||
/**
|
||||
* Returns the number of unallocated bytes in the file store.
|
||||
*
|
||||
* <p> The returned number of unallocated bytes is a hint, but not a
|
||||
* guarantee, that it is possible to use most or any of these bytes. The
|
||||
* number of unallocated bytes is most likely to be accurate immediately
|
||||
* after the space attributes are obtained. It is likely to be
|
||||
* made inaccurate by any external I/O operations including those made on
|
||||
* the system outside of this virtual machine.
|
||||
*/
|
||||
long unallocatedSpace();
|
||||
}
|
@ -35,20 +35,53 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Represents the value of a file's time stamp attribute. For example, it may
|
||||
* represent the time that the file was last modified, accessed, or created.
|
||||
* represent the time that the file was last
|
||||
* {@link BasicFileAttributes#lastModifiedTime() modified},
|
||||
* {@link BasicFileAttributes#lastAccessTime() accessed},
|
||||
* or {@link BasicFileAttributes#creationTime() created}.
|
||||
*
|
||||
* <p> Instances of this class are immutable.
|
||||
*
|
||||
* @since 1.7
|
||||
* @see BasicFileAttributes
|
||||
* @see Attributes#setLastModifiedTime
|
||||
* @see java.nio.file.Files#setLastModifiedTime
|
||||
* @see java.nio.file.Files#getLastModifiedTime
|
||||
*/
|
||||
|
||||
public final class FileTime implements Comparable<FileTime> {
|
||||
public final class FileTime
|
||||
implements Comparable<FileTime>
|
||||
{
|
||||
/**
|
||||
* The value since the epoch; can be negative.
|
||||
*/
|
||||
private final long value;
|
||||
private final TimeUnit unit;
|
||||
private String valueAsString; // created lazily
|
||||
|
||||
/**
|
||||
* The unit of granularity to interpret the value.
|
||||
*/
|
||||
private final TimeUnit unit;
|
||||
|
||||
/**
|
||||
* The value return by toString (created lazily)
|
||||
*/
|
||||
private String valueAsString;
|
||||
|
||||
/**
|
||||
* The value in days and excess nanos (created lazily)
|
||||
*/
|
||||
private DaysAndNanos daysAndNanos;
|
||||
|
||||
/**
|
||||
* Returns a DaysAndNanos object representing the value.
|
||||
*/
|
||||
private DaysAndNanos asDaysAndNanos() {
|
||||
if (daysAndNanos == null)
|
||||
daysAndNanos = new DaysAndNanos(value, unit);
|
||||
return daysAndNanos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
private FileTime(long value, TimeUnit unit) {
|
||||
if (unit == null)
|
||||
throw new NullPointerException();
|
||||
@ -143,9 +176,8 @@ public final class FileTime implements Comparable<FileTime> {
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// hash value for fixed granularity to satisfy contract with equals
|
||||
long ms = toMillis();
|
||||
return (int)(ms ^ (ms >>> 32));
|
||||
// hashcode of days/nanos representation to satisfy contract with equals
|
||||
return asDaysAndNanos().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,46 +194,12 @@ public final class FileTime implements Comparable<FileTime> {
|
||||
@Override
|
||||
public int compareTo(FileTime other) {
|
||||
// same granularity
|
||||
if (unit == other.unit)
|
||||
if (unit == other.unit) {
|
||||
return (value < other.value) ? -1 : (value == other.value ? 0 : 1);
|
||||
|
||||
// compare in days
|
||||
long thisValueInDays = unit.toDays(value);
|
||||
long otherValueInDays = other.unit.toDays(other.value);
|
||||
if (thisValueInDays != otherValueInDays)
|
||||
return (thisValueInDays < otherValueInDays) ? -1 : 1;
|
||||
|
||||
// compare remainder in nanoseconds
|
||||
long thisRemainder = remainderInNanos(thisValueInDays);
|
||||
long otherRemainder = other.remainderInNanos(otherValueInDays);
|
||||
return (thisRemainder < otherRemainder) ? -1 :
|
||||
(thisRemainder == otherRemainder) ? 0 : 1;
|
||||
}
|
||||
|
||||
private long remainderInNanos(long days) {
|
||||
// constants for conversion
|
||||
final long C0 = 1L;
|
||||
final long C1 = C0 * 24L;
|
||||
final long C2 = C1 * 60L;
|
||||
final long C3 = C2 * 60L;
|
||||
final long C4 = C3 * 1000L;
|
||||
final long C5 = C4 * 1000L;
|
||||
final long C6 = C5 * 1000L;
|
||||
|
||||
long scale;
|
||||
switch (unit) {
|
||||
case DAYS : scale = C0; break;
|
||||
case HOURS : scale = C1; break;
|
||||
case MINUTES : scale = C2; break;
|
||||
case SECONDS : scale = C3; break;
|
||||
case MILLISECONDS : scale = C4; break;
|
||||
case MICROSECONDS : scale = C5; break;
|
||||
case NANOSECONDS : scale = C6; break;
|
||||
default:
|
||||
throw new AssertionError("Unit not handled");
|
||||
} else {
|
||||
// compare using days/nanos representation when unit differs
|
||||
return asDaysAndNanos().compareTo(other.asDaysAndNanos());
|
||||
}
|
||||
long rem = value - (days * scale);
|
||||
return unit.toNanos(rem);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,26 +237,12 @@ public final class FileTime implements Comparable<FileTime> {
|
||||
// nothing to do when seconds/minutes/hours/days
|
||||
String fractionAsString = "";
|
||||
if (unit.compareTo(TimeUnit.SECONDS) < 0) {
|
||||
// constants for conversion
|
||||
final long C0 = 1L;
|
||||
final long C1 = C0 * 1000L;
|
||||
final long C2 = C1 * 1000L;
|
||||
final long C3 = C2 * 1000L;
|
||||
|
||||
long scale;
|
||||
int width;
|
||||
switch (unit) {
|
||||
case MILLISECONDS : scale = C1; width = 3; break;
|
||||
case MICROSECONDS : scale = C2; width = 6; break;
|
||||
case NANOSECONDS : scale = C3; width = 9; break;
|
||||
default:
|
||||
throw new AssertionError("Unit not handled");
|
||||
}
|
||||
long fraction = value % scale;
|
||||
long fraction = asDaysAndNanos().fractionOfSecondInNanos();
|
||||
if (fraction != 0L) {
|
||||
// fraction must be positive
|
||||
if (fraction < 0L) {
|
||||
fraction += scale;
|
||||
final long MAX_FRACTION_PLUS_1 = 1000L * 1000L * 1000L;
|
||||
fraction += MAX_FRACTION_PLUS_1;
|
||||
if (ms != Long.MIN_VALUE) ms--;
|
||||
}
|
||||
|
||||
@ -266,7 +250,7 @@ public final class FileTime implements Comparable<FileTime> {
|
||||
// stripping any trailing zeros
|
||||
String s = Long.toString(fraction);
|
||||
int len = s.length();
|
||||
width -= len;
|
||||
int width = 9 - len;
|
||||
StringBuilder sb = new StringBuilder(".");
|
||||
while (width-- > 0) {
|
||||
sb.append('0');
|
||||
@ -302,4 +286,76 @@ public final class FileTime implements Comparable<FileTime> {
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a FileTime's value as two longs: the number of days since
|
||||
* the epoch, and the excess (in nanoseconds). This is used for comparing
|
||||
* values with different units of granularity.
|
||||
*/
|
||||
private static class DaysAndNanos implements Comparable<DaysAndNanos> {
|
||||
// constants for conversion
|
||||
private static final long C0 = 1L;
|
||||
private static final long C1 = C0 * 24L;
|
||||
private static final long C2 = C1 * 60L;
|
||||
private static final long C3 = C2 * 60L;
|
||||
private static final long C4 = C3 * 1000L;
|
||||
private static final long C5 = C4 * 1000L;
|
||||
private static final long C6 = C5 * 1000L;
|
||||
|
||||
/**
|
||||
* The value (in days) since the epoch; can be negative.
|
||||
*/
|
||||
private final long days;
|
||||
|
||||
/**
|
||||
* The excess (in nanoseconds); can be negative if days <= 0.
|
||||
*/
|
||||
private final long excessNanos;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
DaysAndNanos(long value, TimeUnit unit) {
|
||||
long scale;
|
||||
switch (unit) {
|
||||
case DAYS : scale = C0; break;
|
||||
case HOURS : scale = C1; break;
|
||||
case MINUTES : scale = C2; break;
|
||||
case SECONDS : scale = C3; break;
|
||||
case MILLISECONDS : scale = C4; break;
|
||||
case MICROSECONDS : scale = C5; break;
|
||||
case NANOSECONDS : scale = C6; break;
|
||||
default : throw new AssertionError("Unit not handled");
|
||||
}
|
||||
this.days = unit.toDays(value);
|
||||
this.excessNanos = unit.toNanos(value - (this.days * scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fraction of a second, in nanoseconds.
|
||||
*/
|
||||
long fractionOfSecondInNanos() {
|
||||
return excessNanos % (1000L * 1000L * 1000L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof DaysAndNanos) ?
|
||||
compareTo((DaysAndNanos)obj) == 0 : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int)(days ^ (days >>> 32) ^
|
||||
excessNanos ^ (excessNanos >>> 32));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(DaysAndNanos other) {
|
||||
if (this.days != other.days)
|
||||
return (this.days < other.days) ? -1 : 1;
|
||||
return (this.excessNanos < other.excessNanos) ? -1 :
|
||||
(this.excessNanos == other.excessNanos) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,8 +60,8 @@ import java.io.IOException;
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we need to print out the owner and access permissions of a file:
|
||||
* <pre>
|
||||
* FileRef file = ...
|
||||
* PosixFileAttributes attrs = file.getFileAttributeView(PosixFileAttributeView.class)
|
||||
* Path file = ...
|
||||
* PosixFileAttributes attrs = Files.getFileAttributeView(file, PosixFileAttributeView.class)
|
||||
* .readAttributes();
|
||||
* System.out.format("%s %s%n",
|
||||
* attrs.owner().getName(),
|
||||
@ -90,12 +90,12 @@ import java.io.IOException;
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* <p> The {@link FileRef#getAttribute getAttribute} method may be used to read
|
||||
* <p> The {@link Files#getAttribute getAttribute} method may be used to read
|
||||
* any of these attributes, or any of the attributes defined by {@link
|
||||
* BasicFileAttributeView} as if by invoking the {@link #readAttributes
|
||||
* readAttributes()} method.
|
||||
*
|
||||
* <p> The {@link FileRef#setAttribute setAttribute} method may be used to update
|
||||
* <p> The {@link Files#setAttribute setAttribute} method may be used to update
|
||||
* the file's last modified time, last access time or create time attributes as
|
||||
* defined by {@link BasicFileAttributeView}. It may also be used to update
|
||||
* the permissions, owner, or group-owner as if by invoking the {@link
|
||||
@ -105,8 +105,8 @@ import java.io.IOException;
|
||||
* <h4> Setting Initial Permissions </h4>
|
||||
* <p> Implementations supporting this attribute view may also support setting
|
||||
* the initial permissions when creating a file or directory. The
|
||||
* initial permissions are provided to the {@link Path#createFile createFile}
|
||||
* or {@link Path#createDirectory createDirectory} methods as a {@link
|
||||
* initial permissions are provided to the {@link Files#createFile createFile}
|
||||
* or {@link Files#createDirectory createDirectory} methods as a {@link
|
||||
* FileAttribute} with {@link FileAttribute#name name} {@code "posix:permissions"}
|
||||
* and a {@link FileAttribute#value value} that is the set of permissions. The
|
||||
* following example uses the {@link PosixFilePermissions#asFileAttribute
|
||||
@ -117,7 +117,7 @@ import java.io.IOException;
|
||||
* Path path = ...
|
||||
* Set<PosixFilePermission> perms =
|
||||
* EnumSet.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ);
|
||||
* path.createFile(PosixFilePermissions.asFileAttribute(perms));
|
||||
* Files.createFile(path, PosixFilePermissions.asFileAttribute(perms));
|
||||
* </pre>
|
||||
*
|
||||
* <p> When the access permissions are set at file creation time then the actual
|
||||
@ -128,13 +128,11 @@ import java.io.IOException;
|
||||
* the access permissions, and the underlying file system supports access
|
||||
* permissions, then it is required that the value of the actual access
|
||||
* permissions will be equal or less than the value of the attribute
|
||||
* provided to the {@link java.nio.file.Path#createFile createFile} or
|
||||
* {@link java.nio.file.Path#createDirectory createDirectory} methods. In
|
||||
* other words, the file may be more secure than requested.
|
||||
* provided to the {@link Files#createFile createFile} or {@link
|
||||
* Files#createDirectory createDirectory} methods. In other words, the file may
|
||||
* be more secure than requested.
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Attributes#readPosixFileAttributes
|
||||
*/
|
||||
|
||||
public interface PosixFileAttributeView
|
||||
|
@ -37,8 +37,6 @@ import java.util.Set;
|
||||
* PosixFileAttributeView#readAttributes readAttributes} method.
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see Attributes#readPosixFileAttributes
|
||||
*/
|
||||
|
||||
public interface PosixFileAttributes
|
||||
|
@ -25,14 +25,12 @@
|
||||
|
||||
package java.nio.file.attribute;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Defines the bits for use with the {@link PosixFileAttributes#permissions()
|
||||
* permissions} attribute.
|
||||
*
|
||||
* <p> The {@link PosixFileAttributes} class defines method methods for
|
||||
* manipulating {@link Set sets} of permissions.
|
||||
* <p> The {@link PosixFilePermissions} class defines methods for manipulating
|
||||
* set of permissions.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
|
@ -126,7 +126,7 @@ public final class PosixFilePermissions {
|
||||
public static Set<PosixFilePermission> fromString(String perms) {
|
||||
if (perms.length() != 9)
|
||||
throw new IllegalArgumentException("Invalid mode");
|
||||
Set<PosixFilePermission> result = new HashSet<PosixFilePermission>();
|
||||
Set<PosixFilePermission> result = EnumSet.noneOf(PosixFilePermission.class);
|
||||
if (isR(perms.charAt(0))) result.add(OWNER_READ);
|
||||
if (isW(perms.charAt(1))) result.add(OWNER_WRITE);
|
||||
if (isX(perms.charAt(2))) result.add(OWNER_EXECUTE);
|
||||
@ -141,8 +141,8 @@ public final class PosixFilePermissions {
|
||||
|
||||
/**
|
||||
* Creates a {@link FileAttribute}, encapsulating a copy of the given file
|
||||
* permissions, suitable for passing to the {@link java.nio.file.Path#createFile
|
||||
* createFile} or {@link java.nio.file.Path#createDirectory createDirectory}
|
||||
* permissions, suitable for passing to the {@link java.nio.file.Files#createFile
|
||||
* createFile} or {@link java.nio.file.Files#createDirectory createDirectory}
|
||||
* methods.
|
||||
*
|
||||
* @param perms
|
||||
|
@ -59,9 +59,9 @@ import java.io.IOException;
|
||||
* attributes.
|
||||
*
|
||||
* <p> Where dynamic access to file attributes is required, the {@link
|
||||
* java.nio.file.FileRef#getAttribute getAttribute} method may be used to read
|
||||
* java.nio.file.Files#getAttribute getAttribute} method may be used to read
|
||||
* the attribute value. The attribute value is returned as a byte array (byte[]).
|
||||
* The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be used
|
||||
* The {@link java.nio.file.Files#setAttribute setAttribute} method may be used
|
||||
* to write the value of a user-defined attribute from a buffer (as if by
|
||||
* invoking the {@link #write write} method), or byte array (byte[]).
|
||||
*
|
||||
@ -132,8 +132,8 @@ public interface UserDefinedFileAttributeView
|
||||
* Suppose we want to read a file's MIME type that is stored as a user-defined
|
||||
* attribute with the name "{@code user.mimetype}".
|
||||
* <pre>
|
||||
* UserDefinedFileAttributeView view = file
|
||||
* .getFileAttributeView(UserDefinedFileAttributeView.class);
|
||||
* UserDefinedFileAttributeView view =
|
||||
* Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
|
||||
* String name = "user.mimetype";
|
||||
* ByteBuffer buf = ByteBuffer.allocate(view.size(name));
|
||||
* view.read(name, buf);
|
||||
@ -189,8 +189,8 @@ public interface UserDefinedFileAttributeView
|
||||
* <p> <b>Usage Example:</b>
|
||||
* Suppose we want to write a file's MIME type as a user-defined attribute:
|
||||
* <pre>
|
||||
* UserDefinedFileAttributeView view = file
|
||||
* .getFileAttributeView(UserDefinedFileAttributeView.class);
|
||||
* UserDefinedFileAttributeView view =
|
||||
* FIles.getFileAttributeView(path, UserDefinedFileAttributeView.class);
|
||||
* view.write("user.mimetype", Charset.defaultCharset().encode("text/html"));
|
||||
* </pre>
|
||||
*
|
||||
|
@ -46,8 +46,6 @@
|
||||
* <td>Can read or update user-defined file attributes</td></tr>
|
||||
* <tr><td valign=top><tt> <i>{@link java.nio.file.attribute.FileStoreAttributeView}</i></tt></td>
|
||||
* <td>Can read or update file system attributes</td></tr>
|
||||
* <tr><td valign=top><tt> <i>{@link java.nio.file.attribute.FileStoreSpaceAttributeView} </i></tt></td>
|
||||
* <td>Can read file system <em>space usage</em> related attributes</td></tr>
|
||||
* </table></blockquote>
|
||||
*
|
||||
* <p> An attribute view provides a read-only or updatable view of the non-opaque
|
||||
@ -55,7 +53,7 @@
|
||||
* The {@link java.nio.file.attribute.FileAttributeView} interface is
|
||||
* extended by several other interfaces that that views to specific sets of file
|
||||
* attributes. {@code FileAttributeViews} are selected by invoking the {@link
|
||||
* java.nio.file.FileRef#getFileAttributeView} method with a
|
||||
* java.nio.file.Files#getFileAttributeView} method with a
|
||||
* <em>type-token</em> to identify the required view. Views can also be identified
|
||||
* by name. The {@link java.nio.file.attribute.FileStoreAttributeView} interface
|
||||
* provides access to file store attributes. A {@code FileStoreAttributeView} of
|
||||
@ -83,13 +81,6 @@
|
||||
* on the model defined by <a href="http://www.ietf.org/rfc/rfc3530.txt">
|
||||
* <i>RFC 3530: Network File System (NFS) version 4 Protocol</i></a>.
|
||||
*
|
||||
* <p> The {@link java.nio.file.attribute.FileStoreSpaceAttributeView} class
|
||||
* defines methods to read file system space usage related attributes of a file system.
|
||||
*
|
||||
* <p> The {@link java.nio.file.attribute.Attributes} utility class defines
|
||||
* static methods to access file or file system attribute using the above
|
||||
* attribute views.
|
||||
*
|
||||
* <p> In addition to attribute views, this package also defines classes and
|
||||
* interfaces that are used when accessing attributes:
|
||||
*
|
||||
|
@ -31,7 +31,7 @@
|
||||
* systems. The API to access file and file system attributes is defined in the
|
||||
* {@link java.nio.file.attribute} package. The {@link java.nio.file.spi}
|
||||
* package is used by service provider implementors wishing to extend the
|
||||
* platform default provider, or to construct other provider implementations.
|
||||
* platform default provider, or to construct other provider implementations. </p>
|
||||
*
|
||||
* <a name="links"><h3>Symbolic Links</h3></a>
|
||||
* Many operating systems and file systems support for <em>symbolic links</em>.
|
||||
@ -43,7 +43,7 @@
|
||||
* target of the link. This package includes support for symbolic links where
|
||||
* implementations provide these semantics. File systems may support other types
|
||||
* that are semantically close but support for these other types of links is
|
||||
* not included in this package.
|
||||
* not included in this package. </p>
|
||||
*
|
||||
* <a name="interop"><h3>Interoperability</h3></a>
|
||||
* The {@link java.io.File} class defines the {@link java.io.File#toPath
|
||||
@ -52,7 +52,7 @@
|
||||
* {@code Path} can be used to operate on the same file as the {@code File}
|
||||
* object. The {@code Path} specification provides further information
|
||||
* on the <a href="Path.html#interop">interoperability</a> between {@code Path}
|
||||
* and {@code java.io.File} objects.
|
||||
* and {@code java.io.File} objects. </p>
|
||||
*
|
||||
* <h3>Visibility</h3>
|
||||
* The view of the files and file system provided by classes in this package are
|
||||
@ -63,7 +63,7 @@
|
||||
* network-filesystem protocols. This is true regardless of the language in which
|
||||
* these other programs are written, and whether they are running on the same machine
|
||||
* or on some other machine. The exact nature of any such inconsistencies are
|
||||
* system-dependent and are therefore unspecified.
|
||||
* system-dependent and are therefore unspecified. </p>
|
||||
*
|
||||
* <a name="integrity"><h3>Synchronized I/O File Integrity</h3></a>
|
||||
* The {@link java.nio.file.StandardOpenOption#SYNC SYNC} and {@link
|
||||
@ -80,14 +80,14 @@
|
||||
* crash. If the file does not reside on a local device then no such guarantee
|
||||
* is made. Whether this guarantee is possible with other {@link
|
||||
* java.nio.file.spi.FileSystemProvider provider} implementations is provider
|
||||
* specific.
|
||||
* specific. </p>
|
||||
*
|
||||
* <h3>General Exceptions</h3>
|
||||
* Unless otherwise noted, passing a {@code null} argument to a constructor
|
||||
* or method of any class or interface in this package will cause a {@link
|
||||
* java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
|
||||
* invoking a method with a collection containing a {@code null} element will
|
||||
* cause a {@code NullPointerException}, unless otherwise specified.
|
||||
* cause a {@code NullPointerException}, unless otherwise specified. </p>
|
||||
*
|
||||
* <p> Unless otherwise noted, methods that attempt to access the file system
|
||||
* will throw {@link java.nio.file.ClosedFileSystemException} when invoked on
|
||||
@ -95,12 +95,13 @@
|
||||
* {@link java.nio.file.FileSystem#close closed}. Additionally, any methods
|
||||
* that attempt write access to a file system will throw {@link
|
||||
* java.nio.file.ReadOnlyFileSystemException} when invoked on an object associated
|
||||
* with a {@link java.nio.file.FileSystem} that only provides read-only access.
|
||||
* with a {@link java.nio.file.FileSystem} that only provides read-only
|
||||
* access. </p>
|
||||
*
|
||||
* <p> Unless otherwise noted, invoking a method of any class or interface in
|
||||
* this package created by one {@link java.nio.file.spi.FileSystemProvider
|
||||
* provider} with a parameter that is an object created by another provider,
|
||||
* will throw {@link java.nio.file.ProviderMismatchException}.
|
||||
* will throw {@link java.nio.file.ProviderMismatchException}. </p>
|
||||
*
|
||||
* <h3>Optional Specific Exceptions</h3>
|
||||
* Most of the methods defined by classes in this package that access the
|
||||
|
@ -26,17 +26,21 @@
|
||||
package java.nio.file.spi;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.channels.*;
|
||||
import java.net.URI;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Service-provider class for file systems.
|
||||
* Service-provider class for file systems. The methods defined by the {@link
|
||||
* java.nio.file.Files} class will typically delegate to an instance of this
|
||||
* class.
|
||||
*
|
||||
* <p> A file system provider is a concrete implementation of this class that
|
||||
* implements the abstract methods defined by this class. A provider is
|
||||
@ -64,13 +68,6 @@ import java.io.IOException;
|
||||
* the {@code newFileSystem} method is invoked. In the case of the default
|
||||
* provider, the {@code FileSystem} is created when the provider is initialized.
|
||||
*
|
||||
* <p> In addition to file systems, a provider is also a factory for {@link
|
||||
* FileChannel} and {@link AsynchronousFileChannel} channels. The {@link
|
||||
* #newFileChannel newFileChannel} and {@link #newAsynchronousFileChannel
|
||||
* AsynchronousFileChannel} methods are defined to open or create files, returning
|
||||
* a channel to access the file. These methods are invoked by static factory
|
||||
* methods defined in the {@link java.nio.channels} package.
|
||||
*
|
||||
* <p> All of the methods in this class are safe for use by multiple concurrent
|
||||
* threads.
|
||||
*
|
||||
@ -202,9 +199,10 @@ public abstract class FileSystemProvider {
|
||||
*
|
||||
* <p> This method throws {@link FileSystemAlreadyExistsException} if the
|
||||
* file system already exists because it was previously created by an
|
||||
* invocation of this method. Once a file system is {@link FileSystem#close
|
||||
* closed} it is provider-dependent if the provider allows a new file system
|
||||
* to be created with the same URI as a file system it previously created.
|
||||
* invocation of this method. Once a file system is {@link
|
||||
* java.nio.file.FileSystem#close closed} it is provider-dependent if the
|
||||
* provider allows a new file system to be created with the same URI as a
|
||||
* file system it previously created.
|
||||
*
|
||||
* @param uri
|
||||
* URI reference
|
||||
@ -234,20 +232,21 @@ public abstract class FileSystemProvider {
|
||||
*
|
||||
* <p> This method returns a reference to a {@code FileSystem} that was
|
||||
* created by invoking the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)}
|
||||
* method. File systems created the {@link #newFileSystem(FileRef,Map)
|
||||
* newFileSystem(FileRef,Map)} method are not returned by this method.
|
||||
* method. File systems created the {@link #newFileSystem(Path,Map)
|
||||
* newFileSystem(Path,Map)} method are not returned by this method.
|
||||
* The file system is identified by its {@code URI}. Its exact form
|
||||
* is highly provider dependent. In the case of the default provider the URI's
|
||||
* path component is {@code "/"} and the authority, query and fragment components
|
||||
* are undefined (Undefined components are represented by {@code null}).
|
||||
*
|
||||
* <p> Once a file system created by this provider is {@link FileSystem#close
|
||||
* closed} it is provider-dependent if this method returns a reference to
|
||||
* the closed file system or throws {@link FileSystemNotFoundException}.
|
||||
* If the provider allows a new file system to be created with the same URI
|
||||
* as a file system it previously created then this method throws the
|
||||
* exception if invoked after the file system is closed (and before a new
|
||||
* instance is created by the {@link #newFileSystem newFileSystem} method).
|
||||
* <p> Once a file system created by this provider is {@link
|
||||
* java.nio.file.FileSystem#close closed} it is provider-dependent if this
|
||||
* method returns a reference to the closed file system or throws {@link
|
||||
* FileSystemNotFoundException}. If the provider allows a new file system to
|
||||
* be created with the same URI as a file system it previously created then
|
||||
* this method throws the exception if invoked after the file system is
|
||||
* closed (and before a new instance is created by the {@link #newFileSystem
|
||||
* newFileSystem} method).
|
||||
*
|
||||
* <p> If a security manager is installed then a provider implementation
|
||||
* may require to check a permission before returning a reference to an
|
||||
@ -306,17 +305,16 @@ public abstract class FileSystemProvider {
|
||||
*
|
||||
* <p> This method is intended for specialized providers of pseudo file
|
||||
* systems where the contents of one or more files is treated as a file
|
||||
* system. The {@code file} parameter is a reference to an existing file
|
||||
* and the {@code env} parameter is a map of provider specific properties to
|
||||
* configure the file system.
|
||||
* system. The {@code env} parameter is a map of provider specific properties
|
||||
* to configure the file system.
|
||||
*
|
||||
* <p> If this provider does not support the creation of such file systems
|
||||
* or if the provider does not recognize the file type of the given file then
|
||||
* it throws {@code UnsupportedOperationException}. The default implementation
|
||||
* of this method throws {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @param file
|
||||
* The file
|
||||
* @param path
|
||||
* The path to the file
|
||||
* @param env
|
||||
* A map of provider specific properties to configure the file system;
|
||||
* may be empty
|
||||
@ -336,32 +334,121 @@ public abstract class FileSystemProvider {
|
||||
* If a security manager is installed and it denies an unspecified
|
||||
* permission.
|
||||
*/
|
||||
public FileSystem newFileSystem(FileRef file, Map<String,?> env)
|
||||
public FileSystem newFileSystem(Path path, Map<String,?> env)
|
||||
throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens or creates a file for reading and/or writing, returning a file
|
||||
* channel to access the file.
|
||||
* Opens a file, returning an input stream to read from the file. This
|
||||
* method works in exactly the manner specified by the {@link
|
||||
* Files#newInputStream} method.
|
||||
*
|
||||
* <p> This method is invoked by the {@link FileChannel#open(Path,Set,FileAttribute[])
|
||||
* FileChannel.open} method to open a file channel. A provider that does not
|
||||
* support all the features required to construct a file channel throws
|
||||
* {@code UnsupportedOperationException}. The default provider is required
|
||||
* to support the creation of file channels. When not overridden, the
|
||||
* default implementation throws {@code UnsupportedOperationException}.
|
||||
* <p> The default implementation of this method opens a channel to the file
|
||||
* as if by invoking the {@link #newByteChannel} method and constructs a
|
||||
* stream that reads bytes from the channel. This method should be overridden
|
||||
* where appropriate.
|
||||
*
|
||||
* @param path
|
||||
* The path of the file to open or create
|
||||
* the path to the file to open
|
||||
* @param options
|
||||
* Options specifying how the file is opened
|
||||
* options specifying how the file is opened
|
||||
*
|
||||
* @return a new input stream
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if an invalid combination of options is specified
|
||||
* @throws UnsupportedOperationException
|
||||
* if an unsupported option is specified
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file.
|
||||
*/
|
||||
public InputStream newInputStream(Path path, OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if (options.length > 0) {
|
||||
for (OpenOption opt: options) {
|
||||
if (opt != StandardOpenOption.READ)
|
||||
throw new UnsupportedOperationException("'" + opt + "' not allowed");
|
||||
}
|
||||
}
|
||||
return Channels.newInputStream(Files.newByteChannel(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens or creates a file, returning an output stream that may be used to
|
||||
* write bytes to the file. This method works in exactly the manner
|
||||
* specified by the {@link Files#newOutputStream} method.
|
||||
*
|
||||
* <p> The default implementation of this method opens a channel to the file
|
||||
* as if by invoking the {@link #newByteChannel} method and constructs a
|
||||
* stream that writes bytes to the channel. This method should be overridden
|
||||
* where appropriate.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file to open or create
|
||||
* @param options
|
||||
* options specifying how the file is opened
|
||||
*
|
||||
* @return a new output stream
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code options} contains an invalid combination of options
|
||||
* @throws UnsupportedOperationException
|
||||
* if an unsupported option is specified
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method is invoked to check write access to the file. The {@link
|
||||
* SecurityManager#checkDelete(String) checkDelete} method is
|
||||
* invoked to check delete access if the file is opened with the
|
||||
* {@code DELETE_ON_CLOSE} option.
|
||||
*/
|
||||
public OutputStream newOutputStream(Path path, OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
int len = options.length;
|
||||
Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
|
||||
if (len == 0) {
|
||||
opts.add(StandardOpenOption.CREATE);
|
||||
opts.add(StandardOpenOption.TRUNCATE_EXISTING);
|
||||
} else {
|
||||
for (OpenOption opt: options) {
|
||||
if (opt == StandardOpenOption.READ)
|
||||
throw new IllegalArgumentException("READ not allowed");
|
||||
opts.add(opt);
|
||||
}
|
||||
}
|
||||
opts.add(StandardOpenOption.WRITE);
|
||||
return Channels.newOutputStream(newByteChannel(path, opts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens or creates a file for reading and/or writing, returning a file
|
||||
* channel to access the file. This method works in exactly the manner
|
||||
* specified by the {@link FileChannel#open(Path,Set,FileAttribute[])
|
||||
* FileChannel.open} method. A provider that does not support all the
|
||||
* features required to construct a file channel throws {@code
|
||||
* UnsupportedOperationException}. The default provider is required to
|
||||
* support the creation of file channels. When not overridden, the default
|
||||
* implementation throws {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @param path
|
||||
* the path of the file to open or create
|
||||
* @param options
|
||||
* options specifying how the file is opened
|
||||
* @param attrs
|
||||
* An optional list of file attributes to set atomically when
|
||||
* an optional list of file attributes to set atomically when
|
||||
* creating the file
|
||||
*
|
||||
* @return A new file channel
|
||||
* @return a new file channel
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the set contains an invalid combination of options
|
||||
@ -387,11 +474,10 @@ public abstract class FileSystemProvider {
|
||||
|
||||
/**
|
||||
* Opens or creates a file for reading and/or writing, returning an
|
||||
* asynchronous file channel to access the file.
|
||||
*
|
||||
* <p> This method is invoked by the {@link
|
||||
* asynchronous file channel to access the file. This method works in
|
||||
* exactly the manner specified by the {@link
|
||||
* AsynchronousFileChannel#open(Path,Set,ExecutorService,FileAttribute[])
|
||||
* AsynchronousFileChannel.open} method to open an asynchronous file channel.
|
||||
* AsynchronousFileChannel.open} method.
|
||||
* A provider that does not support all the features required to construct
|
||||
* an asynchronous file channel throws {@code UnsupportedOperationException}.
|
||||
* The default provider is required to support the creation of asynchronous
|
||||
@ -399,17 +485,17 @@ public abstract class FileSystemProvider {
|
||||
* method throws {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @param path
|
||||
* The path of the file to open or create
|
||||
* the path of the file to open or create
|
||||
* @param options
|
||||
* Options specifying how the file is opened
|
||||
* options specifying how the file is opened
|
||||
* @param executor
|
||||
* The thread pool or {@code null} to associate the channel with
|
||||
* the thread pool or {@code null} to associate the channel with
|
||||
* the default thread pool
|
||||
* @param attrs
|
||||
* An optional list of file attributes to set atomically when
|
||||
* an optional list of file attributes to set atomically when
|
||||
* creating the file
|
||||
*
|
||||
* @return A new asynchronous file channel
|
||||
* @return a new asynchronous file channel
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the set contains an invalid combination of options
|
||||
@ -434,4 +520,569 @@ public abstract class FileSystemProvider {
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens or creates a file, returning a seekable byte channel to access the
|
||||
* file. This method works in exactly the manner specified by the {@link
|
||||
* Files#newByteChannel(Path,Set,FileAttribute[])} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file to open or create
|
||||
* @param options
|
||||
* options specifying how the file is opened
|
||||
* @param attrs
|
||||
* an optional list of file attributes to set atomically when
|
||||
* creating the file
|
||||
*
|
||||
* @return a new seekable byte channel
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the set contains an invalid combination of options
|
||||
* @throws UnsupportedOperationException
|
||||
* if an unsupported open option is specified or the array contains
|
||||
* attributes that cannot be set atomically when creating the file
|
||||
* @throws FileAlreadyExistsException
|
||||
* if a file of that name already exists and the {@link
|
||||
* StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified
|
||||
* <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the path if the file is
|
||||
* opened for reading. The {@link SecurityManager#checkWrite(String)
|
||||
* checkWrite} method is invoked to check write access to the path
|
||||
* if the file is opened for writing. The {@link
|
||||
* SecurityManager#checkDelete(String) checkDelete} method is
|
||||
* invoked to check delete access if the file is opened with the
|
||||
* {@code DELETE_ON_CLOSE} option.
|
||||
*/
|
||||
public abstract SeekableByteChannel newByteChannel(Path path,
|
||||
Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a directory, returning a {@code DirectoryStream} to iterate over
|
||||
* the entries in the directory. This method works in exactly the manner
|
||||
* specified by the {@link
|
||||
* Files#newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter)}
|
||||
* method.
|
||||
*
|
||||
* @param dir
|
||||
* the path to the directory
|
||||
* @param filter
|
||||
* the directory stream filter
|
||||
*
|
||||
* @return a new and open {@code DirectoryStream} object
|
||||
*
|
||||
* @throws NotDirectoryException
|
||||
* if the file could not otherwise be opened because it is not
|
||||
* a directory <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the directory.
|
||||
*/
|
||||
public abstract DirectoryStream<Path> newDirectoryStream(Path dir,
|
||||
DirectoryStream.Filter<? super Path> filter) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a new directory. This method works in exactly the manner
|
||||
* specified by the {@link Files#createDirectory} method.
|
||||
*
|
||||
* @param dir
|
||||
* the directory to create
|
||||
* @param attrs
|
||||
* an optional list of file attributes to set atomically when
|
||||
* creating the directory
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the array contains an attribute that cannot be set atomically
|
||||
* when creating the directory
|
||||
* @throws FileAlreadyExistsException
|
||||
* if a directory could not otherwise be created because a file of
|
||||
* that name already exists <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs or the parent directory does not exist
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method is invoked to check write access to the new directory.
|
||||
*/
|
||||
public abstract void createDirectory(Path dir, FileAttribute<?>... attrs)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a symbolic link to a target. This method works in exactly the
|
||||
* manner specified by the {@link Files#createSymbolicLink} method.
|
||||
*
|
||||
* <p> The default implementation of this method throws {@code
|
||||
* UnsupportedOperationException}.
|
||||
*
|
||||
* @param link
|
||||
* the path of the symbolic link to create
|
||||
* @param target
|
||||
* the target of the symbolic link
|
||||
* @param attrs
|
||||
* the array of attributes to set atomically when creating the
|
||||
* symbolic link
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the implementation does not support symbolic links or the
|
||||
* array contains an attribute that cannot be set atomically when
|
||||
* creating the symbolic link
|
||||
* @throws FileAlreadyExistsException
|
||||
* if a file with the name already exists <i>(optional specific
|
||||
* exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, it denies {@link LinkPermission}<tt>("symbolic")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the path of the symbolic link.
|
||||
*/
|
||||
public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new link (directory entry) for an existing file. This method
|
||||
* works in exactly the manner specified by the {@link Files#createLink}
|
||||
* method.
|
||||
*
|
||||
* <p> The default implementation of this method throws {@code
|
||||
* UnsupportedOperationException}.
|
||||
*
|
||||
* @param link
|
||||
* the link (directory entry) to create
|
||||
* @param existing
|
||||
* a path to an existing file
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the implementation does not support adding an existing file
|
||||
* to a directory
|
||||
* @throws FileAlreadyExistsException
|
||||
* if the entry could not otherwise be created because a file of
|
||||
* that name already exists <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, it denies {@link LinkPermission}<tt>("hard")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to either the link or the
|
||||
* existing file.
|
||||
*/
|
||||
public void createLink(Path link, Path existing) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file. This method works in exactly the manner specified by the
|
||||
* {@link Files#delete} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file to delete
|
||||
*
|
||||
* @throws NoSuchFileException
|
||||
* if the file does not exist <i>(optional specific exception)</i>
|
||||
* @throws DirectoryNotEmptyException
|
||||
* if the file is a directory and could not otherwise be deleted
|
||||
* because the directory is not empty <i>(optional specific
|
||||
* exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkDelete(String)} method
|
||||
* is invoked to check delete access to the file
|
||||
*/
|
||||
public abstract void delete(Path path) throws IOException;
|
||||
|
||||
/**
|
||||
* Deletes a file if it exists. This method works in exactly the manner
|
||||
* specified by the {@link Files#deleteIfExists} method.
|
||||
*
|
||||
* <p> The default implementation of this method simply invokes {@link
|
||||
* #delete} ignoring the {@code NoSuchFileException} when the file does not
|
||||
* exist. It may be overridden where appropriate.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file to delete
|
||||
*
|
||||
* @return {@code true} if the file was deleted by this method; {@code
|
||||
* false} if the file could not be deleted because it did not
|
||||
* exist
|
||||
*
|
||||
* @throws DirectoryNotEmptyException
|
||||
* if the file is a directory and could not otherwise be deleted
|
||||
* because the directory is not empty <i>(optional specific
|
||||
* exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkDelete(String)} method
|
||||
* is invoked to check delete access to the file
|
||||
*/
|
||||
public boolean deleteIfExists(Path path) throws IOException {
|
||||
try {
|
||||
delete(path);
|
||||
return true;
|
||||
} catch (NoSuchFileException ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the target of a symbolic link. This method works in exactly the
|
||||
* manner specified by the {@link Files#readSymbolicLink} method.
|
||||
*
|
||||
* <p> The default implementation of this method throws {@code
|
||||
* UnsupportedOperationException}.
|
||||
*
|
||||
* @param link
|
||||
* the path to the symbolic link
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the implementation does not support symbolic links
|
||||
* @throws NotLinkException
|
||||
* if the target could otherwise not be read because the file
|
||||
* is not a symbolic link <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, it checks that {@code FilePermission} has been
|
||||
* granted with the "{@code readlink}" action to read the link.
|
||||
*/
|
||||
public Path readSymbolicLink(Path link) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file to a target file. This method works in exactly the manner
|
||||
* specified by the {@link Files#copy(Path,Path,CopyOption[])} method
|
||||
* except that both the source and target paths must be associated with
|
||||
* this provider.
|
||||
*
|
||||
* @param source
|
||||
* the path to the file to copy
|
||||
* @param target
|
||||
* the path to the target file
|
||||
* @param options
|
||||
* options specifying how the copy should be done
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the array contains a copy option that is not supported
|
||||
* @throws FileAlreadyExistsException
|
||||
* if the target file exists but cannot be replaced because the
|
||||
* {@code REPLACE_EXISTING} option is not specified <i>(optional
|
||||
* specific exception)</i>
|
||||
* @throws DirectoryNotEmptyException
|
||||
* the {@code REPLACE_EXISTING} option is specified but the file
|
||||
* cannot be replaced because it is a non-empty directory
|
||||
* <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the source file, the
|
||||
* {@link SecurityManager#checkWrite(String) checkWrite} is invoked
|
||||
* to check write access to the target file. If a symbolic link is
|
||||
* copied the security manager is invoked to check {@link
|
||||
* LinkPermission}{@code ("symbolic")}.
|
||||
*/
|
||||
public abstract void copy(Path source, Path target, CopyOption... options)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Move or rename a file to a target file. This method works in exactly the
|
||||
* manner specified by the {@link Files#move} method except that both the
|
||||
* source and target paths must be associated with this provider.
|
||||
*
|
||||
* @param source
|
||||
* the path to the file to move
|
||||
* @param target
|
||||
* the path to the target file
|
||||
* @param options
|
||||
* options specifying how the move should be done
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the array contains a copy option that is not supported
|
||||
* @throws FileAlreadyExistsException
|
||||
* if the target file exists but cannot be replaced because the
|
||||
* {@code REPLACE_EXISTING} option is not specified <i>(optional
|
||||
* specific exception)</i>
|
||||
* @throws DirectoryNotEmptyException
|
||||
* the {@code REPLACE_EXISTING} option is specified but the file
|
||||
* cannot be replaced because it is a non-empty directory
|
||||
* <i>(optional specific exception)</i>
|
||||
* @throws AtomicMoveNotSupportedException
|
||||
* if the options array contains the {@code ATOMIC_MOVE} option but
|
||||
* the file cannot be moved as an atomic file system operation.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method is invoked to check write access to both the source and
|
||||
* target file.
|
||||
*/
|
||||
public abstract void move(Path source, Path target, CopyOption... options)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Tests if two paths locate the same file. This method works in exactly the
|
||||
* manner specified by the {@link Files#isSameFile} method.
|
||||
*
|
||||
* @param path
|
||||
* one path to the file
|
||||
* @param path2
|
||||
* the other path
|
||||
*
|
||||
* @return {@code true} if, and only if, the two paths locate the same file
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to both files.
|
||||
*/
|
||||
public abstract boolean isSameFile(Path path, Path path2)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Tells whether or not a file is considered <em>hidden</em>. This method
|
||||
* works in exactly the manner specified by the {@link Files#isHidden}
|
||||
* method.
|
||||
*
|
||||
* <p> This method is invoked by the {@link Files#isHidden isHidden} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file to test
|
||||
*
|
||||
* @return {@code true} if the file is considered hidden
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file.
|
||||
*/
|
||||
public abstract boolean isHidden(Path path) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the {@link FileStore} representing the file store where a file
|
||||
* is located. This method works in exactly the manner specified by the
|
||||
* {@link Files#getFileStore} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file
|
||||
*
|
||||
* @return the file store where the file is stored
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file, and in
|
||||
* addition it checks {@link RuntimePermission}<tt>
|
||||
* ("getFileStoreAttributes")</tt>
|
||||
*/
|
||||
public abstract FileStore getFileStore(Path path) throws IOException;
|
||||
|
||||
/**
|
||||
* Checks the existence, and optionally the accessibility, of a file.
|
||||
*
|
||||
* <p> This method may be used by the {@link Files#isReadable isReadable},
|
||||
* {@link Files#isWritable isWritable} and {@link Files#isExecutable
|
||||
* isExecutable} methods to check the accessibility of a file.
|
||||
*
|
||||
* <p> This method checks the existence of a file and that this Java virtual
|
||||
* machine has appropriate privileges that would allow it access the file
|
||||
* according to all of access modes specified in the {@code modes} parameter
|
||||
* as follows:
|
||||
*
|
||||
* <table border=1 cellpadding=5 summary="">
|
||||
* <tr> <th>Value</th> <th>Description</th> </tr>
|
||||
* <tr>
|
||||
* <td> {@link AccessMode#READ READ} </td>
|
||||
* <td> Checks that the file exists and that the Java virtual machine has
|
||||
* permission to read the file. </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link AccessMode#WRITE WRITE} </td>
|
||||
* <td> Checks that the file exists and that the Java virtual machine has
|
||||
* permission to write to the file, </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link AccessMode#EXECUTE EXECUTE} </td>
|
||||
* <td> Checks that the file exists and that the Java virtual machine has
|
||||
* permission to {@link Runtime#exec execute} the file. The semantics
|
||||
* may differ when checking access to a directory. For example, on UNIX
|
||||
* systems, checking for {@code EXECUTE} access checks that the Java
|
||||
* virtual machine has permission to search the directory in order to
|
||||
* access file or subdirectories. </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p> If the {@code modes} parameter is of length zero, then the existence
|
||||
* of the file is checked.
|
||||
*
|
||||
* <p> This method follows symbolic links if the file referenced by this
|
||||
* object is a symbolic link. Depending on the implementation, this method
|
||||
* may require to read file permissions, access control lists, or other
|
||||
* file attributes in order to check the effective access to the file. To
|
||||
* determine the effective access to a file may require access to several
|
||||
* attributes and so in some implementations this method may not be atomic
|
||||
* with respect to other file system operations.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file to check
|
||||
* @param modes
|
||||
* The access modes to check; may have zero elements
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* an implementation is required to support checking for
|
||||
* {@code READ}, {@code WRITE}, and {@code EXECUTE} access. This
|
||||
* exception is specified to allow for the {@code Access} enum to
|
||||
* be extended in future releases.
|
||||
* @throws NoSuchFileException
|
||||
* if a file does not exist <i>(optional specific exception)</i>
|
||||
* @throws AccessDeniedException
|
||||
* the requested access would be denied or the access cannot be
|
||||
* determined because the Java virtual machine has insufficient
|
||||
* privileges or other reasons. <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* is invoked when checking read access to the file or only the
|
||||
* existence of the file, the {@link SecurityManager#checkWrite(String)
|
||||
* checkWrite} is invoked when checking write access to the file,
|
||||
* and {@link SecurityManager#checkExec(String) checkExec} is invoked
|
||||
* when checking execute access.
|
||||
*/
|
||||
public abstract void checkAccess(Path path, AccessMode... modes)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a file attribute view of a given type. This method works in
|
||||
* exactly the manner specified by the {@link Files#getFileAttributeView}
|
||||
* method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file
|
||||
* @param type
|
||||
* the {@code Class} object corresponding to the file attribute view
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
*
|
||||
* @return a file attribute view of the specified type, or {@code null} if
|
||||
* the attribute view type is not available
|
||||
*/
|
||||
public abstract <V extends FileAttributeView> V
|
||||
getFileAttributeView(Path path, Class<V> type, LinkOption... options);
|
||||
|
||||
/**
|
||||
* Reads a file's attributes as a bulk operation. This method works in
|
||||
* exactly the manner specified by the {@link
|
||||
* Files#readAttributes(Path,Class,LinkOption[])} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file
|
||||
* @param type
|
||||
* the {@code Class} of the file attributes required
|
||||
* to read
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
*
|
||||
* @return the file attributes
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if an attributes of the given type are not supported
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, a security manager is
|
||||
* installed, its {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file
|
||||
*/
|
||||
public abstract <A extends BasicFileAttributes> A
|
||||
readAttributes(Path path, Class<A> type, LinkOption... options) throws IOException;
|
||||
|
||||
/**
|
||||
* Reads a set of file attributes as a bulk operation. This method works in
|
||||
* exactly the manner specified by the {@link
|
||||
* Files#readAttributes(Path,String,LinkOption[])} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file
|
||||
* @param attributes
|
||||
* the attributes to read
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
*
|
||||
* @return a map of the attributes returned; may be empty. The map's keys
|
||||
* are the attribute names, its values are the attribute values
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, its {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method denies read access to the file. If this method is invoked
|
||||
* to read security sensitive attributes then the security manager
|
||||
* may be invoke to check for additional permissions.
|
||||
*/
|
||||
public abstract Map<String,Object> readAttributes(Path path, String attributes,
|
||||
LinkOption... options)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the value of a file attribute. This method works in exactly the
|
||||
* manner specified by the {@link Files#setAttribute} method.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file
|
||||
* @param attribute
|
||||
* the attribute to set
|
||||
* @param value
|
||||
* the attribute value
|
||||
* @param options
|
||||
* options indicating how symbolic links are handled
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the attribute view is not available or it does not support
|
||||
* updating the attribute
|
||||
* @throws IllegalArgumentException
|
||||
* if the attribute value is of the correct type but has an
|
||||
* inappropriate value
|
||||
* @throws ClassCastException
|
||||
* If the attribute value is not of the expected type or is a
|
||||
* collection containing elements that are not of the expected
|
||||
* type
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the file. If this method is invoked
|
||||
* to set security sensitive attributes then the security manager
|
||||
* may be invoked to check for additional permissions.
|
||||
*/
|
||||
public abstract void setAttribute(Path path, String attribute,
|
||||
Object value, LinkOption... options)
|
||||
throws IOException;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package java.nio.file.spi;
|
||||
|
||||
import java.nio.file.FileRef;
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ import java.io.IOException;
|
||||
* href="../attribute/package-summary.html"> attribute</a> or the bytes in a
|
||||
* file may be examined to guess its file type.
|
||||
*
|
||||
* @see java.nio.file.Files#probeContentType(FileRef)
|
||||
* @see java.nio.file.Files#probeContentType(Path)
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
@ -83,8 +83,8 @@ public abstract class FileTypeDetector {
|
||||
* Message Bodies</i></a>. The string must be parsable according to the
|
||||
* grammar in the RFC 2045.
|
||||
*
|
||||
* @param file
|
||||
* The file to probe
|
||||
* @param path
|
||||
* the path to the file to probe
|
||||
*
|
||||
* @return The content type or {@code null} if the file type is not
|
||||
* recognized
|
||||
@ -101,6 +101,6 @@ public abstract class FileTypeDetector {
|
||||
*
|
||||
* @see java.nio.file.Files#probeContentType
|
||||
*/
|
||||
public abstract String probeContentType(FileRef file)
|
||||
public abstract String probeContentType(Path path)
|
||||
throws IOException;
|
||||
}
|
||||
|
@ -25,7 +25,8 @@
|
||||
|
||||
package java.util;
|
||||
|
||||
import java.nio.file.FileRef;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Files;
|
||||
import java.util.regex.*;
|
||||
import java.io.*;
|
||||
import java.math.*;
|
||||
@ -699,16 +700,16 @@ public final class Scanner implements Iterator<String>, Closeable {
|
||||
* {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
|
||||
*
|
||||
* @param source
|
||||
* A file to be scanned
|
||||
* the path to the file to be scanned
|
||||
* @throws IOException
|
||||
* if an I/O error occurs opening source
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public Scanner(FileRef source)
|
||||
public Scanner(Path source)
|
||||
throws IOException
|
||||
{
|
||||
this(source.newInputStream());
|
||||
this(Files.newInputStream(source));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -717,7 +718,7 @@ public final class Scanner implements Iterator<String>, Closeable {
|
||||
* characters using the specified charset.
|
||||
*
|
||||
* @param source
|
||||
* A file to be scanned
|
||||
* the path to the file to be scanned
|
||||
* @param charsetName
|
||||
* The encoding type used to convert bytes from the file
|
||||
* into characters to be scanned
|
||||
@ -727,12 +728,12 @@ public final class Scanner implements Iterator<String>, Closeable {
|
||||
* if the specified encoding is not found
|
||||
* @since 1.7
|
||||
*/
|
||||
public Scanner(FileRef source, String charsetName) throws IOException {
|
||||
public Scanner(Path source, String charsetName) throws IOException {
|
||||
this(Objects.nonNull(source), toCharset(charsetName));
|
||||
}
|
||||
|
||||
private Scanner(FileRef source, Charset charset) throws IOException {
|
||||
this(makeReadable(source.newInputStream(), charset));
|
||||
private Scanner(Path source, Charset charset) throws IOException {
|
||||
this(makeReadable(Files.newInputStream(source), charset));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,15 +44,6 @@ abstract class AbstractAclFileAttributeView
|
||||
return "acl";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals(OWNER_NAME))
|
||||
return getOwner();
|
||||
if (attribute.equals(ACL_NAME))
|
||||
return getAcl();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final void setAttribute(String attribute, Object value)
|
||||
@ -71,7 +62,7 @@ abstract class AbstractAclFileAttributeView
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String,?> readAttributes(String[] attributes)
|
||||
public final Map<String,Object> readAttributes(String[] attributes)
|
||||
throws IOException
|
||||
{
|
||||
boolean acl = false;
|
||||
@ -91,7 +82,7 @@ abstract class AbstractAclFileAttributeView
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Map<String,Object> result = new HashMap<String,Object>(2);
|
||||
Map<String,Object> result = new HashMap<>(2);
|
||||
if (acl)
|
||||
result.put(ACL_NAME, getAcl());
|
||||
if (owner)
|
||||
|
@ -53,30 +53,6 @@ abstract class AbstractBasicFileAttributeView
|
||||
return "basic";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
BasicFileAttributes attrs = readAttributes();
|
||||
if (attribute.equals(SIZE_NAME))
|
||||
return attrs.size();
|
||||
if (attribute.equals(CREATION_TIME_NAME))
|
||||
return attrs.creationTime();
|
||||
if (attribute.equals(LAST_ACCESS_TIME_NAME))
|
||||
return attrs.lastAccessTime();
|
||||
if (attribute.equals(LAST_MODIFIED_TIME_NAME))
|
||||
return attrs.lastModifiedTime();
|
||||
if (attribute.equals(FILE_KEY_NAME))
|
||||
return attrs.fileKey();
|
||||
if (attribute.equals(IS_DIRECTORY_NAME))
|
||||
return attrs.isDirectory();
|
||||
if (attribute.equals(IS_REGULAR_FILE_NAME))
|
||||
return attrs.isRegularFile();
|
||||
if (attribute.equals(IS_SYMBOLIC_LINK_NAME))
|
||||
return attrs.isSymbolicLink();
|
||||
if (attribute.equals(IS_OTHER_NAME))
|
||||
return attrs.isOther();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attribute, Object value)
|
||||
throws IOException
|
||||
@ -101,8 +77,8 @@ abstract class AbstractBasicFileAttributeView
|
||||
* Used to build a map of attribute name/values.
|
||||
*/
|
||||
static class AttributesBuilder {
|
||||
private Set<String> set = new HashSet<String>();
|
||||
private Map<String,Object> map = new HashMap<String,Object>();
|
||||
private Set<String> set = new HashSet<>();
|
||||
private Map<String,Object> map = new HashMap<>();
|
||||
private boolean copyAll;
|
||||
|
||||
private AttributesBuilder(String[] attributes) {
|
||||
@ -172,7 +148,7 @@ abstract class AbstractBasicFileAttributeView
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String[] attributes) throws IOException {
|
||||
public Map<String,Object> readAttributes(String[] attributes) throws IOException {
|
||||
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||
addBasicAttributesToBuilder(readAttributes(), builder);
|
||||
return builder.unmodifiableMap();
|
||||
|
107
jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
Normal file
107
jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Base implementation class of FileSystemProvider
|
||||
*/
|
||||
|
||||
abstract class AbstractFileSystemProvider extends FileSystemProvider {
|
||||
protected AbstractFileSystemProvider() { }
|
||||
|
||||
/**
|
||||
* Splits the given attribute name into the name of an attribute view and
|
||||
* the attribute. If the attribute view is not identified then it assumed
|
||||
* to be "basic".
|
||||
*/
|
||||
private static String[] split(String attribute) {
|
||||
String[] s = new String[2];
|
||||
int pos = attribute.indexOf(':');
|
||||
if (pos == -1) {
|
||||
s[0] = "basic";
|
||||
s[1] = attribute;
|
||||
} else {
|
||||
s[0] = attribute.substring(0, pos++);
|
||||
s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a DynamicFileAttributeView by name. Returns {@code null} if the
|
||||
* view is not available.
|
||||
*/
|
||||
abstract DynamicFileAttributeView getFileAttributeView(Path file,
|
||||
String name,
|
||||
LinkOption... options);
|
||||
|
||||
@Override
|
||||
public final void setAttribute(Path file,
|
||||
String attribute,
|
||||
Object value,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
String[] s = split(attribute);
|
||||
DynamicFileAttributeView view = getFileAttributeView(file, s[0], options);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException("View '" + s[0] + "' not available");
|
||||
view.setAttribute(s[1], value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String,Object> readAttributes(Path file, String attributes, LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
String[] s = split(attributes);
|
||||
DynamicFileAttributeView view = getFileAttributeView(file, s[0], options);
|
||||
if (view == null)
|
||||
return Collections.emptyMap();
|
||||
return view.readAttributes(s[1].split(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file. The {@code failIfNotExists} parameters determines if an
|
||||
* {@code IOException} is thrown when the file does not exist.
|
||||
*/
|
||||
abstract boolean implDelete(Path file, boolean failIfNotExists) throws IOException;
|
||||
|
||||
@Override
|
||||
public final void delete(Path file) throws IOException {
|
||||
implDelete(file, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean deleteIfExists(Path file) throws IOException {
|
||||
return implDelete(file, false);
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.FileRef;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.spi.FileTypeDetector;
|
||||
import java.util.Locale;
|
||||
import java.io.IOException;
|
||||
@ -46,7 +46,7 @@ public abstract class AbstractFileTypeDetector
|
||||
* and checks that the content type's syntax is valid.
|
||||
*/
|
||||
@Override
|
||||
public final String probeContentType(FileRef file) throws IOException {
|
||||
public final String probeContentType(Path file) throws IOException {
|
||||
if (file == null)
|
||||
throw new NullPointerException("'file' is null");
|
||||
String result = implProbeContentType(file);
|
||||
@ -56,7 +56,7 @@ public abstract class AbstractFileTypeDetector
|
||||
/**
|
||||
* Probes the given file to guess its content type.
|
||||
*/
|
||||
protected abstract String implProbeContentType(FileRef file)
|
||||
protected abstract String implProbeContentType(Path file)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
|
@ -26,391 +26,81 @@
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Base implementation class for a {@code Path}.
|
||||
* Base implementation class of {@code Path}.
|
||||
*/
|
||||
|
||||
abstract class AbstractPath extends Path {
|
||||
abstract class AbstractPath implements Path {
|
||||
protected AbstractPath() { }
|
||||
|
||||
@Override
|
||||
public final Path createFile(FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
EnumSet<StandardOpenOption> options = EnumSet.of(CREATE_NEW, WRITE);
|
||||
SeekableByteChannel sbc = newByteChannel(options, attrs);
|
||||
try {
|
||||
sbc.close();
|
||||
} catch (IOException x) {
|
||||
// ignore
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file. The {@code failIfNotExists} parameters determines if an
|
||||
* {@code IOException} is thrown when the file does not exist.
|
||||
*/
|
||||
abstract void implDelete(boolean failIfNotExists) throws IOException;
|
||||
|
||||
@Override
|
||||
public final void delete() throws IOException {
|
||||
implDelete(true);
|
||||
public final boolean startsWith(String other) {
|
||||
return startsWith(getFileSystem().getPath(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteIfExists() throws IOException {
|
||||
implDelete(false);
|
||||
public final boolean endsWith(String other) {
|
||||
return endsWith(getFileSystem().getPath(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final InputStream newInputStream(OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if (options.length > 0) {
|
||||
for (OpenOption opt: options) {
|
||||
if (opt != READ)
|
||||
throw new UnsupportedOperationException("'" + opt + "' not allowed");
|
||||
}
|
||||
}
|
||||
return Channels.newInputStream(newByteChannel());
|
||||
public final Path resolve(String other) {
|
||||
return resolve(getFileSystem().getPath(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final OutputStream newOutputStream(OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
int len = options.length;
|
||||
Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
|
||||
if (len == 0) {
|
||||
opts.add(CREATE);
|
||||
opts.add(TRUNCATE_EXISTING);
|
||||
} else {
|
||||
for (OpenOption opt: options) {
|
||||
if (opt == READ)
|
||||
throw new IllegalArgumentException("READ not allowed");
|
||||
opts.add(opt);
|
||||
}
|
||||
}
|
||||
opts.add(WRITE);
|
||||
return Channels.newOutputStream(newByteChannel(opts));
|
||||
public final Path resolveSibling(Path other) {
|
||||
if (other == null)
|
||||
throw new NullPointerException();
|
||||
Path parent = getParent();
|
||||
return (parent == null) ? other : parent.resolve(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SeekableByteChannel newByteChannel(OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
Set<OpenOption> set = new HashSet<OpenOption>(options.length);
|
||||
Collections.addAll(set, options);
|
||||
return newByteChannel(set);
|
||||
}
|
||||
|
||||
private static final DirectoryStream.Filter<Path> acceptAllFilter =
|
||||
new DirectoryStream.Filter<Path>() {
|
||||
@Override public boolean accept(Path entry) { return true; }
|
||||
};
|
||||
|
||||
@Override
|
||||
public final DirectoryStream<Path> newDirectoryStream() throws IOException {
|
||||
return newDirectoryStream(acceptAllFilter);
|
||||
public final Path resolveSibling(String other) {
|
||||
return resolveSibling(getFileSystem().getPath(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DirectoryStream<Path> newDirectoryStream(String glob)
|
||||
throws IOException
|
||||
{
|
||||
// avoid creating a matcher if all entries are required.
|
||||
if (glob.equals("*"))
|
||||
return newDirectoryStream();
|
||||
|
||||
// create a matcher and return a filter that uses it.
|
||||
final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob);
|
||||
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
|
||||
public final Iterator<Path> iterator() {
|
||||
return new Iterator<Path>() {
|
||||
private int i = 0;
|
||||
@Override
|
||||
public boolean accept(Path entry) {
|
||||
return matcher.matches(entry.getName());
|
||||
public boolean hasNext() {
|
||||
return (i < getNameCount());
|
||||
}
|
||||
@Override
|
||||
public Path next() {
|
||||
if (i < getNameCount()) {
|
||||
Path result = getName(i);
|
||||
i++;
|
||||
return result;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return newDirectoryStream(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean exists() {
|
||||
try {
|
||||
checkAccess();
|
||||
return true;
|
||||
} catch (IOException x) {
|
||||
// unable to determine if file exists
|
||||
}
|
||||
return false;
|
||||
public final File toFile() {
|
||||
return new File(toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean notExists() {
|
||||
try {
|
||||
checkAccess();
|
||||
return false;
|
||||
} catch (NoSuchFileException x) {
|
||||
// file confirmed not to exist
|
||||
return true;
|
||||
} catch (IOException x) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0];
|
||||
|
||||
@Override
|
||||
public final WatchKey register(WatchService watcher,
|
||||
WatchEvent.Kind<?>... events)
|
||||
throws IOException
|
||||
{
|
||||
return register(watcher, events, NO_MODIFIERS);
|
||||
}
|
||||
|
||||
abstract void implCopyTo(Path target, CopyOption... options)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public final Path copyTo(Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if ((getFileSystem().provider() == target.getFileSystem().provider())) {
|
||||
implCopyTo(target, options);
|
||||
} else {
|
||||
copyToForeignTarget(target, options);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
abstract void implMoveTo(Path target, CopyOption... options)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public final Path moveTo(Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if ((getFileSystem().provider() == target.getFileSystem().provider())) {
|
||||
implMoveTo(target, options);
|
||||
} else {
|
||||
// different providers so copy + delete
|
||||
copyToForeignTarget(target, convertMoveToCopyOptions(options));
|
||||
delete();
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given array of options for moving a file to options suitable
|
||||
* for copying the file when a move is implemented as copy + delete.
|
||||
*/
|
||||
private static CopyOption[] convertMoveToCopyOptions(CopyOption... options)
|
||||
throws AtomicMoveNotSupportedException
|
||||
{
|
||||
int len = options.length;
|
||||
CopyOption[] newOptions = new CopyOption[len+2];
|
||||
for (int i=0; i<len; i++) {
|
||||
CopyOption option = options[i];
|
||||
if (option == StandardCopyOption.ATOMIC_MOVE) {
|
||||
throw new AtomicMoveNotSupportedException(null, null,
|
||||
"Atomic move between providers is not supported");
|
||||
}
|
||||
newOptions[i] = option;
|
||||
}
|
||||
newOptions[len] = LinkOption.NOFOLLOW_LINKS;
|
||||
newOptions[len+1] = StandardCopyOption.COPY_ATTRIBUTES;
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the arguments for a file copy operation.
|
||||
*/
|
||||
private static class CopyOptions {
|
||||
boolean replaceExisting = false;
|
||||
boolean copyAttributes = false;
|
||||
boolean followLinks = true;
|
||||
|
||||
private CopyOptions() { }
|
||||
|
||||
static CopyOptions parse(CopyOption... options) {
|
||||
CopyOptions result = new CopyOptions();
|
||||
for (CopyOption option: options) {
|
||||
if (option == StandardCopyOption.REPLACE_EXISTING) {
|
||||
result.replaceExisting = true;
|
||||
continue;
|
||||
}
|
||||
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||||
result.followLinks = false;
|
||||
continue;
|
||||
}
|
||||
if (option == StandardCopyOption.COPY_ATTRIBUTES) {
|
||||
result.copyAttributes = true;
|
||||
continue;
|
||||
}
|
||||
if (option == null)
|
||||
throw new NullPointerException();
|
||||
throw new UnsupportedOperationException("'" + option +
|
||||
"' is not a recognized copy option");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple cross-provider copy where the target is a Path.
|
||||
*/
|
||||
private void copyToForeignTarget(Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
CopyOptions opts = CopyOptions.parse(options);
|
||||
LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] :
|
||||
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
|
||||
|
||||
// attributes of source file
|
||||
BasicFileAttributes attrs = Attributes
|
||||
.readBasicFileAttributes(this, linkOptions);
|
||||
if (attrs.isSymbolicLink())
|
||||
throw new IOException("Copying of symbolic links not supported");
|
||||
|
||||
// check if target exists
|
||||
boolean exists;
|
||||
if (opts.replaceExisting) {
|
||||
try {
|
||||
target.deleteIfExists();
|
||||
exists = false;
|
||||
} catch (DirectoryNotEmptyException x) {
|
||||
// let exception translate to FileAlreadyExistsException (6895012)
|
||||
exists = true;
|
||||
}
|
||||
} else {
|
||||
exists = target.exists();
|
||||
}
|
||||
if (exists)
|
||||
throw new FileAlreadyExistsException(target.toString());
|
||||
|
||||
// create directory or file
|
||||
if (attrs.isDirectory()) {
|
||||
target.createDirectory();
|
||||
} else {
|
||||
copyRegularFileToForeignTarget(target);
|
||||
}
|
||||
|
||||
// copy basic attributes to target
|
||||
if (opts.copyAttributes) {
|
||||
BasicFileAttributeView view = target
|
||||
.getFileAttributeView(BasicFileAttributeView.class, linkOptions);
|
||||
try {
|
||||
view.setTimes(attrs.lastModifiedTime(),
|
||||
attrs.lastAccessTime(),
|
||||
attrs.creationTime());
|
||||
} catch (IOException x) {
|
||||
// rollback
|
||||
try {
|
||||
target.delete();
|
||||
} catch (IOException ignore) { }
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple copy of regular file to a target file that exists.
|
||||
*/
|
||||
private void copyRegularFileToForeignTarget(Path target)
|
||||
throws IOException
|
||||
{
|
||||
ReadableByteChannel rbc = newByteChannel();
|
||||
try {
|
||||
// open target file for writing
|
||||
SeekableByteChannel sbc = target.newByteChannel(CREATE_NEW, WRITE);
|
||||
|
||||
// simple copy loop
|
||||
try {
|
||||
ByteBuffer buf = ByteBuffer.wrap(new byte[8192]);
|
||||
int n = 0;
|
||||
for (;;) {
|
||||
n = rbc.read(buf);
|
||||
if (n < 0)
|
||||
break;
|
||||
assert n > 0;
|
||||
buf.flip();
|
||||
while (buf.hasRemaining()) {
|
||||
sbc.write(buf);
|
||||
}
|
||||
buf.rewind();
|
||||
}
|
||||
|
||||
} finally {
|
||||
sbc.close();
|
||||
}
|
||||
} finally {
|
||||
rbc.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the given attribute name into the name of an attribute view and
|
||||
* the attribute. If the attribute view is not identified then it assumed
|
||||
* to be "basic".
|
||||
*/
|
||||
private static String[] split(String attribute) {
|
||||
String[] s = new String[2];
|
||||
int pos = attribute.indexOf(':');
|
||||
if (pos == -1) {
|
||||
s[0] = "basic";
|
||||
s[1] = attribute;
|
||||
} else {
|
||||
s[0] = attribute.substring(0, pos++);
|
||||
s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a DynamicFileAttributeView by name. Returns {@code null} if the
|
||||
* view is not available.
|
||||
*/
|
||||
abstract DynamicFileAttributeView getFileAttributeView(String name,
|
||||
LinkOption... options);
|
||||
|
||||
@Override
|
||||
public final void setAttribute(String attribute,
|
||||
Object value,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
String[] s = split(attribute);
|
||||
DynamicFileAttributeView view = getFileAttributeView(s[0], options);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException("View '" + s[0] + "' not available");
|
||||
view.setAttribute(s[1], value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getAttribute(String attribute, LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
String[] s = split(attribute);
|
||||
DynamicFileAttributeView view = getFileAttributeView(s[0], options);
|
||||
return (view == null) ? null : view.getAttribute(s[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String,?> readAttributes(String attributes, LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
String[] s = split(attributes);
|
||||
DynamicFileAttributeView view = getFileAttributeView(s[0], options);
|
||||
if (view == null)
|
||||
return Collections.emptyMap();
|
||||
return view.readAttributes(s[1].split(","));
|
||||
return register(watcher, events, new WatchEvent.Modifier[0]);
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ abstract class AbstractPoller implements Runnable {
|
||||
/**
|
||||
* Requests, and waits on, poller thread to register given file.
|
||||
*/
|
||||
final WatchKey register(FileRef dir,
|
||||
final WatchKey register(Path dir,
|
||||
WatchEvent.Kind<?>[] events,
|
||||
WatchEvent.Modifier... modifiers)
|
||||
throws IOException
|
||||
@ -102,7 +102,7 @@ abstract class AbstractPoller implements Runnable {
|
||||
throw new NullPointerException();
|
||||
if (events.length == 0)
|
||||
throw new IllegalArgumentException("No events to register");
|
||||
Set<WatchEvent.Kind<?>> eventSet = new HashSet<WatchEvent.Kind<?>>(events.length);
|
||||
Set<WatchEvent.Kind<?>> eventSet = new HashSet<>(events.length);
|
||||
for (WatchEvent.Kind<?> event: events) {
|
||||
// standard events
|
||||
if (event == StandardWatchEventKind.ENTRY_CREATE ||
|
||||
|
@ -59,8 +59,7 @@ abstract class AbstractUserDefinedFileAttributeView
|
||||
return "user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getAttribute(String attribute) throws IOException {
|
||||
private Object getAttribute(String attribute) throws IOException {
|
||||
int size;
|
||||
try {
|
||||
size = size(attribute);
|
||||
@ -90,11 +89,11 @@ abstract class AbstractUserDefinedFileAttributeView
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String,?> readAttributes(String[] attributes)
|
||||
public final Map<String,Object> readAttributes(String[] attributes)
|
||||
throws IOException
|
||||
{
|
||||
// names of attributes to return
|
||||
List<String> names = new ArrayList<String>();
|
||||
List<String> names = new ArrayList<>();
|
||||
|
||||
for (String name: attributes) {
|
||||
if (name.equals("*")) {
|
||||
@ -106,7 +105,7 @@ abstract class AbstractUserDefinedFileAttributeView
|
||||
}
|
||||
|
||||
// read each value and return in map
|
||||
Map<String,Object> result = new HashMap<String,Object>();
|
||||
Map<String,Object> result = new HashMap<>();
|
||||
for (String name: names) {
|
||||
Object value = getAttribute(name);
|
||||
if (value != null)
|
||||
|
@ -32,7 +32,7 @@ import java.util.*;
|
||||
* Base implementation class for watch keys.
|
||||
*/
|
||||
|
||||
abstract class AbstractWatchKey extends WatchKey {
|
||||
abstract class AbstractWatchKey implements WatchKey {
|
||||
|
||||
/**
|
||||
* Maximum size of event list (in the future this may be tunable)
|
||||
@ -53,6 +53,9 @@ abstract class AbstractWatchKey extends WatchKey {
|
||||
// reference to watcher
|
||||
private final AbstractWatchService watcher;
|
||||
|
||||
// reference to the original directory
|
||||
private final Path dir;
|
||||
|
||||
// key state
|
||||
private State state;
|
||||
|
||||
@ -63,8 +66,9 @@ abstract class AbstractWatchKey extends WatchKey {
|
||||
// event for the context is an ENTRY_MODIFY event).
|
||||
private Map<Object,WatchEvent<?>> lastModifyEvents;
|
||||
|
||||
protected AbstractWatchKey(AbstractWatchService watcher) {
|
||||
protected AbstractWatchKey(Path dir, AbstractWatchService watcher) {
|
||||
this.watcher = watcher;
|
||||
this.dir = dir;
|
||||
this.state = State.READY;
|
||||
this.events = new ArrayList<WatchEvent<?>>();
|
||||
this.lastModifyEvents = new HashMap<Object,WatchEvent<?>>();
|
||||
@ -74,6 +78,13 @@ abstract class AbstractWatchKey extends WatchKey {
|
||||
return watcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the original watchable (Path)
|
||||
*/
|
||||
Path watchable() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues this key to the watch service
|
||||
*/
|
||||
@ -175,7 +186,7 @@ abstract class AbstractWatchKey extends WatchKey {
|
||||
/**
|
||||
* WatchEvent implementation
|
||||
*/
|
||||
private static class Event<T> extends WatchEvent<T> {
|
||||
private static class Event<T> implements WatchEvent<T> {
|
||||
private final WatchEvent.Kind<T> kind;
|
||||
private final T context;
|
||||
|
||||
|
@ -33,7 +33,7 @@ import java.io.IOException;
|
||||
* Base implementation class for watch services.
|
||||
*/
|
||||
|
||||
abstract class AbstractWatchService extends WatchService {
|
||||
abstract class AbstractWatchService implements WatchService {
|
||||
|
||||
// signaled keys waiting to be dequeued
|
||||
private final LinkedBlockingDeque<WatchKey> pendingKeys =
|
||||
@ -41,7 +41,7 @@ abstract class AbstractWatchService extends WatchService {
|
||||
|
||||
// special key to indicate that watch service is closed
|
||||
private final WatchKey CLOSE_KEY =
|
||||
new AbstractWatchKey(null) {
|
||||
new AbstractWatchKey(null, null) {
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
@ -54,7 +54,7 @@ abstract class AbstractWatchService extends WatchService {
|
||||
|
||||
// used when closing watch service
|
||||
private volatile boolean closed;
|
||||
private Object closeLock = new Object();
|
||||
private final Object closeLock = new Object();
|
||||
|
||||
protected AbstractWatchService() {
|
||||
}
|
||||
@ -93,7 +93,7 @@ abstract class AbstractWatchService extends WatchService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final WatchKey poll() {
|
||||
public final WatchKey poll() {
|
||||
checkOpen();
|
||||
WatchKey key = pendingKeys.poll();
|
||||
checkKey(key);
|
||||
|
@ -34,11 +34,6 @@ import java.io.IOException;
|
||||
*/
|
||||
|
||||
interface DynamicFileAttributeView {
|
||||
/**
|
||||
* Reads the value of an attribute.
|
||||
*/
|
||||
Object getAttribute(String attribute) throws IOException;
|
||||
|
||||
/**
|
||||
* Sets/updates the value of an attribute.
|
||||
*/
|
||||
@ -47,5 +42,5 @@ interface DynamicFileAttributeView {
|
||||
/**
|
||||
* Reads a set of file attributes as a bulk operation.
|
||||
*/
|
||||
Map<String,?> readAttributes(String[] attributes) throws IOException;
|
||||
Map<String,Object> readAttributes(String[] attributes) throws IOException;
|
||||
}
|
||||
|
@ -57,13 +57,6 @@ final class FileOwnerAttributeViewImpl
|
||||
return "owner";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals(OWNER_NAME))
|
||||
return getOwner();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attribute, Object value)
|
||||
throws IOException
|
||||
@ -77,8 +70,8 @@ final class FileOwnerAttributeViewImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String[] attributes) throws IOException {
|
||||
Map<String,Object> result = new HashMap<String,Object>();
|
||||
public Map<String,Object> readAttributes(String[] attributes) throws IOException {
|
||||
Map<String,Object> result = new HashMap<>();
|
||||
for (String attribute: attributes) {
|
||||
if (attribute.equals("*") || attribute.equals(OWNER_NAME)) {
|
||||
result.put(OWNER_NAME, getOwner());
|
||||
|
@ -146,7 +146,7 @@ class PollingWatchService
|
||||
throws IOException
|
||||
{
|
||||
// check file is a directory and get its file key if possible
|
||||
BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
|
||||
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
|
||||
if (!attrs.isDirectory()) {
|
||||
throw new NotDirectoryException(path.toString());
|
||||
}
|
||||
@ -164,7 +164,7 @@ class PollingWatchService
|
||||
watchKey = map.get(fileKey);
|
||||
if (watchKey == null) {
|
||||
// new registration
|
||||
watchKey = new PollingWatchKey(this, path, fileKey);
|
||||
watchKey = new PollingWatchKey(path, this, fileKey);
|
||||
map.put(fileKey, watchKey);
|
||||
} else {
|
||||
// update to existing registration
|
||||
@ -228,7 +228,6 @@ class PollingWatchService
|
||||
* directory and queue keys when entries are added, modified, or deleted.
|
||||
*/
|
||||
private class PollingWatchKey extends AbstractWatchKey {
|
||||
private final Path dir;
|
||||
private final Object fileKey;
|
||||
|
||||
// current event set
|
||||
@ -246,44 +245,28 @@ class PollingWatchService
|
||||
// map of entries in directory
|
||||
private Map<Path,CacheEntry> entries;
|
||||
|
||||
PollingWatchKey(PollingWatchService watcher,
|
||||
Path dir,
|
||||
Object fileKey)
|
||||
PollingWatchKey(Path dir, PollingWatchService watcher, Object fileKey)
|
||||
throws IOException
|
||||
{
|
||||
super(watcher);
|
||||
this.dir = dir;
|
||||
super(dir, watcher);
|
||||
this.fileKey = fileKey;
|
||||
this.valid = true;
|
||||
this.tickCount = 0;
|
||||
this.entries = new HashMap<Path,CacheEntry>();
|
||||
|
||||
// get the initial entries in the directory
|
||||
DirectoryStream<Path> stream = dir.newDirectoryStream();
|
||||
try {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
|
||||
for (Path entry: stream) {
|
||||
// don't follow links
|
||||
long lastModified = Attributes
|
||||
.readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
|
||||
.lastModifiedTime().toMillis();
|
||||
entries.put(entry.getName(),
|
||||
new CacheEntry(lastModified, tickCount));
|
||||
long lastModified =
|
||||
Files.getLastModifiedTime(entry, LinkOption.NOFOLLOW_LINKS).toMillis();
|
||||
entries.put(entry.getFileName(), new CacheEntry(lastModified, tickCount));
|
||||
}
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
// thrown if directory iteration fails
|
||||
Throwable cause = cme.getCause();
|
||||
if (cause != null && cause instanceof IOException)
|
||||
throw (IOException)cause;
|
||||
throw new AssertionError(cme);
|
||||
} finally {
|
||||
stream.close();
|
||||
} catch (DirectoryIteratorException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
FileRef directory() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
Object fileKey() {
|
||||
return fileKey;
|
||||
}
|
||||
@ -342,7 +325,7 @@ class PollingWatchService
|
||||
// open directory
|
||||
DirectoryStream<Path> stream = null;
|
||||
try {
|
||||
stream = dir.newDirectoryStream();
|
||||
stream = Files.newDirectoryStream(watchable());
|
||||
} catch (IOException x) {
|
||||
// directory is no longer accessible so cancel key
|
||||
cancel();
|
||||
@ -355,9 +338,8 @@ class PollingWatchService
|
||||
for (Path entry: stream) {
|
||||
long lastModified = 0L;
|
||||
try {
|
||||
lastModified = Attributes
|
||||
.readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
|
||||
.lastModifiedTime().toMillis();
|
||||
lastModified =
|
||||
Files.getLastModifiedTime(entry, LinkOption.NOFOLLOW_LINKS).toMillis();
|
||||
} catch (IOException x) {
|
||||
// unable to get attributes of entry. If file has just
|
||||
// been deleted then we'll report it as deleted on the
|
||||
@ -366,15 +348,15 @@ class PollingWatchService
|
||||
}
|
||||
|
||||
// lookup cache
|
||||
CacheEntry e = entries.get(entry.getName());
|
||||
CacheEntry e = entries.get(entry.getFileName());
|
||||
if (e == null) {
|
||||
// new file found
|
||||
entries.put(entry.getName(),
|
||||
entries.put(entry.getFileName(),
|
||||
new CacheEntry(lastModified, tickCount));
|
||||
|
||||
// queue ENTRY_CREATE if event enabled
|
||||
if (events.contains(StandardWatchEventKind.ENTRY_CREATE)) {
|
||||
signalEvent(StandardWatchEventKind.ENTRY_CREATE, entry.getName());
|
||||
signalEvent(StandardWatchEventKind.ENTRY_CREATE, entry.getFileName());
|
||||
continue;
|
||||
} else {
|
||||
// if ENTRY_CREATE is not enabled and ENTRY_MODIFY is
|
||||
@ -382,7 +364,7 @@ class PollingWatchService
|
||||
// modifications to the file immediately after it is
|
||||
// created.
|
||||
if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) {
|
||||
signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName());
|
||||
signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getFileName());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@ -391,15 +373,17 @@ class PollingWatchService
|
||||
// check if file has changed
|
||||
if (e.lastModified != lastModified) {
|
||||
if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) {
|
||||
signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName());
|
||||
signalEvent(StandardWatchEventKind.ENTRY_MODIFY,
|
||||
entry.getFileName());
|
||||
}
|
||||
}
|
||||
// entry in cache so update poll time
|
||||
e.update(lastModified, tickCount);
|
||||
|
||||
}
|
||||
} catch (ConcurrentModificationException x) {
|
||||
// FIXME - should handle this
|
||||
} catch (DirectoryIteratorException e) {
|
||||
// ignore for now; if the directory is no longer accessible
|
||||
// then the key will be cancelled on the next poll
|
||||
} finally {
|
||||
|
||||
// close directory stream
|
||||
|
@ -63,13 +63,14 @@ package sun.security.provider;
|
||||
* @author Gadi Guy
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.*;
|
||||
import java.io.*;
|
||||
import java.util.Properties;
|
||||
import java.util.Enumeration;
|
||||
import java.net.*;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Random;
|
||||
import sun.security.util.Debug;
|
||||
|
||||
@ -177,37 +178,21 @@ abstract class SeedGenerator {
|
||||
|
||||
// The temporary dir
|
||||
File f = new File(p.getProperty("java.io.tmpdir"));
|
||||
|
||||
// Go thru files in the tmp dir using NIO's
|
||||
// DirectoryStream. Fallback to File.list()
|
||||
// if NIO is not available.
|
||||
if (NIODirectoryStream.isAvailable()) {
|
||||
int count = 0;
|
||||
Iterable<?> stream =
|
||||
NIODirectoryStream.newDirectoryStream(f);
|
||||
int count = 0;
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(f.toPath())) {
|
||||
// We use a Random object to choose what file names
|
||||
// should be used. Otherwise on a machine with too
|
||||
// many files, the same first 1024 files always get
|
||||
// used. Any, We make sure the first 512 files are
|
||||
// always used.
|
||||
Random r = new Random();
|
||||
try {
|
||||
for (Object entry: stream) {
|
||||
if (count < 512 || r.nextBoolean()) {
|
||||
md.update(NIODirectoryStream.getName(
|
||||
entry).getBytes());
|
||||
}
|
||||
if (count++ > 1024) {
|
||||
break;
|
||||
}
|
||||
for (Path entry: stream) {
|
||||
if (count < 512 || r.nextBoolean()) {
|
||||
md.update(entry.getFileName().toString().getBytes());
|
||||
}
|
||||
if (count++ > 1024) {
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
((Closeable)stream).close();
|
||||
}
|
||||
} else {
|
||||
String[] sa = f.list();
|
||||
for(int i = 0; i < sa.length; i++) {
|
||||
md.update(sa[i].getBytes());
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
@ -553,77 +538,4 @@ abstract class SeedGenerator {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper of NIO DirectoryStream using reflection.
|
||||
*/
|
||||
private static class NIODirectoryStream {
|
||||
private static final Class<?> pathClass =
|
||||
getClass("java.nio.file.Path");
|
||||
|
||||
private static final Method toPathMethod =
|
||||
(pathClass == null) ? null : getMethod(File.class, "toPath");
|
||||
private static final Method getNameMethod =
|
||||
getMethod(pathClass, "getName");
|
||||
private static final Method newDirectoryStreamMethod =
|
||||
getMethod(pathClass, "newDirectoryStream");
|
||||
|
||||
private static Class<?> getClass(String name) {
|
||||
try {
|
||||
return Class.forName(name, true, null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethod(Class<?> clazz,
|
||||
String name,
|
||||
Class<?>... paramTypes) {
|
||||
if (clazz != null) {
|
||||
try {
|
||||
return clazz.getMethod(name, paramTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isAvailable() {
|
||||
return pathClass != null;
|
||||
}
|
||||
|
||||
static Iterable<?> newDirectoryStream(File dir) throws IOException {
|
||||
assert pathClass != null;
|
||||
try {
|
||||
Object path = toPathMethod.invoke(dir);
|
||||
return (Iterable<?>)newDirectoryStreamMethod.invoke(path);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException)
|
||||
throw (IOException)cause;
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
if (cause instanceof Error)
|
||||
throw (Error)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
static String getName(Object path) {
|
||||
assert pathClass != null;
|
||||
try {
|
||||
Object name = getNameMethod.invoke(path);
|
||||
return name.toString();
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ package sun.tools.jar;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.util.jar.*;
|
||||
@ -1017,17 +1018,17 @@ class Main {
|
||||
Path jarPath = jarFile.toPath();
|
||||
Path tmpPath = createTempFileInSameDirectoryAs(jarFile).toPath();
|
||||
try {
|
||||
if (update(jarPath.newInputStream(),
|
||||
tmpPath.newOutputStream(),
|
||||
if (update(Files.newInputStream(jarPath),
|
||||
Files.newOutputStream(tmpPath),
|
||||
null, index)) {
|
||||
try {
|
||||
tmpPath.moveTo(jarPath, REPLACE_EXISTING);
|
||||
Files.move(tmpPath, jarPath, REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new IOException(getMsg("error.write.file"), e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
tmpPath.deleteIfExists();
|
||||
Files.deleteIfExists(tmpPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,7 @@ public class AclEdit {
|
||||
|
||||
// read file's ACL
|
||||
AclFileAttributeView view =
|
||||
file.getFileAttributeView(AclFileAttributeView.class);
|
||||
Files.getFileAttributeView(file, AclFileAttributeView.class);
|
||||
if (view == null) {
|
||||
System.err.println("ACLs not supported on this platform");
|
||||
System.exit(-1);
|
||||
|
@ -264,11 +264,10 @@ public class Chmod {
|
||||
/**
|
||||
* Changes the permissions of the file using the given Changer.
|
||||
*/
|
||||
static void chmod(FileRef file, Changer changer) {
|
||||
static void chmod(Path file, Changer changer) {
|
||||
try {
|
||||
Set<PosixFilePermission> perms = Attributes
|
||||
.readPosixFileAttributes(file).permissions();
|
||||
Attributes.setPosixFilePermissions(file, changer.change(perms));
|
||||
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(file);
|
||||
Files.setPosixFilePermissions(file, changer.change(perms));
|
||||
} catch (IOException x) {
|
||||
System.err.println(x);
|
||||
}
|
||||
@ -277,7 +276,7 @@ public class Chmod {
|
||||
/**
|
||||
* Changes the permission of each file and directory visited
|
||||
*/
|
||||
static class TreeVisitor implements FileVisitor<FileRef> {
|
||||
static class TreeVisitor implements FileVisitor<Path> {
|
||||
private final Changer changer;
|
||||
|
||||
TreeVisitor(Changer changer) {
|
||||
@ -285,26 +284,26 @@ public class Chmod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) {
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
|
||||
chmod(dir, changer);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
chmod(file, changer);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) {
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
|
||||
if (exc != null)
|
||||
System.err.println("WARNING: " + exc);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFileFailed(FileRef file, IOException exc) {
|
||||
public FileVisitResult visitFileFailed(Path file, IOException exc) {
|
||||
System.err.println("WARNING: " + exc);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public class Copy {
|
||||
/**
|
||||
* Returns {@code true} if okay to overwrite a file ("cp -i")
|
||||
*/
|
||||
static boolean okayToOverwrite(FileRef file) {
|
||||
static boolean okayToOverwrite(Path file) {
|
||||
String answer = System.console().readLine("overwrite %s (yes/no)? ", file);
|
||||
return (answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("yes"));
|
||||
}
|
||||
@ -59,9 +59,9 @@ public class Copy {
|
||||
CopyOption[] options = (preserve) ?
|
||||
new CopyOption[] { COPY_ATTRIBUTES, REPLACE_EXISTING } :
|
||||
new CopyOption[] { REPLACE_EXISTING };
|
||||
if (!prompt || target.notExists() || okayToOverwrite(target)) {
|
||||
if (!prompt || Files.notExists(target) || okayToOverwrite(target)) {
|
||||
try {
|
||||
source.copyTo(target, options);
|
||||
Files.copy(source, target, options);
|
||||
} catch (IOException x) {
|
||||
System.err.format("Unable to copy: %s: %s%n", source, x);
|
||||
}
|
||||
@ -93,7 +93,7 @@ public class Copy {
|
||||
|
||||
Path newdir = target.resolve(source.relativize(dir));
|
||||
try {
|
||||
dir.copyTo(newdir, options);
|
||||
Files.copy(dir, newdir, options);
|
||||
} catch (FileAlreadyExistsException x) {
|
||||
// ignore
|
||||
} catch (IOException x) {
|
||||
@ -116,8 +116,8 @@ public class Copy {
|
||||
if (exc == null && preserve) {
|
||||
Path newdir = target.resolve(source.relativize(dir));
|
||||
try {
|
||||
BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir);
|
||||
Attributes.setLastModifiedTime(newdir, attrs.lastModifiedTime());
|
||||
FileTime time = Files.getLastModifiedTime(dir);
|
||||
Files.setLastModifiedTime(newdir, time);
|
||||
} catch (IOException x) {
|
||||
System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
|
||||
}
|
||||
@ -180,16 +180,11 @@ public class Copy {
|
||||
Path target = Paths.get(args[argi]);
|
||||
|
||||
// check if target is a directory
|
||||
boolean isDir = false;
|
||||
try {
|
||||
isDir = Attributes.readBasicFileAttributes(target).isDirectory();
|
||||
} catch (IOException x) {
|
||||
// ignore (probably target does not exist)
|
||||
}
|
||||
boolean isDir = Files.isDirectory(target);
|
||||
|
||||
// copy each source file/directory to target
|
||||
for (i=0; i<source.length; i++) {
|
||||
Path dest = (isDir) ? target.resolve(source[i].getName()) : target;
|
||||
Path dest = (isDir) ? target.resolve(source[i].getFileName()) : target;
|
||||
|
||||
if (recursive) {
|
||||
// follow links when copying files
|
||||
@ -198,13 +193,9 @@ public class Copy {
|
||||
Files.walkFileTree(source[i], opts, Integer.MAX_VALUE, tc);
|
||||
} else {
|
||||
// not recursive so source must not be a directory
|
||||
try {
|
||||
if (Attributes.readBasicFileAttributes(source[i]).isDirectory()) {
|
||||
System.err.format("%s: is a directory%n", source[i]);
|
||||
continue;
|
||||
}
|
||||
} catch (IOException x) {
|
||||
// assume not directory
|
||||
if (Files.isDirectory(source[i])) {
|
||||
System.err.format("%s: is a directory%n", source[i]);
|
||||
continue;
|
||||
}
|
||||
copyFile(source[i], dest, prompt, preserve);
|
||||
}
|
||||
|
@ -43,11 +43,9 @@ public class DiskUsage {
|
||||
static final long K = 1024;
|
||||
|
||||
static void printFileStore(FileStore store) throws IOException {
|
||||
FileStoreSpaceAttributes attrs = Attributes.readFileStoreSpaceAttributes(store);
|
||||
|
||||
long total = attrs.totalSpace() / K;
|
||||
long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / K;
|
||||
long avail = attrs.usableSpace() / K;
|
||||
long total = store.getTotalSpace() / K;
|
||||
long used = (store.getTotalSpace() - store.getUnallocatedSpace()) / K;
|
||||
long avail = store.getUsableSpace() / K;
|
||||
|
||||
String s = store.toString();
|
||||
if (s.length() > 20) {
|
||||
@ -66,7 +64,7 @@ public class DiskUsage {
|
||||
}
|
||||
} else {
|
||||
for (String file: args) {
|
||||
FileStore store = Paths.get(file).getFileStore();
|
||||
FileStore store = Files.getFileStore(Paths.get(file));
|
||||
printFileStore(store);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@
|
||||
*/
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FileType {
|
||||
@ -41,10 +40,8 @@ public class FileType {
|
||||
}
|
||||
for (String arg: args) {
|
||||
Path file = Paths.get(arg);
|
||||
BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
|
||||
|
||||
String type;
|
||||
if (attrs.isDirectory()) {
|
||||
if (Files.isDirectory(file)) {
|
||||
type = "directory";
|
||||
} else {
|
||||
type = Files.probeContentType(file);
|
||||
|
@ -58,7 +58,7 @@ public class WatchDir {
|
||||
private void register(Path dir) throws IOException {
|
||||
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
|
||||
if (trace) {
|
||||
FileRef prev = keys.get(key);
|
||||
Path prev = keys.get(key);
|
||||
if (prev == null) {
|
||||
System.out.format("register: %s\n", dir);
|
||||
} else {
|
||||
@ -147,7 +147,7 @@ public class WatchDir {
|
||||
// register it and its sub-directories
|
||||
if (recursive && (kind == ENTRY_CREATE)) {
|
||||
try {
|
||||
if (Attributes.readBasicFileAttributes(child, NOFOLLOW_LINKS).isDirectory()) {
|
||||
if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
|
||||
registerAll(child);
|
||||
}
|
||||
} catch (IOException x) {
|
||||
|
@ -58,14 +58,14 @@ public class Xdd {
|
||||
Paths.get(args[0]) : Paths.get(args[2]);
|
||||
|
||||
// check that user defined attributes are supported by the file store
|
||||
FileStore store = file.getFileStore();
|
||||
FileStore store = Files.getFileStore(file);
|
||||
if (!store.supportsFileAttributeView(UserDefinedFileAttributeView.class)) {
|
||||
System.err.format("UserDefinedFileAttributeView not supported on %s\n", store);
|
||||
System.exit(-1);
|
||||
|
||||
}
|
||||
UserDefinedFileAttributeView view = file.
|
||||
getFileAttributeView(UserDefinedFileAttributeView.class);
|
||||
UserDefinedFileAttributeView view =
|
||||
Files.getFileAttributeView(file, UserDefinedFileAttributeView.class);
|
||||
|
||||
// list user defined attributes
|
||||
if (args.length == 1) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.FileRef;
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
@ -57,7 +57,7 @@ public class GnomeFileTypeDetector
|
||||
}
|
||||
|
||||
@Override
|
||||
public String implProbeContentType(FileRef obj) throws IOException {
|
||||
public String implProbeContentType(Path obj) throws IOException {
|
||||
if (!gioAvailable && !gnomeVfsAvailable)
|
||||
return null;
|
||||
if (!(obj instanceof UnixPath))
|
||||
|
@ -66,19 +66,6 @@ class LinuxDosFileAttributeView
|
||||
return "dos";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals(READONLY_NAME))
|
||||
return readAttributes().isReadOnly();
|
||||
if (attribute.equals(ARCHIVE_NAME))
|
||||
return readAttributes().isArchive();
|
||||
if (attribute.equals(SYSTEM_NAME))
|
||||
return readAttributes().isSystem();
|
||||
if (attribute.equals(HIDDEN_NAME))
|
||||
return readAttributes().isHidden();
|
||||
return super.getAttribute(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attribute, Object value)
|
||||
throws IOException
|
||||
@ -103,7 +90,7 @@ class LinuxDosFileAttributeView
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String[] attributes)
|
||||
public Map<String,Object> readAttributes(String[] attributes)
|
||||
throws IOException
|
||||
{
|
||||
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||
|
@ -26,7 +26,6 @@
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.security.AccessController;
|
||||
@ -76,39 +75,14 @@ class LinuxFileSystem extends UnixFileSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
|
||||
UnixPath file,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (view == DosFileAttributeView.class)
|
||||
return (V) new LinuxDosFileAttributeView(file, followLinks(options));
|
||||
if (view == UserDefinedFileAttributeView.class)
|
||||
return (V) new LinuxUserDefinedFileAttributeView(file, followLinks(options));
|
||||
return super.newFileAttributeView(view, file, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public DynamicFileAttributeView newFileAttributeView(String name,
|
||||
UnixPath file,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (name.equals("dos"))
|
||||
return new LinuxDosFileAttributeView(file, followLinks(options));
|
||||
if (name.equals("user"))
|
||||
return new LinuxUserDefinedFileAttributeView(file, followLinks(options));
|
||||
return super.newFileAttributeView(name, file, options);
|
||||
}
|
||||
|
||||
// lazy initialization of the list of supported attribute views
|
||||
private static class SupportedFileFileAttributeViewsHolder {
|
||||
static final Set<String> supportedFileAttributeViews =
|
||||
supportedFileAttributeViews();
|
||||
private static Set<String> supportedFileAttributeViews() {
|
||||
Set<String> result = new HashSet<String>();
|
||||
result.addAll(UnixFileSystem.standardFileAttributeViews());
|
||||
Set<String> result = new HashSet<>();
|
||||
result.addAll(standardFileAttributeViews());
|
||||
// additional Linux-specific views
|
||||
result.add("dos");
|
||||
result.add("user");
|
||||
@ -130,7 +104,7 @@ class LinuxFileSystem extends UnixFileSystem {
|
||||
* Returns object to iterate over the mount entries in the given fstab file.
|
||||
*/
|
||||
Iterable<UnixMountEntry> getMountEntries(String fstab) {
|
||||
ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
|
||||
ArrayList<UnixMountEntry> entries = new ArrayList<>();
|
||||
try {
|
||||
long fp = setmntent(fstab.getBytes(), "r".getBytes());
|
||||
try {
|
||||
@ -159,10 +133,7 @@ class LinuxFileSystem extends UnixFileSystem {
|
||||
return getMountEntries("/etc/mtab");
|
||||
}
|
||||
|
||||
@Override
|
||||
FileStore getFileStore(UnixPath path) throws IOException {
|
||||
return new LinuxFileStore(path);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
FileStore getFileStore(UnixMountEntry entry) throws IOException {
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Linux implementation of FileSystemProvider
|
||||
*/
|
||||
@ -38,4 +42,58 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider {
|
||||
LinuxFileSystem newFileSystem(String dir) {
|
||||
return new LinuxFileSystem(this, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
LinuxFileStore getFileStore(UnixPath path) throws IOException {
|
||||
return new LinuxFileStore(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V getFileAttributeView(Path obj,
|
||||
Class<V> type,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (type == DosFileAttributeView.class) {
|
||||
return (V) new LinuxDosFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
}
|
||||
if (type == UserDefinedFileAttributeView.class) {
|
||||
return (V) new LinuxUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
}
|
||||
return super.getFileAttributeView(obj, type, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFileAttributeView getFileAttributeView(Path obj,
|
||||
String name,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (name.equals("dos")) {
|
||||
return new LinuxDosFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
}
|
||||
if (name.equals("user")) {
|
||||
return new LinuxUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
}
|
||||
return super.getFileAttributeView(obj, name, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends BasicFileAttributes> A readAttributes(Path file,
|
||||
Class<A> type,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if (type == DosFileAttributes.class) {
|
||||
DosFileAttributeView view =
|
||||
getFileAttributeView(file, DosFileAttributeView.class, options);
|
||||
return (A) view.readAttributes();
|
||||
} else {
|
||||
return super.readAttributes(file, type, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ class LinuxUserDefinedFileAttributeView
|
||||
|
||||
// Parses buffer as array of NULL-terminated C strings.
|
||||
private List<String> asList(long address, int size) {
|
||||
final List<String> list = new ArrayList<String>();
|
||||
List<String> list = new ArrayList<>();
|
||||
int start = 0;
|
||||
int pos = 0;
|
||||
while (pos < size) {
|
||||
|
@ -102,8 +102,8 @@ class LinuxWatchService
|
||||
// watch descriptor
|
||||
private volatile int wd;
|
||||
|
||||
LinuxWatchKey(LinuxWatchService watcher, int ifd, int wd) {
|
||||
super(watcher);
|
||||
LinuxWatchKey(UnixPath dir, LinuxWatchService watcher, int ifd, int wd) {
|
||||
super(dir, watcher);
|
||||
this.ifd = ifd;
|
||||
this.wd = wd;
|
||||
}
|
||||
@ -266,7 +266,7 @@ class LinuxWatchService
|
||||
// ensure watch descriptor is in map
|
||||
LinuxWatchKey key = wdToKey.get(wd);
|
||||
if (key == null) {
|
||||
key = new LinuxWatchKey(watcher, ifd, wd);
|
||||
key = new LinuxWatchKey(dir, watcher, ifd, wd);
|
||||
wdToKey.put(wd, key);
|
||||
}
|
||||
return key;
|
||||
|
@ -198,7 +198,7 @@ class SolarisAclFileAttributeView
|
||||
* Decode the buffer, returning an ACL
|
||||
*/
|
||||
private static List<AclEntry> decode(long address, int n) {
|
||||
ArrayList<AclEntry> acl = new ArrayList<AclEntry>(n);
|
||||
ArrayList<AclEntry> acl = new ArrayList<>(n);
|
||||
for (int i=0; i<n; i++) {
|
||||
long offset = address + i*SIZEOF_ACE_T;
|
||||
|
||||
@ -244,7 +244,7 @@ class SolarisAclFileAttributeView
|
||||
assert false;
|
||||
}
|
||||
|
||||
HashSet<AclEntryPermission> aceMask = new HashSet<AclEntryPermission>();
|
||||
Set<AclEntryPermission> aceMask = EnumSet.noneOf(AclEntryPermission.class);
|
||||
if ((mask & ACE_READ_DATA) > 0)
|
||||
aceMask.add(AclEntryPermission.READ_DATA);
|
||||
if ((mask & ACE_WRITE_DATA) > 0)
|
||||
@ -274,7 +274,7 @@ class SolarisAclFileAttributeView
|
||||
if ((mask & ACE_SYNCHRONIZE) > 0)
|
||||
aceMask.add(AclEntryPermission.SYNCHRONIZE);
|
||||
|
||||
HashSet<AclEntryFlag> aceFlags = new HashSet<AclEntryFlag>();
|
||||
Set<AclEntryFlag> aceFlags = EnumSet.noneOf(AclEntryFlag.class);
|
||||
if ((flags & ACE_FILE_INHERIT_ACE) > 0)
|
||||
aceFlags.add(AclEntryFlag.FILE_INHERIT);
|
||||
if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0)
|
||||
|
@ -26,7 +26,6 @@
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.security.AccessController;
|
||||
@ -71,38 +70,14 @@ class SolarisFileSystem extends UnixFileSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
|
||||
UnixPath file, LinkOption... options)
|
||||
{
|
||||
if (view == AclFileAttributeView.class)
|
||||
return (V) new SolarisAclFileAttributeView(file, followLinks(options));
|
||||
if (view == UserDefinedFileAttributeView.class) {
|
||||
return(V) new SolarisUserDefinedFileAttributeView(file, followLinks(options));
|
||||
}
|
||||
return super.newFileAttributeView(view, file, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DynamicFileAttributeView newFileAttributeView(String name,
|
||||
UnixPath file,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (name.equals("acl"))
|
||||
return new SolarisAclFileAttributeView(file, followLinks(options));
|
||||
if (name.equals("user"))
|
||||
return new SolarisUserDefinedFileAttributeView(file, followLinks(options));
|
||||
return super.newFileAttributeView(name, file, options);
|
||||
}
|
||||
|
||||
// lazy initialization of the list of supported attribute views
|
||||
private static class SupportedFileFileAttributeViewsHolder {
|
||||
static final Set<String> supportedFileAttributeViews =
|
||||
supportedFileAttributeViews();
|
||||
private static Set<String> supportedFileAttributeViews() {
|
||||
Set<String> result = new HashSet<String>();
|
||||
result.addAll(UnixFileSystem.standardFileAttributeViews());
|
||||
Set<String> result = new HashSet<>();
|
||||
result.addAll(standardFileAttributeViews());
|
||||
// additional Solaris-specific views
|
||||
result.add("acl");
|
||||
result.add("user");
|
||||
@ -126,7 +101,7 @@ class SolarisFileSystem extends UnixFileSystem {
|
||||
*/
|
||||
@Override
|
||||
Iterable<UnixMountEntry> getMountEntries() {
|
||||
ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
|
||||
ArrayList<UnixMountEntry> entries = new ArrayList<>();
|
||||
try {
|
||||
UnixPath mnttab = new UnixPath(this, "/etc/mnttab");
|
||||
long fp = fopen(mnttab, "r");
|
||||
@ -147,11 +122,6 @@ class SolarisFileSystem extends UnixFileSystem {
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
FileStore getFileStore(UnixPath path) throws IOException {
|
||||
return new SolarisFileStore(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
FileStore getFileStore(UnixMountEntry entry) throws IOException {
|
||||
return new SolarisFileStore(this, entry);
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Solaris implementation of FileSystemProvider
|
||||
*/
|
||||
@ -38,4 +42,41 @@ public class SolarisFileSystemProvider extends UnixFileSystemProvider {
|
||||
SolarisFileSystem newFileSystem(String dir) {
|
||||
return new SolarisFileSystem(this, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
SolarisFileStore getFileStore(UnixPath path) throws IOException {
|
||||
return new SolarisFileStore(path);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V getFileAttributeView(Path obj,
|
||||
Class<V> type,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (type == AclFileAttributeView.class) {
|
||||
return (V) new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
}
|
||||
if (type == UserDefinedFileAttributeView.class) {
|
||||
return(V) new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
}
|
||||
return super.getFileAttributeView(obj, type, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFileAttributeView getFileAttributeView(Path obj,
|
||||
String name,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (name.equals("acl"))
|
||||
return new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
if (name.equals("user"))
|
||||
return new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
followLinks(options));
|
||||
return super.getFileAttributeView(obj, name, options);
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class SolarisUserDefinedFileAttributeView
|
||||
}
|
||||
|
||||
// read list of extended attributes
|
||||
final List<String> list = new ArrayList<String>();
|
||||
List<String> list = new ArrayList<>();
|
||||
try {
|
||||
byte[] name;
|
||||
while ((name = readdir(dp)) != null) {
|
||||
|
@ -128,7 +128,6 @@ class SolarisWatchService
|
||||
private class SolarisWatchKey extends AbstractWatchKey
|
||||
implements DirectoryNode
|
||||
{
|
||||
private final UnixPath dir;
|
||||
private final UnixFileKey fileKey;
|
||||
|
||||
// pointer to native file_obj object
|
||||
@ -147,15 +146,14 @@ class SolarisWatchService
|
||||
long object,
|
||||
Set<? extends WatchEvent.Kind<?>> events)
|
||||
{
|
||||
super(watcher);
|
||||
this.dir = dir;
|
||||
super(dir, watcher);
|
||||
this.fileKey = fileKey;
|
||||
this.object = object;
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
UnixPath getFileRef() {
|
||||
return dir;
|
||||
UnixPath getDirectory() {
|
||||
return (UnixPath)watchable();
|
||||
}
|
||||
|
||||
UnixFileKey getFileKey() {
|
||||
@ -487,7 +485,7 @@ class SolarisWatchService
|
||||
*/
|
||||
void processDirectoryEvents(SolarisWatchKey key, int mask) {
|
||||
if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
|
||||
registerChildren(key.getFileRef(), key,
|
||||
registerChildren(key.getDirectory(), key,
|
||||
key.events().contains(StandardWatchEventKind.ENTRY_CREATE));
|
||||
}
|
||||
}
|
||||
@ -524,7 +522,7 @@ class SolarisWatchService
|
||||
boolean removed = true;
|
||||
try {
|
||||
UnixFileAttributes
|
||||
.get(key.getFileRef().resolve(node.name()), false);
|
||||
.get(key.getDirectory().resolve(node.name()), false);
|
||||
removed = false;
|
||||
} catch (UnixException x) { }
|
||||
|
||||
@ -554,14 +552,14 @@ class SolarisWatchService
|
||||
|
||||
DirectoryStream<Path> stream = null;
|
||||
try {
|
||||
stream = dir.newDirectoryStream();
|
||||
stream = Files.newDirectoryStream(dir);
|
||||
} catch (IOException x) {
|
||||
// nothing we can do
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for (Path entry: stream) {
|
||||
Path name = entry.getName();
|
||||
Path name = entry.getFileName();
|
||||
|
||||
// skip entry if already registered
|
||||
if (parent.getChild(name) != null)
|
||||
@ -582,9 +580,9 @@ class SolarisWatchService
|
||||
}
|
||||
|
||||
// create node
|
||||
EntryNode node = new EntryNode(object, entry.getName(), parent);
|
||||
EntryNode node = new EntryNode(object, entry.getFileName(), parent);
|
||||
// tell the parent about it
|
||||
parent.addChild(entry.getName(), node);
|
||||
parent.addChild(entry.getFileName(), node);
|
||||
object2Node.put(object, node);
|
||||
}
|
||||
} catch (ConcurrentModificationException x) {
|
||||
|
@ -237,7 +237,7 @@ class UnixCopyFile {
|
||||
fo = open(target,
|
||||
(O_WRONLY |
|
||||
O_CREAT |
|
||||
O_TRUNC),
|
||||
O_EXCL),
|
||||
attrs.mode());
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(target);
|
||||
@ -435,10 +435,8 @@ class UnixCopyFile {
|
||||
if (targetAttrs.isDirectory() &&
|
||||
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||||
{
|
||||
throw new FileAlreadyExistsException(
|
||||
source.getPathForExecptionMessage(),
|
||||
target.getPathForExecptionMessage(),
|
||||
x.getMessage());
|
||||
throw new DirectoryNotEmptyException(
|
||||
target.getPathForExecptionMessage());
|
||||
}
|
||||
x.rethrowAsIOException(target);
|
||||
}
|
||||
@ -556,10 +554,8 @@ class UnixCopyFile {
|
||||
if (targetAttrs.isDirectory() &&
|
||||
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||||
{
|
||||
throw new FileAlreadyExistsException(
|
||||
source.getPathForExecptionMessage(),
|
||||
target.getPathForExecptionMessage(),
|
||||
x.getMessage());
|
||||
throw new DirectoryNotEmptyException(
|
||||
target.getPathForExecptionMessage());
|
||||
}
|
||||
x.rethrowAsIOException(target);
|
||||
}
|
||||
|
@ -148,17 +148,6 @@ class UnixFileAttributeViews {
|
||||
return "posix";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals(PERMISSIONS_NAME))
|
||||
return readAttributes().permissions();
|
||||
if (attribute.equals(OWNER_NAME))
|
||||
return readAttributes().owner();
|
||||
if (attribute.equals(GROUP_NAME))
|
||||
return readAttributes().group();
|
||||
return super.getAttribute(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setAttribute(String attribute, Object value)
|
||||
@ -195,7 +184,7 @@ class UnixFileAttributeViews {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String[] attributes)
|
||||
public Map<String,Object> readAttributes(String[] attributes)
|
||||
throws IOException
|
||||
{
|
||||
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||
@ -307,27 +296,6 @@ class UnixFileAttributeViews {
|
||||
return "unix";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals(MODE_NAME))
|
||||
return readAttributes().mode();
|
||||
if (attribute.equals(INO_NAME))
|
||||
return readAttributes().ino();
|
||||
if (attribute.equals(DEV_NAME))
|
||||
return readAttributes().dev();
|
||||
if (attribute.equals(RDEV_NAME))
|
||||
return readAttributes().rdev();
|
||||
if (attribute.equals(NLINK_NAME))
|
||||
return readAttributes().nlink();
|
||||
if (attribute.equals(UID_NAME))
|
||||
return readAttributes().uid();
|
||||
if (attribute.equals(GID_NAME))
|
||||
return readAttributes().gid();
|
||||
if (attribute.equals(CTIME_NAME))
|
||||
return readAttributes().ctime();
|
||||
return super.getAttribute(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attribute, Object value)
|
||||
throws IOException
|
||||
@ -348,7 +316,7 @@ class UnixFileAttributeViews {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String[] attributes)
|
||||
public Map<String,Object> readAttributes(String[] attributes)
|
||||
throws IOException
|
||||
{
|
||||
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||
|
@ -124,7 +124,7 @@ class UnixFileAttributes
|
||||
|
||||
@Override
|
||||
public FileTime creationTime() {
|
||||
return null;
|
||||
return lastModifiedTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -194,7 +194,7 @@ class UnixFileAttributes
|
||||
@Override
|
||||
public Set<PosixFilePermission> permissions() {
|
||||
int bits = (st_mode & UnixConstants.S_IAMB);
|
||||
HashSet<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
|
||||
HashSet<PosixFilePermission> perms = new HashSet<>();
|
||||
|
||||
if ((bits & UnixConstants.S_IRUSR) > 0)
|
||||
perms.add(PosixFilePermission.OWNER_READ);
|
||||
|
@ -103,28 +103,50 @@ abstract class UnixFileStore
|
||||
return entry.isReadOnly();
|
||||
}
|
||||
|
||||
// uses statvfs to read the file system information
|
||||
private UnixFileStoreAttributes readAttributes() throws IOException {
|
||||
try {
|
||||
return UnixFileStoreAttributes.get(file);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
return null; // keep compile happy
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalSpace() throws IOException {
|
||||
UnixFileStoreAttributes attrs = readAttributes();
|
||||
return attrs.blockSize() * attrs.totalBlocks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUsableSpace() throws IOException {
|
||||
UnixFileStoreAttributes attrs = readAttributes();
|
||||
return attrs.blockSize() * attrs.availableBlocks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUnallocatedSpace() throws IOException {
|
||||
UnixFileStoreAttributes attrs = readAttributes();
|
||||
return attrs.blockSize() * attrs.freeBlocks();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view)
|
||||
{
|
||||
if (view == null)
|
||||
throw new NullPointerException();
|
||||
if (view == FileStoreSpaceAttributeView.class)
|
||||
return (V) new UnixFileStoreSpaceAttributeView(this);
|
||||
return (V) null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals("space:totalSpace"))
|
||||
return new UnixFileStoreSpaceAttributeView(this)
|
||||
.readAttributes().totalSpace();
|
||||
if (attribute.equals("space:usableSpace"))
|
||||
return new UnixFileStoreSpaceAttributeView(this)
|
||||
.readAttributes().usableSpace();
|
||||
if (attribute.equals("space:unallocatedSpace"))
|
||||
return new UnixFileStoreSpaceAttributeView(this)
|
||||
.readAttributes().unallocatedSpace();
|
||||
if (attribute.equals("totalSpace"))
|
||||
return getTotalSpace();
|
||||
if (attribute.equals("usableSpace"))
|
||||
return getUsableSpace();
|
||||
if (attribute.equals("unallocatedSpace"))
|
||||
return getUnallocatedSpace();
|
||||
throw new UnsupportedOperationException("'" + attribute + "' not recognized");
|
||||
}
|
||||
|
||||
@ -181,50 +203,6 @@ abstract class UnixFileStore
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static class UnixFileStoreSpaceAttributeView
|
||||
implements FileStoreSpaceAttributeView
|
||||
{
|
||||
private final UnixFileStore fs;
|
||||
|
||||
UnixFileStoreSpaceAttributeView(UnixFileStore fs) {
|
||||
this.fs = fs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "space";
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStoreSpaceAttributes readAttributes()
|
||||
throws IOException
|
||||
{
|
||||
UnixPath file = fs.file();
|
||||
final UnixFileStoreAttributes attrs;
|
||||
try {
|
||||
attrs = UnixFileStoreAttributes.get(file);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
return null; // keep compile happy
|
||||
}
|
||||
|
||||
return new FileStoreSpaceAttributes() {
|
||||
@Override
|
||||
public long totalSpace() {
|
||||
return attrs.blockSize() * attrs.totalBlocks();
|
||||
}
|
||||
@Override
|
||||
public long usableSpace() {
|
||||
return attrs.blockSize() * attrs.availableBlocks();
|
||||
}
|
||||
@Override
|
||||
public long unallocatedSpace() {
|
||||
return attrs.blockSize() * attrs.freeBlocks();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// -- fstypes.properties --
|
||||
|
||||
private static final Object loadLock = new Object();
|
||||
@ -277,11 +255,8 @@ abstract class UnixFileStore
|
||||
String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
|
||||
Path file = Paths.get(fstypes);
|
||||
try {
|
||||
ReadableByteChannel rbc = file.newByteChannel();
|
||||
try {
|
||||
try (ReadableByteChannel rbc = Files.newByteChannel(file)) {
|
||||
result.load(Channels.newReader(rbc, "UTF-8"));
|
||||
} finally {
|
||||
rbc.close();
|
||||
}
|
||||
} catch (IOException x) {
|
||||
}
|
||||
|
@ -98,6 +98,10 @@ abstract class UnixFileSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
static List<String> standardFileAttributeViews() {
|
||||
return Arrays.asList("basic", "posix", "unix", "owner");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final FileSystemProvider provider() {
|
||||
return provider;
|
||||
@ -168,12 +172,6 @@ abstract class UnixFileSystem
|
||||
*/
|
||||
abstract Iterable<UnixMountEntry> getMountEntries();
|
||||
|
||||
/**
|
||||
* Returns a FileStore to represent the file system where the given file
|
||||
* reside.
|
||||
*/
|
||||
abstract FileStore getFileStore(UnixPath path) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a FileStore to represent the file system for the given mount
|
||||
* mount.
|
||||
@ -264,7 +262,22 @@ abstract class UnixFileSystem
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UnixPath getPath(String path) {
|
||||
public final Path getPath(String first, String... more) {
|
||||
String path;
|
||||
if (more.length == 0) {
|
||||
path = first;
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(first);
|
||||
for (String segment: more) {
|
||||
if (segment.length() > 0) {
|
||||
if (sb.length() > 0)
|
||||
sb.append('/');
|
||||
sb.append(segment);
|
||||
}
|
||||
}
|
||||
path = sb.toString();
|
||||
}
|
||||
return new UnixPath(this, path);
|
||||
}
|
||||
|
||||
@ -300,77 +313,30 @@ abstract class UnixFileSystem
|
||||
private static final String GLOB_SYNTAX = "glob";
|
||||
private static final String REGEX_SYNTAX = "regex";
|
||||
|
||||
protected boolean followLinks(LinkOption... options) {
|
||||
boolean followLinks = true;
|
||||
for (LinkOption option: options) {
|
||||
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||||
followLinks = false;
|
||||
continue;
|
||||
}
|
||||
if (option == null)
|
||||
throw new NullPointerException();
|
||||
throw new AssertionError("Should not get here");
|
||||
}
|
||||
return followLinks;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
|
||||
UnixPath file,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (view == null)
|
||||
throw new NullPointerException();
|
||||
boolean followLinks = followLinks(options);
|
||||
Class<?> c = view;
|
||||
if (c == BasicFileAttributeView.class)
|
||||
return (V) UnixFileAttributeViews.createBasicView(file, followLinks);
|
||||
if (c == PosixFileAttributeView.class)
|
||||
return (V) UnixFileAttributeViews.createPosixView(file, followLinks);
|
||||
if (c == FileOwnerAttributeView.class)
|
||||
return (V) UnixFileAttributeViews.createOwnerView(file, followLinks);
|
||||
return (V) null;
|
||||
}
|
||||
|
||||
static List<String> standardFileAttributeViews() {
|
||||
return Arrays.asList("basic", "posix", "unix", "owner");
|
||||
}
|
||||
|
||||
protected DynamicFileAttributeView newFileAttributeView(String name,
|
||||
UnixPath file,
|
||||
LinkOption... options)
|
||||
{
|
||||
boolean followLinks = followLinks(options);
|
||||
if (name.equals("basic"))
|
||||
return UnixFileAttributeViews.createBasicView(file, followLinks);
|
||||
if (name.equals("posix"))
|
||||
return UnixFileAttributeViews.createPosixView(file, followLinks);
|
||||
if (name.equals("unix"))
|
||||
return UnixFileAttributeViews.createUnixView(file, followLinks);
|
||||
if (name.equals("owner"))
|
||||
return UnixFileAttributeViews.createOwnerView(file, followLinks);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UserPrincipalLookupService getUserPrincipalLookupService() {
|
||||
return theLookupService;
|
||||
return LookupService.instance;
|
||||
}
|
||||
|
||||
private static final UserPrincipalLookupService theLookupService =
|
||||
new UserPrincipalLookupService() {
|
||||
@Override
|
||||
public UserPrincipal lookupPrincipalByName(String name)
|
||||
throws IOException
|
||||
{
|
||||
return UnixUserPrincipals.lookupUser(name);
|
||||
}
|
||||
private static class LookupService {
|
||||
static final UserPrincipalLookupService instance =
|
||||
new UserPrincipalLookupService() {
|
||||
@Override
|
||||
public UserPrincipal lookupPrincipalByName(String name)
|
||||
throws IOException
|
||||
{
|
||||
return UnixUserPrincipals.lookupUser(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupPrincipal lookupPrincipalByGroupName(String group)
|
||||
throws IOException
|
||||
{
|
||||
return UnixUserPrincipals.lookupGroup(group);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupPrincipal lookupPrincipalByGroupName(String group)
|
||||
throws IOException
|
||||
{
|
||||
return UnixUserPrincipals.lookupGroup(group);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -27,21 +27,25 @@ package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.nio.channels.*;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.io.IOException;
|
||||
import java.io.FilePermission;
|
||||
import java.util.*;
|
||||
import java.security.AccessController;
|
||||
|
||||
import sun.nio.ch.ThreadPool;
|
||||
import sun.security.util.SecurityConstants;
|
||||
import static sun.nio.fs.UnixNativeDispatcher.*;
|
||||
import static sun.nio.fs.UnixConstants.*;
|
||||
|
||||
/**
|
||||
* Base implementation of FileSystemProvider
|
||||
*/
|
||||
|
||||
public abstract class UnixFileSystemProvider
|
||||
extends FileSystemProvider
|
||||
extends AbstractFileSystemProvider
|
||||
{
|
||||
private static final String USER_DIR = "user.dir";
|
||||
private final UnixFileSystem theFileSystem;
|
||||
@ -93,7 +97,7 @@ public abstract class UnixFileSystemProvider
|
||||
return UnixUriUtils.fromUri(theFileSystem, uri);
|
||||
}
|
||||
|
||||
protected UnixPath checkPath(Path obj) {
|
||||
UnixPath checkPath(Path obj) {
|
||||
if (obj == null)
|
||||
throw new NullPointerException();
|
||||
if (!(obj instanceof UnixPath))
|
||||
@ -101,6 +105,76 @@ public abstract class UnixFileSystemProvider
|
||||
return (UnixPath)obj;
|
||||
}
|
||||
|
||||
boolean followLinks(LinkOption... options) {
|
||||
boolean followLinks = true;
|
||||
for (LinkOption option: options) {
|
||||
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||||
followLinks = false;
|
||||
continue;
|
||||
}
|
||||
if (option == null)
|
||||
throw new NullPointerException();
|
||||
throw new AssertionError("Should not get here");
|
||||
}
|
||||
return followLinks;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V getFileAttributeView(Path obj,
|
||||
Class<V> type,
|
||||
LinkOption... options)
|
||||
{
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
boolean followLinks = followLinks(options);
|
||||
if (type == BasicFileAttributeView.class)
|
||||
return (V) UnixFileAttributeViews.createBasicView(file, followLinks);
|
||||
if (type == PosixFileAttributeView.class)
|
||||
return (V) UnixFileAttributeViews.createPosixView(file, followLinks);
|
||||
if (type == FileOwnerAttributeView.class)
|
||||
return (V) UnixFileAttributeViews.createOwnerView(file, followLinks);
|
||||
if (type == null)
|
||||
throw new NullPointerException();
|
||||
return (V) null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends BasicFileAttributes> A readAttributes(Path file,
|
||||
Class<A> type,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
Class<? extends BasicFileAttributeView> view;
|
||||
if (type == BasicFileAttributes.class)
|
||||
view = BasicFileAttributeView.class;
|
||||
else if (type == PosixFileAttributes.class)
|
||||
view = PosixFileAttributeView.class;
|
||||
else if (type == null)
|
||||
throw new NullPointerException();
|
||||
else
|
||||
throw new UnsupportedOperationException();
|
||||
return (A) getFileAttributeView(file, view, options).readAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DynamicFileAttributeView getFileAttributeView(Path obj,
|
||||
String name,
|
||||
LinkOption... options)
|
||||
{
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
boolean followLinks = followLinks(options);
|
||||
if (name.equals("basic"))
|
||||
return UnixFileAttributeViews.createBasicView(file, followLinks);
|
||||
if (name.equals("posix"))
|
||||
return UnixFileAttributeViews.createPosixView(file, followLinks);
|
||||
if (name.equals("unix"))
|
||||
return UnixFileAttributeViews.createUnixView(file, followLinks);
|
||||
if (name.equals("owner"))
|
||||
return UnixFileAttributeViews.createOwnerView(file, followLinks);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileChannel newFileChannel(Path obj,
|
||||
Set<? extends OpenOption> options,
|
||||
@ -136,4 +210,303 @@ public abstract class UnixFileSystemProvider
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SeekableByteChannel newByteChannel(Path obj,
|
||||
Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
int mode = UnixFileModeAttribute
|
||||
.toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
|
||||
try {
|
||||
return UnixChannelFactory.newFileChannel(file, options, mode);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
return null; // keep compiler happy
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean implDelete(Path obj, boolean failIfNotExists) throws IOException {
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
file.checkDelete();
|
||||
|
||||
// need file attributes to know if file is directory
|
||||
UnixFileAttributes attrs = null;
|
||||
try {
|
||||
attrs = UnixFileAttributes.get(file, false);
|
||||
if (attrs.isDirectory()) {
|
||||
rmdir(file);
|
||||
} else {
|
||||
unlink(file);
|
||||
}
|
||||
return true;
|
||||
} catch (UnixException x) {
|
||||
// no-op if file does not exist
|
||||
if (!failIfNotExists && x.errno() == ENOENT)
|
||||
return false;
|
||||
|
||||
// DirectoryNotEmptyException if not empty
|
||||
if (attrs != null && attrs.isDirectory() &&
|
||||
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||||
throw new DirectoryNotEmptyException(file.getPathForExecptionMessage());
|
||||
|
||||
x.rethrowAsIOException(file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(Path source, Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
UnixCopyFile.copy(UnixPath.toUnixPath(source),
|
||||
UnixPath.toUnixPath(target),
|
||||
options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(Path source, Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
UnixCopyFile.move(UnixPath.toUnixPath(source),
|
||||
UnixPath.toUnixPath(target),
|
||||
options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(Path obj, AccessMode... modes) throws IOException {
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
boolean e = false;
|
||||
boolean r = false;
|
||||
boolean w = false;
|
||||
boolean x = false;
|
||||
|
||||
if (modes.length == 0) {
|
||||
e = true;
|
||||
} else {
|
||||
for (AccessMode mode: modes) {
|
||||
switch (mode) {
|
||||
case READ : r = true; break;
|
||||
case WRITE : w = true; break;
|
||||
case EXECUTE : x = true; break;
|
||||
default: throw new AssertionError("Should not get here");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mode = 0;
|
||||
if (e || r) {
|
||||
file.checkRead();
|
||||
mode |= (r) ? R_OK : F_OK;
|
||||
}
|
||||
if (w) {
|
||||
file.checkWrite();
|
||||
mode |= W_OK;
|
||||
}
|
||||
if (x) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
// not cached
|
||||
sm.checkExec(file.getPathForPermissionCheck());
|
||||
}
|
||||
mode |= X_OK;
|
||||
}
|
||||
try {
|
||||
access(file, mode);
|
||||
} catch (UnixException exc) {
|
||||
exc.rethrowAsIOException(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameFile(Path obj1, Path obj2) throws IOException {
|
||||
UnixPath file1 = UnixPath.toUnixPath(obj1);
|
||||
if (file1.equals(obj2))
|
||||
return true;
|
||||
if (obj2 == null)
|
||||
throw new NullPointerException();
|
||||
if (!(obj2 instanceof UnixPath))
|
||||
return false;
|
||||
UnixPath file2 = (UnixPath)obj2;
|
||||
|
||||
// check security manager access to both files
|
||||
file1.checkRead();
|
||||
file2.checkRead();
|
||||
|
||||
UnixFileAttributes attrs1;
|
||||
UnixFileAttributes attrs2;
|
||||
try {
|
||||
attrs1 = UnixFileAttributes.get(file1, true);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file1);
|
||||
return false; // keep compiler happy
|
||||
}
|
||||
try {
|
||||
attrs2 = UnixFileAttributes.get(file2, true);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file2);
|
||||
return false; // keep compiler happy
|
||||
}
|
||||
return attrs1.isSameFile(attrs2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden(Path obj) {
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
file.checkRead();
|
||||
UnixPath name = file.getFileName();
|
||||
if (name == null)
|
||||
return false;
|
||||
return (name.asByteArray()[0] == '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a FileStore to represent the file system where the given file
|
||||
* reside.
|
||||
*/
|
||||
abstract FileStore getFileStore(UnixPath path) throws IOException;
|
||||
|
||||
@Override
|
||||
public FileStore getFileStore(Path obj) throws IOException {
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
|
||||
file.checkRead();
|
||||
}
|
||||
return getFileStore(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createDirectory(Path obj, FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath dir = UnixPath.toUnixPath(obj);
|
||||
dir.checkWrite();
|
||||
|
||||
int mode = UnixFileModeAttribute
|
||||
.toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs);
|
||||
try {
|
||||
mkdir(dir, mode);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DirectoryStream<Path> newDirectoryStream(Path obj, DirectoryStream.Filter<? super Path> filter)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath dir = UnixPath.toUnixPath(obj);
|
||||
dir.checkRead();
|
||||
if (filter == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
// can't return SecureDirectoryStream on kernels that don't support
|
||||
// openat, etc.
|
||||
if (!supportsAtSysCalls()) {
|
||||
try {
|
||||
long ptr = opendir(dir);
|
||||
return new UnixDirectoryStream(dir, ptr, filter);
|
||||
} catch (UnixException x) {
|
||||
if (x.errno() == ENOTDIR)
|
||||
throw new NotDirectoryException(dir.getPathForExecptionMessage());
|
||||
x.rethrowAsIOException(dir);
|
||||
}
|
||||
}
|
||||
|
||||
// open directory and dup file descriptor for use by
|
||||
// opendir/readdir/closedir
|
||||
int dfd1 = -1;
|
||||
int dfd2 = -1;
|
||||
long dp = 0L;
|
||||
try {
|
||||
dfd1 = open(dir, O_RDONLY, 0);
|
||||
dfd2 = dup(dfd1);
|
||||
dp = fdopendir(dfd1);
|
||||
} catch (UnixException x) {
|
||||
if (dfd1 != -1)
|
||||
UnixNativeDispatcher.close(dfd1);
|
||||
if (dfd2 != -1)
|
||||
UnixNativeDispatcher.close(dfd2);
|
||||
if (x.errno() == UnixConstants.ENOTDIR)
|
||||
throw new NotDirectoryException(dir.getPathForExecptionMessage());
|
||||
x.rethrowAsIOException(dir);
|
||||
}
|
||||
return new UnixSecureDirectoryStream(dir, dp, dfd2, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createSymbolicLink(Path obj1, Path obj2, FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath link = UnixPath.toUnixPath(obj1);
|
||||
UnixPath target = UnixPath.toUnixPath(obj2);
|
||||
|
||||
// no attributes supported when creating links
|
||||
if (attrs.length > 0) {
|
||||
UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE
|
||||
throw new UnsupportedOperationException("Initial file attributes" +
|
||||
"not supported when creating symbolic link");
|
||||
}
|
||||
|
||||
// permission check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new LinkPermission("symbolic"));
|
||||
link.checkWrite();
|
||||
}
|
||||
|
||||
// create link
|
||||
try {
|
||||
symlink(target.asByteArray(), link);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(link);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLink(Path obj1, Path obj2) throws IOException {
|
||||
UnixPath link = UnixPath.toUnixPath(obj1);
|
||||
UnixPath existing = UnixPath.toUnixPath(obj2);
|
||||
|
||||
// permission check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new LinkPermission("hard"));
|
||||
link.checkWrite();
|
||||
existing.checkWrite();
|
||||
}
|
||||
try {
|
||||
link(existing, link);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(link, existing);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path readSymbolicLink(Path obj1) throws IOException {
|
||||
UnixPath link = UnixPath.toUnixPath(obj1);
|
||||
// permission check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
FilePermission perm = new FilePermission(link.getPathForPermissionCheck(),
|
||||
SecurityConstants.FILE_READLINK_ACTION);
|
||||
AccessController.checkPermission(perm);
|
||||
}
|
||||
try {
|
||||
byte[] target = readlink(link);
|
||||
return new UnixPath(link.getFileSystem(), target);
|
||||
} catch (UnixException x) {
|
||||
if (x.errno() == UnixConstants.EINVAL)
|
||||
throw new NotLinkException(link.getPathForExecptionMessage());
|
||||
x.rethrowAsIOException(link);
|
||||
return null; // keep compiler happy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,15 +27,11 @@ package sun.nio.fs;
|
||||
|
||||
import java.nio.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.charset.*;
|
||||
import java.nio.channels.*;
|
||||
import java.security.AccessController;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import java.lang.ref.SoftReference;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
import static sun.nio.fs.UnixNativeDispatcher.*;
|
||||
import static sun.nio.fs.UnixConstants.*;
|
||||
@ -79,8 +75,6 @@ class UnixPath
|
||||
// removes redundant slashes and check input for invalid characters
|
||||
static String normalizeAndCheck(String input) {
|
||||
int n = input.length();
|
||||
if (n == 0)
|
||||
throw new InvalidPathException(input, "Path is empty");
|
||||
char prevChar = 0;
|
||||
for (int i=0; i < n; i++) {
|
||||
char c = input.charAt(i);
|
||||
@ -174,7 +168,13 @@ class UnixPath
|
||||
if (getFileSystem().needToResolveAgainstDefaultDirectory()) {
|
||||
return resolve(getFileSystem().defaultDirectory(), path);
|
||||
} else {
|
||||
return path;
|
||||
if (!isEmpty()) {
|
||||
return path;
|
||||
} else {
|
||||
// empty path case will access current directory
|
||||
byte[] here = { '.' };
|
||||
return here;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ class UnixPath
|
||||
}
|
||||
|
||||
// Checks that the given file is a UnixPath
|
||||
private UnixPath checkPath(FileRef obj) {
|
||||
static UnixPath toUnixPath(Path obj) {
|
||||
if (obj == null)
|
||||
throw new NullPointerException();
|
||||
if (!(obj instanceof UnixPath))
|
||||
@ -209,12 +209,17 @@ class UnixPath
|
||||
// count names
|
||||
count = 0;
|
||||
index = 0;
|
||||
while (index < path.length) {
|
||||
byte c = path[index++];
|
||||
if (c != '/') {
|
||||
count++;
|
||||
while (index < path.length && path[index] != '/')
|
||||
index++;
|
||||
if (isEmpty()) {
|
||||
// empty path has one name
|
||||
count = 1;
|
||||
} else {
|
||||
while (index < path.length) {
|
||||
byte c = path[index++];
|
||||
if (c != '/') {
|
||||
count++;
|
||||
while (index < path.length && path[index] != '/')
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +244,16 @@ class UnixPath
|
||||
}
|
||||
}
|
||||
|
||||
// returns {@code true} if this path is an empty path
|
||||
private boolean isEmpty() {
|
||||
return path.length == 0;
|
||||
}
|
||||
|
||||
// returns an empty path
|
||||
private UnixPath emptyPath() {
|
||||
return new UnixPath(getFileSystem(), new byte[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixFileSystem getFileSystem() {
|
||||
return fs;
|
||||
@ -246,7 +261,7 @@ class UnixPath
|
||||
|
||||
@Override
|
||||
public UnixPath getRoot() {
|
||||
if (path[0] == '/') {
|
||||
if (path.length > 0 && path[0] == '/') {
|
||||
return getFileSystem().rootDirectory();
|
||||
} else {
|
||||
return null;
|
||||
@ -254,14 +269,17 @@ class UnixPath
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath getName() {
|
||||
public UnixPath getFileName() {
|
||||
initOffsets();
|
||||
|
||||
int count = offsets.length;
|
||||
if (count == 0)
|
||||
return null; // no elements so no name
|
||||
|
||||
if (count == 1 && path[0] != '/')
|
||||
// no elements so no name
|
||||
if (count == 0)
|
||||
return null;
|
||||
|
||||
// one name element and no root component
|
||||
if (count == 1 && path.length > 0 && path[0] != '/')
|
||||
return this;
|
||||
|
||||
int lastOffset = offsets[count-1];
|
||||
@ -349,57 +367,58 @@ class UnixPath
|
||||
|
||||
@Override
|
||||
public boolean isAbsolute() {
|
||||
return (path[0] == '/');
|
||||
return (path.length > 0 && path[0] == '/');
|
||||
}
|
||||
|
||||
// Resolve child against given base
|
||||
private static byte[] resolve(byte[] base, byte[] child) {
|
||||
if (child[0] == '/')
|
||||
int baseLength = base.length;
|
||||
int childLength = child.length;
|
||||
if (childLength == 0)
|
||||
return base;
|
||||
if (baseLength == 0 || child[0] == '/')
|
||||
return child;
|
||||
byte[] result;
|
||||
if (base.length == 1 && base[0] == '/') {
|
||||
result = new byte[child.length + 1];
|
||||
if (baseLength == 1 && base[0] == '/') {
|
||||
result = new byte[childLength + 1];
|
||||
result[0] = '/';
|
||||
System.arraycopy(child, 0, result, 1, child.length);
|
||||
System.arraycopy(child, 0, result, 1, childLength);
|
||||
} else {
|
||||
result = new byte[base.length + 1 + child.length];
|
||||
System.arraycopy(base, 0, result, 0, base.length);
|
||||
result = new byte[baseLength + 1 + childLength];
|
||||
System.arraycopy(base, 0, result, 0, baseLength);
|
||||
result[base.length] = '/';
|
||||
System.arraycopy(child, 0, result, base.length+1, child.length);
|
||||
System.arraycopy(child, 0, result, baseLength+1, childLength);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath resolve(Path obj) {
|
||||
if (obj == null)
|
||||
return this;
|
||||
byte[] other = checkPath(obj).path;
|
||||
if (other[0] == '/')
|
||||
byte[] other = toUnixPath(obj).path;
|
||||
if (other.length > 0 && other[0] == '/')
|
||||
return ((UnixPath)obj);
|
||||
byte[] result = resolve(path, other);
|
||||
return new UnixPath(getFileSystem(), result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath resolve(String other) {
|
||||
return resolve(new UnixPath(getFileSystem(), other));
|
||||
}
|
||||
|
||||
UnixPath resolve(byte[] other) {
|
||||
return resolve(new UnixPath(getFileSystem(), other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath relativize(Path obj) {
|
||||
UnixPath other = checkPath(obj);
|
||||
UnixPath other = toUnixPath(obj);
|
||||
if (other.equals(this))
|
||||
return null;
|
||||
return emptyPath();
|
||||
|
||||
// can only relativize paths of the same type
|
||||
if (this.isAbsolute() != other.isAbsolute())
|
||||
throw new IllegalArgumentException("'other' is different type of Path");
|
||||
|
||||
// this path is the empty path
|
||||
if (this.isEmpty())
|
||||
return other;
|
||||
|
||||
int bn = this.getNameCount();
|
||||
int cn = other.getNameCount();
|
||||
|
||||
@ -419,14 +438,27 @@ class UnixPath
|
||||
if (dotdots == 0)
|
||||
return remainder;
|
||||
|
||||
// other is the empty path
|
||||
boolean isOtherEmpty = other.isEmpty();
|
||||
|
||||
// result is a "../" for each remaining name in base
|
||||
// followed by the remaining names in other
|
||||
byte[] result = new byte[dotdots*3 + remainder.path.length];
|
||||
// followed by the remaining names in other. If the remainder is
|
||||
// the empty path then we don't add the final trailing slash.
|
||||
int len = dotdots*3 + remainder.path.length;
|
||||
if (isOtherEmpty) {
|
||||
assert remainder.isEmpty();
|
||||
len--;
|
||||
}
|
||||
byte[] result = new byte[len];
|
||||
int pos = 0;
|
||||
while (dotdots > 0) {
|
||||
result[pos++] = (byte)'.';
|
||||
result[pos++] = (byte)'.';
|
||||
result[pos++] = (byte)'/';
|
||||
if (isOtherEmpty) {
|
||||
if (dotdots > 1) result[pos++] = (byte)'/';
|
||||
} else {
|
||||
result[pos++] = (byte)'/';
|
||||
}
|
||||
dotdots--;
|
||||
}
|
||||
System.arraycopy(remainder.path, 0, result, pos, remainder.path.length);
|
||||
@ -457,7 +489,7 @@ class UnixPath
|
||||
int[] size = new int[count]; // length of name
|
||||
int remaining = count; // number of names remaining
|
||||
boolean hasDotDot = false; // has at least one ..
|
||||
boolean isAbsolute = path[0] == '/';
|
||||
boolean isAbsolute = isAbsolute();
|
||||
|
||||
// first pass:
|
||||
// 1. compute length of names
|
||||
@ -542,7 +574,7 @@ class UnixPath
|
||||
|
||||
// corner case - all names removed
|
||||
if (remaining == 0) {
|
||||
return isAbsolute ? getFileSystem().rootDirectory() : null;
|
||||
return isAbsolute ? getFileSystem().rootDirectory() : emptyPath();
|
||||
}
|
||||
|
||||
// compute length of result
|
||||
@ -574,7 +606,7 @@ class UnixPath
|
||||
|
||||
@Override
|
||||
public boolean startsWith(Path other) {
|
||||
UnixPath that = checkPath(other);
|
||||
UnixPath that = toUnixPath(other);
|
||||
|
||||
// other path is longer
|
||||
if (that.path.length > path.length)
|
||||
@ -584,8 +616,9 @@ class UnixPath
|
||||
int thatOffsetCount = that.getNameCount();
|
||||
|
||||
// other path has no name elements
|
||||
if (thatOffsetCount == 0 && this.isAbsolute())
|
||||
return true;
|
||||
if (thatOffsetCount == 0 && this.isAbsolute()) {
|
||||
return that.isEmpty() ? false : true;
|
||||
}
|
||||
|
||||
// given path has more elements that this path
|
||||
if (thatOffsetCount > thisOffsetCount)
|
||||
@ -622,7 +655,7 @@ class UnixPath
|
||||
|
||||
@Override
|
||||
public boolean endsWith(Path other) {
|
||||
UnixPath that = checkPath(other);
|
||||
UnixPath that = toUnixPath(other);
|
||||
|
||||
int thisLen = path.length;
|
||||
int thatLen = that.path.length;
|
||||
@ -631,6 +664,10 @@ class UnixPath
|
||||
if (thatLen > thisLen)
|
||||
return false;
|
||||
|
||||
// other path is the empty path
|
||||
if (thisLen > 0 && thatLen == 0)
|
||||
return false;
|
||||
|
||||
// other path is absolute so this path must be absolute
|
||||
if (that.isAbsolute() && !this.isAbsolute())
|
||||
return false;
|
||||
@ -721,32 +758,6 @@ class UnixPath
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Path> iterator() {
|
||||
initOffsets();
|
||||
return new Iterator<Path>() {
|
||||
int i = 0;
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return (i < offsets.length);
|
||||
}
|
||||
@Override
|
||||
public Path next() {
|
||||
if (i < offsets.length) {
|
||||
Path result = getName(i);
|
||||
i++;
|
||||
return result;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// -- file operations --
|
||||
|
||||
// package-private
|
||||
@ -770,7 +781,6 @@ class UnixPath
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void checkRead() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
@ -789,296 +799,6 @@ class UnixPath
|
||||
sm.checkDelete(getPathForPermissionCheck());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStore getFileStore()
|
||||
throws IOException
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
|
||||
checkRead();
|
||||
}
|
||||
return getFileSystem().getFileStore(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(AccessMode... modes) throws IOException {
|
||||
boolean e = false;
|
||||
boolean r = false;
|
||||
boolean w = false;
|
||||
boolean x = false;
|
||||
|
||||
if (modes.length == 0) {
|
||||
e = true;
|
||||
} else {
|
||||
for (AccessMode mode: modes) {
|
||||
switch (mode) {
|
||||
case READ : r = true; break;
|
||||
case WRITE : w = true; break;
|
||||
case EXECUTE : x = true; break;
|
||||
default: throw new AssertionError("Should not get here");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mode = 0;
|
||||
if (e || r) {
|
||||
checkRead();
|
||||
mode |= (r) ? R_OK : F_OK;
|
||||
}
|
||||
if (w) {
|
||||
checkWrite();
|
||||
mode |= W_OK;
|
||||
}
|
||||
if (x) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
// not cached
|
||||
sm.checkExec(getPathForPermissionCheck());
|
||||
}
|
||||
mode |= X_OK;
|
||||
}
|
||||
try {
|
||||
access(this, mode);
|
||||
} catch (UnixException exc) {
|
||||
exc.rethrowAsIOException(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void implDelete(boolean failIfNotExists) throws IOException {
|
||||
checkDelete();
|
||||
|
||||
// need file attributes to know if file is directory
|
||||
UnixFileAttributes attrs = null;
|
||||
try {
|
||||
attrs = UnixFileAttributes.get(this, false);
|
||||
if (attrs.isDirectory()) {
|
||||
rmdir(this);
|
||||
} else {
|
||||
unlink(this);
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
// no-op if file does not exist
|
||||
if (!failIfNotExists && x.errno() == ENOENT)
|
||||
return;
|
||||
|
||||
// DirectoryNotEmptyException if not empty
|
||||
if (attrs != null && attrs.isDirectory() &&
|
||||
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||||
throw new DirectoryNotEmptyException(getPathForExecptionMessage());
|
||||
|
||||
x.rethrowAsIOException(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirectoryStream<Path> newDirectoryStream(DirectoryStream.Filter<? super Path> filter)
|
||||
throws IOException
|
||||
{
|
||||
if (filter == null)
|
||||
throw new NullPointerException();
|
||||
checkRead();
|
||||
|
||||
// can't return SecureDirectoryStream on kernels that don't support
|
||||
// openat, etc.
|
||||
if (!supportsAtSysCalls()) {
|
||||
try {
|
||||
long ptr = opendir(this);
|
||||
return new UnixDirectoryStream(this, ptr, filter);
|
||||
} catch (UnixException x) {
|
||||
if (x.errno() == ENOTDIR)
|
||||
throw new NotDirectoryException(getPathForExecptionMessage());
|
||||
x.rethrowAsIOException(this);
|
||||
}
|
||||
}
|
||||
|
||||
// open directory and dup file descriptor for use by
|
||||
// opendir/readdir/closedir
|
||||
int dfd1 = -1;
|
||||
int dfd2 = -1;
|
||||
long dp = 0L;
|
||||
try {
|
||||
dfd1 = open(this, O_RDONLY, 0);
|
||||
dfd2 = dup(dfd1);
|
||||
dp = fdopendir(dfd1);
|
||||
} catch (UnixException x) {
|
||||
if (dfd1 != -1)
|
||||
close(dfd1);
|
||||
if (dfd2 != -1)
|
||||
close(dfd2);
|
||||
if (x.errno() == UnixConstants.ENOTDIR)
|
||||
throw new NotDirectoryException(getPathForExecptionMessage());
|
||||
x.rethrowAsIOException(this);
|
||||
}
|
||||
return new UnixSecureDirectoryStream(this, dp, dfd2, filter);
|
||||
}
|
||||
|
||||
// invoked by AbstractPath#copyTo
|
||||
@Override
|
||||
public void implCopyTo(Path obj, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath target = (UnixPath)obj;
|
||||
UnixCopyFile.copy(this, target, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implMoveTo(Path obj, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath target = (UnixPath)obj;
|
||||
UnixCopyFile.move(this, target, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V
|
||||
getFileAttributeView(Class<V> type, LinkOption... options)
|
||||
{
|
||||
FileAttributeView view = getFileSystem()
|
||||
.newFileAttributeView(type, this, options);
|
||||
if (view == null)
|
||||
return null;
|
||||
return (V) view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFileAttributeView getFileAttributeView(String name,
|
||||
LinkOption... options)
|
||||
{
|
||||
return getFileSystem().newFileAttributeView(name, this, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createDirectory(FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
checkWrite();
|
||||
|
||||
int mode = UnixFileModeAttribute
|
||||
.toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs);
|
||||
try {
|
||||
mkdir(this, mode);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
int mode = UnixFileModeAttribute
|
||||
.toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
|
||||
try {
|
||||
return UnixChannelFactory.newFileChannel(this, options, mode);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(this);
|
||||
return null; // keep compiler happy
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameFile(Path obj) throws IOException {
|
||||
if (this.equals(obj))
|
||||
return true;
|
||||
if (!(obj instanceof UnixPath)) // includes null check
|
||||
return false;
|
||||
UnixPath other = (UnixPath)obj;
|
||||
|
||||
// check security manager access to both files
|
||||
this.checkRead();
|
||||
other.checkRead();
|
||||
|
||||
UnixFileAttributes thisAttrs;
|
||||
UnixFileAttributes otherAttrs;
|
||||
try {
|
||||
thisAttrs = UnixFileAttributes.get(this, true);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(this);
|
||||
return false; // keep compiler happy
|
||||
}
|
||||
try {
|
||||
otherAttrs = UnixFileAttributes.get(other, true);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(other);
|
||||
return false; // keep compiler happy
|
||||
}
|
||||
return thisAttrs.isSameFile(otherAttrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createSymbolicLink(Path obj, FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
UnixPath target = checkPath(obj);
|
||||
|
||||
// no attributes supported when creating links
|
||||
if (attrs.length > 0) {
|
||||
UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE
|
||||
throw new UnsupportedOperationException("Initial file attributes" +
|
||||
"not supported when creating symbolic link");
|
||||
}
|
||||
|
||||
// permission check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new LinkPermission("symbolic"));
|
||||
checkWrite();
|
||||
}
|
||||
|
||||
// create link
|
||||
try {
|
||||
symlink(target.asByteArray(), this);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createLink(Path obj) throws IOException {
|
||||
UnixPath existing = checkPath(obj);
|
||||
|
||||
// permission check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new LinkPermission("hard"));
|
||||
this.checkWrite();
|
||||
existing.checkWrite();
|
||||
}
|
||||
try {
|
||||
link(existing, this);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(this, existing);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path readSymbolicLink() throws IOException {
|
||||
// permission check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
FilePermission perm = new FilePermission(getPathForPermissionCheck(),
|
||||
SecurityConstants.FILE_READLINK_ACTION);
|
||||
AccessController.checkPermission(perm);
|
||||
}
|
||||
try {
|
||||
byte[] target = readlink(this);
|
||||
return new UnixPath(getFileSystem(), target);
|
||||
} catch (UnixException x) {
|
||||
if (x.errno() == UnixConstants.EINVAL)
|
||||
throw new NotLinkException(getPathForExecptionMessage());
|
||||
x.rethrowAsIOException(this);
|
||||
return null; // keep compiler happy
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath toAbsolutePath() {
|
||||
if (isAbsolute()) {
|
||||
@ -1095,7 +815,7 @@ class UnixPath
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath toRealPath(boolean resolveLinks) throws IOException {
|
||||
public Path toRealPath(boolean resolveLinks) throws IOException {
|
||||
checkRead();
|
||||
|
||||
UnixPath absolute = toAbsolutePath();
|
||||
@ -1112,8 +832,7 @@ class UnixPath
|
||||
|
||||
// if resolveLinks is false then eliminate "." and also ".."
|
||||
// where the previous element is not a link.
|
||||
UnixPath root = getFileSystem().rootDirectory();
|
||||
UnixPath result = root;
|
||||
UnixPath result = fs.rootDirectory();
|
||||
for (int i=0; i<absolute.getNameCount(); i++) {
|
||||
UnixPath element = absolute.getName(i);
|
||||
|
||||
@ -1134,7 +853,7 @@ class UnixPath
|
||||
if (!attrs.isSymbolicLink()) {
|
||||
result = result.getParent();
|
||||
if (result == null) {
|
||||
result = root;
|
||||
result = fs.rootDirectory();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -1151,15 +870,6 @@ class UnixPath
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
checkRead();
|
||||
UnixPath name = getName();
|
||||
if (name == null)
|
||||
return false;
|
||||
return (name.asByteArray()[0] == '.');
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toUri() {
|
||||
return UnixUriUtils.toUri(this);
|
||||
|
@ -40,7 +40,7 @@ import static sun.nio.fs.UnixConstants.*;
|
||||
*/
|
||||
|
||||
class UnixSecureDirectoryStream
|
||||
extends SecureDirectoryStream<Path>
|
||||
implements SecureDirectoryStream<Path>
|
||||
{
|
||||
private final UnixDirectoryStream ds;
|
||||
private final int dfd;
|
||||
@ -81,6 +81,20 @@ class UnixSecureDirectoryStream
|
||||
return (UnixPath)obj;
|
||||
}
|
||||
|
||||
private boolean followLinks(LinkOption... options) {
|
||||
boolean followLinks = true;
|
||||
for (LinkOption option: options) {
|
||||
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||||
followLinks = false;
|
||||
continue;
|
||||
}
|
||||
if (option == null)
|
||||
throw new NullPointerException();
|
||||
throw new AssertionError("Should not get here");
|
||||
}
|
||||
return followLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens sub-directory in this directory
|
||||
*/
|
||||
@ -91,7 +105,7 @@ class UnixSecureDirectoryStream
|
||||
{
|
||||
UnixPath file = getName(obj);
|
||||
UnixPath child = ds.directory().resolve(file);
|
||||
boolean followLinks = file.getFileSystem().followLinks(options);
|
||||
boolean followLinks = followLinks(options);
|
||||
|
||||
// permission check using name resolved against original path of directory
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
@ -302,7 +316,7 @@ class UnixSecureDirectoryStream
|
||||
LinkOption... options)
|
||||
{
|
||||
UnixPath file = getName(obj);
|
||||
boolean followLinks = file.getFileSystem().followLinks(options);
|
||||
boolean followLinks = followLinks(options);
|
||||
return getFileAttributeViewImpl(file, type, followLinks);
|
||||
}
|
||||
|
||||
@ -336,7 +350,11 @@ class UnixSecureDirectoryStream
|
||||
private void checkWriteAccess() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ds.directory().resolve(file).checkWrite();
|
||||
if (file == null) {
|
||||
ds.directory().checkWrite();
|
||||
} else {
|
||||
ds.directory().resolve(file).checkWrite();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,12 @@ public class RegistryFileTypeDetector
|
||||
}
|
||||
|
||||
@Override
|
||||
public String implProbeContentType(FileRef file) throws IOException {
|
||||
public String implProbeContentType(Path file) throws IOException {
|
||||
if (!(file instanceof Path))
|
||||
return null;
|
||||
|
||||
// get file extension
|
||||
Path name = ((Path)file).getName();
|
||||
Path name = file.getFileName();
|
||||
if (name == null)
|
||||
return null;
|
||||
String filename = name.toString();
|
||||
|
@ -166,22 +166,6 @@ class WindowsFileAttributeViews {
|
||||
return "dos";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals(READONLY_NAME))
|
||||
return readAttributes().isReadOnly();
|
||||
if (attribute.equals(ARCHIVE_NAME))
|
||||
return readAttributes().isArchive();
|
||||
if (attribute.equals(SYSTEM_NAME))
|
||||
return readAttributes().isSystem();
|
||||
if (attribute.equals(HIDDEN_NAME))
|
||||
return readAttributes().isHidden();
|
||||
// implementation specific
|
||||
if (attribute.equals(ATTRIBUTES_NAME))
|
||||
return readAttributes().attributes();
|
||||
return super.getAttribute(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attribute, Object value)
|
||||
throws IOException
|
||||
@ -206,7 +190,7 @@ class WindowsFileAttributeViews {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String[] attributes)
|
||||
public Map<String,Object> readAttributes(String[] attributes)
|
||||
throws IOException
|
||||
{
|
||||
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||
|
@ -158,7 +158,7 @@ class WindowsFileCopy {
|
||||
if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
|
||||
x.lastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
throw new FileAlreadyExistsException(
|
||||
throw new DirectoryNotEmptyException(
|
||||
target.getPathForExceptionMessage());
|
||||
}
|
||||
}
|
||||
@ -369,7 +369,7 @@ class WindowsFileCopy {
|
||||
if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
|
||||
x.lastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
throw new FileAlreadyExistsException(
|
||||
throw new DirectoryNotEmptyException(
|
||||
target.getPathForExceptionMessage());
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user