Merge
This commit is contained in:
commit
82ca44035d
@ -412,6 +412,7 @@ JAVA_JAVA_java = \
|
|||||||
java/io/FileReader.java \
|
java/io/FileReader.java \
|
||||||
java/io/PipedReader.java \
|
java/io/PipedReader.java \
|
||||||
java/io/StringReader.java \
|
java/io/StringReader.java \
|
||||||
|
java/io/TempFileHelper.java \
|
||||||
java/io/Writer.java \
|
java/io/Writer.java \
|
||||||
java/io/BufferedWriter.java \
|
java/io/BufferedWriter.java \
|
||||||
java/io/PrintWriter.java \
|
java/io/PrintWriter.java \
|
||||||
|
@ -86,8 +86,6 @@ FILES_src = \
|
|||||||
java/nio/file/CopyOption.java \
|
java/nio/file/CopyOption.java \
|
||||||
java/nio/file/DirectoryNotEmptyException.java \
|
java/nio/file/DirectoryNotEmptyException.java \
|
||||||
java/nio/file/DirectoryStream.java \
|
java/nio/file/DirectoryStream.java \
|
||||||
java/nio/file/DirectoryStreamFilters.java \
|
|
||||||
java/nio/file/FileAction.java \
|
|
||||||
java/nio/file/FileAlreadyExistsException.java \
|
java/nio/file/FileAlreadyExistsException.java \
|
||||||
java/nio/file/FileRef.java \
|
java/nio/file/FileRef.java \
|
||||||
java/nio/file/FileStore.java \
|
java/nio/file/FileStore.java \
|
||||||
@ -141,6 +139,7 @@ FILES_src = \
|
|||||||
java/nio/file/attribute/FileStoreAttributeView.java \
|
java/nio/file/attribute/FileStoreAttributeView.java \
|
||||||
java/nio/file/attribute/FileStoreSpaceAttributeView.java \
|
java/nio/file/attribute/FileStoreSpaceAttributeView.java \
|
||||||
java/nio/file/attribute/FileStoreSpaceAttributes.java \
|
java/nio/file/attribute/FileStoreSpaceAttributes.java \
|
||||||
|
java/nio/file/attribute/FileTime.java \
|
||||||
java/nio/file/attribute/GroupPrincipal.java \
|
java/nio/file/attribute/GroupPrincipal.java \
|
||||||
java/nio/file/attribute/UserDefinedFileAttributeView.java \
|
java/nio/file/attribute/UserDefinedFileAttributeView.java \
|
||||||
java/nio/file/attribute/PosixFileAttributeView.java \
|
java/nio/file/attribute/PosixFileAttributeView.java \
|
||||||
@ -151,7 +150,6 @@ FILES_src = \
|
|||||||
java/nio/file/attribute/UserPrincipalLookupService.java \
|
java/nio/file/attribute/UserPrincipalLookupService.java \
|
||||||
java/nio/file/attribute/UserPrincipalNotFoundException.java \
|
java/nio/file/attribute/UserPrincipalNotFoundException.java \
|
||||||
\
|
\
|
||||||
java/nio/file/spi/AbstractPath.java \
|
|
||||||
java/nio/file/spi/FileSystemProvider.java \
|
java/nio/file/spi/FileSystemProvider.java \
|
||||||
java/nio/file/spi/FileTypeDetector.java \
|
java/nio/file/spi/FileTypeDetector.java \
|
||||||
\
|
\
|
||||||
@ -248,8 +246,8 @@ FILES_src = \
|
|||||||
\
|
\
|
||||||
sun/nio/fs/AbstractAclFileAttributeView.java \
|
sun/nio/fs/AbstractAclFileAttributeView.java \
|
||||||
sun/nio/fs/AbstractBasicFileAttributeView.java \
|
sun/nio/fs/AbstractBasicFileAttributeView.java \
|
||||||
sun/nio/fs/AbstractFileStoreSpaceAttributeView.java \
|
|
||||||
sun/nio/fs/AbstractFileTypeDetector.java \
|
sun/nio/fs/AbstractFileTypeDetector.java \
|
||||||
|
sun/nio/fs/AbstractPath.java \
|
||||||
sun/nio/fs/AbstractPoller.java \
|
sun/nio/fs/AbstractPoller.java \
|
||||||
sun/nio/fs/AbstractUserDefinedFileAttributeView.java \
|
sun/nio/fs/AbstractUserDefinedFileAttributeView.java \
|
||||||
sun/nio/fs/AbstractWatchKey.java \
|
sun/nio/fs/AbstractWatchKey.java \
|
||||||
@ -258,12 +256,13 @@ FILES_src = \
|
|||||||
sun/nio/fs/Cancellable.java \
|
sun/nio/fs/Cancellable.java \
|
||||||
sun/nio/fs/DefaultFileSystemProvider.java \
|
sun/nio/fs/DefaultFileSystemProvider.java \
|
||||||
sun/nio/fs/DefaultFileTypeDetector.java \
|
sun/nio/fs/DefaultFileTypeDetector.java \
|
||||||
|
sun/nio/fs/DynamicFileAttributeView.java \
|
||||||
sun/nio/fs/FileOwnerAttributeViewImpl.java \
|
sun/nio/fs/FileOwnerAttributeViewImpl.java \
|
||||||
sun/nio/fs/Globs.java \
|
sun/nio/fs/Globs.java \
|
||||||
sun/nio/fs/MimeType.java \
|
|
||||||
sun/nio/fs/NativeBuffer.java \
|
sun/nio/fs/NativeBuffer.java \
|
||||||
sun/nio/fs/NativeBuffers.java \
|
sun/nio/fs/NativeBuffers.java \
|
||||||
sun/nio/fs/Reflect.java \
|
sun/nio/fs/Reflect.java \
|
||||||
|
sun/nio/fs/Util.java \
|
||||||
\
|
\
|
||||||
java/net/DatagramSocket.java \
|
java/net/DatagramSocket.java \
|
||||||
java/net/DatagramSocketImpl.java \
|
java/net/DatagramSocketImpl.java \
|
||||||
|
@ -142,7 +142,7 @@ SUNWprivate_1.1 {
|
|||||||
Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0;
|
Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0;
|
||||||
Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0;
|
Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0;
|
||||||
Java_sun_nio_fs_LinuxNativeDispatcher_endmntent;
|
Java_sun_nio_fs_LinuxNativeDispatcher_endmntent;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_initIDs;
|
Java_sun_nio_fs_UnixNativeDispatcher_init;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
|
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
|
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_dup;
|
Java_sun_nio_fs_UnixNativeDispatcher_dup;
|
||||||
|
@ -120,7 +120,7 @@ SUNWprivate_1.1 {
|
|||||||
Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio;
|
Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio;
|
||||||
Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs;
|
Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs;
|
||||||
Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs;
|
Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_initIDs;
|
Java_sun_nio_fs_UnixNativeDispatcher_init;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
|
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
|
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_dup;
|
Java_sun_nio_fs_UnixNativeDispatcher_dup;
|
||||||
|
@ -30,15 +30,15 @@ import java.net.URI;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
import java.nio.file.*;
|
import java.util.ArrayList;
|
||||||
import java.nio.file.attribute.*;
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.attribute.FileAttribute;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract representation of file and directory pathnames.
|
* An abstract representation of file and directory pathnames.
|
||||||
*
|
*
|
||||||
@ -787,7 +787,7 @@ public class File
|
|||||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||||
* method denies read access to the file
|
* method denies read access to the file
|
||||||
*
|
*
|
||||||
* @see Attributes#readBasicFileAttributes
|
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||||
*/
|
*/
|
||||||
public boolean isDirectory() {
|
public boolean isDirectory() {
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
@ -813,7 +813,7 @@ public class File
|
|||||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||||
* method denies read access to the file
|
* method denies read access to the file
|
||||||
*
|
*
|
||||||
* @see Attributes#readBasicFileAttributes
|
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||||
*/
|
*/
|
||||||
public boolean isFile() {
|
public boolean isFile() {
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
@ -863,7 +863,7 @@ public class File
|
|||||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||||
* method denies read access to the file
|
* method denies read access to the file
|
||||||
*
|
*
|
||||||
* @see Attributes#readBasicFileAttributes
|
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||||
*/
|
*/
|
||||||
public long lastModified() {
|
public long lastModified() {
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
@ -887,7 +887,7 @@ public class File
|
|||||||
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
* java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||||
* method denies read access to the file
|
* method denies read access to the file
|
||||||
*
|
*
|
||||||
* @see Attributes#readBasicFileAttributes
|
* @see java.nio.file.attribute.Attributes#readBasicFileAttributes
|
||||||
*/
|
*/
|
||||||
public long length() {
|
public long length() {
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
@ -1369,9 +1369,10 @@ public class File
|
|||||||
* Sets the owner's or everybody's write permission for this abstract
|
* Sets the owner's or everybody's write permission for this abstract
|
||||||
* pathname.
|
* pathname.
|
||||||
*
|
*
|
||||||
* <p> The {@link Attributes Attributes} class defines methods that operate
|
* <p> The {@link java.nio.file.attribute.Attributes Attributes} class
|
||||||
* on file attributes including file permissions. This may be used when
|
* defines methods that operate on file attributes including file
|
||||||
* finer manipulation of file permissions is required.
|
* permissions. This may be used when finer manipulation of file permissions
|
||||||
|
* is required.
|
||||||
*
|
*
|
||||||
* @param writable
|
* @param writable
|
||||||
* If <code>true</code>, sets the access permission to allow write
|
* If <code>true</code>, sets the access permission to allow write
|
||||||
@ -1436,9 +1437,10 @@ public class File
|
|||||||
* Sets the owner's or everybody's read permission for this abstract
|
* Sets the owner's or everybody's read permission for this abstract
|
||||||
* pathname.
|
* pathname.
|
||||||
*
|
*
|
||||||
* <p> The {@link Attributes Attributes} class defines methods that operate
|
* <p> The {@link java.nio.file.attribute.Attributes Attributes} class
|
||||||
* on file attributes including file permissions. This may be used when
|
* defines methods that operate on file attributes including file
|
||||||
* finer manipulation of file permissions is required.
|
* permissions. This may be used when finer manipulation of file permissions
|
||||||
|
* is required.
|
||||||
*
|
*
|
||||||
* @param readable
|
* @param readable
|
||||||
* If <code>true</code>, sets the access permission to allow read
|
* If <code>true</code>, sets the access permission to allow read
|
||||||
@ -1509,9 +1511,10 @@ public class File
|
|||||||
* Sets the owner's or everybody's execute permission for this abstract
|
* Sets the owner's or everybody's execute permission for this abstract
|
||||||
* pathname.
|
* pathname.
|
||||||
*
|
*
|
||||||
* <p> The {@link Attributes Attributes} class defines methods that operate
|
* <p> The {@link java.nio.file.attribute.Attributes Attributes} class
|
||||||
* on file attributes including file permissions. This may be used when
|
* defines methods that operate on file attributes including file
|
||||||
* finer manipulation of file permissions is required.
|
* permissions. This may be used when finer manipulation of file permissions
|
||||||
|
* is required.
|
||||||
*
|
*
|
||||||
* @param executable
|
* @param executable
|
||||||
* If <code>true</code>, sets the access permission to allow execute
|
* If <code>true</code>, sets the access permission to allow execute
|
||||||
@ -1748,16 +1751,17 @@ public class File
|
|||||||
return fs.getSpace(this, FileSystem.SPACE_USABLE);
|
return fs.getSpace(this, FileSystem.SPACE_USABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -- Temporary files -- */
|
/* -- Temporary files -- */
|
||||||
|
|
||||||
private static class TemporaryDirectory {
|
static class TempDirectory {
|
||||||
private TemporaryDirectory() { }
|
private TempDirectory() { }
|
||||||
|
|
||||||
static final String valueAsString = fs.normalize(
|
// temporary directory location
|
||||||
AccessController.doPrivileged(new GetPropertyAction("java.io.tmpdir")));
|
private static final File tmpdir = new File(fs.normalize(AccessController
|
||||||
static final File valueAsFile =
|
.doPrivileged(new GetPropertyAction("java.io.tmpdir"))));
|
||||||
new File(valueAsString, fs.prefixLength(valueAsString));
|
static File location() {
|
||||||
|
return tmpdir;
|
||||||
|
}
|
||||||
|
|
||||||
// file name generation
|
// file name generation
|
||||||
private static final SecureRandom random = new SecureRandom();
|
private static final SecureRandom random = new SecureRandom();
|
||||||
@ -1770,25 +1774,6 @@ public class File
|
|||||||
}
|
}
|
||||||
return new File(dir, prefix + Long.toString(n) + suffix);
|
return new File(dir, prefix + Long.toString(n) + suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default file permissions
|
|
||||||
static final FileAttribute<Set<PosixFilePermission>> defaultPosixFilePermissions =
|
|
||||||
PosixFilePermissions.asFileAttribute(EnumSet
|
|
||||||
.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE));
|
|
||||||
static final boolean isPosix = isPosix();
|
|
||||||
static boolean isPosix() {
|
|
||||||
return AccessController.doPrivileged(
|
|
||||||
new PrivilegedAction<Boolean>() {
|
|
||||||
public Boolean run() {
|
|
||||||
try {
|
|
||||||
return FileSystems.getDefault().getPath(valueAsString)
|
|
||||||
.getFileStore().supportsFileAttributeView("posix");
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IOError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1869,12 +1854,11 @@ public class File
|
|||||||
if (suffix == null)
|
if (suffix == null)
|
||||||
suffix = ".tmp";
|
suffix = ".tmp";
|
||||||
|
|
||||||
File tmpdir = (directory != null) ?
|
File tmpdir = (directory != null) ? directory : TempDirectory.location();
|
||||||
directory : TemporaryDirectory.valueAsFile;
|
|
||||||
SecurityManager sm = System.getSecurityManager();
|
SecurityManager sm = System.getSecurityManager();
|
||||||
File f;
|
File f;
|
||||||
do {
|
do {
|
||||||
f = TemporaryDirectory.generateFile(prefix, suffix, tmpdir);
|
f = TempDirectory.generateFile(prefix, suffix, tmpdir);
|
||||||
if (sm != null) {
|
if (sm != null) {
|
||||||
try {
|
try {
|
||||||
sm.checkWrite(f.getPath());
|
sm.checkWrite(f.getPath());
|
||||||
@ -1891,11 +1875,17 @@ public class File
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty file in the default temporary-file directory, using
|
* Creates an empty file in the default temporary-file directory, using
|
||||||
* the given prefix and suffix to generate its name. Invoking this method
|
* the given prefix and suffix to generate its name. Invoking this method
|
||||||
* is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
|
* is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
|
||||||
* java.lang.String, java.io.File)
|
* java.lang.String, java.io.File)
|
||||||
* createTempFile(prefix, suffix, null)}</code>.
|
* 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.
|
||||||
|
*
|
||||||
* @param prefix The prefix string to be used in generating the file's
|
* @param prefix The prefix string to be used in generating the file's
|
||||||
* name; must be at least three characters long
|
* name; must be at least three characters long
|
||||||
*
|
*
|
||||||
@ -1926,17 +1916,7 @@ public class File
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty file in the default temporary-file directory, using
|
* Creates an empty file in the default temporary-file directory, using
|
||||||
* the given prefix and suffix to generate its name. This method is
|
* the given prefix and suffix to generate its name.
|
||||||
* equivalent to invoking the {@link #createTempFile(String,String)
|
|
||||||
* createTempFile(prefix, suffix)} method with the addition that the
|
|
||||||
* resulting pathname may be requested to be deleted when the Java virtual
|
|
||||||
* machine terminates, and the initial file attributes to set atomically
|
|
||||||
* when creating the file may be specified.
|
|
||||||
*
|
|
||||||
* <p> When the value of the {@code deleteOnExit} method is {@code true}
|
|
||||||
* then the resulting file is requested to be deleted when the Java virtual
|
|
||||||
* machine terminates as if by invoking the {@link #deleteOnExit deleteOnExit}
|
|
||||||
* method.
|
|
||||||
*
|
*
|
||||||
* <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
|
* <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
|
||||||
* attributes} to set atomically when creating the file. Each attribute is
|
* attributes} to set atomically when creating the file. Each attribute is
|
||||||
@ -1944,6 +1924,12 @@ public class File
|
|||||||
* of the same name is included in the array then all but the last occurrence
|
* of the same name is included in the array then all but the last occurrence
|
||||||
* is ignored.
|
* 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
|
* @param prefix
|
||||||
* The prefix string to be used in generating the file's
|
* The prefix string to be used in generating the file's
|
||||||
* name; must be at least three characters long
|
* name; must be at least three characters long
|
||||||
@ -1951,9 +1937,6 @@ public class File
|
|||||||
* The suffix string to be used in generating the file's
|
* The suffix string to be used in generating the file's
|
||||||
* name; may be {@code null}, in which case the suffix
|
* name; may be {@code null}, in which case the suffix
|
||||||
* {@code ".tmp"} will be used
|
* {@code ".tmp"} will be used
|
||||||
* @param deleteOnExit
|
|
||||||
* {@code true} if the file denoted by resulting pathname be
|
|
||||||
* deleted when the Java virtual machine terminates
|
|
||||||
* @param attrs
|
* @param attrs
|
||||||
* An optional list of file attributes to set atomically when creating
|
* An optional list of file attributes to set atomically when creating
|
||||||
* the file
|
* the file
|
||||||
@ -1961,7 +1944,7 @@ public class File
|
|||||||
* @return An abstract pathname denoting a newly-created empty file
|
* @return An abstract pathname denoting a newly-created empty file
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* If the <code>prefix</code> argument contains fewer than three
|
* If the {@code prefix} argument contains fewer than three
|
||||||
* characters
|
* characters
|
||||||
* @throws UnsupportedOperationException
|
* @throws UnsupportedOperationException
|
||||||
* If the array contains an attribute that cannot be set atomically
|
* If the array contains an attribute that cannot be set atomically
|
||||||
@ -1971,74 +1954,19 @@ public class File
|
|||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* If a security manager exists and its <code>{@link
|
* If a security manager exists and its <code>{@link
|
||||||
* java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
|
* java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
|
||||||
* method does not allow a file to be created. When the {@code
|
* method does not allow a file to be created.
|
||||||
* deleteOnExit} parameter has the value {@code true} then the
|
*
|
||||||
* security manager's {@link
|
|
||||||
* java.lang.SecurityManager#checkDelete(java.lang.String)} is
|
|
||||||
* invoked to check delete access to the file.
|
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public static File createTempFile(String prefix,
|
public static File createTemporaryFile(String prefix,
|
||||||
String suffix,
|
String suffix,
|
||||||
boolean deleteOnExit,
|
FileAttribute<?>... attrs)
|
||||||
FileAttribute<?>... attrs)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if (prefix.length() < 3)
|
if (prefix.length() < 3)
|
||||||
throw new IllegalArgumentException("Prefix string too short");
|
throw new IllegalArgumentException("Prefix string too short");
|
||||||
suffix = (suffix == null) ? ".tmp" : suffix;
|
suffix = (suffix == null) ? ".tmp" : suffix;
|
||||||
|
return TempFileHelper.createFile(prefix, suffix, attrs);
|
||||||
// special case POSIX environments so that 0600 is used as the file mode
|
|
||||||
if (TemporaryDirectory.isPosix) {
|
|
||||||
if (attrs.length == 0) {
|
|
||||||
// no attributes so use default permissions
|
|
||||||
attrs = new FileAttribute<?>[1];
|
|
||||||
attrs[0] = TemporaryDirectory.defaultPosixFilePermissions;
|
|
||||||
} else {
|
|
||||||
// check if posix permissions given; if not use default
|
|
||||||
boolean hasPermissions = false;
|
|
||||||
for (int i=0; i<attrs.length; i++) {
|
|
||||||
if (attrs[i].name().equals("posix:permissions")) {
|
|
||||||
hasPermissions = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasPermissions) {
|
|
||||||
FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length+1];
|
|
||||||
System.arraycopy(attrs, 0, copy, 0, attrs.length);
|
|
||||||
attrs = copy;
|
|
||||||
attrs[attrs.length-1] =
|
|
||||||
TemporaryDirectory.defaultPosixFilePermissions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use Path#createFile to create file
|
|
||||||
SecurityManager sm = System.getSecurityManager();
|
|
||||||
for (;;) {
|
|
||||||
File f = TemporaryDirectory
|
|
||||||
.generateFile(prefix, suffix, TemporaryDirectory.valueAsFile);
|
|
||||||
if (sm != null && deleteOnExit)
|
|
||||||
sm.checkDelete(f.getPath());
|
|
||||||
try {
|
|
||||||
f.toPath().createFile(attrs);
|
|
||||||
if (deleteOnExit)
|
|
||||||
DeleteOnExitHook.add(f.getPath());
|
|
||||||
return f;
|
|
||||||
} catch (InvalidPathException e) {
|
|
||||||
// don't reveal temporary directory location
|
|
||||||
if (sm != null)
|
|
||||||
throw new IllegalArgumentException("Invalid prefix or suffix");
|
|
||||||
throw e;
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
// don't reveal temporary directory location
|
|
||||||
if (sm != null)
|
|
||||||
throw new SecurityException("Unable to create temporary file");
|
|
||||||
throw e;
|
|
||||||
} catch (FileAlreadyExistsException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Basic infrastructure -- */
|
/* -- Basic infrastructure -- */
|
||||||
@ -2153,40 +2081,45 @@ public class File
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link Path java.nio.file.Path} object constructed from the
|
* Returns a {@link Path java.nio.file.Path} object constructed from the
|
||||||
* this abstract path. The first invocation of this method works as if
|
* this abstract path. The resulting {@code Path} is associated with the
|
||||||
* invoking it were equivalent to evaluating the expression:
|
* {@link java.nio.file.FileSystems#getDefault default-filesystem}.
|
||||||
|
*
|
||||||
|
* <p> The first invocation of this method works as if invoking it were
|
||||||
|
* equivalent to evaluating the expression:
|
||||||
* <blockquote><pre>
|
* <blockquote><pre>
|
||||||
* {@link FileSystems#getDefault FileSystems.getDefault}().{@link FileSystem#getPath getPath}(this.{@link #getPath getPath}());
|
* {@link java.nio.file.FileSystems#getDefault FileSystems.getDefault}().{@link
|
||||||
|
* java.nio.file.FileSystem#getPath getPath}(this.{@link #getPath getPath}());
|
||||||
* </pre></blockquote>
|
* </pre></blockquote>
|
||||||
* Subsequent invocations of this method return the same {@code Path}.
|
* Subsequent invocations of this method return the same {@code Path}.
|
||||||
*
|
*
|
||||||
* <p> If this abstract pathname is the empty abstract pathname then this
|
* <p> If this abstract pathname is the empty abstract pathname then this
|
||||||
* method returns a {@code Path} that may be used to access to the current
|
* method returns a {@code Path} that may be used to access the current
|
||||||
* user directory.
|
* user directory.
|
||||||
*
|
*
|
||||||
* @return A {@code Path} constructed from this abstract path. The resulting
|
* @return a {@code Path} constructed from this abstract path
|
||||||
* {@code Path} is associated with the {@link FileSystems#getDefault
|
|
||||||
* default-filesystem}.
|
|
||||||
*
|
*
|
||||||
* @throws InvalidPathException
|
* @throws InvalidPathException
|
||||||
* If a {@code Path} object cannot be constructed from the abstract
|
* if a {@code Path} object cannot be constructed from the abstract
|
||||||
* path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})
|
* path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public Path toPath() {
|
public Path toPath() {
|
||||||
if (filePath == null) {
|
Path result = filePath;
|
||||||
|
if (result == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (filePath == null) {
|
result = filePath;
|
||||||
|
if (result == null) {
|
||||||
if (path.length() == 0) {
|
if (path.length() == 0) {
|
||||||
// assume default file system treats "." as current directory
|
// assume default file system treats "." as current directory
|
||||||
filePath = Paths.get(".");
|
result = Paths.get(".");
|
||||||
} else {
|
} else {
|
||||||
filePath = Paths.get(path);
|
result = Paths.get(path);
|
||||||
}
|
}
|
||||||
|
filePath = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filePath;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
139
jdk/src/share/classes/java/io/TempFileHelper.java
Normal file
139
jdk/src/share/classes/java/io/TempFileHelper.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.io;
|
||||||
|
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.InvalidPathException;
|
||||||
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to support creation of temporary files and directory with
|
||||||
|
* initial attributes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TempFileHelper {
|
||||||
|
private TempFileHelper() { }
|
||||||
|
|
||||||
|
// default file and directory permissions (lazily initialized)
|
||||||
|
private static class PermissionsHolder {
|
||||||
|
static final boolean hasPosixPermissions = FileSystems.getDefault()
|
||||||
|
.supportedFileAttributeViews().contains("posix");
|
||||||
|
static final FileAttribute<Set<PosixFilePermission>> filePermissions =
|
||||||
|
PosixFilePermissions.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE));
|
||||||
|
static final FileAttribute<Set<PosixFilePermission>> directoryPermissions =
|
||||||
|
PosixFilePermissions.asFileAttribute(EnumSet
|
||||||
|
.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a file or directory in the temporary directory.
|
||||||
|
*/
|
||||||
|
private static File create(String prefix,
|
||||||
|
String suffix,
|
||||||
|
FileAttribute[] attrs,
|
||||||
|
boolean isDirectory)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// in POSIX environments use default file and directory permissions
|
||||||
|
// if initial permissions not given by caller.
|
||||||
|
if (PermissionsHolder.hasPosixPermissions) {
|
||||||
|
if (attrs.length == 0) {
|
||||||
|
// no attributes so use default permissions
|
||||||
|
attrs = new FileAttribute<?>[1];
|
||||||
|
attrs[0] = (isDirectory) ? PermissionsHolder.directoryPermissions :
|
||||||
|
PermissionsHolder.filePermissions;
|
||||||
|
} else {
|
||||||
|
// check if posix permissions given; if not use default
|
||||||
|
boolean hasPermissions = false;
|
||||||
|
for (int i=0; i<attrs.length; i++) {
|
||||||
|
if (attrs[i].name().equals("posix:permissions")) {
|
||||||
|
hasPermissions = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasPermissions) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
try {
|
||||||
|
if (isDirectory) {
|
||||||
|
f.toPath().createDirectory(attrs);
|
||||||
|
} else {
|
||||||
|
f.toPath().createFile(attrs);
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
} catch (InvalidPathException e) {
|
||||||
|
// don't reveal temporary directory location
|
||||||
|
if (sm != null)
|
||||||
|
throw new IllegalArgumentException("Invalid prefix or suffix");
|
||||||
|
throw e;
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
// don't reveal temporary directory location
|
||||||
|
if (sm != null)
|
||||||
|
throw new SecurityException("Unable to create temporary file");
|
||||||
|
throw e;
|
||||||
|
} catch (FileAlreadyExistsException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a file in the temporary directory.
|
||||||
|
*/
|
||||||
|
static File createFile(String prefix, String suffix, FileAttribute[] attrs)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
return create(prefix, suffix, attrs, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a directory in the temporary directory.
|
||||||
|
*/
|
||||||
|
static File createDirectory(String prefix, FileAttribute[] attrs)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
return create(prefix, "", attrs, true);
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,6 @@ import java.util.logging.LoggingMXBean;
|
|||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
import java.nio.BufferPoolMXBean;
|
import java.nio.BufferPoolMXBean;
|
||||||
import javax.management.MBeanServerConnection;
|
import javax.management.MBeanServerConnection;
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
import com.sun.management.HotSpotDiagnosticMXBean;
|
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||||
@ -198,10 +197,7 @@ enum PlatformComponent {
|
|||||||
"java.nio", "BufferPool", keyProperties("name"),
|
"java.nio", "BufferPool", keyProperties("name"),
|
||||||
new MXBeanFetcher<BufferPoolMXBean>() {
|
new MXBeanFetcher<BufferPoolMXBean>() {
|
||||||
public List<BufferPoolMXBean> getMXBeans() {
|
public List<BufferPoolMXBean> getMXBeans() {
|
||||||
List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2);
|
return ManagementFactoryHelper.getBufferPoolMXBeans();
|
||||||
pools.add( sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPoolMXBean() );
|
|
||||||
pools.add( sun.nio.ch.FileChannelImpl.getMappedBufferPoolMXBean() );
|
|
||||||
return pools;
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -26,11 +26,8 @@
|
|||||||
package java.nio;
|
package java.nio;
|
||||||
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
import sun.misc.VM;
|
import sun.misc.VM;
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to bits, native and otherwise.
|
* Access to bits, native and otherwise.
|
||||||
@ -676,55 +673,34 @@ class Bits { // package-private
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Management interface for monitoring of direct buffer usage --
|
// -- Monitoring of direct buffer usage --
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// setup access to this package in SharedSecrets
|
// setup access to this package in SharedSecrets
|
||||||
sun.misc.SharedSecrets.setJavaNioAccess(
|
sun.misc.SharedSecrets.setJavaNioAccess(
|
||||||
new sun.misc.JavaNioAccess() {
|
new sun.misc.JavaNioAccess() {
|
||||||
@Override
|
@Override
|
||||||
public BufferPoolMXBean getDirectBufferPoolMXBean() {
|
public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {
|
||||||
return LazyInitialization.directBufferPoolMXBean;
|
return new sun.misc.JavaNioAccess.BufferPool() {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "direct";
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getCount() {
|
||||||
|
return Bits.count;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getTotalCapacity() {
|
||||||
|
return Bits.usedMemory;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getMemoryUsed() {
|
||||||
|
return Bits.reservedMemory;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lazy initialization of management interface
|
|
||||||
private static class LazyInitialization {
|
|
||||||
static final BufferPoolMXBean directBufferPoolMXBean = directBufferPoolMXBean();
|
|
||||||
|
|
||||||
private static BufferPoolMXBean directBufferPoolMXBean() {
|
|
||||||
final String pool = "direct";
|
|
||||||
final ObjectName obj;
|
|
||||||
try {
|
|
||||||
obj = new ObjectName("java.nio:type=BufferPool,name=" + pool);
|
|
||||||
} catch (MalformedObjectNameException x) {
|
|
||||||
throw new AssertionError(x);
|
|
||||||
}
|
|
||||||
return new BufferPoolMXBean() {
|
|
||||||
@Override
|
|
||||||
public ObjectName getObjectName() {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public long getCount() {
|
|
||||||
return Bits.count;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public long getTotalCapacity() {
|
|
||||||
return Bits.usedMemory;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public long getMemoryUsed() {
|
|
||||||
return Bits.reservedMemory;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Bulk get/put acceleration --
|
// -- Bulk get/put acceleration --
|
||||||
|
@ -30,7 +30,6 @@ package java.nio;
|
|||||||
import sun.misc.Cleaner;
|
import sun.misc.Cleaner;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
import sun.nio.ch.DirectBuffer;
|
import sun.nio.ch.DirectBuffer;
|
||||||
import sun.nio.ch.FileChannelImpl;
|
|
||||||
|
|
||||||
|
|
||||||
class Direct$Type$Buffer$RW$$BO$
|
class Direct$Type$Buffer$RW$$BO$
|
||||||
|
@ -47,7 +47,7 @@ import java.io.IOException;
|
|||||||
* so that method invocations on the implementation class can be chained.
|
* so that method invocations on the implementation class can be chained.
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
* @see java.nio.file.FileRef#newByteChannel
|
* @see java.nio.file.Path#newByteChannel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface SeekableByteChannel
|
public interface SeekableByteChannel
|
||||||
|
@ -30,7 +30,7 @@ package java.nio.file;
|
|||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*
|
*
|
||||||
* @see FileRef#checkAccess
|
* @see Path#checkAccess
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public enum AccessMode {
|
public enum AccessMode {
|
||||||
|
@ -27,6 +27,7 @@ package java.nio.file;
|
|||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object to iterate over the entries in a directory. A directory stream
|
* An object to iterate over the entries in a directory. A directory stream
|
||||||
@ -50,13 +51,10 @@ import java.io.Closeable;
|
|||||||
*
|
*
|
||||||
* <p> A {@code DirectoryStream} is opened upon creation and is closed by
|
* <p> A {@code DirectoryStream} is opened upon creation and is closed by
|
||||||
* invoking the {@link #close close} method. Closing the directory stream
|
* invoking the {@link #close close} method. Closing the directory stream
|
||||||
* releases any resources associated with the stream. The {@link
|
* releases any resources associated with the stream. Once a directory stream
|
||||||
* Files#withDirectory Files.withDirectory} utility method is useful for cases
|
* is closed, all further method invocations on the iterator throw {@link
|
||||||
* where a task is performed on entries in a directory. This method automatically
|
* java.util.concurrent.ConcurrentModificationException} with cause {@link
|
||||||
* closes the directory stream when iteration is complete (or an error occurs).
|
* ClosedDirectoryStreamException}.
|
||||||
* Once a directory stream is closed, all further method invocations on the
|
|
||||||
* iterator throw {@link java.util.concurrent.ConcurrentModificationException}
|
|
||||||
* with cause {@link ClosedDirectoryStreamException}.
|
|
||||||
*
|
*
|
||||||
* <p> A directory stream is not required to be <i>asynchronously closeable</i>.
|
* <p> A directory stream is not required to be <i>asynchronously closeable</i>.
|
||||||
* If a thread is blocked on the directory stream's iterator reading from the
|
* If a thread is blocked on the directory stream's iterator reading from the
|
||||||
@ -79,7 +77,7 @@ import java.io.Closeable;
|
|||||||
*
|
*
|
||||||
* <p> The iterator's {@link Iterator#remove() remove} method removes the
|
* <p> The iterator's {@link Iterator#remove() remove} method removes the
|
||||||
* directory entry for the last element returned by the iterator, as if by
|
* directory entry for the last element returned by the iterator, as if by
|
||||||
* invoking the {@link FileRef#delete delete} method. If an I/O error or
|
* invoking the {@link Path#delete delete} method. If an I/O error or
|
||||||
* security exception occurs then {@code ConcurrentModificationException} is
|
* security exception occurs then {@code ConcurrentModificationException} is
|
||||||
* thrown with the cause.
|
* thrown with the cause.
|
||||||
*
|
*
|
||||||
@ -104,10 +102,6 @@ public interface DirectoryStream<T>
|
|||||||
* newDirectoryStream} method when opening a directory to iterate over the
|
* newDirectoryStream} method when opening a directory to iterate over the
|
||||||
* entries in the directory.
|
* entries in the directory.
|
||||||
*
|
*
|
||||||
* <p> The {@link DirectoryStreamFilters} class defines factory methods to
|
|
||||||
* create filters for a number of common usages and also methods to combine
|
|
||||||
* filters.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the directory entry
|
* @param <T> the type of the directory entry
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
@ -120,8 +114,11 @@ public interface DirectoryStream<T>
|
|||||||
* the directory entry to be tested
|
* the directory entry to be tested
|
||||||
*
|
*
|
||||||
* @return {@code true} if the directory entry should be accepted
|
* @return {@code true} if the directory entry should be accepted
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
boolean accept(T entry);
|
boolean accept(T entry) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,210 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007-2009 Sun Microsystems, Inc. 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. Sun designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
||||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
||||||
* have any questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.nio.file;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.IOError;
|
|
||||||
import sun.nio.fs.MimeType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class consists exclusively of static methods that construct or combine
|
|
||||||
* filters.
|
|
||||||
*
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class DirectoryStreamFilters {
|
|
||||||
private DirectoryStreamFilters() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a directory stream filter that filters directory entries by
|
|
||||||
* their <a href="http://www.ietf.org/rfc/rfc2045.txt">MIME</a> content
|
|
||||||
* type. The directory stream filter's {@link
|
|
||||||
* java.nio.file.DirectoryStream.Filter#accept accept} method returns {@code
|
|
||||||
* true} if the content type of the directory entry can be determined by
|
|
||||||
* invoking the {@link Files#probeContentType probeContentType} method, and
|
|
||||||
* the content type matches the given content type.
|
|
||||||
*
|
|
||||||
* <p> The {@code type} parameter is the value of a Multipurpose Internet
|
|
||||||
* Mail Extension (MIME) content type as defined by <a
|
|
||||||
* href="http://www.ietf.org/rfc/rfc2045.txt"><i>RFC 2045: Multipurpose
|
|
||||||
* Internet Mail Extensions (MIME) Part One: Format of Internet Message
|
|
||||||
* Bodies</i></a>. It is parsable according to the grammar in the RFC. Any
|
|
||||||
* space characters (<code>'\u0020'</code>) surrounding its components are
|
|
||||||
* ignored. The {@code type} parameter is parsed into its primary and subtype
|
|
||||||
* components which are used to match the primary and subtype components of
|
|
||||||
* each directory entry's content type. Parameters are not allowed. The
|
|
||||||
* primary type matches if it has value {@code '*'} or is equal to the
|
|
||||||
* primary type of the directory entry's content type without regard to
|
|
||||||
* case. The subtype matches if has the value {@code '*'} or is equal to the
|
|
||||||
* subtype of the directory entry's content type without regard to case. If
|
|
||||||
* both the primary and subtype match then the filter's {@code accept} method
|
|
||||||
* returns {@code true}. If the content type of a directory entry cannot be
|
|
||||||
* determined then the entry is filtered.
|
|
||||||
*
|
|
||||||
* <p> The {@code accept} method of the resulting directory stream filter
|
|
||||||
* throws {@link IOError} if the probing of the content type fails by
|
|
||||||
* throwing an {@link IOException}. Security exceptions are also propogated
|
|
||||||
* to the caller of the {@code accept} method.
|
|
||||||
*
|
|
||||||
* <p> <b>Usage Example:</b>
|
|
||||||
* Suppose we require to list only the HTML files in a directory.
|
|
||||||
* <pre>
|
|
||||||
* DirectoryStream.Filter<FileRef> filter =
|
|
||||||
* DirectoryStreamFilters.newContentTypeFilter("text/html");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* the content type
|
|
||||||
*
|
|
||||||
* @return a new directory stream filter
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* if the {@code type} parameter cannot be parsed as a MIME type
|
|
||||||
* or it has parameters
|
|
||||||
*/
|
|
||||||
public static <T extends FileRef> DirectoryStream.Filter<T>
|
|
||||||
newContentTypeFilter(String type)
|
|
||||||
{
|
|
||||||
final MimeType matchType = MimeType.parse(type);
|
|
||||||
if (matchType.hasParameters())
|
|
||||||
throw new IllegalArgumentException("Parameters not allowed");
|
|
||||||
return new DirectoryStream.Filter<T>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(T entry) {
|
|
||||||
String fileType;
|
|
||||||
try {
|
|
||||||
fileType = Files.probeContentType(entry);
|
|
||||||
} catch (IOException x) {
|
|
||||||
throw new IOError(x);
|
|
||||||
}
|
|
||||||
if (fileType != null) {
|
|
||||||
return matchType.match(fileType);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a directory stream filter that {@link DirectoryStream.Filter#accept
|
|
||||||
* accepts} a directory entry if the entry is accepted by all of the given
|
|
||||||
* filters.
|
|
||||||
*
|
|
||||||
* <p> This method returns a filter that invokes, in iterator order, the
|
|
||||||
* {@code accept} method of each of the filters. If {@code false} is returned
|
|
||||||
* by any of the filters then the directory entry is filtered. If the
|
|
||||||
* directory entry is not filtered then the resulting filter accepts the
|
|
||||||
* entry. If the iterator returns zero elements then the resulting filter
|
|
||||||
* accepts all directory entries.
|
|
||||||
*
|
|
||||||
* <p> <b>Usage Example:</b>
|
|
||||||
* <pre>
|
|
||||||
* List<DirectoryStream.Filter<? super Path>> filters = ...
|
|
||||||
* DirectoryStream.Filter<Path> filter = DirectoryStreamFilters.allOf(filters);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param filters
|
|
||||||
* the sequence of filters
|
|
||||||
*
|
|
||||||
* @return the resulting filter
|
|
||||||
*/
|
|
||||||
public static <T> DirectoryStream.Filter<T>
|
|
||||||
allOf(final Iterable<? extends DirectoryStream.Filter<? super T>> filters)
|
|
||||||
{
|
|
||||||
if (filters == null)
|
|
||||||
throw new NullPointerException("'filters' is null");
|
|
||||||
return new DirectoryStream.Filter<T>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(T entry) {
|
|
||||||
for (DirectoryStream.Filter<? super T> filter: filters) {
|
|
||||||
if (!filter.accept(entry))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a directory stream filter that {@link DirectoryStream.Filter#accept
|
|
||||||
* accepts} a directory entry if the entry is accepted by one or more of
|
|
||||||
* the given filters.
|
|
||||||
*
|
|
||||||
* <p> This method returns a filter that invokes, in iteration order, the
|
|
||||||
* {@code accept} method of each of filter. If {@code true} is returned by
|
|
||||||
* any of the filters then the directory entry is accepted. If none of the
|
|
||||||
* filters accepts the directory entry then it is filtered. If the iterator
|
|
||||||
* returns zero elements then the resulting filter filters all directory
|
|
||||||
* entries.
|
|
||||||
*
|
|
||||||
* @param filters
|
|
||||||
* the sequence of filters
|
|
||||||
*
|
|
||||||
* @return the resulting filter
|
|
||||||
*/
|
|
||||||
public static <T> DirectoryStream.Filter<T>
|
|
||||||
anyOf(final Iterable<? extends DirectoryStream.Filter<? super T>> filters)
|
|
||||||
{
|
|
||||||
if (filters == null)
|
|
||||||
throw new NullPointerException("'filters' is null");
|
|
||||||
return new DirectoryStream.Filter<T>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(T entry) {
|
|
||||||
for (DirectoryStream.Filter<? super T> filter: filters) {
|
|
||||||
if (filter.accept(entry))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a directory stream filter that is the <em>complement</em> of the
|
|
||||||
* given filter. The resulting filter {@link
|
|
||||||
* java.nio.file.DirectoryStream.Filter#accept accepts} a directory entry
|
|
||||||
* if filtered by the given filter, and filters any entries that are accepted
|
|
||||||
* by the given filter.
|
|
||||||
*
|
|
||||||
* @param filter
|
|
||||||
* the given filter
|
|
||||||
*
|
|
||||||
* @return the resulting filter that is the complement of the given filter
|
|
||||||
*/
|
|
||||||
public static <T> DirectoryStream.Filter<T>
|
|
||||||
complementOf(final DirectoryStream.Filter<T> filter)
|
|
||||||
{
|
|
||||||
if (filter == null)
|
|
||||||
throw new NullPointerException("'filter' is null");
|
|
||||||
return new DirectoryStream.Filter<T>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(T entry) {
|
|
||||||
return !filter.accept(entry);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,225 +26,85 @@
|
|||||||
package java.nio.file;
|
package java.nio.file;
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.util.Map;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reference to a file.
|
* A reference to a file.
|
||||||
*
|
*
|
||||||
* <p> A {@code FileRef} is an object that locates a file and defines methods to
|
* <p> A {@code FileRef} is an object that locates a file and defines methods to
|
||||||
* access the file. The means by which the file is located depends on the
|
* open the file for reading or writing. It also provides access to associated
|
||||||
* implementation. In many cases, a file is located by a {@link Path} but it may
|
* metadata or file attributes.
|
||||||
* be located by other means such as a file-system identifier.
|
|
||||||
*
|
|
||||||
* <p> This interface defines the following operations:
|
|
||||||
* <ul>
|
|
||||||
* <li><p> The {@link #newByteChannel newByteChannel} method
|
|
||||||
* may be used to open a file and obtain a byte channel for reading or
|
|
||||||
* writing. </p></li>
|
|
||||||
* <li><p> The {@link #delete delete} method may be used to delete a file.
|
|
||||||
* </p></li>
|
|
||||||
* <li><p> The {@link #checkAccess checkAccess} method may be used to check
|
|
||||||
* the existence or accessibility of a file. </p></li>
|
|
||||||
* <li><p> The {@link #isSameFile isSameFile} method may be used to test if
|
|
||||||
* two file references locate the same file. </p></li>
|
|
||||||
* <li><p> The {@link #getFileStore getFileStore} method may be used to
|
|
||||||
* obtain the {@link FileStore} representing the storage where a file is
|
|
||||||
* located. </p></li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p> Access to associated metadata or file attributes requires an appropriate
|
|
||||||
* {@link FileAttributeView FileAttributeView}. The {@link
|
|
||||||
* #getFileAttributeView(Class,LinkOption[]) getFileAttributeView(Class,LinkOption[])}
|
|
||||||
* method may be used to obtain a file attribute view that defines type-safe
|
|
||||||
* methods to read or update file attributes. The {@link
|
|
||||||
* #getFileAttributeView(String,LinkOption[]) getFileAttributeView(String,LinkOption[])}
|
|
||||||
* method may be used to obtain a file attribute view where dynamic access to
|
|
||||||
* file attributes where required.
|
|
||||||
*
|
|
||||||
* <p> A {@code FileRef} is immutable and safe for use by multiple concurrent
|
|
||||||
* threads.
|
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
|
* @see java.io.Inputs
|
||||||
|
* @see java.io.Outputs
|
||||||
|
* @see java.nio.file.attribute.Attributes
|
||||||
|
* @see java.io.File#toPath
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface FileRef {
|
public interface FileRef {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the file referenced by this object, returning a seekable byte
|
* Opens the file referenced by this object, returning an input stream to
|
||||||
* channel to access the file.
|
* 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.
|
* <p> The {@code options} parameter determines how the file is opened.
|
||||||
* The {@link StandardOpenOption#READ READ} and {@link StandardOpenOption#WRITE
|
* If no options are present then it is equivalent to opening the file with
|
||||||
* WRITE} options determine if the file should be opened for reading and/or
|
* the {@link StandardOpenOption#READ READ} option. In addition to the {@code
|
||||||
* writing. If neither option (or the {@link StandardOpenOption#APPEND APPEND}
|
* READ} option, an implementation may also support additional implementation
|
||||||
* option) is contained in the array then the file is opened for reading.
|
* specific options.
|
||||||
* By default reading or writing commences at the beginning of the file.
|
|
||||||
*
|
*
|
||||||
* <p> In the addition to {@code READ} and {@code WRITE}, the following
|
* @return an input stream to read bytes from the file
|
||||||
* options may be present:
|
|
||||||
*
|
|
||||||
* <table border=1 cellpadding=5 summary="">
|
|
||||||
* <tr> <th>Option</th> <th>Description</th> </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td> {@link StandardOpenOption#APPEND APPEND} </td>
|
|
||||||
* <td> If this option is present then the file is opened for writing and
|
|
||||||
* each invocation of the channel's {@code write} method first advances
|
|
||||||
* the position to the end of the file and then writes the requested
|
|
||||||
* data. Whether the advancement of the position and the writing of the
|
|
||||||
* data are done in a single atomic operation is system-dependent and
|
|
||||||
* therefore unspecified. This option may not be used in conjunction
|
|
||||||
* with the {@code READ} or {@code TRUNCATE_EXISTING} options. </td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td> {@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} </td>
|
|
||||||
* <td> If this option is present then the existing file is truncated to
|
|
||||||
* a size of 0 bytes. This option is ignored when the file is opened only
|
|
||||||
* for reading. </td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td> {@link StandardOpenOption#SYNC SYNC} </td>
|
|
||||||
* <td> Requires that every update to the file's content or metadata be
|
|
||||||
* written synchronously to the underlying storage device. (see <a
|
|
||||||
* href="package-summary.html#integrity"> Synchronized I/O file
|
|
||||||
* integrity</a>). </td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td> {@link StandardOpenOption#DSYNC DSYNC} </td>
|
|
||||||
* <td> Requires that every update to the file's content be written
|
|
||||||
* synchronously to the underlying storage device. (see <a
|
|
||||||
* href="package-summary.html#integrity"> Synchronized I/O file
|
|
||||||
* integrity</a>). </td>
|
|
||||||
* </tr>
|
|
||||||
* </table>
|
|
||||||
*
|
|
||||||
* <p> An implementation of this interface may support additional options
|
|
||||||
* defined by the {@link StandardOpenOption} enumeration type or other
|
|
||||||
* implementation specific options.
|
|
||||||
*
|
|
||||||
* <p> The {@link java.nio.channels.Channels} utility classes defines methods
|
|
||||||
* to construct input and output streams where inter-operation with the
|
|
||||||
* {@link java.io} package is required.
|
|
||||||
*
|
|
||||||
* @param options
|
|
||||||
* Options specifying how the file is opened
|
|
||||||
*
|
|
||||||
* @return a new seekable byte channel
|
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* If an invalid combination of options is specified
|
* if an invalid combination of options is specified
|
||||||
* @throws UnsupportedOperationException
|
* @throws UnsupportedOperationException
|
||||||
* If an unsupported open option is specified
|
* if an unsupported option is specified
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* If an I/O error occurs
|
* if an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* In the case of the default provider, and a security manager is
|
* In the case of the default provider, and a security manager is
|
||||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||||
* method is invoked to check read access to the path if the file is
|
* method is invoked to check read access to the file.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
SeekableByteChannel newByteChannel(OpenOption... options)
|
InputStream newInputStream(OpenOption... options) throws IOException;
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link FileStore} representing the file store where the file
|
* Opens or creates the file located by this object for writing, returning
|
||||||
* referenced by this object is stored.
|
* an output stream to write bytes to the file.
|
||||||
*
|
*
|
||||||
* <p> Once a reference to the {@code FileStore} is obtained it is
|
* <p> The {@code options} parameter determines how the file is opened.
|
||||||
* implementation specific if operations on the returned {@code FileStore},
|
* If no options are present then this method creates a new file for writing
|
||||||
* or {@link FileStoreAttributeView} objects obtained from it, continue
|
* or truncates an existing file. In addition to the {@link StandardOpenOption
|
||||||
* to depend on the existence of the file. In particular the behavior is not
|
* standard} options, an implementation may also support additional
|
||||||
* defined for the case that the file is deleted or moved to a different
|
* implementation specific options.
|
||||||
* file store.
|
|
||||||
*
|
*
|
||||||
* @return The file store where the file is stored
|
* <p> The resulting stream will not be buffered. The stream will be safe
|
||||||
|
* for access by multiple concurrent threads.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @param options
|
||||||
* If an I/O error occurs
|
* options specifying how the file is opened
|
||||||
* @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>
|
|
||||||
*/
|
|
||||||
FileStore getFileStore() throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks the existence and optionally the accessibility of the file
|
|
||||||
* referenced by this object.
|
|
||||||
*
|
*
|
||||||
* <p> This method checks the existence of a file and that this Java virtual
|
* @return a new output stream
|
||||||
* 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. Furthermore, as the result
|
|
||||||
* of this method is immediately outdated, there is no guarantee that a
|
|
||||||
* subsequence access will succeed (or even that it will access the same
|
|
||||||
* file). Care should be taken when using this method in security sensitive
|
|
||||||
* applications.
|
|
||||||
*
|
|
||||||
* @param modes
|
|
||||||
* The access modes to check; may have zero elements
|
|
||||||
*
|
*
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if {@code options} contains an invalid combination of options
|
||||||
* @throws UnsupportedOperationException
|
* @throws UnsupportedOperationException
|
||||||
* An implementation is required to support checking for
|
* if an unsupported option is specified
|
||||||
* {@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
|
* @throws IOException
|
||||||
* If an I/O error occurs
|
* if an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* In the case of the default provider, and a security manager is
|
* In the case of the default provider, and a security manager is
|
||||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
||||||
* is invoked when checking read access to the file or only the
|
* method is invoked to check write access to the file.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
void checkAccess(AccessMode... modes) throws IOException;
|
OutputStream newOutputStream(OpenOption... options) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a file attribute view of a given type.
|
* Returns a file attribute view of a given type.
|
||||||
@ -266,11 +126,11 @@ public interface FileRef {
|
|||||||
* that do not support symbolic links.
|
* that do not support symbolic links.
|
||||||
*
|
*
|
||||||
* @param type
|
* @param type
|
||||||
* The {@code Class} object corresponding to the file attribute view
|
* the {@code Class} object corresponding to the file attribute view
|
||||||
* @param options
|
* @param options
|
||||||
* Options indicating how symbolic links are handled
|
* options indicating how symbolic links are handled
|
||||||
*
|
*
|
||||||
* @return A file attribute view of the specified type, or {@code null} if
|
* @return a file attribute view of the specified type, or {@code null} if
|
||||||
* the attribute view type is not available
|
* the attribute view type is not available
|
||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException
|
* @throws UnsupportedOperationException
|
||||||
@ -280,145 +140,185 @@ public interface FileRef {
|
|||||||
*
|
*
|
||||||
* @see Attributes#readBasicFileAttributes
|
* @see Attributes#readBasicFileAttributes
|
||||||
*/
|
*/
|
||||||
<V extends FileAttributeView> V getFileAttributeView(Class<V> type, LinkOption... options);
|
<V extends FileAttributeView> V getFileAttributeView(Class<V> type,
|
||||||
|
LinkOption... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a file attribute view of the given name.
|
* Sets the value of a file attribute.
|
||||||
*
|
*
|
||||||
* <p> A file attribute view provides a read-only or updatable view of a
|
* <p> The {@code attribute} parameter identifies the attribute to be set
|
||||||
* set of file attributes. This method is intended to be used where
|
* and takes the form:
|
||||||
* <em>dynamic access</em> to the file attributes is required. The {@code
|
* <blockquote>
|
||||||
* name} parameter specifies the {@link FileAttributeView#name name} of the
|
* [<i>view-name</i><b>:</b>]<i>attribute-name</i>
|
||||||
* file attribute view and this method returns an instance of that view if
|
* </blockquote>
|
||||||
* supported. The {@link BasicFileAttributeView} type supports access to the
|
* where square brackets [...] delineate an optional component and the
|
||||||
* basic attributes of a file and is name {@code "basic"}. Invoking this
|
* character {@code ':'} stands for itself.
|
||||||
* method to select a file attribute view named {@code "basic"} will always
|
*
|
||||||
* return an instance of that class.
|
* <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
|
* <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
|
* are handled for the case that the file is a symbolic link. By default,
|
||||||
* file is a symbolic link. By default, symbolic links are followed. If the
|
* symbolic links are followed and the file attribute of the final target
|
||||||
* option {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} is present then
|
* of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS
|
||||||
* symbolic links are not followed. This option is ignored by implementations
|
* NOFOLLOW_LINKS} is present then symbolic links are not followed and so
|
||||||
* that do not support symbolic links.
|
* the method returns the file attribute of the symbolic link.
|
||||||
*
|
*
|
||||||
* @param name
|
* <p> <b>Usage Example:</b>
|
||||||
* The name of the file attribute view
|
* 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
|
* @param options
|
||||||
* Options indicating how symbolic links are handled
|
* Options indicating how symbolic links are handled
|
||||||
*
|
*
|
||||||
* @return A file attribute view of the given name, or {@code null} if
|
* @return A map of the attributes returned; may be empty. The map's keys
|
||||||
* the attribute view is not available
|
* are the attribute names, its values are the attribute values
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
* If options contains an unsupported option. This exception is
|
|
||||||
* specified to allow the {@code LinkOption} enum be extended
|
|
||||||
* in future releases.
|
|
||||||
*/
|
|
||||||
FileAttributeView getFileAttributeView(String name, LinkOption... options);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the file referenced by this object is the same file referenced
|
|
||||||
* by another object.
|
|
||||||
*
|
|
||||||
* <p> If this {@code FileRef} and the given {@code FileRef} are {@link
|
|
||||||
* #equals(Object) equal} then this method returns {@code true} without checking
|
|
||||||
* if the file exists. If the {@code FileRef} and the given {@code FileRef}
|
|
||||||
* are associated with different providers, or the given {@code FileRef} is
|
|
||||||
* {@code null} then this method returns {@code false}. Otherwise, this method
|
|
||||||
* checks if both {@code FileRefs} locate the same file, and depending on the
|
|
||||||
* implementation, may require to open or access both files.
|
|
||||||
*
|
|
||||||
* <p> If the file system and files remain static, then this method implements
|
|
||||||
* an equivalence relation for non-null {@code FileRefs}.
|
|
||||||
* <ul>
|
|
||||||
* <li>It is <i>reflexive</i>: for a non-null {@code FileRef} {@code f},
|
|
||||||
* {@code f.isSameFile(f)} should return {@code true}.
|
|
||||||
* <li>It is <i>symmetric</i>: for two non-null {@code FileRefs}
|
|
||||||
* {@code f} and {@code g}, {@code f.isSameFile(g)} will equal
|
|
||||||
* {@code g.isSameFile(f)}.
|
|
||||||
* <li>It is <i>transitive</i>: for three {@code FileRefs}
|
|
||||||
* {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns
|
|
||||||
* {@code true} and {@code g.isSameFile(h)} returns {@code true}, then
|
|
||||||
* {@code f.isSameFile(h)} will return return {@code true}.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param other
|
|
||||||
* The other file reference
|
|
||||||
*
|
|
||||||
* @return {@code true} if, and only if, this object and the given object
|
|
||||||
* locate the same file
|
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* If an I/O error occurs
|
* If an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* In the case of the default provider, and a security manager is
|
* In the case of the default provider, and a security manager is
|
||||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
* installed, its {@link SecurityManager#checkRead(String) checkRead}
|
||||||
* method is invoked to check read access to both files.
|
* method denies read access to the file. If this method is invoked
|
||||||
*
|
* to read security sensitive attributes then the security manager
|
||||||
* @see java.nio.file.attribute.BasicFileAttributes#fileKey
|
* may be invoke to check for additional permissions.
|
||||||
*/
|
*/
|
||||||
boolean isSameFile(FileRef other) throws IOException;
|
Map<String,?> readAttributes(String attributes, LinkOption... options)
|
||||||
|
throws IOException;
|
||||||
/**
|
|
||||||
* Deletes the file referenced by this object.
|
|
||||||
*
|
|
||||||
* <p> An implementation may require to examine the file to determine if the
|
|
||||||
* file is a directory. Consequently this method may not be atomic with respect
|
|
||||||
* to other file system operations. If the file is a symbolic-link then the
|
|
||||||
* link is deleted and not the final target of the link.
|
|
||||||
*
|
|
||||||
* <p> If the file is a directory then the directory must be empty. In some
|
|
||||||
* implementations a directory has entries for special files or links that
|
|
||||||
* are created when the directory is created. In such implementations a
|
|
||||||
* directory is considered empty when only the special entries exist.
|
|
||||||
*
|
|
||||||
* <p> On some operating systems it may not be possible to remove a file when
|
|
||||||
* it is open and in use by this Java virtual machine or other programs.
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
*/
|
|
||||||
void delete() throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests this object for equality with another object.
|
|
||||||
*
|
|
||||||
* <p> If the given object is not a {@code FileRef} then this method
|
|
||||||
* immediately returns {@code false}.
|
|
||||||
*
|
|
||||||
* <p> For two file references to be considered equal requires that they
|
|
||||||
* are both the same type of {@code FileRef} and encapsulate components
|
|
||||||
* to locate the same file. This method does not access the file system and
|
|
||||||
* the file may not exist.
|
|
||||||
*
|
|
||||||
* <p> This method satisfies the general contract of the {@link
|
|
||||||
* java.lang.Object#equals(Object) Object.equals} method. </p>
|
|
||||||
*
|
|
||||||
* @param ob The object to which this object is to be compared
|
|
||||||
*
|
|
||||||
* @return {@code true} if, and only if, the given object is a {@code FileRef}
|
|
||||||
* that is identical to this {@code FileRef}
|
|
||||||
*
|
|
||||||
* @see #isSameFile
|
|
||||||
*/
|
|
||||||
boolean equals(Object ob);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the hash-code value for this object.
|
|
||||||
*
|
|
||||||
* <p> This method satisfies the general contract of the
|
|
||||||
* {@link java.lang.Object#hashCode() Object.hashCode} method.
|
|
||||||
*/
|
|
||||||
int hashCode();
|
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,13 @@
|
|||||||
package java.nio.file;
|
package java.nio.file;
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage for files. A {@code FileStore} represents a storage pool, device,
|
* Storage for files. A {@code FileStore} represents a storage pool, device,
|
||||||
* partition, volume, concrete file system or other implementation specific means
|
* partition, volume, concrete file system or other implementation specific means
|
||||||
* of file storage. The {@code FileStore} for where a file is stored is obtained
|
* of file storage. The {@code FileStore} for where a file is stored is obtained
|
||||||
* by invoking the {@link FileRef#getFileStore getFileStore} method, or all file
|
* by invoking the {@link Path#getFileStore getFileStore} method, or all file
|
||||||
* stores can be enumerated by invoking the {@link FileSystem#getFileStores
|
* stores can be enumerated by invoking the {@link FileSystem#getFileStores
|
||||||
* getFileStores} method.
|
* getFileStores} method.
|
||||||
*
|
*
|
||||||
@ -146,24 +147,41 @@ public abstract class FileStore {
|
|||||||
getFileStoreAttributeView(Class<V> type);
|
getFileStoreAttributeView(Class<V> type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code FileStoreAttributeView} of the given name.
|
* Reads the value of a file store attribute.
|
||||||
*
|
*
|
||||||
* <p> This method is intended to be used where <em>dynamic access</em> to
|
* <p> The {@code attribute} parameter identifies the attribute to be read
|
||||||
* file store attributes is required. The {@code name} parameter specifies
|
* and takes the form:
|
||||||
* the {@link FileAttributeView#name name} of the file store attribute view
|
* <blockquote>
|
||||||
* and this method returns an instance of that view if supported.
|
* <i>view-name</i><b>:</b><i>attribute-name</i>
|
||||||
|
* </blockquote>
|
||||||
|
* where the character {@code ':'} stands for itself.
|
||||||
|
*
|
||||||
|
* <p> <i>view-name</i> is the {@link FileStoreAttributeView#name name} of
|
||||||
|
* 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
|
* <p> For {@code FileStore} objects created by the default provider, then
|
||||||
* the file stores support the {@link FileStoreSpaceAttributeView} that
|
* the file stores support the {@link FileStoreSpaceAttributeView} that
|
||||||
* provides access to space attributes. In that case invoking this method
|
* provides access to space attributes.
|
||||||
* with a parameter value of {@code "space"} will always return an instance
|
|
||||||
* of that class.
|
|
||||||
*
|
*
|
||||||
* @param name
|
* <p> <b>Usage Example:</b>
|
||||||
* the name of the attribute view
|
* Suppose we want to know if ZFS compression is enabled (assuming the "zfs"
|
||||||
|
* view is supported):
|
||||||
|
* <pre>
|
||||||
|
* boolean compression = (Boolean)fs.getAttribute("zfs:compression");
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @return a file store attribute view of the given name, or {@code null}
|
* @param attribute
|
||||||
* if the attribute view is not available
|
* the attribute to read
|
||||||
|
|
||||||
|
* @return the attribute value; {@code null} may be a valid valid for some
|
||||||
|
* attributes
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
* if the attribute view is not available or it does not support
|
||||||
|
* reading the attribute
|
||||||
|
* @throws IOException
|
||||||
|
* if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public abstract FileStoreAttributeView getFileStoreAttributeView(String name);
|
public abstract Object getAttribute(String attribute) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,6 @@ class FileTreeWalker {
|
|||||||
case FOLLOW_LINKS : fl = true; break;
|
case FOLLOW_LINKS : fl = true; break;
|
||||||
case DETECT_CYCLES : dc = true; break;
|
case DETECT_CYCLES : dc = true; break;
|
||||||
default:
|
default:
|
||||||
if (option == null)
|
|
||||||
throw new NullPointerException("Visit options contains 'null'");
|
|
||||||
throw new AssertionError("Should not get here");
|
throw new AssertionError("Should not get here");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,13 +237,13 @@ class FileTreeWalker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class AncestorDirectory {
|
private static class AncestorDirectory {
|
||||||
private final FileRef dir;
|
private final Path dir;
|
||||||
private final Object key;
|
private final Object key;
|
||||||
AncestorDirectory(FileRef dir, Object key) {
|
AncestorDirectory(Path dir, Object key) {
|
||||||
this.dir = dir;
|
this.dir = dir;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
FileRef file() {
|
Path file() {
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
Object fileKey() {
|
Object fileKey() {
|
||||||
|
@ -42,9 +42,9 @@ import java.io.IOException;
|
|||||||
* @Override
|
* @Override
|
||||||
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||||
* try {
|
* try {
|
||||||
* file.delete(false);
|
* file.delete();
|
||||||
* } catch (IOException exc) {
|
* } catch (IOException exc) {
|
||||||
* // failed to delete
|
* // failed to delete, do error handling here
|
||||||
* }
|
* }
|
||||||
* return FileVisitResult.CONTINUE;
|
* return FileVisitResult.CONTINUE;
|
||||||
* }
|
* }
|
||||||
@ -52,9 +52,9 @@ import java.io.IOException;
|
|||||||
* public FileVisitResult postVisitDirectory(Path dir, IOException e) {
|
* public FileVisitResult postVisitDirectory(Path dir, IOException e) {
|
||||||
* if (e == null) {
|
* if (e == null) {
|
||||||
* try {
|
* try {
|
||||||
* dir.delete(false);
|
* dir.delete();
|
||||||
* } catch (IOException exc) {
|
* } catch (IOException exc) {
|
||||||
* // failed to delete
|
* // failed to delete, do error handling here
|
||||||
* }
|
* }
|
||||||
* } else {
|
* } else {
|
||||||
* // directory iteration failed
|
* // directory iteration failed
|
||||||
@ -80,7 +80,8 @@ import java.io.IOException;
|
|||||||
* } catch (FileAlreadyExistsException e) {
|
* } catch (FileAlreadyExistsException e) {
|
||||||
* // ignore
|
* // ignore
|
||||||
* } catch (IOException e) {
|
* } catch (IOException e) {
|
||||||
* // copy failed, skip rest of directory and descendants
|
* // copy failed, do error handling here
|
||||||
|
* // skip rest of directory and descendants
|
||||||
* return SKIP_SUBTREE;
|
* return SKIP_SUBTREE;
|
||||||
* }
|
* }
|
||||||
* return CONTINUE;
|
* return CONTINUE;
|
||||||
@ -90,7 +91,7 @@ import java.io.IOException;
|
|||||||
* try {
|
* try {
|
||||||
* file.copyTo(target.resolve(source.relativize(file)));
|
* file.copyTo(target.resolve(source.relativize(file)));
|
||||||
* } catch (IOException e) {
|
* } catch (IOException e) {
|
||||||
* // copy failed
|
* // copy failed, do error handling here
|
||||||
* }
|
* }
|
||||||
* return CONTINUE;
|
* return CONTINUE;
|
||||||
* }
|
* }
|
||||||
@ -100,7 +101,7 @@ import java.io.IOException;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface FileVisitor<T extends FileRef> {
|
public interface FileVisitor<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked for a directory before entries in the directory are visited.
|
* Invoked for a directory before entries in the directory are visited.
|
||||||
|
@ -26,13 +26,15 @@
|
|||||||
package java.nio.file;
|
package java.nio.file;
|
||||||
|
|
||||||
import java.nio.file.spi.FileTypeDetector;
|
import java.nio.file.spi.FileTypeDetector;
|
||||||
|
import java.nio.file.attribute.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for files and directories.
|
* This class consists exclusively of static methods that operate on files or
|
||||||
|
* directories.
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
@ -109,8 +111,6 @@ public final class Files {
|
|||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* If a security manager is installed and it denies an unspecified
|
* If a security manager is installed and it denies an unspecified
|
||||||
* permission required by a file type detector implementation.
|
* permission required by a file type detector implementation.
|
||||||
*
|
|
||||||
* @see DirectoryStreamFilters#newContentTypeFilter
|
|
||||||
*/
|
*/
|
||||||
public static String probeContentType(FileRef file)
|
public static String probeContentType(FileRef file)
|
||||||
throws IOException
|
throws IOException
|
||||||
@ -127,158 +127,6 @@ public final class Files {
|
|||||||
.probeContentType(file);
|
.probeContentType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes a {@link FileAction} for each entry in a directory accepted
|
|
||||||
* by a given {@link java.nio.file.DirectoryStream.Filter filter}.
|
|
||||||
*
|
|
||||||
* <p> This method opens the given directory and invokes the file action's
|
|
||||||
* {@link FileAction#invoke invoke} method for each entry accepted by the
|
|
||||||
* filter. When iteration is completed then the directory is closed. If the
|
|
||||||
* {@link DirectoryStream#close close} method throws an {@code IOException}
|
|
||||||
* then it is silently ignored.
|
|
||||||
*
|
|
||||||
* <p> If the {@code FileAction}'s {@code invoke} method terminates due
|
|
||||||
* to an uncaught {@link IOException}, {@code Error} or {@code RuntimeException}
|
|
||||||
* then the exception is propagated by this method after closing the
|
|
||||||
* directory.
|
|
||||||
*
|
|
||||||
* @param dir
|
|
||||||
* The directory
|
|
||||||
* @param filter
|
|
||||||
* The filter
|
|
||||||
* @param action
|
|
||||||
* The {@code FileAction} to invoke for each accepted entry
|
|
||||||
*
|
|
||||||
* @throws NotDirectoryException
|
|
||||||
* If the {@code dir} parameter is not a directory <i>(optional
|
|
||||||
* specific exception)</i>
|
|
||||||
* @throws IOException
|
|
||||||
* If an I/O error occurs or the {@code invoke} method terminates
|
|
||||||
* due to an uncaught {@code IOException}
|
|
||||||
* @throws SecurityException
|
|
||||||
* In the case of the default provider, the {@link
|
|
||||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
|
||||||
* to check read access to the directory.
|
|
||||||
*/
|
|
||||||
public static void withDirectory(Path dir,
|
|
||||||
DirectoryStream.Filter<? super Path> filter,
|
|
||||||
FileAction<? super Path> action)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
// explicit null check required in case directory is empty
|
|
||||||
if (action == null)
|
|
||||||
throw new NullPointerException();
|
|
||||||
|
|
||||||
DirectoryStream<Path> stream = dir.newDirectoryStream(filter);
|
|
||||||
try {
|
|
||||||
// set to true when invoking the action so as to distinguish a
|
|
||||||
// CME thrown by the iteration from a CME thrown by the invoke
|
|
||||||
boolean inAction = false;
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
inAction = true;
|
|
||||||
action.invoke(entry);
|
|
||||||
inAction = false;
|
|
||||||
}
|
|
||||||
} catch (ConcurrentModificationException cme) {
|
|
||||||
if (!inAction) {
|
|
||||||
Throwable cause = cme.getCause();
|
|
||||||
if (cause instanceof IOException)
|
|
||||||
throw (IOException)cause;
|
|
||||||
}
|
|
||||||
throw cme;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
stream.close();
|
|
||||||
} catch (IOException x) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes a {@link FileAction} for each entry in a directory with a
|
|
||||||
* file name that matches a given pattern.
|
|
||||||
*
|
|
||||||
* <p> This method opens the given directory and invokes the file action's
|
|
||||||
* {@link FileAction#invoke invoke} method for each entry that matches the
|
|
||||||
* given pattern. When iteration is completed then the directory is closed.
|
|
||||||
* If the {@link DirectoryStream#close close} method throws an {@code
|
|
||||||
* IOException} then it is silently ignored.
|
|
||||||
*
|
|
||||||
* <p> If the {@code FileAction}'s {@code invoke} method terminates due
|
|
||||||
* to an uncaught {@link IOException}, {@code Error} or {@code RuntimeException}
|
|
||||||
* then the exception is propagated by this method after closing the
|
|
||||||
* directory.
|
|
||||||
*
|
|
||||||
* <p> The globbing pattern language supported by this method is as
|
|
||||||
* specified by the {@link FileSystem#getPathMatcher getPathMatcher} method.
|
|
||||||
*
|
|
||||||
* @param dir
|
|
||||||
* The directory
|
|
||||||
* @param glob
|
|
||||||
* The globbing pattern
|
|
||||||
* @param action
|
|
||||||
* The {@code FileAction} to invoke for each entry
|
|
||||||
*
|
|
||||||
* @throws NotDirectoryException
|
|
||||||
* If the {@code dir} parameter is not a directory <i>(optional
|
|
||||||
* specific exception)</i>
|
|
||||||
* @throws IOException
|
|
||||||
* If an I/O error occurs or the {@code invoke} method terminates
|
|
||||||
* due to an uncaught {@code IOException}
|
|
||||||
* @throws SecurityException
|
|
||||||
* In the case of the default provider, the {@link
|
|
||||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
|
||||||
* to check read access to the directory.
|
|
||||||
*/
|
|
||||||
public static void withDirectory(Path dir,
|
|
||||||
String glob,
|
|
||||||
FileAction<? super Path> action)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (glob == null)
|
|
||||||
throw new NullPointerException("'glob' is null");
|
|
||||||
final PathMatcher matcher = dir.getFileSystem().getPathMatcher("glob:" + glob);
|
|
||||||
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(Path entry) {
|
|
||||||
return matcher.matches(entry.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
withDirectory(dir, filter, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes a {@link FileAction} for all entries in a directory.
|
|
||||||
*
|
|
||||||
* <p> This method works as if invoking it were equivalent to evaluating the
|
|
||||||
* expression:
|
|
||||||
* <blockquote><pre>
|
|
||||||
* withDirectory(dir, "*", action)
|
|
||||||
* </pre></blockquote>
|
|
||||||
*
|
|
||||||
* @param dir
|
|
||||||
* The directory
|
|
||||||
* @param action
|
|
||||||
* The {@code FileAction} to invoke for each entry
|
|
||||||
*
|
|
||||||
* @throws NotDirectoryException
|
|
||||||
* If the {@code dir} parameter is not a directory <i>(optional
|
|
||||||
* specific exception)</i>
|
|
||||||
* @throws IOException
|
|
||||||
* If an I/O error occurs or the {@code invoke} method terminates
|
|
||||||
* due to an uncaught {@code IOException}
|
|
||||||
* @throws SecurityException
|
|
||||||
* In the case of the default provider, the {@link
|
|
||||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
|
||||||
* to check read access to the directory.
|
|
||||||
*/
|
|
||||||
public static void withDirectory(Path dir, FileAction<? super Path> action)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
withDirectory(dir, "*", action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walks a file tree.
|
* Walks a file tree.
|
||||||
*
|
*
|
||||||
@ -328,7 +176,7 @@ public final class Files {
|
|||||||
* arises when there is an entry in a directory that is an ancestor of the
|
* arises when there is an entry in a directory that is an ancestor of the
|
||||||
* directory. Cycle detection is done by recording the {@link
|
* directory. Cycle detection is done by recording the {@link
|
||||||
* java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
|
* java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
|
||||||
* or if file keys are not available, by invoking the {@link FileRef#isSameFile
|
* or if file keys are not available, by invoking the {@link Path#isSameFile
|
||||||
* isSameFile} method to test if a directory is the same file as an
|
* isSameFile} method to test if a directory is the same file as an
|
||||||
* ancestor. When a cycle is detected the {@link FileVisitor#visitFile
|
* ancestor. When a cycle is detected the {@link FileVisitor#visitFile
|
||||||
* visitFile} is invoked with the attributes of the directory. The {@link
|
* visitFile} is invoked with the attributes of the directory. The {@link
|
||||||
@ -403,4 +251,108 @@ public final class Files {
|
|||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
visitor);
|
visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a directory by creating all nonexistent parent directories first.
|
||||||
|
*
|
||||||
|
* <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
|
||||||
|
* file-attributes} to set atomically when creating the nonexistent
|
||||||
|
* directories. Each file 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> If this method fails, then it may do so after creating some, but not
|
||||||
|
* all, of the parent directories.
|
||||||
|
*
|
||||||
|
* @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 {@code dir} exists but 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#checkWrite(String) checkWrite}
|
||||||
|
* method is invoked prior to attempting to create a directory and
|
||||||
|
* its {@link SecurityManager#checkRead(String) checkRead} is
|
||||||
|
* invoked for each parent directory that is checked. If {@code
|
||||||
|
* dir} is not an absolute path then its {@link Path#toAbsolutePath
|
||||||
|
* toAbsolutePath} may need to be invoked to get its absolute path.
|
||||||
|
* This may invoke the security manager's {@link
|
||||||
|
* SecurityManager#checkPropertyAccess(String) checkPropertyAccess}
|
||||||
|
* method to check access to the system property {@code user.dir}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static void createDirectories(Path dir, FileAttribute<?>... attrs)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// attempt to create the directory
|
||||||
|
try {
|
||||||
|
createAndCheckIsDirectory(dir, attrs);
|
||||||
|
return;
|
||||||
|
} catch (FileAlreadyExistsException x) {
|
||||||
|
// file exists and is not a directory
|
||||||
|
throw x;
|
||||||
|
} catch (IOException x) {
|
||||||
|
// parent may not exist or other reason
|
||||||
|
}
|
||||||
|
|
||||||
|
// find existing parent (may require absolute path)
|
||||||
|
SecurityException se = null;
|
||||||
|
try {
|
||||||
|
dir = dir.toAbsolutePath();
|
||||||
|
} catch (SecurityException x) {
|
||||||
|
// don't have permission to get absolute path
|
||||||
|
se = x;
|
||||||
|
}
|
||||||
|
Path parent = dir.getParent();
|
||||||
|
while (parent != null) {
|
||||||
|
try {
|
||||||
|
parent.checkAccess();
|
||||||
|
break;
|
||||||
|
} catch (NoSuchFileException x) {
|
||||||
|
// does not exist
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
if (parent == null) {
|
||||||
|
// unable to find existing parent
|
||||||
|
if (se != null)
|
||||||
|
throw se;
|
||||||
|
throw new IOException("Root directory does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create directories
|
||||||
|
Path child = parent;
|
||||||
|
for (Path name: parent.relativize(dir)) {
|
||||||
|
child = child.resolve(name);
|
||||||
|
createAndCheckIsDirectory(child, attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to create a directory. Does nothing if the directory already
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
private static void createAndCheckIsDirectory(Path dir, FileAttribute<?>... attrs)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
dir.createDirectory(attrs);
|
||||||
|
} catch (FileAlreadyExistsException x) {
|
||||||
|
boolean isDirectory = Attributes
|
||||||
|
.readBasicFileAttributes(dir, LinkOption.NOFOLLOW_LINKS).isDirectory();
|
||||||
|
if (!isDirectory)
|
||||||
|
throw x;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ public final class LinkPermission extends BasicPermission {
|
|||||||
* {@code null}
|
* {@code null}
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if name is empty or invalid
|
* if name is empty or invalid, or actions is a non-empty string
|
||||||
*/
|
*/
|
||||||
public LinkPermission(String name, String actions) {
|
public LinkPermission(String name, String actions) {
|
||||||
super(name);
|
super(name);
|
||||||
|
@ -30,7 +30,7 @@ package java.nio.file;
|
|||||||
*
|
*
|
||||||
* <p> Objects of this type are used by methods such as {@link
|
* <p> Objects of this type are used by methods such as {@link
|
||||||
* Path#newOutputStream(OpenOption[]) newOutputStream}, {@link
|
* Path#newOutputStream(OpenOption[]) newOutputStream}, {@link
|
||||||
* FileRef#newByteChannel newByteChannel}, {@link
|
* Path#newByteChannel newByteChannel}, {@link
|
||||||
* java.nio.channels.FileChannel#open FileChannel.open}, and {@link
|
* java.nio.channels.FileChannel#open FileChannel.open}, and {@link
|
||||||
* java.nio.channels.AsynchronousFileChannel#open AsynchronousFileChannel.open}
|
* java.nio.channels.AsynchronousFileChannel#open AsynchronousFileChannel.open}
|
||||||
* when opening or creating a file.
|
* when opening or creating a file.
|
||||||
|
@ -26,10 +26,12 @@
|
|||||||
package java.nio.file;
|
package java.nio.file;
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.*;
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A file reference that locates a file using a system dependent path. The file
|
* A file reference that locates a file using a system dependent path. The file
|
||||||
@ -70,19 +72,27 @@ import java.util.*;
|
|||||||
* this class defines the following operations:
|
* this class defines the following operations:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
|
* <li><p> The {@link #newByteChannel newByteChannel} method
|
||||||
|
* may be used to open a file and obtain a byte channel for reading or
|
||||||
|
* writing. </p></li>
|
||||||
* <li><p> Files may be {@link #createFile(FileAttribute[]) created}, or
|
* <li><p> Files may be {@link #createFile(FileAttribute[]) created}, or
|
||||||
* directories may be {@link #createDirectory(FileAttribute[]) created}.
|
* directories may be {@link #createDirectory(FileAttribute[]) created}.
|
||||||
* </p></li>
|
* </p></li>
|
||||||
|
* <li><p> The {@link #delete delete} method may be used to delete a file.
|
||||||
|
* </p></li>
|
||||||
|
* <li><p> The {@link #checkAccess checkAccess} method may be used to check
|
||||||
|
* the existence or accessibility of a file. </p></li>
|
||||||
|
* <li><p> The {@link #isSameFile isSameFile} method may be used to test if
|
||||||
|
* two file references locate the same file. </p></li>
|
||||||
|
* <li><p> The {@link #getFileStore getFileStore} method may be used to
|
||||||
|
* obtain the {@link FileStore} representing the storage where a file is
|
||||||
|
* located. </p></li>
|
||||||
* <li><p> Directories can be {@link #newDirectoryStream opened} so as to
|
* <li><p> Directories can be {@link #newDirectoryStream opened} so as to
|
||||||
* iterate over the entries in the directory. </p></li>
|
* iterate over the entries in the directory. </p></li>
|
||||||
* <li><p> Files can be {@link #copyTo(Path,CopyOption[]) copied} or
|
* <li><p> Files can be {@link #copyTo(Path,CopyOption[]) copied} or
|
||||||
* {@link #moveTo(Path,CopyOption[]) moved}. </p></li>
|
* {@link #moveTo(Path,CopyOption[]) moved}. </p></li>
|
||||||
* <li><p> Symbolic-links may be {@link #createSymbolicLink created}, or the
|
* <li><p> Symbolic-links may be {@link #createSymbolicLink created}, or the
|
||||||
* target of a link may be {@link #readSymbolicLink read}. </p></li>
|
* target of a link may be {@link #readSymbolicLink read}. </p></li>
|
||||||
* <li><p> {@link #newInputStream InputStream} or {@link #newOutputStream
|
|
||||||
* OutputStream} streams can be created to allow for interoperation with the
|
|
||||||
* <a href="../../../java/io/package-summary.html">{@code java.io}</a> package
|
|
||||||
* where required. </li></p>
|
|
||||||
* <li><p> The {@link #toRealPath real} path of an existing file may be
|
* <li><p> The {@link #toRealPath real} path of an existing file may be
|
||||||
* obtained. </li></p>
|
* obtained. </li></p>
|
||||||
* </ul>
|
* </ul>
|
||||||
@ -93,13 +103,14 @@ import java.util.*;
|
|||||||
*
|
*
|
||||||
* <h4>File attributes</h4>
|
* <h4>File attributes</h4>
|
||||||
*
|
*
|
||||||
* The <a href="attribute/package-summary.html">{@code java.nio.file.attribute}</a>
|
* In addition to the {@link #setAttribute setAttribute} and {@link #getAttribute
|
||||||
* package provides access to file attributes or <em>meta-data</em> associated
|
* getAttribute} methods, the <a href="attribute/package-summary.html">{@code
|
||||||
* with files. The {@link Attributes Attributes} class defines methods that
|
* java.nio.file.attribute}</a> package provides type-safe and efficient access
|
||||||
* operate on or return file attributes. For example, the file type, size,
|
* to file attributes or <em>meta-data</em> associated with files. The {@link
|
||||||
* timestamps, and other <em>basic</em> meta-data are obtained, in bulk, by
|
* Attributes Attributes} class defines methods that operate on or return file
|
||||||
* invoking the {@link Attributes#readBasicFileAttributes
|
* attributes. For example, the file type, size, timestamps, and other
|
||||||
* Attributes.readBasicFileAttributes} method:
|
* <em>basic</em> meta-data are obtained, in bulk, by invoking the {@link
|
||||||
|
* Attributes#readBasicFileAttributes Attributes.readBasicFileAttributes} method:
|
||||||
* <pre>
|
* <pre>
|
||||||
* Path file = ...
|
* Path file = ...
|
||||||
* BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
|
* BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
|
||||||
@ -417,12 +428,38 @@ public abstract class Path
|
|||||||
/**
|
/**
|
||||||
* Deletes the file located by this path.
|
* Deletes the file located by this path.
|
||||||
*
|
*
|
||||||
* <p> The {@code failIfNotExists} parameter determines how the method
|
* <p> An implementation may require to examine the file to determine if the
|
||||||
* behaves when the file does not exist. When {@code true}, and the file
|
* file is a directory. Consequently this method may not be atomic with respect
|
||||||
* does not exist, then the method fails. When {@code false} then the method
|
* to other file system operations. If the file is a symbolic-link then the
|
||||||
* does not fail.
|
* link is deleted and not the final target of the link.
|
||||||
*
|
*
|
||||||
* <p> As with the {@link FileRef#delete delete()} method, an implementation
|
* <p> If the file is a directory then the directory must be empty. In some
|
||||||
|
* implementations a directory has entries for special files or links that
|
||||||
|
* are created when the directory is created. In such implementations a
|
||||||
|
* directory is considered empty when only the special entries exist.
|
||||||
|
*
|
||||||
|
* <p> On some operating systems it may not be possible to remove a file when
|
||||||
|
* it is open and in use by this Java virtual machine or other programs.
|
||||||
|
*
|
||||||
|
* @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() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the file located by this path, if it exists.
|
||||||
|
*
|
||||||
|
* <p> As with the {@link #delete delete()} method, an implementation
|
||||||
* may require to examine the file to determine if the file is a directory.
|
* may require to examine the file to determine if the file is a directory.
|
||||||
* Consequently this method may not be atomic with respect to other file
|
* Consequently this method may not be atomic with respect to other file
|
||||||
* system operations. If the file is a symbolic-link then the link is
|
* system operations. If the file is a symbolic-link then the link is
|
||||||
@ -436,13 +473,6 @@ public abstract class Path
|
|||||||
* <p> On some operating systems it may not be possible to remove a file when
|
* <p> On some operating systems it may not be possible to remove a file when
|
||||||
* it is open and in use by this Java virtual machine or other programs.
|
* it is open and in use by this Java virtual machine or other programs.
|
||||||
*
|
*
|
||||||
* @param failIfNotExists
|
|
||||||
* {@code true} if the method should fail when the file does not
|
|
||||||
* exist
|
|
||||||
*
|
|
||||||
* @throws NoSuchFileException
|
|
||||||
* if the value of the {@code failIfNotExists} is {@code true} and
|
|
||||||
* the file does not exist <i>(optional specific exception)</i>
|
|
||||||
* @throws DirectoryNotEmptyException
|
* @throws DirectoryNotEmptyException
|
||||||
* if the file is a directory and could not otherwise be deleted
|
* if the file is a directory and could not otherwise be deleted
|
||||||
* because the directory is not empty <i>(optional specific
|
* because the directory is not empty <i>(optional specific
|
||||||
@ -454,7 +484,7 @@ public abstract class Path
|
|||||||
* installed, the {@link SecurityManager#checkDelete(String)} method
|
* installed, the {@link SecurityManager#checkDelete(String)} method
|
||||||
* is invoked to check delete access to the file.
|
* is invoked to check delete access to the file.
|
||||||
*/
|
*/
|
||||||
public abstract void delete(boolean failIfNotExists) throws IOException;
|
public abstract void deleteIfExists() throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a symbolic link to a target <i>(optional operation)</i>.
|
* Creates a symbolic link to a target <i>(optional operation)</i>.
|
||||||
@ -536,8 +566,6 @@ public abstract class Path
|
|||||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||||
* method denies write access to both this path and the path of the
|
* method denies write access to both this path and the path of the
|
||||||
* existing file.
|
* existing file.
|
||||||
*
|
|
||||||
* @see BasicFileAttributes#linkCount
|
|
||||||
*/
|
*/
|
||||||
public abstract Path createLink(Path existing) throws IOException;
|
public abstract Path createLink(Path existing) throws IOException;
|
||||||
|
|
||||||
@ -608,7 +636,7 @@ public abstract class Path
|
|||||||
*
|
*
|
||||||
* @return an absolute, hierarchical URI with a non-empty path component
|
* @return an absolute, hierarchical URI with a non-empty path component
|
||||||
*
|
*
|
||||||
* @throws IOError
|
* @throws java.io.IOError
|
||||||
* if an I/O error occurs obtaining the absolute path, or where a
|
* if an I/O error occurs obtaining the absolute path, or where a
|
||||||
* file system is constructed to access the contents of a file as
|
* file system is constructed to access the contents of a file as
|
||||||
* a file system, and the URI of the enclosing file system cannot be
|
* a file system, and the URI of the enclosing file system cannot be
|
||||||
@ -636,8 +664,9 @@ public abstract class Path
|
|||||||
* @throws IOError
|
* @throws IOError
|
||||||
* if an I/O error occurs
|
* if an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* In the case of the default provider, and a security manager
|
* In the case of the default provider, a security manager
|
||||||
* is installed, its {@link SecurityManager#checkPropertyAccess(String)
|
* is installed, and this path is not absolute, then the security
|
||||||
|
* manager's {@link SecurityManager#checkPropertyAccess(String)
|
||||||
* checkPropertyAccess} method is invoked to check access to the
|
* checkPropertyAccess} method is invoked to check access to the
|
||||||
* system property {@code user.dir}
|
* system property {@code user.dir}
|
||||||
*/
|
*/
|
||||||
@ -720,7 +749,9 @@ public abstract class Path
|
|||||||
* the target file. The exact file attributes that are copied is platform
|
* the target file. The exact file attributes that are copied is platform
|
||||||
* and file system dependent and therefore unspecified. Minimally, the
|
* and file system dependent and therefore unspecified. Minimally, the
|
||||||
* {@link BasicFileAttributes#lastModifiedTime last-modified-time} is
|
* {@link BasicFileAttributes#lastModifiedTime last-modified-time} is
|
||||||
* copied to the target file. </td>
|
* copied to the target file if supported by both the source and target
|
||||||
|
* file store. Copying of file timestamps may result in precision
|
||||||
|
* loss. </td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td> {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} </td>
|
* <td> {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} </td>
|
||||||
@ -867,10 +898,7 @@ public abstract class Path
|
|||||||
*
|
*
|
||||||
* <p> The directory stream's {@code close} method should be invoked after
|
* <p> The directory stream's {@code close} method should be invoked after
|
||||||
* iteration is completed so as to free any resources held for the open
|
* iteration is completed so as to free any resources held for the open
|
||||||
* directory. The {@link Files#withDirectory Files.withDirectory} utility
|
* directory.
|
||||||
* method is useful for cases where a task is performed on each accepted
|
|
||||||
* entry in a directory. This method closes the directory when iteration is
|
|
||||||
* complete (or an error occurs).
|
|
||||||
*
|
*
|
||||||
* <p> When an implementation supports operations on entries in the
|
* <p> When an implementation supports operations on entries in the
|
||||||
* directory that execute in a race-free manner then the returned directory
|
* directory that execute in a race-free manner then the returned directory
|
||||||
@ -927,8 +955,6 @@ public abstract class Path
|
|||||||
*
|
*
|
||||||
* @throws java.util.regex.PatternSyntaxException
|
* @throws java.util.regex.PatternSyntaxException
|
||||||
* if the pattern is invalid
|
* if the pattern is invalid
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
* if the pattern syntax is not known to the implementation
|
|
||||||
* @throws NotDirectoryException
|
* @throws NotDirectoryException
|
||||||
* if the file could not otherwise be opened because it is not
|
* if the file could not otherwise be opened because it is not
|
||||||
* a directory <i>(optional specific exception)</i>
|
* a directory <i>(optional specific exception)</i>
|
||||||
@ -950,19 +976,18 @@ public abstract class Path
|
|||||||
* directory. The {@code Path} objects are obtained as if by {@link
|
* directory. The {@code Path} objects are obtained as if by {@link
|
||||||
* #resolve(Path) resolving} the name of the directory entry against this
|
* #resolve(Path) resolving} the name of the directory entry against this
|
||||||
* path. The entries returned by the iterator are filtered by the given
|
* path. The entries returned by the iterator are filtered by the given
|
||||||
* {@link DirectoryStream.Filter filter}. The {@link DirectoryStreamFilters}
|
* {@link DirectoryStream.Filter filter}.
|
||||||
* class defines factory methods that create useful filters.
|
|
||||||
*
|
*
|
||||||
* <p> The directory stream's {@code close} method should be invoked after
|
* <p> The directory stream's {@code close} method should be invoked after
|
||||||
* iteration is completed so as to free any resources held for the open
|
* iteration is completed so as to free any resources held for the open
|
||||||
* directory. The {@link Files#withDirectory Files.withDirectory} utility
|
* directory.
|
||||||
* method is useful for cases where a task is performed on each accepted
|
|
||||||
* entry in a directory. This method closes the directory when iteration is
|
|
||||||
* complete (or an error occurs).
|
|
||||||
*
|
*
|
||||||
* <p> Where the filter terminates due to an uncaught error or runtime
|
* <p> Where the filter terminates due to an uncaught error or runtime
|
||||||
* exception then it propogated to the caller of the iterator's {@link
|
* exception then it is propogated to the iterator's {@link Iterator#hasNext()
|
||||||
* Iterator#hasNext() hasNext} or {@link Iterator#next() next} methods.
|
* hasNext} or {@link Iterator#next() next} method. Where an {@code
|
||||||
|
* IOException} is thrown, it is propogated as a {@link
|
||||||
|
* java.util.concurrent.ConcurrentModificationException} with the {@code
|
||||||
|
* IOException} as the cause.
|
||||||
*
|
*
|
||||||
* <p> When an implementation supports operations on entries in the
|
* <p> When an implementation supports operations on entries in the
|
||||||
* directory that execute in a race-free manner then the returned directory
|
* directory that execute in a race-free manner then the returned directory
|
||||||
@ -973,14 +998,9 @@ public abstract class Path
|
|||||||
* larger than 8K.
|
* larger than 8K.
|
||||||
* <pre>
|
* <pre>
|
||||||
* DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
|
* DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
|
||||||
* public boolean accept(Path file) {
|
* public boolean accept(Path file) throws IOException {
|
||||||
* try {
|
* long size = Attributes.readBasicFileAttributes(file).size();
|
||||||
* long size = Attributes.readBasicFileAttributes(file).size();
|
* return (size > 8192L);
|
||||||
* return (size > 8192L);
|
|
||||||
* } catch (IOException e) {
|
|
||||||
* // failed to get size
|
|
||||||
* return false;
|
|
||||||
* }
|
|
||||||
* }
|
* }
|
||||||
* };
|
* };
|
||||||
* Path dir = ...
|
* Path dir = ...
|
||||||
@ -1071,6 +1091,8 @@ public abstract class Path
|
|||||||
* In the case of the default provider, and a security manager is
|
* In the case of the default provider, and a security manager is
|
||||||
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
* installed, the {@link SecurityManager#checkWrite(String) checkWrite}
|
||||||
* method is invoked to check write access to the new directory.
|
* method is invoked to check write access to the new directory.
|
||||||
|
*
|
||||||
|
* @see Files#createDirectories
|
||||||
*/
|
*/
|
||||||
public abstract Path createDirectory(FileAttribute<?>... attrs)
|
public abstract Path createDirectory(FileAttribute<?>... attrs)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
@ -1159,7 +1181,7 @@ public abstract class Path
|
|||||||
* FileAttribute file-attributes} to set atomically when a new file is created.
|
* FileAttribute file-attributes} to set atomically when a new file is created.
|
||||||
*
|
*
|
||||||
* <p> In the case of the default provider, the returned seekable byte channel
|
* <p> In the case of the default provider, the returned seekable byte channel
|
||||||
* is a {@link FileChannel}.
|
* is a {@link java.nio.channels.FileChannel}.
|
||||||
*
|
*
|
||||||
* <p> <b>Usage Examples:</b>
|
* <p> <b>Usage Examples:</b>
|
||||||
* <pre>
|
* <pre>
|
||||||
@ -1212,12 +1234,9 @@ public abstract class Path
|
|||||||
* Opens or creates a file, returning a seekable byte channel to access the
|
* Opens or creates a file, returning a seekable byte channel to access the
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* <p> This method extends the options defined by the {@code FileRef}
|
* <p> This method opens or creates a file in exactly the manner specified
|
||||||
* interface and to the options specified by the {@link
|
* by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel}
|
||||||
* #newByteChannel(Set,FileAttribute[]) newByteChannel} method
|
* method.
|
||||||
* except that the options are specified by an array. In the case of the
|
|
||||||
* default provider, the returned seekable byte channel is a {@link
|
|
||||||
* FileChannel}.
|
|
||||||
*
|
*
|
||||||
* @param options
|
* @param options
|
||||||
* options specifying how the file is opened
|
* options specifying how the file is opened
|
||||||
@ -1232,108 +1251,40 @@ public abstract class Path
|
|||||||
* if a file of that name already exists and the {@link
|
* if a file of that name already exists and the {@link
|
||||||
* StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified
|
* StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified
|
||||||
* <i>(optional specific exception)</i>
|
* <i>(optional specific exception)</i>
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public abstract SeekableByteChannel newByteChannel(OpenOption... options)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the file located by this path for reading, returning an input
|
|
||||||
* stream to read bytes 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.
|
|
||||||
*
|
|
||||||
* @return an input stream to read bytes from the file
|
|
||||||
*
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if an I/O error occurs
|
* if an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* In the case of the default provider, and a security manager is
|
* In the case of the default provider, and a security manager is
|
||||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||||
* method is invoked to check read access to the file.
|
* 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.
|
||||||
*/
|
*/
|
||||||
public abstract InputStream newInputStream() throws IOException;
|
public abstract SeekableByteChannel newByteChannel(OpenOption... options)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens or creates the file located by this path for writing, returning an
|
* Opens or creates the file located by this object for writing, returning
|
||||||
* output stream to write bytes to the file.
|
* an output stream to write bytes to the file.
|
||||||
*
|
*
|
||||||
* <p> This method opens or creates a file in exactly the manner specified
|
* <p> This method opens or creates a file in exactly the manner specified
|
||||||
* by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel}
|
* by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel}
|
||||||
* method except that the {@link StandardOpenOption#READ READ} option may not
|
* method except that the {@link StandardOpenOption#READ READ} option may not
|
||||||
* be present in the array of open options. If no open options are present
|
* be present in the array of open options.
|
||||||
* then this method creates a new file for writing or truncates an existing
|
|
||||||
* file.
|
|
||||||
*
|
|
||||||
* <p> The resulting stream will not be buffered. The stream will be safe
|
|
||||||
* for access by multiple concurrent threads.
|
|
||||||
*
|
|
||||||
* <p> <b>Usage Example:</b>
|
|
||||||
* Suppose we wish to open a log file for writing so that we append to the
|
|
||||||
* file if it already exists, or create it when it doesn't exist.
|
|
||||||
* <pre>
|
|
||||||
* Path logfile = ...
|
|
||||||
* OutputStream out = new BufferedOutputStream(logfile.newOutputStream(CREATE, APPEND));
|
|
||||||
* </pre>
|
|
||||||
*
|
*
|
||||||
* @param options
|
* @param options
|
||||||
* options specifying how the file is opened
|
* options specifying how the file is opened
|
||||||
*
|
*
|
||||||
* @return a new seekable byte channel
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* if {@code options} contains an invalid combination of options
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
* if an unsupported open 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.
|
|
||||||
*/
|
|
||||||
public abstract OutputStream newOutputStream(OpenOption... options)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens or creates the file located by this path for writing, returning an
|
|
||||||
* output stream to write bytes to the file.
|
|
||||||
*
|
|
||||||
* <p> This method opens or creates a file in exactly the manner specified
|
|
||||||
* by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel}
|
|
||||||
* method except that {@code options} parameter may not contain the {@link
|
|
||||||
* StandardOpenOption#READ READ} option. If no open options are present
|
|
||||||
* then this method creates a new file for writing or truncates an existing
|
|
||||||
* file.
|
|
||||||
*
|
|
||||||
* <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
|
|
||||||
* @param attrs
|
|
||||||
* an optional list of file attributes to set atomically when
|
|
||||||
* creating the file
|
|
||||||
*
|
|
||||||
* @return a new output stream
|
* @return a new output stream
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException {@inheritDoc}
|
||||||
* if the set contains an invalid combination of options
|
* @throws UnsupportedOperationException {@inheritDoc}
|
||||||
* @throws UnsupportedOperationException
|
* @throws IOException {@inheritDoc}
|
||||||
* if an unsupported open option is specified or the array contains
|
* @throws SecurityException {@inheritDoc}
|
||||||
* attributes that cannot be set atomically when creating the 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#checkWrite(String) checkWrite}
|
|
||||||
* method is invoked to check write access to the file.
|
|
||||||
*/
|
*/
|
||||||
public abstract OutputStream newOutputStream(Set<? extends OpenOption> options,
|
@Override
|
||||||
FileAttribute<?>... attrs)
|
public abstract OutputStream newOutputStream(OpenOption... options)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1358,6 +1309,80 @@ public abstract class Path
|
|||||||
*/
|
*/
|
||||||
public abstract boolean isHidden() throws IOException;
|
public abstract boolean isHidden() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the existence and optionally the accessibility of the file
|
||||||
|
* located by this path.
|
||||||
|
*
|
||||||
|
* <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. Furthermore, as the result
|
||||||
|
* of this method is immediately outdated, there is no guarantee that a
|
||||||
|
* subsequence access will succeed (or even that it will access the same
|
||||||
|
* file). Care should be taken when using this method in security sensitive
|
||||||
|
* applications.
|
||||||
|
*
|
||||||
|
* @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(AccessMode... modes) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether the file located by this path exists.
|
* Tests whether the file located by this path exists.
|
||||||
*
|
*
|
||||||
@ -1414,6 +1439,30 @@ public abstract class Path
|
|||||||
*/
|
*/
|
||||||
public abstract boolean notExists();
|
public abstract boolean notExists();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link FileStore} representing the file store where an
|
||||||
|
* existing file, located by this path, is stored.
|
||||||
|
*
|
||||||
|
* <p> Once a reference to the {@code FileStore} is obtained it is
|
||||||
|
* implementation specific if operations on the returned {@code FileStore},
|
||||||
|
* or {@link FileStoreAttributeView} objects obtained from it, continue
|
||||||
|
* to depend on the existence of the file. In particular the behavior is not
|
||||||
|
* defined for the case that the file is deleted or moved to a different
|
||||||
|
* file store.
|
||||||
|
*
|
||||||
|
* @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() throws IOException;
|
||||||
|
|
||||||
// -- watchable --
|
// -- watchable --
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1561,6 +1610,49 @@ public abstract class Path
|
|||||||
@Override
|
@Override
|
||||||
public abstract int compareTo(Path other);
|
public abstract int compareTo(Path other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if the file referenced by this object is the same file referenced
|
||||||
|
* by another object.
|
||||||
|
*
|
||||||
|
* <p> If this {@code FileRef} and the given {@code FileRef} are {@link
|
||||||
|
* #equals(Object) equal} then this method returns {@code true} without checking
|
||||||
|
* if the file exists. If the {@code FileRef} and the given {@code FileRef}
|
||||||
|
* are associated with different providers, or the given {@code FileRef} is
|
||||||
|
* {@code null} then this method returns {@code false}. Otherwise, this method
|
||||||
|
* checks if both {@code FileRefs} locate the same file, and depending on the
|
||||||
|
* implementation, may require to open or access both files.
|
||||||
|
*
|
||||||
|
* <p> If the file system and files remain static, then this method implements
|
||||||
|
* an equivalence relation for non-null {@code FileRefs}.
|
||||||
|
* <ul>
|
||||||
|
* <li>It is <i>reflexive</i>: for a non-null {@code FileRef} {@code f},
|
||||||
|
* {@code f.isSameFile(f)} should return {@code true}.
|
||||||
|
* <li>It is <i>symmetric</i>: for two non-null {@code FileRefs}
|
||||||
|
* {@code f} and {@code g}, {@code f.isSameFile(g)} will equal
|
||||||
|
* {@code g.isSameFile(f)}.
|
||||||
|
* <li>It is <i>transitive</i>: for three {@code FileRefs}
|
||||||
|
* {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns
|
||||||
|
* {@code true} and {@code g.isSameFile(h)} returns {@code true}, then
|
||||||
|
* {@code f.isSameFile(h)} will return return {@code true}.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* the other file reference
|
||||||
|
*
|
||||||
|
* @return {@code true} if, and only if, this object and the given object
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @see java.nio.file.attribute.BasicFileAttributes#fileKey
|
||||||
|
*/
|
||||||
|
public abstract boolean isSameFile(Path other) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests this path for equality with the given object.
|
* Tests this path for equality with the given object.
|
||||||
*
|
*
|
||||||
|
@ -35,7 +35,7 @@ import java.net.URI;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Paths {
|
public final class Paths {
|
||||||
private Paths() { }
|
private Paths() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,8 +106,9 @@ public class Paths {
|
|||||||
* if preconditions on the {@code uri} parameter do not hold. The
|
* if preconditions on the {@code uri} parameter do not hold. The
|
||||||
* format of the URI is provider specific.
|
* format of the URI is provider specific.
|
||||||
* @throws FileSystemNotFoundException
|
* @throws FileSystemNotFoundException
|
||||||
* if the file system identified by the URI does not exist or the
|
* The file system, identified by the URI, does not exist and
|
||||||
* provider identified by the URI's scheme component is not installed
|
* cannot be created automatically, or the provider identified by
|
||||||
|
* the URI's scheme component is not installed
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* if a security manager is installed and it denies an unspecified
|
* if a security manager is installed and it denies an unspecified
|
||||||
* permission to access the file system
|
* permission to access the file system
|
||||||
|
@ -36,7 +36,7 @@ import java.io.IOException;
|
|||||||
* traverse file trees or otherwise operate on directories in a race-free manner.
|
* traverse file trees or otherwise operate on directories in a race-free manner.
|
||||||
* Race conditions can arise when a sequence of file operations cannot be
|
* Race conditions can arise when a sequence of file operations cannot be
|
||||||
* carried out in isolation. Each of the file operations defined by this
|
* carried out in isolation. Each of the file operations defined by this
|
||||||
* interface specify a relative {@link Path}. All access to the file is relative
|
* interface specify a relative path. All access to the file is relative
|
||||||
* to the open directory irrespective of if the directory is moved or replaced
|
* to the open directory irrespective of if the directory is moved or replaced
|
||||||
* by an attacker while the directory is open. A {@code SecureDirectoryStream}
|
* by an attacker while the directory is open. A {@code SecureDirectoryStream}
|
||||||
* may also be used as a virtual <em>working directory</em>.
|
* may also be used as a virtual <em>working directory</em>.
|
||||||
@ -65,8 +65,8 @@ import java.io.IOException;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class SecureDirectoryStream
|
public abstract class SecureDirectoryStream<T>
|
||||||
implements DirectoryStream<Path>
|
implements DirectoryStream<T>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Initialize a new instance of this class.
|
* Initialize a new instance of this class.
|
||||||
@ -78,13 +78,12 @@ public abstract class SecureDirectoryStream
|
|||||||
* SecureDirectoryStream} to iterate over the entries in the directory.
|
* SecureDirectoryStream} to iterate over the entries in the directory.
|
||||||
*
|
*
|
||||||
* <p> This method works in exactly the manner specified by the {@link
|
* <p> This method works in exactly the manner specified by the {@link
|
||||||
* Path#newDirectoryStream newDirectoryStream} method for the case that
|
* Path#newDirectoryStream() newDirectoryStream} method for the case that
|
||||||
* the {@code path} parameter is an {@link Path#isAbsolute absolute} path.
|
* the {@code path} parameter is an {@link Path#isAbsolute absolute} path.
|
||||||
* When the parameter is a relative path then the directory to open is
|
* When the parameter is a relative path then the directory to open is
|
||||||
* relative to this open directory. The {@code followLinks} parameter
|
* relative to this open directory. The {@link
|
||||||
* determines if links should be followed. If this parameter is {@code
|
* LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} option may be used to
|
||||||
* false} and the file is a symbolic link then this method fails (by
|
* ensure that this method fails if the file is a symbolic link.
|
||||||
* throwing an I/O exception).
|
|
||||||
*
|
*
|
||||||
* <p> The new directory stream, once created, is not dependent upon the
|
* <p> The new directory stream, once created, is not dependent upon the
|
||||||
* directory stream used to create it. Closing this directory stream has no
|
* directory stream used to create it. Closing this directory stream has no
|
||||||
@ -92,10 +91,8 @@ public abstract class SecureDirectoryStream
|
|||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* the path to the directory to open
|
* the path to the directory to open
|
||||||
* @param followLinks
|
* @param options
|
||||||
* {@code true} if the links should be followed
|
* options indicating how symbolic links are handled
|
||||||
* @param filter
|
|
||||||
* the directory stream filter or {@code null}.
|
|
||||||
*
|
*
|
||||||
* @return a new and open {@code SecureDirectoryStream} object
|
* @return a new and open {@code SecureDirectoryStream} object
|
||||||
*
|
*
|
||||||
@ -111,9 +108,8 @@ public abstract class SecureDirectoryStream
|
|||||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||||
* method is invoked to check read access to the directory.
|
* method is invoked to check read access to the directory.
|
||||||
*/
|
*/
|
||||||
public abstract SecureDirectoryStream newDirectoryStream(Path path,
|
public abstract SecureDirectoryStream<T> newDirectoryStream(T path,
|
||||||
boolean followLinks,
|
LinkOption... options)
|
||||||
DirectoryStream.Filter<? super Path> filter)
|
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,7 +158,7 @@ public abstract class SecureDirectoryStream
|
|||||||
* checkWrite} method is invoked to check write access to the path
|
* checkWrite} method is invoked to check write access to the path
|
||||||
* if the file is opened for writing.
|
* if the file is opened for writing.
|
||||||
*/
|
*/
|
||||||
public abstract SeekableByteChannel newByteChannel(Path path,
|
public abstract SeekableByteChannel newByteChannel(T path,
|
||||||
Set<? extends OpenOption> options,
|
Set<? extends OpenOption> options,
|
||||||
FileAttribute<?>... attrs)
|
FileAttribute<?>... attrs)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
@ -170,7 +166,7 @@ public abstract class SecureDirectoryStream
|
|||||||
/**
|
/**
|
||||||
* Deletes a file.
|
* Deletes a file.
|
||||||
*
|
*
|
||||||
* <p> Unlike the {@link FileRef#delete delete()} method, this method
|
* <p> Unlike the {@link Path#delete delete()} method, this method
|
||||||
* does not first examine the file to determine if the file is a directory.
|
* 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
|
* 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 is
|
* therefore not specified. If the file is a symbolic-link then the link is
|
||||||
@ -191,12 +187,12 @@ public abstract class SecureDirectoryStream
|
|||||||
* installed, the {@link SecurityManager#checkDelete(String) checkDelete}
|
* installed, the {@link SecurityManager#checkDelete(String) checkDelete}
|
||||||
* method is invoked to check delete access to the file
|
* method is invoked to check delete access to the file
|
||||||
*/
|
*/
|
||||||
public abstract void deleteFile(Path path) throws IOException;
|
public abstract void deleteFile(T path) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a directory.
|
* Deletes a directory.
|
||||||
*
|
*
|
||||||
* <p> Unlike the {@link FileRef#delete delete()} method, this method
|
* <p> Unlike the {@link Path#delete delete()} method, this method
|
||||||
* does not first examine the file to determine if the file is a directory.
|
* 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
|
* Whether non-directories are deleted by this method is system dependent and
|
||||||
* therefore not specified. When the parameter is a relative path then the
|
* therefore not specified. When the parameter is a relative path then the
|
||||||
@ -219,7 +215,7 @@ public abstract class SecureDirectoryStream
|
|||||||
* installed, the {@link SecurityManager#checkDelete(String) checkDelete}
|
* installed, the {@link SecurityManager#checkDelete(String) checkDelete}
|
||||||
* method is invoked to check delete access to the directory
|
* method is invoked to check delete access to the directory
|
||||||
*/
|
*/
|
||||||
public abstract void deleteDirectory(Path path) throws IOException;
|
public abstract void deleteDirectory(T path) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move a file from this directory to another directory.
|
* Move a file from this directory to another directory.
|
||||||
@ -259,7 +255,7 @@ public abstract class SecureDirectoryStream
|
|||||||
* method is invoked to check write access to both the source and
|
* method is invoked to check write access to both the source and
|
||||||
* target file.
|
* target file.
|
||||||
*/
|
*/
|
||||||
public abstract void move(Path srcpath, SecureDirectoryStream targetdir, Path targetpath)
|
public abstract void move(T srcpath, SecureDirectoryStream<T> targetdir, T targetpath)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,7 +314,7 @@ public abstract class SecureDirectoryStream
|
|||||||
* type is not available
|
* type is not available
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract <V extends FileAttributeView> V getFileAttributeView(Path path,
|
public abstract <V extends FileAttributeView> V getFileAttributeView(T path,
|
||||||
Class<V> type,
|
Class<V> type,
|
||||||
LinkOption... options);
|
LinkOption... options);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import java.io.IOError;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SimpleFileVisitor<T extends FileRef> implements FileVisitor<T> {
|
public class SimpleFileVisitor<T> implements FileVisitor<T> {
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of this class.
|
* Initializes a new instance of this class.
|
||||||
*/
|
*/
|
||||||
|
@ -31,7 +31,7 @@ package java.nio.file;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class StandardWatchEventKind {
|
public final class StandardWatchEventKind {
|
||||||
private StandardWatchEventKind() { }
|
private StandardWatchEventKind() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,7 +103,7 @@ public abstract class WatchKey {
|
|||||||
*
|
*
|
||||||
* <p> Note that this method does not wait if there are no events pending.
|
* <p> Note that this method does not wait if there are no events pending.
|
||||||
*
|
*
|
||||||
* @return the list of the events retrieved
|
* @return the list of the events retrieved; may be empty
|
||||||
*/
|
*/
|
||||||
public abstract List<WatchEvent<?>> pollEvents();
|
public abstract List<WatchEvent<?>> pollEvents();
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public abstract class WatchKey {
|
|||||||
* will be invalid. If the watch key is enqueued, waiting to be retrieved
|
* will be invalid. If the watch key is enqueued, waiting to be retrieved
|
||||||
* from the watch service, then it will remain in the queue until it is
|
* from the watch service, then it will remain in the queue until it is
|
||||||
* removed. Pending events, if any, remain pending and may be retrieved by
|
* removed. Pending events, if any, remain pending and may be retrieved by
|
||||||
* invoking the {@link #pollEvents pollEvents} method event after the key is
|
* invoking the {@link #pollEvents pollEvents} method after the key is
|
||||||
* cancelled.
|
* cancelled.
|
||||||
*
|
*
|
||||||
* <p> If this watch key has already been cancelled then invoking this
|
* <p> If this watch key has already been cancelled then invoking this
|
||||||
|
@ -110,13 +110,13 @@ import java.io.IOException;
|
|||||||
* </table>
|
* </table>
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* <p> The {@link #getAttribute getAttribute} or {@link #readAttributes
|
* <p> The {@link FileRef#getAttribute getAttribute} method may be used to read
|
||||||
* readAttributes} methods may be used to read the ACL or owner attributes as if
|
* the ACL or owner attributes as if by invoking the {@link #getAcl getAcl} or
|
||||||
* by invoking the {@link #getAcl getAcl} or {@link #getOwner getOwner} methods.
|
* {@link #getOwner getOwner} methods.
|
||||||
*
|
*
|
||||||
* <p> The {@link #setAttribute setAttribute} method may be used to update the
|
* <p> The {@link FileRef#setAttribute setAttribute} method may be used to
|
||||||
* ACL or owner attributes as if by invoking the {@link #setAcl setAcl} or {@link
|
* update the ACL or owner attributes as if by invoking the {@link #setAcl setAcl}
|
||||||
* #setOwner setOwner} methods.
|
* or {@link #setOwner setOwner} methods.
|
||||||
*
|
*
|
||||||
* <h4> Setting the ACL when creating a file </h4>
|
* <h4> Setting the ACL when creating a file </h4>
|
||||||
*
|
*
|
||||||
|
@ -25,20 +25,12 @@
|
|||||||
|
|
||||||
package java.nio.file.attribute;
|
package java.nio.file.attribute;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object that provides a read-only or updatable <em>view</em> of non-opaque
|
* An object that provides a read-only or updatable <em>view</em> of non-opaque
|
||||||
* values associated with an object in a filesystem. This interface is extended
|
* values associated with an object in a filesystem. This interface is extended
|
||||||
* or implemented by specific attribute views that define the attributes
|
* or implemented by specific attribute views that define the attributes
|
||||||
* supported by the view. A specific attribute view will typically define
|
* supported by the view. A specific attribute view will typically define
|
||||||
* type-safe methods to read or update the attributes that it supports. It also
|
* type-safe methods to read or update the attributes that it supports.
|
||||||
* provides <em>dynamic access</em> where the {@link #readAttributes
|
|
||||||
* readAttributes}, {@link #getAttribute getAttribute} and {@link #setAttribute
|
|
||||||
* setAttributs} methods are used to access the attributes by names defined
|
|
||||||
* by the attribute view. Implementations must ensure that the attribute names
|
|
||||||
* do not contain the colon (':') or comma (',') characters.
|
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
@ -48,71 +40,4 @@ public interface AttributeView {
|
|||||||
* Returns the name of the attribute view.
|
* Returns the name of the attribute view.
|
||||||
*/
|
*/
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the value of an attribute.
|
|
||||||
*
|
|
||||||
* @param attribute
|
|
||||||
* the attribute name (case sensitive)
|
|
||||||
*
|
|
||||||
* @return the value of the attribute, or {@code null} if the attribute is
|
|
||||||
* not supported
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
* if an I/O error occurs
|
|
||||||
* @throws SecurityException
|
|
||||||
* if a security manager is set and it denies access
|
|
||||||
*/
|
|
||||||
Object getAttribute(String attribute) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets/updates the value of an attribute.
|
|
||||||
*
|
|
||||||
* @param attribute
|
|
||||||
* the attribute name (case sensitive)
|
|
||||||
* @param value
|
|
||||||
* the attribute value
|
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
* if the attribute is not supported or this attribute view does
|
|
||||||
* not support updating the value of 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
|
|
||||||
* if a security manager is set and it denies access
|
|
||||||
*/
|
|
||||||
void setAttribute(String attribute, Object value) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads all, or a subset, of the attributes supported by this file attribute
|
|
||||||
* view.
|
|
||||||
*
|
|
||||||
* <p> The {@code first} and {@code rest} parameters are the names of the
|
|
||||||
* attributes to read. If any of the parameters has 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.
|
|
||||||
*
|
|
||||||
* @param first
|
|
||||||
* the name of an attribute to read (case sensitive)
|
|
||||||
* @param rest
|
|
||||||
* the names of other attributes to read (case sensitive)
|
|
||||||
*
|
|
||||||
* @return an unmodifiable map of the attributes; may be empty. Its keys are
|
|
||||||
* the attribute names, its values are the attribute values
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
* if an I/O error occurs
|
|
||||||
* @throws SecurityException
|
|
||||||
* if a security manager is set and it denies access
|
|
||||||
*/
|
|
||||||
Map<String,?> readAttributes(String first, String... rest) throws IOException;
|
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ package java.nio.file.attribute;
|
|||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class consists exclusively of static methods that operate on or return
|
* This class consists exclusively of static methods that operate on or return
|
||||||
@ -39,245 +38,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public final class Attributes {
|
public final class Attributes {
|
||||||
private Attributes() {
|
private Attributes() { }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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>
|
|
||||||
* Attributes.setAttribute(file, "dos:hidden", true);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* A file reference that locates the file
|
|
||||||
* @param attribute
|
|
||||||
* The attribute to set
|
|
||||||
* @param value
|
|
||||||
* The attribute value
|
|
||||||
*
|
|
||||||
* @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 static void setAttribute(FileRef file, String attribute, Object value)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
String[] s = split(attribute);
|
|
||||||
FileAttributeView view = file.getFileAttributeView(s[0]);
|
|
||||||
if (view == null)
|
|
||||||
throw new UnsupportedOperationException("View '" + s[0] + "' not available");
|
|
||||||
view.setAttribute(s[1], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)Attributes.getAttribute(file, "unix:uid");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* A file reference that locates the file
|
|
||||||
* @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
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
public static Object getAttribute(FileRef file,
|
|
||||||
String attribute,
|
|
||||||
LinkOption... options)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
String[] s = split(attribute);
|
|
||||||
FileAttributeView view = file.getFileAttributeView(s[0], options);
|
|
||||||
if (view != null)
|
|
||||||
return view.getAttribute(s[1]);
|
|
||||||
// view not available
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 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.
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* A file reference that locates 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 static Map<String,?> readAttributes(FileRef file,
|
|
||||||
String attributes,
|
|
||||||
LinkOption... options)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
String[] s = split(attributes);
|
|
||||||
FileAttributeView view = file.getFileAttributeView(s[0], options);
|
|
||||||
if (view != null) {
|
|
||||||
// further split attributes into the first and rest.
|
|
||||||
String[] names = s[1].split(",");
|
|
||||||
int rem = names.length-1;
|
|
||||||
String first = names[0];
|
|
||||||
String[] rest = new String[rem];
|
|
||||||
if (rem > 0) System.arraycopy(names, 1, rest, 0, rem);
|
|
||||||
|
|
||||||
return view.readAttributes(first, rest);
|
|
||||||
}
|
|
||||||
// view not available
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the basic file attributes of a file.
|
* Reads the basic file attributes of a file.
|
||||||
@ -551,29 +312,28 @@ public final class Attributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the value of a file's last modified time attribute.
|
* 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> The time value is measured since the epoch
|
* <p> If the file system does not support a last modified time attribute
|
||||||
* (00:00:00 GMT, January 1, 1970) and is converted to the precision supported
|
* then this method has no effect.
|
||||||
* by the file system. Converting from finer to coarser granularities result
|
|
||||||
* in precision loss.
|
|
||||||
*
|
*
|
||||||
* <p> If the file system does not support a last modified time attribute then
|
* <p> <b>Usage Example:</b>
|
||||||
* this method has no effect.
|
* 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
|
* @param file
|
||||||
* A file reference that locates the file
|
* A file reference that locates the file
|
||||||
*
|
|
||||||
* @param lastModifiedTime
|
* @param lastModifiedTime
|
||||||
* The new last modified time, or {@code -1L} to update it to
|
* The new last modified time
|
||||||
* the current time
|
|
||||||
* @param unit
|
|
||||||
* A {@code TimeUnit} determining how to interpret the
|
|
||||||
* {@code lastModifiedTime} parameter
|
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* If the {@code lastModifiedime} parameter is a negative value other
|
|
||||||
* than {@code -1L}
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* If an I/O error occurs
|
* If an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
@ -584,35 +344,31 @@ public final class Attributes {
|
|||||||
* @see BasicFileAttributeView#setTimes
|
* @see BasicFileAttributeView#setTimes
|
||||||
*/
|
*/
|
||||||
public static void setLastModifiedTime(FileRef file,
|
public static void setLastModifiedTime(FileRef file,
|
||||||
long lastModifiedTime,
|
FileTime lastModifiedTime)
|
||||||
TimeUnit unit)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
|
if (lastModifiedTime == null)
|
||||||
|
throw new NullPointerException("'lastModifiedTime' is null");
|
||||||
file.getFileAttributeView(BasicFileAttributeView.class)
|
file.getFileAttributeView(BasicFileAttributeView.class)
|
||||||
.setTimes(lastModifiedTime, null, null, unit);
|
.setTimes(lastModifiedTime, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the value of a file's last access time attribute.
|
* 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
|
||||||
* <p> The time value is measured since the epoch
|
* finer to coarser granularities result in precision loss. The behavior of
|
||||||
* (00:00:00 GMT, January 1, 1970) and is converted to the precision supported
|
* this method when attempting to set a timestamp to a value that is outside
|
||||||
* by the file system. Converting from finer to coarser granularities result
|
* the range supported by the underlying file store is not defined. It may
|
||||||
* in precision loss.
|
* or not fail by throwing an {@code IOException}.
|
||||||
*
|
*
|
||||||
* <p> If the file system does not support a last access time attribute then
|
* <p> If the file system does not support a last access time attribute then
|
||||||
* this method has no effect.
|
* this method has no effect.
|
||||||
*
|
*
|
||||||
|
* @param file
|
||||||
|
* A file reference that locates the file
|
||||||
* @param lastAccessTime
|
* @param lastAccessTime
|
||||||
* The new last access time, or {@code -1L} to update it to
|
* The new last access time
|
||||||
* the current time
|
|
||||||
* @param unit
|
|
||||||
* A {@code TimeUnit} determining how to interpret the
|
|
||||||
* {@code lastModifiedTime} parameter
|
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* If the {@code lastAccessTime} parameter is a negative value other
|
|
||||||
* than {@code -1L}
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* If an I/O error occurs
|
* If an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
@ -623,12 +379,13 @@ public final class Attributes {
|
|||||||
* @see BasicFileAttributeView#setTimes
|
* @see BasicFileAttributeView#setTimes
|
||||||
*/
|
*/
|
||||||
public static void setLastAccessTime(FileRef file,
|
public static void setLastAccessTime(FileRef file,
|
||||||
long lastAccessTime,
|
FileTime lastAccessTime)
|
||||||
TimeUnit unit)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
|
if (lastAccessTime == null)
|
||||||
|
throw new NullPointerException("'lastAccessTime' is null");
|
||||||
file.getFileAttributeView(BasicFileAttributeView.class)
|
file.getFileAttributeView(BasicFileAttributeView.class)
|
||||||
.setTimes(null, lastAccessTime, null, unit);
|
.setTimes(null, lastAccessTime, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
package java.nio.file.attribute;
|
package java.nio.file.attribute;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,19 +48,15 @@ import java.io.IOException;
|
|||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td> "lastModifiedTime" </td>
|
* <td> "lastModifiedTime" </td>
|
||||||
* <td> {@link Long} </td>
|
* <td> {@link FileTime} </td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td> "lastAccessTime" </td>
|
* <td> "lastAccessTime" </td>
|
||||||
* <td> {@link Long} </td>
|
* <td> {@link FileTime} </td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td> "creationTime" </td>
|
* <td> "creationTime" </td>
|
||||||
* <td> {@link Long} </td>
|
* <td> {@link FileTime} </td>
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td> "resolution" </td>
|
|
||||||
* <td> {@link java.util.concurrent.TimeUnit} </td>
|
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td> "size" </td>
|
* <td> "size" </td>
|
||||||
@ -84,26 +79,19 @@ import java.io.IOException;
|
|||||||
* <td> {@link Boolean} </td>
|
* <td> {@link Boolean} </td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td> "linkCount" </td>
|
|
||||||
* <td> {@link Integer} </td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td> "fileKey" </td>
|
* <td> "fileKey" </td>
|
||||||
* <td> {@link Object} </td>
|
* <td> {@link Object} </td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* </table>
|
* </table>
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* <p> The {@link #getAttribute getAttribute} or {@link
|
* <p> The {@link java.nio.file.FileRef#getAttribute getAttribute} method may be
|
||||||
* #readAttributes(String,String[]) readAttributes(String,String[])} methods may
|
* used to read any of these attributes as if by invoking the {@link
|
||||||
* be used to read any of these attributes as if by invoking the {@link
|
|
||||||
* #readAttributes() readAttributes()} method.
|
* #readAttributes() readAttributes()} method.
|
||||||
*
|
*
|
||||||
* <p> The {@link #setAttribute setAttribute} method may be used to update the
|
* <p> The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be
|
||||||
* file's last modified time, last access time or create time attributes as if
|
* used to update the file's last modified time, last access time or create time
|
||||||
* by invoking the {@link #setTimes setTimes} method. In that case, the time
|
* attributes as if by invoking the {@link #setTimes setTimes} method.
|
||||||
* value is interpreted in {@link TimeUnit#MILLISECONDS milliseconds} and
|
|
||||||
* converted to the precision supported by the file system.
|
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
* @see Attributes
|
* @see Attributes
|
||||||
@ -141,11 +129,11 @@ public interface BasicFileAttributeView
|
|||||||
* and create time attributes.
|
* and create time attributes.
|
||||||
*
|
*
|
||||||
* <p> This method updates the file's timestamp attributes. The values are
|
* <p> This method updates the file's timestamp attributes. The values are
|
||||||
* measured since the epoch (00:00:00 GMT, January 1, 1970) and converted to
|
* converted to the epoch and precision supported by the file system.
|
||||||
* the precision supported by the file system. Converting from finer to
|
* Converting from finer to coarser granularities result in precision loss.
|
||||||
* coarser granularities result in precision loss. If a value is larger
|
* The behavior of this method when attempting to set a timestamp to a value
|
||||||
* than the maximum supported by the file system then the corresponding
|
* that is outside the range supported by the underlying file store is not
|
||||||
* timestamp is set to its maximum value.
|
* defined. It may or not fail by throwing an {@code IOException}.
|
||||||
*
|
*
|
||||||
* <p> If any of the {@code lastModifiedTime}, {@code lastAccessTime},
|
* <p> If any of the {@code lastModifiedTime}, {@code lastAccessTime},
|
||||||
* or {@code createTime} parameters has the value {@code null} then the
|
* or {@code createTime} parameters has the value {@code null} then the
|
||||||
@ -153,25 +141,19 @@ public interface BasicFileAttributeView
|
|||||||
* read the existing values of the file attributes when only some, but not
|
* read the existing values of the file attributes when only some, but not
|
||||||
* all, of the timestamp attributes are updated. Consequently, this method
|
* all, of the timestamp attributes are updated. Consequently, this method
|
||||||
* may not be an atomic operation with respect to other file system
|
* may not be an atomic operation with respect to other file system
|
||||||
* operations. If all of the {@code lastModifiedTime}, {@code
|
* operations. Reading and re-writing existing values may also result in
|
||||||
|
* precision loss. If all of the {@code lastModifiedTime}, {@code
|
||||||
* lastAccessTime} and {@code createTime} parameters are {@code null} then
|
* lastAccessTime} and {@code createTime} parameters are {@code null} then
|
||||||
* this method has no effect.
|
* this method has no effect.
|
||||||
*
|
*
|
||||||
* @param lastModifiedTime
|
* @param lastModifiedTime
|
||||||
* the new last modified time, or {@code -1L} to update it to
|
* the new last modified time, or {@code null} to not change the
|
||||||
* the current time, or {@code null} to not change the attribute
|
* value
|
||||||
* @param lastAccessTime
|
* @param lastAccessTime
|
||||||
* the last access time, or {@code -1L} to update it to
|
* the last access time, or {@code null} to not change the value
|
||||||
* the current time, or {@code null} to not change the attribute.
|
|
||||||
* @param createTime
|
* @param createTime
|
||||||
* the file's create time, or {@code -1L} to update it to
|
* the file's create time, or {@code null} to not change the value
|
||||||
* the current time, or {@code null} to not change the attribute
|
|
||||||
* @param unit
|
|
||||||
* a {@code TimeUnit} determining how to interpret the time values
|
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* if any of the parameters is a negative value other than {@code
|
|
||||||
* -1L}
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if an I/O error occurs
|
* if an I/O error occurs
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
@ -179,8 +161,7 @@ public interface BasicFileAttributeView
|
|||||||
* installed, its {@link SecurityManager#checkWrite(String) checkWrite}
|
* installed, its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||||
* method is invoked to check write access to the file
|
* method is invoked to check write access to the file
|
||||||
*/
|
*/
|
||||||
void setTimes(Long lastModifiedTime,
|
void setTimes(FileTime lastModifiedTime,
|
||||||
Long lastAccessTime,
|
FileTime lastAccessTime,
|
||||||
Long createTime,
|
FileTime createTime) throws IOException;
|
||||||
TimeUnit unit) throws IOException;
|
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
package java.nio.file.attribute;
|
package java.nio.file.attribute;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic attributes associated with a file in a file system.
|
* Basic attributes associated with a file in a file system.
|
||||||
*
|
*
|
||||||
@ -50,47 +48,27 @@ public interface BasicFileAttributes {
|
|||||||
/**
|
/**
|
||||||
* Returns the time of last modification.
|
* Returns the time of last modification.
|
||||||
*
|
*
|
||||||
* <p> The {@link #resolution() resolution} method returns the {@link TimeUnit}
|
* @return a {@code FileTime} representing the time the file was last
|
||||||
* to interpret the return value of this method.
|
* modified or {@code null} if the attribute is not supported.
|
||||||
*
|
|
||||||
* @return a <code>long</code> value representing the time the file was
|
|
||||||
* last modified since the epoch (00:00:00 GMT, January 1, 1970),
|
|
||||||
* or {@code -1L} if the attribute is not supported.
|
|
||||||
*/
|
*/
|
||||||
long lastModifiedTime();
|
FileTime lastModifiedTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time of last access if supported.
|
* Returns the time of last access if supported.
|
||||||
*
|
*
|
||||||
* <p> The {@link #resolution() resolution} method returns the {@link TimeUnit}
|
* @return a {@code FileTime} representing the time of last access or
|
||||||
* to interpret the return value of this method.
|
* {@code null} if the attribute is not supported.
|
||||||
*
|
|
||||||
* @return a <code>long</code> value representing the time of last access
|
|
||||||
* since the epoch (00:00:00 GMT, January 1, 1970), or {@code -1L}
|
|
||||||
* if the attribute is not supported.
|
|
||||||
*/
|
*/
|
||||||
long lastAccessTime();
|
FileTime lastAccessTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the creation time if supported. The creation time is the time
|
* Returns the creation time if supported. The creation time is the time
|
||||||
* that the file was created.
|
* that the file was created.
|
||||||
*
|
*
|
||||||
* <p> The {@link #resolution() resolution} method returns the {@link TimeUnit}
|
* @return a {@code FileTime} representing the time the file was created
|
||||||
* to interpret the return value of this method.
|
* or {@code null} if the attribute is not supported.
|
||||||
*
|
|
||||||
* @return a <code>long</code> value representing the time the file was
|
|
||||||
* created since the epoch (00:00:00 GMT, January 1, 1970), or
|
|
||||||
* {@code -1L} if the attribute is not supported.
|
|
||||||
*/
|
*/
|
||||||
long creationTime();
|
FileTime creationTime();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link TimeUnit} required to interpret the time of last
|
|
||||||
* modification, time of last access, and creation time.
|
|
||||||
*
|
|
||||||
* @return the {@code TimeUnit} required to interpret the file time stamps
|
|
||||||
*/
|
|
||||||
TimeUnit resolution();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells whether the file is a regular file with opaque content.
|
* Tells whether the file is a regular file with opaque content.
|
||||||
@ -124,18 +102,6 @@ public interface BasicFileAttributes {
|
|||||||
*/
|
*/
|
||||||
long size();
|
long size();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of <em>links</em> to this file.
|
|
||||||
*
|
|
||||||
* <p> On file systems where the same file may be in several directories then
|
|
||||||
* the link count is the number of directory entries for the file. The return
|
|
||||||
* value is {@code 1} on file systems that only allow a file to have a
|
|
||||||
* single name in a single directory.
|
|
||||||
*
|
|
||||||
* @see java.nio.file.Path#createLink
|
|
||||||
*/
|
|
||||||
int linkCount();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object that uniquely identifies the given file, or {@code
|
* Returns an object that uniquely identifies the given file, or {@code
|
||||||
* null} if a file key is not available. On some platforms or file systems
|
* null} if a file key is not available. On some platforms or file systems
|
||||||
@ -154,7 +120,7 @@ public interface BasicFileAttributes {
|
|||||||
*
|
*
|
||||||
* <p> File keys returned by this method can be compared for equality and are
|
* <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,
|
* suitable for use in collections. If the file system and files remain static,
|
||||||
* and two files are the {@link java.nio.file.FileRef#isSameFile same} with
|
* and two files are the {@link java.nio.file.Path#isSameFile same} with
|
||||||
* non-{@code null} file keys, then their file keys are equal.
|
* non-{@code null} file keys, then their file keys are equal.
|
||||||
*
|
*
|
||||||
* @see java.nio.file.Files#walkFileTree
|
* @see java.nio.file.Files#walkFileTree
|
||||||
|
@ -65,17 +65,17 @@ import java.io.IOException;
|
|||||||
* </table>
|
* </table>
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* <p> The {@link #getAttribute getAttribute} or {@link #readAttributes(String,String[])
|
* <p> The {@link java.nio.file.FileRef#getAttribute getAttribute} method may
|
||||||
* readAttributes(String,String[])} methods may be used to read any of these
|
* be used to read any of these attributes, or any of the attributes defined by
|
||||||
* attributes, or any of the attributes defined by {@link BasicFileAttributeView}
|
* {@link BasicFileAttributeView} as if by invoking the {@link #readAttributes
|
||||||
* as if by invoking the {@link #readAttributes readAttributes()} method.
|
* readAttributes()} method.
|
||||||
*
|
*
|
||||||
* <p> The {@link #setAttribute setAttribute} method may be used to update the
|
* <p> The {@link java.nio.file.FileRef#setAttribute setAttribute} method may
|
||||||
* file's last modified time, last access time or create time attributes as
|
* be used to update the file's last modified time, last access time or create
|
||||||
* defined by {@link BasicFileAttributeView}. It may also be used to update
|
* time attributes as defined by {@link BasicFileAttributeView}. It may also be
|
||||||
* the DOS attributes as if by invoking the {@link #setReadOnly setReadOnly},
|
* used to update the DOS attributes as if by invoking the {@link #setReadOnly
|
||||||
* {@link #setHidden setHidden}, {@link #setSystem setSystem}, and {@link
|
* setReadOnly}, {@link #setHidden setHidden}, {@link #setSystem setSystem}, and
|
||||||
* #setArchive setArchive} methods respectively.
|
* {@link #setArchive setArchive} methods respectively.
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
@ -34,7 +34,6 @@ package java.nio.file.attribute;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*
|
*
|
||||||
* @see java.nio.file.FileRef#getFileAttributeView(Class,java.nio.file.LinkOption[])
|
* @see java.nio.file.FileRef#getFileAttributeView(Class,java.nio.file.LinkOption[])
|
||||||
* @see java.nio.file.FileRef#getFileAttributeView(String,java.nio.file.LinkOption[])
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface FileAttributeView
|
public interface FileAttributeView
|
||||||
|
@ -37,11 +37,11 @@ import java.io.IOException;
|
|||||||
* <p> The {@link #getOwner getOwner} or {@link #setOwner setOwner} methods may
|
* <p> The {@link #getOwner getOwner} or {@link #setOwner setOwner} methods may
|
||||||
* be used to read or update the owner of the file.
|
* be used to read or update the owner of the file.
|
||||||
*
|
*
|
||||||
* <p> Where dynamic access to file attributes is required, the owner attribute
|
* <p> The {@link java.nio.file.FileRef#getAttribute getAttribute} and
|
||||||
* is identified by the name {@code "owner"}, and the value of the attribute is
|
* {@link java.nio.file.FileRef#setAttribute setAttribute} methods may also be
|
||||||
* a {@link UserPrincipal}. The {@link #readAttributes readAttributes}, {@link
|
* used to read or update the owner. In that case, the owner attribute is
|
||||||
* #getAttribute getAttribute} and {@link #setAttribute setAttributes} methods
|
* identified by the name {@code "owner"}, and the value of the attribute is
|
||||||
* may be used to read or update the file owner.
|
* a {@link UserPrincipal}.
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
@ -52,10 +52,8 @@ import java.io.IOException;
|
|||||||
* </tr>
|
* </tr>
|
||||||
* </table>
|
* </table>
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
* <p> The {@link #getAttribute getAttribute} or {@link #readAttributes
|
* <p> The {@link java.nio.file.FileStore#getAttribute getAttribute} method may
|
||||||
* readAttributes(String,String[])} methods may be used to read any of these
|
* be used to read any of these attributes.
|
||||||
* attributes as if by invoking the {@link #readAttributes readAttributes()}
|
|
||||||
* method.
|
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
305
jdk/src/share/classes/java/nio/file/attribute/FileTime.java
Normal file
305
jdk/src/share/classes/java/nio/file/attribute/FileTime.java
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.nio.file.attribute;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Formatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* <p> Instances of this class are immutable.
|
||||||
|
*
|
||||||
|
* @since 1.7
|
||||||
|
* @see BasicFileAttributes
|
||||||
|
* @see Attributes#setLastModifiedTime
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class FileTime implements Comparable<FileTime> {
|
||||||
|
private final long value;
|
||||||
|
private final TimeUnit unit;
|
||||||
|
private String valueAsString; // created lazily
|
||||||
|
|
||||||
|
private FileTime(long value, TimeUnit unit) {
|
||||||
|
if (unit == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
this.value = value;
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code FileTime} representing a value at the given unit of
|
||||||
|
* granularity.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value since the epoch (1970-01-01T00:00:00Z); can be
|
||||||
|
* negative
|
||||||
|
* @param unit
|
||||||
|
* the unit of granularity to interpret the value
|
||||||
|
*
|
||||||
|
* @return a {@code FileTime} representing the given value
|
||||||
|
*/
|
||||||
|
public static FileTime from(long value, TimeUnit unit) {
|
||||||
|
return new FileTime(value, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code FileTime} representing the given value in milliseconds.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value, in milliseconds, since the epoch
|
||||||
|
* (1970-01-01T00:00:00Z); can be negative
|
||||||
|
*
|
||||||
|
* @return a {@code FileTime} representing the given value
|
||||||
|
*/
|
||||||
|
public static FileTime fromMillis(long value) {
|
||||||
|
return new FileTime(value, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value at the given unit of granularity.
|
||||||
|
*
|
||||||
|
* <p> Conversion from a coarser granularity that would numerically overflow
|
||||||
|
* saturate to {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE}
|
||||||
|
* if positive.
|
||||||
|
*
|
||||||
|
* @param unit
|
||||||
|
* the unit of granularity for the return value
|
||||||
|
*
|
||||||
|
* @return value in the given unit of granularity, since the epoch
|
||||||
|
* since the epoch (1970-01-01T00:00:00Z); can be negative
|
||||||
|
*/
|
||||||
|
public long to(TimeUnit unit) {
|
||||||
|
return unit.convert(this.value, this.unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value in milliseconds.
|
||||||
|
*
|
||||||
|
* <p> Conversion from a coarser granularity that would numerically overflow
|
||||||
|
* saturate to {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE}
|
||||||
|
* if positive.
|
||||||
|
*
|
||||||
|
* @return the value in milliseconds, since the epoch (1970-01-01T00:00:00Z)
|
||||||
|
*/
|
||||||
|
public long toMillis() {
|
||||||
|
return unit.toMillis(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests this {@code FileTime} for equality with the given object.
|
||||||
|
*
|
||||||
|
* <p> The result is {@code true} if and only if the argument is not {@code
|
||||||
|
* null} and is a {@code FileTime} that represents the same time. This
|
||||||
|
* method satisfies the general contract of the {@code Object.equals} method.
|
||||||
|
*
|
||||||
|
* @param obj
|
||||||
|
* the object to compare with
|
||||||
|
*
|
||||||
|
* @return {@code true} if, and only if, the given object is a {@code
|
||||||
|
* FileTime} that represents the same time
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return (obj instanceof FileTime) ? compareTo((FileTime)obj) == 0 : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a hash code for this file time.
|
||||||
|
*
|
||||||
|
* <p> The hash code is based upon the value represented, and satisfies the
|
||||||
|
* general contract of the {@link Object#hashCode} method.
|
||||||
|
*
|
||||||
|
* @return the hash-code value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
// hash value for fixed granularity to satisfy contract with equals
|
||||||
|
long ms = toMillis();
|
||||||
|
return (int)(ms ^ (ms >>> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the value of two {@code FileTime} objects for order.
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* the other {@code FileTime} to be compared
|
||||||
|
*
|
||||||
|
* @return {@code 0} if this {@code FileTime} is equal to {@code other}, a
|
||||||
|
* value less than 0 if this {@code FileTime} represents a time
|
||||||
|
* that is before {@code other}, and a value greater than 0 if this
|
||||||
|
* {@code FileTime} represents a time that is after {@code other}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(FileTime other) {
|
||||||
|
// same granularity
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
long rem = value - (days * scale);
|
||||||
|
return unit.toNanos(rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of this {@code FileTime}. The string
|
||||||
|
* is returned in the <a
|
||||||
|
* href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a> format:
|
||||||
|
* <pre>
|
||||||
|
* YYYY-MM-DDThh:mm:ss[.s+]Z
|
||||||
|
* </pre>
|
||||||
|
* where "{@code [.s+]}" represents a dot followed by one of more digits
|
||||||
|
* for the decimal fraction of a second. It is only present when the decimal
|
||||||
|
* fraction of a second is not zero. For example, {@code
|
||||||
|
* FileTime.fromMillis(1234567890000L).toString()} yields {@code
|
||||||
|
* "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()}
|
||||||
|
* yields {@code "2009-02-13T23:31:30.123Z"}.
|
||||||
|
*
|
||||||
|
* <p> A {@code FileTime} is primarly intended to represent the value of a
|
||||||
|
* file's time stamp. Where used to represent <i>extreme values</i>, where
|
||||||
|
* the year is less than "{@code 0001}" or greater than "{@code 9999}" then
|
||||||
|
* the year may be expanded to more than four digits and may be
|
||||||
|
* negative-signed. If more than four digits then leading zeros are not
|
||||||
|
* present. The year before "{@code 0001}" is "{@code -0001}".
|
||||||
|
*
|
||||||
|
* @return the string representation of this file time
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String v = valueAsString;
|
||||||
|
if (v == null) {
|
||||||
|
// overflow saturates to Long.MIN_VALUE or Long.MAX_VALUE so this
|
||||||
|
// limits the range:
|
||||||
|
// [-292275056-05-16T16:47:04.192Z,292278994-08-17T07:12:55.807Z]
|
||||||
|
long ms = toMillis();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
if (fraction != 0L) {
|
||||||
|
// fraction must be positive
|
||||||
|
if (fraction < 0L) {
|
||||||
|
fraction += scale;
|
||||||
|
if (ms != Long.MIN_VALUE) ms--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to String, adding leading zeros as required and
|
||||||
|
// stripping any trailing zeros
|
||||||
|
String s = Long.toString(fraction);
|
||||||
|
int len = s.length();
|
||||||
|
width -= len;
|
||||||
|
StringBuilder sb = new StringBuilder(".");
|
||||||
|
while (width-- > 0) {
|
||||||
|
sb.append('0');
|
||||||
|
}
|
||||||
|
if (s.charAt(len-1) == '0') {
|
||||||
|
// drop trailing zeros
|
||||||
|
len--;
|
||||||
|
while (s.charAt(len-1) == '0')
|
||||||
|
len--;
|
||||||
|
sb.append(s.substring(0, len));
|
||||||
|
} else {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
fractionAsString = sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create calendar to use with formatter.
|
||||||
|
GregorianCalendar cal =
|
||||||
|
new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT);
|
||||||
|
if (value < 0L)
|
||||||
|
cal.setGregorianChange(new Date(Long.MIN_VALUE));
|
||||||
|
cal.setTimeInMillis(ms);
|
||||||
|
|
||||||
|
// years are negative before common era
|
||||||
|
String sign = (cal.get(Calendar.ERA) == GregorianCalendar.BC) ? "-" : "";
|
||||||
|
|
||||||
|
// [-]YYYY-MM-DDThh:mm:ss[.s]Z
|
||||||
|
v = new Formatter(Locale.ROOT)
|
||||||
|
.format("%s%tFT%tR:%tS%sZ", sign, cal, cal, cal, fractionAsString)
|
||||||
|
.toString();
|
||||||
|
valueAsString = v;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
@ -90,14 +90,13 @@ import java.io.IOException;
|
|||||||
* </table>
|
* </table>
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* <p> The {@link #getAttribute getAttribute} or {@link
|
* <p> The {@link FileRef#getAttribute getAttribute} method may be used to read
|
||||||
* #readAttributes(String,String[]) readAttributes(String,String[])} methods may
|
* any of these attributes, or any of the attributes defined by {@link
|
||||||
* be used to read any of these attributes, or any of the attributes defined by
|
* BasicFileAttributeView} as if by invoking the {@link #readAttributes
|
||||||
* {@link BasicFileAttributeView} as if by invoking the {@link #readAttributes
|
|
||||||
* readAttributes()} method.
|
* readAttributes()} method.
|
||||||
*
|
*
|
||||||
* <p> The {@link #setAttribute setAttribute} method may be used to update the
|
* <p> The {@link FileRef#setAttribute setAttribute} method may be used to update
|
||||||
* file's last modified time, last access time or create time attributes as
|
* 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
|
* defined by {@link BasicFileAttributeView}. It may also be used to update
|
||||||
* the permissions, owner, or group-owner as if by invoking the {@link
|
* the permissions, owner, or group-owner as if by invoking the {@link
|
||||||
* #setPermissions setPermissions}, {@link #setOwner setOwner}, and {@link
|
* #setPermissions setPermissions}, {@link #setOwner setOwner}, and {@link
|
||||||
|
@ -35,7 +35,7 @@ import java.util.*;
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PosixFilePermissions {
|
public final class PosixFilePermissions {
|
||||||
private PosixFilePermissions() { }
|
private PosixFilePermissions() { }
|
||||||
|
|
||||||
// Write string representation of permission bits to {@code sb}.
|
// Write string representation of permission bits to {@code sb}.
|
||||||
@ -58,7 +58,9 @@ public class PosixFilePermissions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@code String} representation of a set of permissions.
|
* Returns the {@code String} representation of a set of permissions. It
|
||||||
|
* is guaranteed that the returned {@code String} can be parsed by the
|
||||||
|
* {@link #fromString} method.
|
||||||
*
|
*
|
||||||
* <p> If the set contains {@code null} or elements that are not of type
|
* <p> If the set contains {@code null} or elements that are not of type
|
||||||
* {@code PosixFilePermission} then these elements are ignored.
|
* {@code PosixFilePermission} then these elements are ignored.
|
||||||
@ -67,8 +69,6 @@ public class PosixFilePermissions {
|
|||||||
* the set of permissions
|
* the set of permissions
|
||||||
*
|
*
|
||||||
* @return the string representation of the permission set
|
* @return the string representation of the permission set
|
||||||
*
|
|
||||||
* @see #fromString
|
|
||||||
*/
|
*/
|
||||||
public static String toString(Set<PosixFilePermission> perms) {
|
public static String toString(Set<PosixFilePermission> perms) {
|
||||||
StringBuilder sb = new StringBuilder(9);
|
StringBuilder sb = new StringBuilder(9);
|
||||||
|
@ -59,12 +59,11 @@ import java.io.IOException;
|
|||||||
* attributes.
|
* attributes.
|
||||||
*
|
*
|
||||||
* <p> Where dynamic access to file attributes is required, the {@link
|
* <p> Where dynamic access to file attributes is required, the {@link
|
||||||
* #getAttribute getAttribute} or {@link #readAttributes(String,String[])
|
* java.nio.file.FileRef#getAttribute getAttribute} method may be used to read
|
||||||
* readAttributes(String,String[])} methods may be used to read the attribute
|
* the attribute value. The attribute value is returned as a byte array (byte[]).
|
||||||
* value. The attribute value is returned as a byte array (byte[]). The {@link
|
* The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be used
|
||||||
* #setAttribute setAttribute} method may be used to write the value of a
|
* to write the value of a user-defined attribute from a buffer (as if by
|
||||||
* user-defined attribute from a buffer (as if by invoking the {@link #write
|
* invoking the {@link #write write} method), or byte array (byte[]).
|
||||||
* write} method), or byte array (byte[]).
|
|
||||||
*
|
*
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
@ -74,7 +73,7 @@ public interface UserDefinedFileAttributeView
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns the name of this attribute view. Attribute views of this type
|
* Returns the name of this attribute view. Attribute views of this type
|
||||||
* have the name {@code "xattr"}.
|
* have the name {@code "user"}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
String name();
|
String name();
|
||||||
|
@ -89,7 +89,7 @@ public abstract class UserPrincipalLookupService {
|
|||||||
* @param group
|
* @param group
|
||||||
* the string representation of the group to lookup
|
* the string representation of the group to lookup
|
||||||
*
|
*
|
||||||
* @return a user principal
|
* @return a group principal
|
||||||
*
|
*
|
||||||
* @throws UserPrincipalNotFoundException
|
* @throws UserPrincipalNotFoundException
|
||||||
* the principal does not exist or is not a group
|
* the principal does not exist or is not a group
|
||||||
|
@ -1,568 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007-2009 Sun Microsystems, Inc. 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. Sun designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
||||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
||||||
* have any questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.nio.file.spi;
|
|
||||||
|
|
||||||
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.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base implementation class for a {@code Path}.
|
|
||||||
*
|
|
||||||
* <p> This class is intended to be extended by provider implementors. It
|
|
||||||
* implements, or provides default implementations for several of the methods
|
|
||||||
* defined by the {@code Path} class. It implements the {@link #copyTo copyTo}
|
|
||||||
* and {@link #moveTo moveTo} methods for the case that the source and target
|
|
||||||
* are not associated with the same provider.
|
|
||||||
*
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class AbstractPath extends Path {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a new instance of this class.
|
|
||||||
*/
|
|
||||||
protected AbstractPath() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the file referenced by this object.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link #delete(boolean) delete(boolean)}
|
|
||||||
* method with a parameter of {@code true}. It may be overridden where
|
|
||||||
* required.
|
|
||||||
*
|
|
||||||
* @throws NoSuchFileException {@inheritDoc}
|
|
||||||
* @throws DirectoryNotEmptyException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void delete() throws IOException {
|
|
||||||
delete(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new and empty file, failing if the file already exists.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link #newByteChannel(Set,FileAttribute[])
|
|
||||||
* newByteChannel(Set,FileAttribute...)} method to create the file. It may be
|
|
||||||
* overridden where required.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException {@inheritDoc}
|
|
||||||
* @throws FileAlreadyExistsException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens or creates a file, returning a seekable byte channel to access the
|
|
||||||
* file.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link #newByteChannel(Set,FileAttribute[])
|
|
||||||
* newByteChannel(Set,FileAttribute...)} method to open or create the file.
|
|
||||||
* It may be overridden where required.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException {@inheritDoc}
|
|
||||||
* @throws FileAlreadyExistsException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SeekableByteChannel newByteChannel(OpenOption... options)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
Set<OpenOption> set = new HashSet<OpenOption>(options.length);
|
|
||||||
Collections.addAll(set, options);
|
|
||||||
return newByteChannel(set);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the file located by this path for reading, returning an input
|
|
||||||
* stream to read bytes from the file.
|
|
||||||
*
|
|
||||||
* <p> This method returns an {@code InputStream} that is constructed by
|
|
||||||
* invoking the {@link java.nio.channels.Channels#newInputStream
|
|
||||||
* Channels.newInputStream} method. It may be overridden where a more
|
|
||||||
* efficient implementation is available.
|
|
||||||
*
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public InputStream newInputStream() throws IOException {
|
|
||||||
return Channels.newInputStream(newByteChannel());
|
|
||||||
}
|
|
||||||
|
|
||||||
// opts must be modifiable
|
|
||||||
private OutputStream implNewOutputStream(Set<OpenOption> opts,
|
|
||||||
FileAttribute<?>... attrs)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (opts.isEmpty()) {
|
|
||||||
opts.add(CREATE);
|
|
||||||
opts.add(TRUNCATE_EXISTING);
|
|
||||||
} else {
|
|
||||||
if (opts.contains(READ))
|
|
||||||
throw new IllegalArgumentException("READ not allowed");
|
|
||||||
}
|
|
||||||
opts.add(WRITE);
|
|
||||||
return Channels.newOutputStream(newByteChannel(opts, attrs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens or creates the file located by this path for writing, returning an
|
|
||||||
* output stream to write bytes to the file.
|
|
||||||
*
|
|
||||||
* <p> This method returns an {@code OutputStream} that is constructed by
|
|
||||||
* invoking the {@link java.nio.channels.Channels#newOutputStream
|
|
||||||
* Channels.newOutputStream} method. It may be overridden where a more
|
|
||||||
* efficient implementation is available.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public OutputStream newOutputStream(OpenOption... options) throws IOException {
|
|
||||||
int len = options.length;
|
|
||||||
Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
|
|
||||||
if (len > 0) {
|
|
||||||
for (OpenOption opt: options) {
|
|
||||||
opts.add(opt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implNewOutputStream(opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens or creates the file located by this path for writing, returning an
|
|
||||||
* output stream to write bytes to the file.
|
|
||||||
*
|
|
||||||
* <p> This method returns an {@code OutputStream} that is constructed by
|
|
||||||
* invoking the {@link java.nio.channels.Channels#newOutputStream
|
|
||||||
* Channels.newOutputStream} method. It may be overridden where a more
|
|
||||||
* efficient implementation is available.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public OutputStream newOutputStream(Set<? extends OpenOption> options,
|
|
||||||
FileAttribute<?>... attrs)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
Set<OpenOption> opts = new HashSet<OpenOption>(options);
|
|
||||||
return implNewOutputStream(opts, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the directory referenced by this object, returning a {@code
|
|
||||||
* DirectoryStream} to iterate over all entries in the directory.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link
|
|
||||||
* #newDirectoryStream(java.nio.file.DirectoryStream.Filter)
|
|
||||||
* newDirectoryStream(Filter)} method with a filter that accept all entries.
|
|
||||||
* It may be overridden where required.
|
|
||||||
*
|
|
||||||
* @throws NotDirectoryException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DirectoryStream<Path> newDirectoryStream() throws IOException {
|
|
||||||
return newDirectoryStream(acceptAllFilter);
|
|
||||||
}
|
|
||||||
private static final DirectoryStream.Filter<Path> acceptAllFilter =
|
|
||||||
new DirectoryStream.Filter<Path>() {
|
|
||||||
@Override public boolean accept(Path entry) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the directory referenced by this object, returning a {@code
|
|
||||||
* DirectoryStream} to iterate over the entries in the directory. The
|
|
||||||
* entries are filtered by matching the {@code String} representation of
|
|
||||||
* their file names against a given pattern.
|
|
||||||
*
|
|
||||||
* <p> This method constructs a {@link PathMatcher} by invoking the
|
|
||||||
* file system's {@link java.nio.file.FileSystem#getPathMatcher
|
|
||||||
* getPathMatcher} method. This method may be overridden where a more
|
|
||||||
* efficient implementation is available.
|
|
||||||
*
|
|
||||||
* @throws java.util.regex.PatternSyntaxException {@inheritDoc}
|
|
||||||
* @throws UnsupportedOperationException {@inheritDoc}
|
|
||||||
* @throws NotDirectoryException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public 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>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(Path entry) {
|
|
||||||
return matcher.matches(entry.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return newDirectoryStream(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether the file located by this path exists.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link #checkAccess checkAccess} method to
|
|
||||||
* check if the file exists. It may be overridden where a more efficient
|
|
||||||
* implementation is available.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean exists() {
|
|
||||||
try {
|
|
||||||
checkAccess();
|
|
||||||
return true;
|
|
||||||
} catch (IOException x) {
|
|
||||||
// unable to determine if file exists
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether the file located by this path does not exist.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link #checkAccess checkAccess} method to
|
|
||||||
* check if the file exists. It may be overridden where a more efficient
|
|
||||||
* implementation is available.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean notExists() {
|
|
||||||
try {
|
|
||||||
checkAccess();
|
|
||||||
return false;
|
|
||||||
} catch (NoSuchFileException x) {
|
|
||||||
// file confirmed not to exist
|
|
||||||
return true;
|
|
||||||
} catch (IOException x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the file located by this path with a watch service.
|
|
||||||
*
|
|
||||||
* <p> This method invokes the {@link #register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier[])
|
|
||||||
* register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier...)}
|
|
||||||
* method to register the file. It may be overridden where required.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
return register(watcher, events, NO_MODIFIERS);
|
|
||||||
}
|
|
||||||
private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy the file located by this path to a target location.
|
|
||||||
*
|
|
||||||
* <p> This method is invoked by the {@link #copyTo copyTo} method for
|
|
||||||
* the case that this {@code Path} and the target {@code Path} are
|
|
||||||
* associated with the same provider.
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* The target location
|
|
||||||
* @param options
|
|
||||||
* Options specifying how the copy should be done
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* If an invalid option is specified
|
|
||||||
* @throws FileAlreadyExistsException
|
|
||||||
* The target file exists and cannot be replaced because the
|
|
||||||
* {@code REPLACE_EXISTING} option is not specified, or the target
|
|
||||||
* file 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")}.
|
|
||||||
*/
|
|
||||||
protected abstract void implCopyTo(Path target, CopyOption... options)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the file located by this path to a target location.
|
|
||||||
*
|
|
||||||
* <p> This method is invoked by the {@link #moveTo moveTo} method for
|
|
||||||
* the case that this {@code Path} and the target {@code Path} are
|
|
||||||
* associated with the same provider.
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* The target location
|
|
||||||
* @param options
|
|
||||||
* Options specifying how the move should be done
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* If an invalid option is specified
|
|
||||||
* @throws FileAlreadyExistsException
|
|
||||||
* The target file exists and cannot be replaced because the
|
|
||||||
* {@code REPLACE_EXISTING} option is not specified, or the target
|
|
||||||
* file is a non-empty directory
|
|
||||||
* @throws AtomicMoveNotSupportedException
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
protected abstract void implMoveTo(Path target, CopyOption... options)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy the file located by this path to a target location.
|
|
||||||
*
|
|
||||||
* <p> If this path is associated with the same {@link FileSystemProvider
|
|
||||||
* provider} as the {@code target} then the {@link #implCopyTo implCopyTo}
|
|
||||||
* method is invoked to copy the file. Otherwise, this method attempts to
|
|
||||||
* copy the file to the target location in a manner that may be less
|
|
||||||
* efficient than would be the case that target is associated with the same
|
|
||||||
* provider as this path.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException {@inheritDoc}
|
|
||||||
* @throws FileAlreadyExistsException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final Path copyTo(Path target, CopyOption... options)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if ((getFileSystem().provider() == target.getFileSystem().provider())) {
|
|
||||||
implCopyTo(target, options);
|
|
||||||
} else {
|
|
||||||
xProviderCopyTo(target, options);
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move or rename the file located by this path to a target location.
|
|
||||||
*
|
|
||||||
* <p> If this path is associated with the same {@link FileSystemProvider
|
|
||||||
* provider} as the {@code target} then the {@link #implCopyTo implMoveTo}
|
|
||||||
* method is invoked to move the file. Otherwise, this method attempts to
|
|
||||||
* copy the file to the target location and delete the source file. This
|
|
||||||
* implementation may be less efficient than would be the case that
|
|
||||||
* target is associated with the same provider as this path.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException {@inheritDoc}
|
|
||||||
* @throws FileAlreadyExistsException {@inheritDoc}
|
|
||||||
* @throws IOException {@inheritDoc}
|
|
||||||
* @throws SecurityException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@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
|
|
||||||
xProviderCopyTo(target, convertMoveToCopyOptions(options));
|
|
||||||
delete(false);
|
|
||||||
}
|
|
||||||
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 IllegalArgumentException("'" + option +
|
|
||||||
"' is not a valid copy option");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple cross-provider copy where the target is a Path.
|
|
||||||
*/
|
|
||||||
private void xProviderCopyTo(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");
|
|
||||||
|
|
||||||
// delete target file
|
|
||||||
if (opts.replaceExisting)
|
|
||||||
target.delete(false);
|
|
||||||
|
|
||||||
// create directory or file
|
|
||||||
if (attrs.isDirectory()) {
|
|
||||||
target.createDirectory();
|
|
||||||
} else {
|
|
||||||
xProviderCopyRegularFileTo(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(),
|
|
||||||
attrs.resolution());
|
|
||||||
} catch (IOException x) {
|
|
||||||
// rollback
|
|
||||||
try {
|
|
||||||
target.delete(false);
|
|
||||||
} catch (IOException ignore) { }
|
|
||||||
throw x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple copy of regular file to a target file that exists.
|
|
||||||
*/
|
|
||||||
private void xProviderCopyRegularFileTo(FileRef target)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
ReadableByteChannel rbc = newByteChannel();
|
|
||||||
try {
|
|
||||||
// open target file for writing
|
|
||||||
SeekableByteChannel sbc = target.newByteChannel(CREATE, 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -270,7 +270,9 @@ public abstract class FileSystemProvider {
|
|||||||
public abstract FileSystem getFileSystem(URI uri);
|
public abstract FileSystem getFileSystem(URI uri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a {@code Path} object by converting the given {@link URI}.
|
* Return a {@code Path} object by converting the given {@link URI}. The
|
||||||
|
* resulting {@code Path} is associated with a {@link FileSystem} that
|
||||||
|
* already exists or is constructed automatically.
|
||||||
*
|
*
|
||||||
* <p> The exact form of the URI is file system provider dependent. In the
|
* <p> The exact form of the URI is file system provider dependent. In the
|
||||||
* case of the default provider, the URI scheme is {@code "file"} and the
|
* case of the default provider, the URI scheme is {@code "file"} and the
|
||||||
@ -290,7 +292,8 @@ public abstract class FileSystemProvider {
|
|||||||
* If the URI scheme does not identify this provider or other
|
* If the URI scheme does not identify this provider or other
|
||||||
* preconditions on the uri parameter do not hold
|
* preconditions on the uri parameter do not hold
|
||||||
* @throws FileSystemNotFoundException
|
* @throws FileSystemNotFoundException
|
||||||
* The file system, identified by the URI, does not exist
|
* The file system, identified by the URI, does not exist and
|
||||||
|
* cannot be created automatically
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* If a security manager is installed and it denies an unspecified
|
* If a security manager is installed and it denies an unspecified
|
||||||
* permission.
|
* permission.
|
||||||
|
@ -690,7 +690,7 @@ public final class Scanner implements Iterator<String> {
|
|||||||
public Scanner(FileRef source)
|
public Scanner(FileRef source)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
this(source.newByteChannel());
|
this(source.newInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -713,7 +713,7 @@ public final class Scanner implements Iterator<String> {
|
|||||||
public Scanner(FileRef source, String charsetName)
|
public Scanner(FileRef source, String charsetName)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
this(source.newByteChannel(), charsetName);
|
this(source.newInputStream(), charsetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,22 +26,15 @@
|
|||||||
package sun.management;
|
package sun.management;
|
||||||
|
|
||||||
import java.lang.management.*;
|
import java.lang.management.*;
|
||||||
import java.util.logging.LogManager;
|
|
||||||
|
|
||||||
import javax.management.DynamicMBean;
|
|
||||||
import javax.management.MBeanServer;
|
import javax.management.MBeanServer;
|
||||||
import javax.management.MBeanServerFactory;
|
|
||||||
import javax.management.MBeanInfo;
|
|
||||||
import javax.management.NotificationEmitter;
|
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
import javax.management.ObjectInstance;
|
|
||||||
import javax.management.InstanceAlreadyExistsException;
|
import javax.management.InstanceAlreadyExistsException;
|
||||||
import javax.management.InstanceNotFoundException;
|
import javax.management.InstanceNotFoundException;
|
||||||
import javax.management.MBeanRegistrationException;
|
import javax.management.MBeanRegistrationException;
|
||||||
import javax.management.NotCompliantMBeanException;
|
import javax.management.NotCompliantMBeanException;
|
||||||
import javax.management.RuntimeOperationsException;
|
import javax.management.RuntimeOperationsException;
|
||||||
import javax.management.StandardEmitterMBean;
|
import java.nio.BufferPoolMXBean;
|
||||||
import javax.management.StandardMBean;
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedActionException;
|
import java.security.PrivilegedActionException;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
@ -49,11 +42,6 @@ import sun.security.action.LoadLibraryAction;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
import com.sun.management.OSMBeanFactory;
|
import com.sun.management.OSMBeanFactory;
|
||||||
import com.sun.management.HotSpotDiagnosticMXBean;
|
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||||
|
|
||||||
@ -68,7 +56,6 @@ public class ManagementFactoryHelper {
|
|||||||
|
|
||||||
private static VMManagement jvm;
|
private static VMManagement jvm;
|
||||||
|
|
||||||
private static boolean mbeansCreated = false;
|
|
||||||
private static ClassLoadingImpl classMBean = null;
|
private static ClassLoadingImpl classMBean = null;
|
||||||
private static MemoryImpl memoryMBean = null;
|
private static MemoryImpl memoryMBean = null;
|
||||||
private static ThreadImpl threadMBean = null;
|
private static ThreadImpl threadMBean = null;
|
||||||
@ -148,6 +135,58 @@ public class ManagementFactoryHelper {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<BufferPoolMXBean> getBufferPoolMXBeans() {
|
||||||
|
List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2);
|
||||||
|
pools.add(createBufferPoolMXBean(sun.misc.SharedSecrets.getJavaNioAccess()
|
||||||
|
.getDirectBufferPool()));
|
||||||
|
pools.add(createBufferPoolMXBean(sun.nio.ch.FileChannelImpl
|
||||||
|
.getMappedBufferPool()));
|
||||||
|
return pools;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static String BUFFER_POOL_MXBEAN_NAME = "java.nio:type=BufferPool";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates management interface for the given buffer pool.
|
||||||
|
*/
|
||||||
|
private static BufferPoolMXBean
|
||||||
|
createBufferPoolMXBean(final sun.misc.JavaNioAccess.BufferPool pool)
|
||||||
|
{
|
||||||
|
return new BufferPoolMXBean() {
|
||||||
|
private volatile ObjectName objname; // created lazily
|
||||||
|
@Override
|
||||||
|
public ObjectName getObjectName() {
|
||||||
|
ObjectName result = objname;
|
||||||
|
if (result == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (objname == null) {
|
||||||
|
result = ObjectName.valueOf(BUFFER_POOL_MXBEAN_NAME +
|
||||||
|
",name=" + pool.getName());
|
||||||
|
objname = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return pool.getName();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getCount() {
|
||||||
|
return pool.getCount();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getTotalCapacity() {
|
||||||
|
return pool.getTotalCapacity();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getMemoryUsed() {
|
||||||
|
return pool.getMemoryUsed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static HotSpotDiagnostic hsDiagMBean = null;
|
private static HotSpotDiagnostic hsDiagMBean = null;
|
||||||
private static HotspotRuntime hsRuntimeMBean = null;
|
private static HotspotRuntime hsRuntimeMBean = null;
|
||||||
private static HotspotClassLoading hsClassMBean = null;
|
private static HotspotClassLoading hsClassMBean = null;
|
||||||
@ -162,8 +201,6 @@ public class ManagementFactoryHelper {
|
|||||||
return hsDiagMBean;
|
return hsDiagMBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is for testing only.
|
* This method is for testing only.
|
||||||
*/
|
*/
|
||||||
|
@ -25,8 +25,15 @@
|
|||||||
|
|
||||||
package sun.misc;
|
package sun.misc;
|
||||||
|
|
||||||
import java.nio.BufferPoolMXBean;
|
|
||||||
|
|
||||||
public interface JavaNioAccess {
|
public interface JavaNioAccess {
|
||||||
BufferPoolMXBean getDirectBufferPoolMXBean();
|
/**
|
||||||
|
* Provides access to information on buffer usage.
|
||||||
|
*/
|
||||||
|
interface BufferPool {
|
||||||
|
String getName();
|
||||||
|
long getCount();
|
||||||
|
long getTotalCapacity();
|
||||||
|
long getMemoryUsed();
|
||||||
|
}
|
||||||
|
BufferPool getDirectBufferPool();
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,10 @@ import java.io.FileDescriptor;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.MappedByteBuffer;
|
import java.nio.MappedByteBuffer;
|
||||||
import java.nio.BufferPoolMXBean;
|
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import sun.misc.Cleaner;
|
import sun.misc.Cleaner;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
@ -805,47 +802,28 @@ public class FileChannelImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the management interface for mapped buffers
|
* Invoked by sun.management.ManagementFactoryHelper to create the management
|
||||||
|
* interface for mapped buffers.
|
||||||
*/
|
*/
|
||||||
public static BufferPoolMXBean getMappedBufferPoolMXBean() {
|
public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() {
|
||||||
return LazyInitialization.mappedBufferPoolMXBean;
|
return new sun.misc.JavaNioAccess.BufferPool() {
|
||||||
}
|
@Override
|
||||||
|
public String getName() {
|
||||||
// Lazy initialization of management interface
|
return "mapped";
|
||||||
private static class LazyInitialization {
|
|
||||||
static final BufferPoolMXBean mappedBufferPoolMXBean = mappedBufferPoolMXBean();
|
|
||||||
|
|
||||||
private static BufferPoolMXBean mappedBufferPoolMXBean() {
|
|
||||||
final String pool = "mapped";
|
|
||||||
final ObjectName obj;
|
|
||||||
try {
|
|
||||||
obj = new ObjectName("java.nio:type=BufferPool,name=" + pool);
|
|
||||||
} catch (MalformedObjectNameException x) {
|
|
||||||
throw new AssertionError(x);
|
|
||||||
}
|
}
|
||||||
return new BufferPoolMXBean() {
|
@Override
|
||||||
@Override
|
public long getCount() {
|
||||||
public ObjectName getObjectName() {
|
return Unmapper.count;
|
||||||
return obj;
|
}
|
||||||
}
|
@Override
|
||||||
@Override
|
public long getTotalCapacity() {
|
||||||
public String getName() {
|
return Unmapper.totalCapacity;
|
||||||
return pool;
|
}
|
||||||
}
|
@Override
|
||||||
@Override
|
public long getMemoryUsed() {
|
||||||
public long getCount() {
|
return Unmapper.totalSize;
|
||||||
return Unmapper.count;
|
}
|
||||||
}
|
};
|
||||||
@Override
|
|
||||||
public long getTotalCapacity() {
|
|
||||||
return Unmapper.totalCapacity;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public long getMemoryUsed() {
|
|
||||||
return Unmapper.totalSize;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Locks --
|
// -- Locks --
|
||||||
|
@ -26,15 +26,15 @@
|
|||||||
package sun.nio.fs;
|
package sun.nio.fs;
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of AclFileAttributeView
|
* Base implementation of AclFileAttributeView
|
||||||
*/
|
*/
|
||||||
|
|
||||||
abstract class AbstractAclFileAttributeView
|
abstract class AbstractAclFileAttributeView
|
||||||
implements AclFileAttributeView
|
implements AclFileAttributeView, DynamicFileAttributeView
|
||||||
{
|
{
|
||||||
private static final String OWNER_NAME = "owner";
|
private static final String OWNER_NAME = "owner";
|
||||||
private static final String ACL_NAME = "acl";
|
private static final String ACL_NAME = "acl";
|
||||||
@ -66,38 +66,29 @@ abstract class AbstractAclFileAttributeView
|
|||||||
setAcl((List<AclEntry>)value);
|
setAcl((List<AclEntry>)value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("'" + name() + ":" +
|
||||||
|
attribute + "' not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Map<String,?> readAttributes(String first, String[] rest)
|
public final Map<String,?> readAttributes(String[] attributes)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
boolean acl = false;
|
boolean acl = false;
|
||||||
boolean owner = false;
|
boolean owner = false;
|
||||||
|
for (String attribute: attributes) {
|
||||||
if (first.equals(ACL_NAME)) acl = true;
|
if (attribute.equals("*")) {
|
||||||
else if (first.equals(OWNER_NAME)) owner = true;
|
owner = true;
|
||||||
else if (first.equals("*")) {
|
acl = true;
|
||||||
owner = true;
|
continue;
|
||||||
acl = true;
|
}
|
||||||
}
|
if (attribute.equals(ACL_NAME)) {
|
||||||
|
acl = true;
|
||||||
if (!acl || !owner) {
|
continue;
|
||||||
for (String attribute: rest) {
|
}
|
||||||
if (attribute.equals("*")) {
|
if (attribute.equals(OWNER_NAME)) {
|
||||||
owner = true;
|
owner = true;
|
||||||
acl = true;
|
continue;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (attribute.equals(ACL_NAME)) {
|
|
||||||
acl = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (attribute.equals(OWNER_NAME)) {
|
|
||||||
owner = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Map<String,Object> result = new HashMap<String,Object>(2);
|
Map<String,Object> result = new HashMap<String,Object>(2);
|
||||||
|
@ -26,24 +26,21 @@
|
|||||||
package sun.nio.fs;
|
package sun.nio.fs;
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of BasicFileAttributeView
|
* Base implementation of BasicFileAttributeView
|
||||||
*/
|
*/
|
||||||
|
|
||||||
abstract class AbstractBasicFileAttributeView
|
abstract class AbstractBasicFileAttributeView
|
||||||
implements BasicFileAttributeView
|
implements BasicFileAttributeView, DynamicFileAttributeView
|
||||||
{
|
{
|
||||||
private static final String SIZE_NAME = "size";
|
private static final String SIZE_NAME = "size";
|
||||||
private static final String CREATION_TIME_NAME = "creationTime";
|
private static final String CREATION_TIME_NAME = "creationTime";
|
||||||
private static final String LAST_ACCESS_TIME_NAME = "lastAccessTime";
|
private static final String LAST_ACCESS_TIME_NAME = "lastAccessTime";
|
||||||
private static final String LAST_MODIFIED_TIME_NAME = "lastModifiedTime";
|
private static final String LAST_MODIFIED_TIME_NAME = "lastModifiedTime";
|
||||||
private static final String RESOLUTION_NAME = "resolution";
|
|
||||||
private static final String FILE_KEY_NAME = "fileKey";
|
private static final String FILE_KEY_NAME = "fileKey";
|
||||||
private static final String LINK_COUNT_NAME = "linkCount";
|
|
||||||
private static final String IS_DIRECTORY_NAME = "isDirectory";
|
private static final String IS_DIRECTORY_NAME = "isDirectory";
|
||||||
private static final String IS_REGULAR_FILE_NAME = "isRegularFile";
|
private static final String IS_REGULAR_FILE_NAME = "isRegularFile";
|
||||||
private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink";
|
private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink";
|
||||||
@ -67,12 +64,8 @@ abstract class AbstractBasicFileAttributeView
|
|||||||
return attrs.lastAccessTime();
|
return attrs.lastAccessTime();
|
||||||
if (attribute.equals(LAST_MODIFIED_TIME_NAME))
|
if (attribute.equals(LAST_MODIFIED_TIME_NAME))
|
||||||
return attrs.lastModifiedTime();
|
return attrs.lastModifiedTime();
|
||||||
if (attribute.equals(RESOLUTION_NAME))
|
|
||||||
return attrs.resolution();
|
|
||||||
if (attribute.equals(FILE_KEY_NAME))
|
if (attribute.equals(FILE_KEY_NAME))
|
||||||
return attrs.fileKey();
|
return attrs.fileKey();
|
||||||
if (attribute.equals(LINK_COUNT_NAME))
|
|
||||||
return attrs.linkCount();
|
|
||||||
if (attribute.equals(IS_DIRECTORY_NAME))
|
if (attribute.equals(IS_DIRECTORY_NAME))
|
||||||
return attrs.isDirectory();
|
return attrs.isDirectory();
|
||||||
if (attribute.equals(IS_REGULAR_FILE_NAME))
|
if (attribute.equals(IS_REGULAR_FILE_NAME))
|
||||||
@ -84,29 +77,20 @@ abstract class AbstractBasicFileAttributeView
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long toTimeValue(Object value) {
|
|
||||||
if (value == null)
|
|
||||||
throw new NullPointerException();
|
|
||||||
Long time = (Long)value;
|
|
||||||
if (time < 0L && time != -1L)
|
|
||||||
throw new IllegalArgumentException("time value cannot be negative");
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAttribute(String attribute, Object value)
|
public void setAttribute(String attribute, Object value)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if (attribute.equals(LAST_MODIFIED_TIME_NAME)) {
|
if (attribute.equals(LAST_MODIFIED_TIME_NAME)) {
|
||||||
setTimes(toTimeValue(value), null, null, TimeUnit.MILLISECONDS);
|
setTimes((FileTime)value, null, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attribute.equals(LAST_ACCESS_TIME_NAME)) {
|
if (attribute.equals(LAST_ACCESS_TIME_NAME)) {
|
||||||
setTimes(null, toTimeValue(value), null, TimeUnit.MILLISECONDS);
|
setTimes(null, (FileTime)value, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attribute.equals(CREATION_TIME_NAME)) {
|
if (attribute.equals(CREATION_TIME_NAME)) {
|
||||||
setTimes(null, null, toTimeValue(value), TimeUnit.MILLISECONDS);
|
setTimes(null, null, (FileTime)value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException("'" + attribute +
|
throw new UnsupportedOperationException("'" + attribute +
|
||||||
@ -114,24 +98,18 @@ abstract class AbstractBasicFileAttributeView
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Used to build a map of attribute name/values.
|
||||||
*/
|
*/
|
||||||
static class AttributesBuilder {
|
static class AttributesBuilder {
|
||||||
private Set<String> set = new HashSet<String>();
|
private Set<String> set = new HashSet<String>();
|
||||||
private Map<String,Object> map = new HashMap<String,Object>();
|
private Map<String,Object> map = new HashMap<String,Object>();
|
||||||
private boolean copyAll;
|
private boolean copyAll;
|
||||||
|
|
||||||
private AttributesBuilder(String first, String[] rest) {
|
private AttributesBuilder(String[] attributes) {
|
||||||
if (first.equals("*")) {
|
for (String attribute: attributes) {
|
||||||
copyAll = true;
|
if (attribute.equals("*")) {
|
||||||
} else {
|
copyAll = true;
|
||||||
set.add(first);
|
} else {
|
||||||
// copy names into the given Set bailing out if "*" is found
|
|
||||||
for (String attribute: rest) {
|
|
||||||
if (attribute.equals("*")) {
|
|
||||||
copyAll = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
set.add(attribute);
|
set.add(attribute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,8 +118,8 @@ abstract class AbstractBasicFileAttributeView
|
|||||||
/**
|
/**
|
||||||
* Creates builder to build up a map of the matching attributes
|
* Creates builder to build up a map of the matching attributes
|
||||||
*/
|
*/
|
||||||
static AttributesBuilder create(String first, String[] rest) {
|
static AttributesBuilder create(String[] attributes) {
|
||||||
return new AttributesBuilder(first, rest);
|
return new AttributesBuilder(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,12 +159,8 @@ abstract class AbstractBasicFileAttributeView
|
|||||||
builder.add(LAST_ACCESS_TIME_NAME, attrs.lastAccessTime());
|
builder.add(LAST_ACCESS_TIME_NAME, attrs.lastAccessTime());
|
||||||
if (builder.match(LAST_MODIFIED_TIME_NAME))
|
if (builder.match(LAST_MODIFIED_TIME_NAME))
|
||||||
builder.add(LAST_MODIFIED_TIME_NAME, attrs.lastModifiedTime());
|
builder.add(LAST_MODIFIED_TIME_NAME, attrs.lastModifiedTime());
|
||||||
if (builder.match(RESOLUTION_NAME))
|
|
||||||
builder.add(RESOLUTION_NAME, attrs.resolution());
|
|
||||||
if (builder.match(FILE_KEY_NAME))
|
if (builder.match(FILE_KEY_NAME))
|
||||||
builder.add(FILE_KEY_NAME, attrs.fileKey());
|
builder.add(FILE_KEY_NAME, attrs.fileKey());
|
||||||
if (builder.match(LINK_COUNT_NAME))
|
|
||||||
builder.add(LINK_COUNT_NAME, attrs.linkCount());
|
|
||||||
if (builder.match(IS_DIRECTORY_NAME))
|
if (builder.match(IS_DIRECTORY_NAME))
|
||||||
builder.add(IS_DIRECTORY_NAME, attrs.isDirectory());
|
builder.add(IS_DIRECTORY_NAME, attrs.isDirectory());
|
||||||
if (builder.match(IS_REGULAR_FILE_NAME))
|
if (builder.match(IS_REGULAR_FILE_NAME))
|
||||||
@ -198,10 +172,8 @@ abstract class AbstractBasicFileAttributeView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,?> readAttributes(String first, String[] rest)
|
public Map<String,?> readAttributes(String[] attributes) throws IOException {
|
||||||
throws IOException
|
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||||
{
|
|
||||||
AttributesBuilder builder = AttributesBuilder.create(first, rest);
|
|
||||||
addBasicAttributesToBuilder(readAttributes(), builder);
|
addBasicAttributesToBuilder(readAttributes(), builder);
|
||||||
return builder.unmodifiableMap();
|
return builder.unmodifiableMap();
|
||||||
}
|
}
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
||||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
||||||
* have any questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.nio.fs;
|
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base implementation of FileStoreSpaceAttributeView
|
|
||||||
*/
|
|
||||||
|
|
||||||
abstract class AbstractFileStoreSpaceAttributeView
|
|
||||||
implements FileStoreSpaceAttributeView
|
|
||||||
{
|
|
||||||
private static final String TOTAL_SPACE_NAME = "totalSpace";
|
|
||||||
private static final String USABLE_SPACE_NAME = "usableSpace";
|
|
||||||
private static final String UNALLOCATED_SPACE_NAME = "unallocatedSpace";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String name() {
|
|
||||||
return "space";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Object getAttribute(String attribute) throws IOException {
|
|
||||||
FileStoreSpaceAttributes attrs = readAttributes();
|
|
||||||
if (attribute.equals(TOTAL_SPACE_NAME))
|
|
||||||
return attrs.totalSpace();
|
|
||||||
if (attribute.equals(USABLE_SPACE_NAME))
|
|
||||||
return attrs.usableSpace();
|
|
||||||
if (attribute.equals(UNALLOCATED_SPACE_NAME))
|
|
||||||
return attrs.unallocatedSpace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void setAttribute(String attribute, Object value)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (attribute == null || value == null)
|
|
||||||
throw new NullPointerException();
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Map<String,?> readAttributes(String first, String[] rest)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
boolean total = false;
|
|
||||||
boolean usable = false;
|
|
||||||
boolean unallocated = false;
|
|
||||||
|
|
||||||
if (first.equals(TOTAL_SPACE_NAME)) total = true;
|
|
||||||
else if (first.equals(USABLE_SPACE_NAME)) usable = true;
|
|
||||||
else if (first.equals(UNALLOCATED_SPACE_NAME)) unallocated = true;
|
|
||||||
else if (first.equals("*")) {
|
|
||||||
total = true;
|
|
||||||
usable = true;
|
|
||||||
unallocated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!total || !usable || !unallocated) {
|
|
||||||
for (String attribute: rest) {
|
|
||||||
if (attribute.equals("*")) {
|
|
||||||
total = true;
|
|
||||||
usable = true;
|
|
||||||
unallocated = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (attribute.equals(TOTAL_SPACE_NAME)) {
|
|
||||||
total = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (attribute.equals(USABLE_SPACE_NAME)) {
|
|
||||||
usable = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (attribute.equals(UNALLOCATED_SPACE_NAME)) {
|
|
||||||
unallocated = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileStoreSpaceAttributes attrs = readAttributes();
|
|
||||||
Map<String,Object> result = new HashMap<String,Object>(2);
|
|
||||||
if (total)
|
|
||||||
result.put(TOTAL_SPACE_NAME, attrs.totalSpace());
|
|
||||||
if (usable)
|
|
||||||
result.put(USABLE_SPACE_NAME, attrs.usableSpace());
|
|
||||||
if (unallocated)
|
|
||||||
result.put(UNALLOCATED_SPACE_NAME, attrs.unallocatedSpace());
|
|
||||||
return Collections.unmodifiableMap(result);
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,8 +27,8 @@ package sun.nio.fs;
|
|||||||
|
|
||||||
import java.nio.file.FileRef;
|
import java.nio.file.FileRef;
|
||||||
import java.nio.file.spi.FileTypeDetector;
|
import java.nio.file.spi.FileTypeDetector;
|
||||||
|
import java.util.Locale;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import sun.nio.fs.MimeType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of FileTypeDetector
|
* Base implementation of FileTypeDetector
|
||||||
@ -42,23 +42,15 @@ public abstract class AbstractFileTypeDetector
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the implProbeContentType method to guess the file's content type,
|
* Invokes the appropriate probe method to guess a file's content type,
|
||||||
* and this validates that the content type's syntax is valid.
|
* and checks that the content type's syntax is valid.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final String probeContentType(FileRef file) throws IOException {
|
public final String probeContentType(FileRef file) throws IOException {
|
||||||
if (file == null)
|
if (file == null)
|
||||||
throw new NullPointerException("'file' is null");
|
throw new NullPointerException("'file' is null");
|
||||||
String result = implProbeContentType(file);
|
String result = implProbeContentType(file);
|
||||||
if (result != null) {
|
return (result == null) ? null : parse(result);
|
||||||
// check the content type
|
|
||||||
try {
|
|
||||||
MimeType.parse(result);
|
|
||||||
} catch (IllegalArgumentException ignore) {
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,4 +58,54 @@ public abstract class AbstractFileTypeDetector
|
|||||||
*/
|
*/
|
||||||
protected abstract String implProbeContentType(FileRef file)
|
protected abstract String implProbeContentType(FileRef file)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a candidate content type into its type and subtype, returning
|
||||||
|
* null if either token is invalid.
|
||||||
|
*/
|
||||||
|
private static String parse(String s) {
|
||||||
|
int slash = s.indexOf('/');
|
||||||
|
int semicolon = s.indexOf(';');
|
||||||
|
if (slash < 0)
|
||||||
|
return null; // no subtype
|
||||||
|
String type = s.substring(0, slash).trim().toLowerCase(Locale.ENGLISH);
|
||||||
|
if (!isValidToken(type))
|
||||||
|
return null; // invalid type
|
||||||
|
String subtype = (semicolon < 0) ? s.substring(slash + 1) :
|
||||||
|
s.substring(slash + 1, semicolon);
|
||||||
|
subtype = subtype.trim().toLowerCase(Locale.ENGLISH);
|
||||||
|
if (!isValidToken(subtype))
|
||||||
|
return null; // invalid subtype
|
||||||
|
StringBuilder sb = new StringBuilder(type.length() + subtype.length() + 1);
|
||||||
|
sb.append(type);
|
||||||
|
sb.append('/');
|
||||||
|
sb.append(subtype);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special characters
|
||||||
|
*/
|
||||||
|
private static final String TSPECIALS = "()<>@,;:/[]?=\\\"";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the character is a valid token character.
|
||||||
|
*/
|
||||||
|
private static boolean isTokenChar(char c) {
|
||||||
|
return (c > 040) && (c < 0177) && (TSPECIALS.indexOf(c) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given string is a legal type or subtype.
|
||||||
|
*/
|
||||||
|
private static boolean isValidToken(String s) {
|
||||||
|
int len = s.length();
|
||||||
|
if (len == 0)
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (!isTokenChar(s.charAt(i)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
404
jdk/src/share/classes/sun/nio/fs/AbstractPath.java
Normal file
404
jdk/src/share/classes/sun/nio/fs/AbstractPath.java
Normal file
@ -0,0 +1,404 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007-2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base implementation class for a {@code Path}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class AbstractPath extends 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void deleteIfExists() throws IOException {
|
||||||
|
implDelete(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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>() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(Path entry) {
|
||||||
|
return matcher.matches(entry.getName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return newDirectoryStream(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean exists() {
|
||||||
|
try {
|
||||||
|
checkAccess();
|
||||||
|
return true;
|
||||||
|
} catch (IOException x) {
|
||||||
|
// unable to determine if file exists
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 IllegalArgumentException("'" + option +
|
||||||
|
"' is not a valid 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");
|
||||||
|
|
||||||
|
// delete target file
|
||||||
|
if (opts.replaceExisting)
|
||||||
|
target.deleteIfExists();
|
||||||
|
|
||||||
|
// 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, 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(","));
|
||||||
|
}
|
||||||
|
}
|
@ -31,11 +31,11 @@ import java.io.IOException;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of NamedAttributeView
|
* Base implementation of UserDefinedAttributeView
|
||||||
*/
|
*/
|
||||||
|
|
||||||
abstract class AbstractUserDefinedFileAttributeView
|
abstract class AbstractUserDefinedFileAttributeView
|
||||||
implements UserDefinedFileAttributeView
|
implements UserDefinedFileAttributeView, DynamicFileAttributeView
|
||||||
{
|
{
|
||||||
protected AbstractUserDefinedFileAttributeView() { }
|
protected AbstractUserDefinedFileAttributeView() { }
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ abstract class AbstractUserDefinedFileAttributeView
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String name() {
|
public final String name() {
|
||||||
return "xattr";
|
return "user";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -70,6 +70,7 @@ abstract class AbstractUserDefinedFileAttributeView
|
|||||||
throw e;
|
throw e;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] buf = new byte[size];
|
byte[] buf = new byte[size];
|
||||||
int n = read(attribute, ByteBuffer.wrap(buf));
|
int n = read(attribute, ByteBuffer.wrap(buf));
|
||||||
return (n == size) ? buf : Arrays.copyOf(buf, n);
|
return (n == size) ? buf : Arrays.copyOf(buf, n);
|
||||||
@ -89,27 +90,20 @@ abstract class AbstractUserDefinedFileAttributeView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Map<String,?> readAttributes(String first, String... rest)
|
public final Map<String,?> readAttributes(String[] attributes)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// names of attributes to return
|
// names of attributes to return
|
||||||
List<String> names = new ArrayList<String>();
|
List<String> names = new ArrayList<String>();
|
||||||
|
|
||||||
boolean readAll = false;
|
for (String name: attributes) {
|
||||||
if (first.equals("*")) {
|
|
||||||
readAll = true;
|
|
||||||
} else {
|
|
||||||
names.add(first);
|
|
||||||
}
|
|
||||||
for (String name: rest) {
|
|
||||||
if (name.equals("*")) {
|
if (name.equals("*")) {
|
||||||
readAll = true;
|
names = list();
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
names.add(name);
|
names.add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (readAll)
|
|
||||||
names = list();
|
|
||||||
|
|
||||||
// read each value and return in map
|
// read each value and return in map
|
||||||
Map<String,Object> result = new HashMap<String,Object>();
|
Map<String,Object> result = new HashMap<String,Object>();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,42 +23,29 @@
|
|||||||
* have any questions.
|
* have any questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package java.nio.file;
|
package sun.nio.fs;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface that is implemented by objects that operate on a file. An
|
* Implemented by FileAttributeView implementations to support access to
|
||||||
* implementation of this interface is provided to the {@link Files#withDirectory
|
* attributes by names.
|
||||||
* withDirectory} utility method so that the file action is {@link #invoke
|
|
||||||
* invoked} for all accepted entries in the directory, after which, the directory
|
|
||||||
* is automatically closed.
|
|
||||||
*
|
|
||||||
* <p> <b>Usage Example:</b>
|
|
||||||
* Suppose we require to perform a task on all class files in a directory:
|
|
||||||
* <pre>
|
|
||||||
* Path dir = ...
|
|
||||||
* Files.withDirectory(dir, "*.class", new FileAction<Path>() {
|
|
||||||
* public void invoke(Path entry) {
|
|
||||||
* :
|
|
||||||
* }
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> the type of file reference
|
|
||||||
*
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface FileAction<T extends FileRef> {
|
interface DynamicFileAttributeView {
|
||||||
/**
|
/**
|
||||||
* Invoked for a file.
|
* Reads the value of an attribute.
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* the file
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
* if the block terminates due an uncaught I/O exception
|
|
||||||
*/
|
*/
|
||||||
void invoke(T file) throws IOException;
|
Object getAttribute(String attribute) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets/updates the value of an attribute.
|
||||||
|
*/
|
||||||
|
void setAttribute(String attribute, Object value) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a set of file attributes as a bulk operation.
|
||||||
|
*/
|
||||||
|
Map<String,?> readAttributes(String[] attributes) throws IOException;
|
||||||
}
|
}
|
@ -34,7 +34,9 @@ import java.io.IOException;
|
|||||||
* PosixFileAttributeView or AclFileAttributeView object.
|
* PosixFileAttributeView or AclFileAttributeView object.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final class FileOwnerAttributeViewImpl implements FileOwnerAttributeView {
|
final class FileOwnerAttributeViewImpl
|
||||||
|
implements FileOwnerAttributeView, DynamicFileAttributeView
|
||||||
|
{
|
||||||
private static final String OWNER_NAME = "owner";
|
private static final String OWNER_NAME = "owner";
|
||||||
|
|
||||||
private final FileAttributeView view;
|
private final FileAttributeView view;
|
||||||
@ -70,20 +72,16 @@ final class FileOwnerAttributeViewImpl implements FileOwnerAttributeView {
|
|||||||
setOwner((UserPrincipal)value);
|
setOwner((UserPrincipal)value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("'" + name() + ":" +
|
||||||
|
attribute + "' not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,?> readAttributes(String first, String[] rest) throws IOException {
|
public Map<String,?> readAttributes(String[] attributes) throws IOException {
|
||||||
Map<String,Object> result = new HashMap<String,Object>();
|
Map<String,Object> result = new HashMap<String,Object>();
|
||||||
if (first.equals("*") || first.equals(OWNER_NAME)) {
|
for (String attribute: attributes) {
|
||||||
result.put(OWNER_NAME, getOwner());
|
if (attribute.equals("*") || attribute.equals(OWNER_NAME)) {
|
||||||
} else {
|
result.put(OWNER_NAME, getOwner());
|
||||||
for (String attribute: rest) {
|
|
||||||
if (attribute.equals("*") || attribute.equals(OWNER_NAME)) {
|
|
||||||
result.put(OWNER_NAME, getOwner());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
||||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
||||||
* have any questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.nio.fs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a MIME type for the purposes of validation and matching. For
|
|
||||||
* now this class is implemented using the javax.activation.MimeType class but
|
|
||||||
* this dependency can easily be eliminated when required.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MimeType {
|
|
||||||
private final javax.activation.MimeType type;
|
|
||||||
|
|
||||||
private MimeType(javax.activation.MimeType type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the given string as a MIME type.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* If the string is not a valid MIME type
|
|
||||||
*/
|
|
||||||
public static MimeType parse(String type) {
|
|
||||||
try {
|
|
||||||
return new MimeType(new javax.activation.MimeType(type));
|
|
||||||
} catch (javax.activation.MimeTypeParseException x) {
|
|
||||||
throw new IllegalArgumentException(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns {@code true} if this MIME type has parameters.
|
|
||||||
*/
|
|
||||||
public boolean hasParameters() {
|
|
||||||
return !type.getParameters().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches this MIME type against a given MIME type. This method returns
|
|
||||||
* true if the given string is a MIME type and it matches this type.
|
|
||||||
*/
|
|
||||||
public boolean match(String other) {
|
|
||||||
try {
|
|
||||||
return type.match(other);
|
|
||||||
} catch (javax.activation.MimeTypeParseException x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -265,7 +265,7 @@ class PollingWatchService
|
|||||||
// don't follow links
|
// don't follow links
|
||||||
long lastModified = Attributes
|
long lastModified = Attributes
|
||||||
.readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
|
.readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
|
||||||
.lastModifiedTime();
|
.lastModifiedTime().toMillis();
|
||||||
entries.put(entry.getName(),
|
entries.put(entry.getName(),
|
||||||
new CacheEntry(lastModified, tickCount));
|
new CacheEntry(lastModified, tickCount));
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ class PollingWatchService
|
|||||||
try {
|
try {
|
||||||
lastModified = Attributes
|
lastModified = Attributes
|
||||||
.readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
|
.readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
|
||||||
.lastModifiedTime();
|
.lastModifiedTime().toMillis();
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
// unable to get attributes of entry. If file has just
|
// unable to get attributes of entry. If file has just
|
||||||
// been deleted then we'll report it as deleted on the
|
// been deleted then we'll report it as deleted on the
|
||||||
|
59
jdk/src/share/classes/sun/nio/fs/Util.java
Normal file
59
jdk/src/share/classes/sun/nio/fs/Util.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.nio.fs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Util {
|
||||||
|
private Util() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a string around the given character. The array returned by this
|
||||||
|
* method contains each substring that is terminated by the character. Use
|
||||||
|
* for simple string spilting cases when needing to avoid loading regex.
|
||||||
|
*/
|
||||||
|
static String[] split(String s, char c) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i=0; i<s.length(); i++) {
|
||||||
|
if (s.charAt(i) == c)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
String[] result = new String[count+1];
|
||||||
|
int n = 0;
|
||||||
|
int last = 0;
|
||||||
|
for (int i=0; i<s.length(); i++) {
|
||||||
|
if (s.charAt(i) == c) {
|
||||||
|
result[n++] = s.substring(last, i);
|
||||||
|
last = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[n] = s.substring(last, s.length());
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -127,8 +127,7 @@ public class Copy {
|
|||||||
Path newdir = target.resolve(source.relativize(dir));
|
Path newdir = target.resolve(source.relativize(dir));
|
||||||
try {
|
try {
|
||||||
BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir);
|
BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir);
|
||||||
Attributes.setLastModifiedTime(newdir,
|
Attributes.setLastModifiedTime(newdir, attrs.lastModifiedTime());
|
||||||
attrs.lastModifiedTime(), attrs.resolution());
|
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
|
System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ public class Xdd {
|
|||||||
|
|
||||||
// check that user defined attributes are supported by the file system
|
// check that user defined attributes are supported by the file system
|
||||||
FileStore store = file.getFileStore();
|
FileStore store = file.getFileStore();
|
||||||
if (!store.supportsFileAttributeView("xattr")) {
|
if (!store.supportsFileAttributeView("user")) {
|
||||||
System.err.format("UserDefinedFileAttributeView not supported on %s\n", store);
|
System.err.format("UserDefinedFileAttributeView not supported on %s\n", store);
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
|
|
||||||
|
@ -26,8 +26,7 @@
|
|||||||
package sun.nio.fs;
|
package sun.nio.fs;
|
||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.util.*;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
@ -104,10 +103,10 @@ class LinuxDosFileAttributeView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,?> readAttributes(String first, String[] rest)
|
public Map<String,?> readAttributes(String[] attributes)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
AttributesBuilder builder = AttributesBuilder.create(first, rest);
|
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||||
DosFileAttributes attrs = readAttributes();
|
DosFileAttributes attrs = readAttributes();
|
||||||
addBasicAttributesToBuilder(attrs, builder);
|
addBasicAttributesToBuilder(attrs, builder);
|
||||||
if (builder.match(READONLY_NAME))
|
if (builder.match(READONLY_NAME))
|
||||||
@ -132,22 +131,18 @@ class LinuxDosFileAttributeView
|
|||||||
|
|
||||||
return new DosFileAttributes() {
|
return new DosFileAttributes() {
|
||||||
@Override
|
@Override
|
||||||
public long lastModifiedTime() {
|
public FileTime lastModifiedTime() {
|
||||||
return attrs.lastModifiedTime();
|
return attrs.lastModifiedTime();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long lastAccessTime() {
|
public FileTime lastAccessTime() {
|
||||||
return attrs.lastAccessTime();
|
return attrs.lastAccessTime();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long creationTime() {
|
public FileTime creationTime() {
|
||||||
return attrs.creationTime();
|
return attrs.creationTime();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public TimeUnit resolution() {
|
|
||||||
return attrs.resolution();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean isRegularFile() {
|
public boolean isRegularFile() {
|
||||||
return attrs.isRegularFile();
|
return attrs.isRegularFile();
|
||||||
}
|
}
|
||||||
@ -168,10 +163,6 @@ class LinuxDosFileAttributeView
|
|||||||
return attrs.size();
|
return attrs.size();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int linkCount() {
|
|
||||||
return attrs.linkCount();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Object fileKey() {
|
public Object fileKey() {
|
||||||
return attrs.fileKey();
|
return attrs.fileKey();
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class LinuxFileStore
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
UnixMountEntry findMountEntry() throws IOException {
|
UnixMountEntry findMountEntry() throws IOException {
|
||||||
UnixFileSystem fs = file().getFileSystem();
|
LinuxFileSystem fs = (LinuxFileSystem)file().getFileSystem();
|
||||||
|
|
||||||
// step 1: get realpath
|
// step 1: get realpath
|
||||||
UnixPath path = null;
|
UnixPath path = null;
|
||||||
@ -79,14 +79,15 @@ class LinuxFileStore
|
|||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 3: lookup mounted file systems
|
// step 3: lookup mounted file systems (use /proc/mounts to ensure we
|
||||||
|
// find the file system even when not in /etc/mtab)
|
||||||
byte[] dir = path.asByteArray();
|
byte[] dir = path.asByteArray();
|
||||||
for (UnixMountEntry entry: fs.getMountEntries()) {
|
for (UnixMountEntry entry: fs.getMountEntries("/proc/mounts")) {
|
||||||
if (Arrays.equals(dir, entry.dir()))
|
if (Arrays.equals(dir, entry.dir()))
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IOException("Mount point not found in mtab");
|
throw new IOException("Mount point not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if extended attributes enabled on file system where given
|
// returns true if extended attributes enabled on file system where given
|
||||||
@ -113,9 +114,9 @@ class LinuxFileStore
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsFileAttributeView(String name) {
|
public boolean supportsFileAttributeView(String name) {
|
||||||
// support DosFileAttributeView and NamedAttributeView if extended
|
// support DosFileAttributeView and UserDefinedAttributeView if extended
|
||||||
// attributes enabled
|
// attributes enabled
|
||||||
if (name.equals("dos") || name.equals("xattr")) {
|
if (name.equals("dos") || name.equals("user")) {
|
||||||
// lookup fstypes.properties
|
// lookup fstypes.properties
|
||||||
FeatureStatus status = checkIfFeaturePresent("user_xattr");
|
FeatureStatus status = checkIfFeaturePresent("user_xattr");
|
||||||
if (status == FeatureStatus.PRESENT)
|
if (status == FeatureStatus.PRESENT)
|
||||||
|
@ -39,7 +39,6 @@ import static sun.nio.fs.LinuxNativeDispatcher.*;
|
|||||||
|
|
||||||
class LinuxFileSystem extends UnixFileSystem {
|
class LinuxFileSystem extends UnixFileSystem {
|
||||||
private final boolean hasInotify;
|
private final boolean hasInotify;
|
||||||
private final boolean hasAtSysCalls;
|
|
||||||
|
|
||||||
LinuxFileSystem(UnixFileSystemProvider provider, String dir) {
|
LinuxFileSystem(UnixFileSystemProvider provider, String dir) {
|
||||||
super(provider, dir);
|
super(provider, dir);
|
||||||
@ -47,14 +46,14 @@ class LinuxFileSystem extends UnixFileSystem {
|
|||||||
// assume X.Y[-Z] format
|
// assume X.Y[-Z] format
|
||||||
String osversion = AccessController
|
String osversion = AccessController
|
||||||
.doPrivileged(new GetPropertyAction("os.version"));
|
.doPrivileged(new GetPropertyAction("os.version"));
|
||||||
String[] vers = osversion.split("\\.", 0);
|
String[] vers = Util.split(osversion, '.');
|
||||||
assert vers.length >= 2;
|
assert vers.length >= 2;
|
||||||
|
|
||||||
int majorVersion = Integer.parseInt(vers[0]);
|
int majorVersion = Integer.parseInt(vers[0]);
|
||||||
int minorVersion = Integer.parseInt(vers[1]);
|
int minorVersion = Integer.parseInt(vers[1]);
|
||||||
int microVersion = 0;
|
int microVersion = 0;
|
||||||
if (vers.length > 2) {
|
if (vers.length > 2) {
|
||||||
String[] microVers = vers[2].split("-", 0);
|
String[] microVers = Util.split(vers[2], '-');
|
||||||
microVersion = (microVers.length > 0) ?
|
microVersion = (microVers.length > 0) ?
|
||||||
Integer.parseInt(microVers[0]) : 0;
|
Integer.parseInt(microVers[0]) : 0;
|
||||||
}
|
}
|
||||||
@ -63,11 +62,6 @@ class LinuxFileSystem extends UnixFileSystem {
|
|||||||
this.hasInotify = ((majorVersion > 2) ||
|
this.hasInotify = ((majorVersion > 2) ||
|
||||||
(majorVersion == 2 && minorVersion > 6) ||
|
(majorVersion == 2 && minorVersion > 6) ||
|
||||||
((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13)));
|
((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13)));
|
||||||
|
|
||||||
// openat etc. available since 2.6.16
|
|
||||||
this.hasAtSysCalls = ((majorVersion > 2) ||
|
|
||||||
(majorVersion == 2 && minorVersion > 6) ||
|
|
||||||
((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 16)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -97,13 +91,13 @@ class LinuxFileSystem extends UnixFileSystem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public FileAttributeView newFileAttributeView(String name,
|
public DynamicFileAttributeView newFileAttributeView(String name,
|
||||||
UnixPath file,
|
UnixPath file,
|
||||||
LinkOption... options)
|
LinkOption... options)
|
||||||
{
|
{
|
||||||
if (name.equals("dos"))
|
if (name.equals("dos"))
|
||||||
return new LinuxDosFileAttributeView(file, followLinks(options));
|
return new LinuxDosFileAttributeView(file, followLinks(options));
|
||||||
if (name.equals("xattr"))
|
if (name.equals("user"))
|
||||||
return new LinuxUserDefinedFileAttributeView(file, followLinks(options));
|
return new LinuxUserDefinedFileAttributeView(file, followLinks(options));
|
||||||
return super.newFileAttributeView(name, file, options);
|
return super.newFileAttributeView(name, file, options);
|
||||||
}
|
}
|
||||||
@ -117,7 +111,7 @@ class LinuxFileSystem extends UnixFileSystem {
|
|||||||
result.addAll(UnixFileSystem.standardFileAttributeViews());
|
result.addAll(UnixFileSystem.standardFileAttributeViews());
|
||||||
// additional Linux-specific views
|
// additional Linux-specific views
|
||||||
result.add("dos");
|
result.add("dos");
|
||||||
result.add("xattr");
|
result.add("user");
|
||||||
return Collections.unmodifiableSet(result);
|
return Collections.unmodifiableSet(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,19 +126,13 @@ class LinuxFileSystem extends UnixFileSystem {
|
|||||||
LinuxUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
|
LinuxUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean supportsSecureDirectoryStreams() {
|
|
||||||
return hasAtSysCalls;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns object to iterate over entries in /etc/mtab
|
* Returns object to iterate over the mount entries in the given fstab file.
|
||||||
*/
|
*/
|
||||||
@Override
|
Iterable<UnixMountEntry> getMountEntries(String fstab) {
|
||||||
Iterable<UnixMountEntry> getMountEntries() {
|
|
||||||
ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
|
ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
|
||||||
try {
|
try {
|
||||||
long fp = setmntent("/etc/mtab".getBytes(), "r".getBytes());
|
long fp = setmntent(fstab.getBytes(), "r".getBytes());
|
||||||
try {
|
try {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
UnixMountEntry entry = new UnixMountEntry();
|
UnixMountEntry entry = new UnixMountEntry();
|
||||||
@ -163,6 +151,14 @@ class LinuxFileSystem extends UnixFileSystem {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns object to iterate over the mount entries in /etc/mtab
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
Iterable<UnixMountEntry> getMountEntries() {
|
||||||
|
return getMountEntries("/etc/mtab");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
FileStore getFileStore(UnixPath path) throws IOException {
|
FileStore getFileStore(UnixPath path) throws IOException {
|
||||||
return new LinuxFileStore(path);
|
return new LinuxFileStore(path);
|
||||||
|
@ -98,7 +98,7 @@ class SolarisAclFileAttributeView
|
|||||||
|
|
||||||
// map UserPrincipal to uid and flags
|
// map UserPrincipal to uid and flags
|
||||||
UserPrincipal who = ace.principal();
|
UserPrincipal who = ace.principal();
|
||||||
if (!(who instanceof UnixUserPrincipals))
|
if (!(who instanceof UnixUserPrincipals.User))
|
||||||
throw new ProviderMismatchException();
|
throw new ProviderMismatchException();
|
||||||
UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
|
UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
|
||||||
int uid;
|
int uid;
|
||||||
|
@ -83,7 +83,7 @@ class SolarisFileStore
|
|||||||
// AclFileAttributeView available on ZFS
|
// AclFileAttributeView available on ZFS
|
||||||
return (type().equals("zfs"));
|
return (type().equals("zfs"));
|
||||||
}
|
}
|
||||||
if (name.equals("xattr")) {
|
if (name.equals("user")) {
|
||||||
// lookup fstypes.properties
|
// lookup fstypes.properties
|
||||||
FeatureStatus status = checkIfFeaturePresent("xattr");
|
FeatureStatus status = checkIfFeaturePresent("xattr");
|
||||||
if (status == FeatureStatus.PRESENT)
|
if (status == FeatureStatus.PRESENT)
|
||||||
|
@ -46,7 +46,7 @@ class SolarisFileSystem extends UnixFileSystem {
|
|||||||
// check os.version
|
// check os.version
|
||||||
String osversion = AccessController
|
String osversion = AccessController
|
||||||
.doPrivileged(new GetPropertyAction("os.version"));
|
.doPrivileged(new GetPropertyAction("os.version"));
|
||||||
String[] vers = osversion.split("\\.", 0);
|
String[] vers = Util.split(osversion, '.');
|
||||||
assert vers.length >= 2;
|
assert vers.length >= 2;
|
||||||
int majorVersion = Integer.parseInt(vers[0]);
|
int majorVersion = Integer.parseInt(vers[0]);
|
||||||
int minorVersion = Integer.parseInt(vers[1]);
|
int minorVersion = Integer.parseInt(vers[1]);
|
||||||
@ -85,13 +85,13 @@ class SolarisFileSystem extends UnixFileSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FileAttributeView newFileAttributeView(String name,
|
protected DynamicFileAttributeView newFileAttributeView(String name,
|
||||||
UnixPath file,
|
UnixPath file,
|
||||||
LinkOption... options)
|
LinkOption... options)
|
||||||
{
|
{
|
||||||
if (name.equals("acl"))
|
if (name.equals("acl"))
|
||||||
return new SolarisAclFileAttributeView(file, followLinks(options));
|
return new SolarisAclFileAttributeView(file, followLinks(options));
|
||||||
if (name.equals("xattr"))
|
if (name.equals("user"))
|
||||||
return new SolarisUserDefinedFileAttributeView(file, followLinks(options));
|
return new SolarisUserDefinedFileAttributeView(file, followLinks(options));
|
||||||
return super.newFileAttributeView(name, file, options);
|
return super.newFileAttributeView(name, file, options);
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ class SolarisFileSystem extends UnixFileSystem {
|
|||||||
result.addAll(UnixFileSystem.standardFileAttributeViews());
|
result.addAll(UnixFileSystem.standardFileAttributeViews());
|
||||||
// additional Solaris-specific views
|
// additional Solaris-specific views
|
||||||
result.add("acl");
|
result.add("acl");
|
||||||
result.add("xattr");
|
result.add("user");
|
||||||
return Collections.unmodifiableSet(result);
|
return Collections.unmodifiableSet(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,11 +121,6 @@ class SolarisFileSystem extends UnixFileSystem {
|
|||||||
// TDB: copy ACL from source to target
|
// TDB: copy ACL from source to target
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean supportsSecureDirectoryStreams() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns object to iterate over entries in /etc/mnttab
|
* Returns object to iterate over entries in /etc/mnttab
|
||||||
*/
|
*/
|
||||||
|
@ -49,13 +49,13 @@ class UnixChannelFactory {
|
|||||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||||
|
|
||||||
private UnixChannelFactory() {
|
protected UnixChannelFactory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the flags from a user-supplied set of open options.
|
* Represents the flags from a user-supplied set of open options.
|
||||||
*/
|
*/
|
||||||
private static class Flags {
|
protected static class Flags {
|
||||||
boolean read;
|
boolean read;
|
||||||
boolean write;
|
boolean write;
|
||||||
boolean append;
|
boolean append;
|
||||||
@ -179,11 +179,11 @@ class UnixChannelFactory {
|
|||||||
* Opens file based on parameters and options, returning a FileDescriptor
|
* Opens file based on parameters and options, returning a FileDescriptor
|
||||||
* encapsulating the handle to the open file.
|
* encapsulating the handle to the open file.
|
||||||
*/
|
*/
|
||||||
static FileDescriptor open(int dfd,
|
protected static FileDescriptor open(int dfd,
|
||||||
UnixPath path,
|
UnixPath path,
|
||||||
String pathForPermissionCheck,
|
String pathForPermissionCheck,
|
||||||
Flags flags,
|
Flags flags,
|
||||||
int mode)
|
int mode)
|
||||||
throws UnixException
|
throws UnixException
|
||||||
{
|
{
|
||||||
// map to oflags
|
// map to oflags
|
||||||
|
@ -30,6 +30,7 @@ import java.io.IOException;
|
|||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import com.sun.nio.file.ExtendedCopyOption;
|
import com.sun.nio.file.ExtendedCopyOption;
|
||||||
|
|
||||||
import static sun.nio.fs.UnixNativeDispatcher.*;
|
import static sun.nio.fs.UnixNativeDispatcher.*;
|
||||||
@ -189,11 +190,13 @@ class UnixCopyFile {
|
|||||||
if (flags.copyBasicAttributes) {
|
if (flags.copyBasicAttributes) {
|
||||||
try {
|
try {
|
||||||
if (dfd >= 0) {
|
if (dfd >= 0) {
|
||||||
futimes(dfd, attrs.lastAccessTime(),
|
futimes(dfd,
|
||||||
attrs.lastModifiedTime());
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||||||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||||||
} else {
|
} else {
|
||||||
utimes(target, attrs.lastAccessTime(),
|
utimes(target,
|
||||||
attrs.lastModifiedTime());
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||||||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||||||
}
|
}
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
// unable to set times
|
// unable to set times
|
||||||
@ -266,7 +269,9 @@ class UnixCopyFile {
|
|||||||
// copy time attributes
|
// copy time attributes
|
||||||
if (flags.copyBasicAttributes) {
|
if (flags.copyBasicAttributes) {
|
||||||
try {
|
try {
|
||||||
futimes(fo, attrs.lastAccessTime(), attrs.lastModifiedTime());
|
futimes(fo,
|
||||||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||||||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
if (flags.failIfUnableToCopyBasic)
|
if (flags.failIfUnableToCopyBasic)
|
||||||
x.rethrowAsIOException(target);
|
x.rethrowAsIOException(target);
|
||||||
@ -341,7 +346,9 @@ class UnixCopyFile {
|
|||||||
}
|
}
|
||||||
if (flags.copyBasicAttributes) {
|
if (flags.copyBasicAttributes) {
|
||||||
try {
|
try {
|
||||||
utimes(target, attrs.lastAccessTime(), attrs.lastModifiedTime());
|
utimes(target,
|
||||||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||||||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
if (flags.failIfUnableToCopyBasic)
|
if (flags.failIfUnableToCopyBasic)
|
||||||
x.rethrowAsIOException(target);
|
x.rethrowAsIOException(target);
|
||||||
|
@ -194,8 +194,11 @@ class UnixDirectoryStream
|
|||||||
Path entry = dir.resolve(nameAsBytes);
|
Path entry = dir.resolve(nameAsBytes);
|
||||||
|
|
||||||
// return entry if no filter or filter accepts it
|
// return entry if no filter or filter accepts it
|
||||||
if (filter.accept(entry)) {
|
try {
|
||||||
return entry;
|
if (filter == null || filter.accept(entry))
|
||||||
|
return entry;
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throwAsConcurrentModificationException(ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,7 +251,7 @@ class UnixDirectoryStream
|
|||||||
((UnixSecureDirectoryStream)stream)
|
((UnixSecureDirectoryStream)stream)
|
||||||
.implDelete(entry.getName(), false, 0);
|
.implDelete(entry.getName(), false, 0);
|
||||||
} else {
|
} else {
|
||||||
entry.delete(true);
|
entry.delete();
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throwAsConcurrentModificationException(ioe);
|
throwAsConcurrentModificationException(ioe);
|
||||||
|
@ -56,11 +56,11 @@ class UnixFileAttributeViews {
|
|||||||
return null; // keep compiler happy
|
return null; // keep compiler happy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTimes(Long lastModifiedTime,
|
public void setTimes(FileTime lastModifiedTime,
|
||||||
Long lastAccessTime,
|
FileTime lastAccessTime,
|
||||||
Long createTime,
|
FileTime createTime) throws IOException
|
||||||
TimeUnit unit) throws IOException
|
|
||||||
{
|
{
|
||||||
// null => don't change
|
// null => don't change
|
||||||
if (lastModifiedTime == null && lastAccessTime == null) {
|
if (lastModifiedTime == null && lastAccessTime == null) {
|
||||||
@ -68,53 +68,49 @@ class UnixFileAttributeViews {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// permission check
|
||||||
file.checkWrite();
|
file.checkWrite();
|
||||||
|
|
||||||
int fd = file.openForAttributeAccess(followLinks);
|
int fd = file.openForAttributeAccess(followLinks);
|
||||||
try {
|
try {
|
||||||
UnixFileAttributes attrs = null;
|
|
||||||
|
|
||||||
// if not changing both attributes then need existing attributes
|
// if not changing both attributes then need existing attributes
|
||||||
if (lastModifiedTime == null || lastAccessTime == null) {
|
if (lastModifiedTime == null || lastAccessTime == null) {
|
||||||
try {
|
try {
|
||||||
attrs = UnixFileAttributes.get(fd);
|
UnixFileAttributes attrs = UnixFileAttributes.get(fd);
|
||||||
|
if (lastModifiedTime == null)
|
||||||
|
lastModifiedTime = attrs.lastModifiedTime();
|
||||||
|
if (lastAccessTime == null)
|
||||||
|
lastAccessTime = attrs.lastAccessTime();
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
x.rethrowAsIOException(file);
|
x.rethrowAsIOException(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// modified time = existing, now, or new value
|
// uptime times
|
||||||
long modTime;
|
long modValue = lastModifiedTime.to(TimeUnit.MICROSECONDS);
|
||||||
if (lastModifiedTime == null) {
|
long accessValue= lastAccessTime.to(TimeUnit.MICROSECONDS);
|
||||||
modTime = attrs.lastModifiedTime();
|
|
||||||
} else {
|
|
||||||
if (lastModifiedTime >= 0L) {
|
|
||||||
modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit);
|
|
||||||
} else {
|
|
||||||
if (lastModifiedTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
modTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// access time = existing, now, or new value
|
|
||||||
long accTime;
|
|
||||||
if (lastAccessTime == null) {
|
|
||||||
accTime = attrs.lastAccessTime();
|
|
||||||
} else {
|
|
||||||
if (lastAccessTime >= 0L) {
|
|
||||||
accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit);
|
|
||||||
} else {
|
|
||||||
if (lastAccessTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
accTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
boolean retry = false;
|
||||||
try {
|
try {
|
||||||
futimes(fd, accTime, modTime);
|
futimes(fd, accessValue, modValue);
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
x.rethrowAsIOException(file);
|
// if futimes fails with EINVAL and one/both of the times is
|
||||||
|
// negative then we adjust the value to the epoch and retry.
|
||||||
|
if (x.errno() == UnixConstants.EINVAL &&
|
||||||
|
(modValue < 0L || accessValue < 0L)) {
|
||||||
|
retry = true;
|
||||||
|
} else {
|
||||||
|
x.rethrowAsIOException(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retry) {
|
||||||
|
if (modValue < 0L) modValue = 0L;
|
||||||
|
if (accessValue < 0L) accessValue= 0L;
|
||||||
|
try {
|
||||||
|
futimes(fd, accessValue, modValue);
|
||||||
|
} catch (UnixException x) {
|
||||||
|
x.rethrowAsIOException(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -199,10 +195,10 @@ class UnixFileAttributeViews {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,?> readAttributes(String first, String[] rest)
|
public Map<String,?> readAttributes(String[] attributes)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
AttributesBuilder builder = AttributesBuilder.create(first, rest);
|
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||||
PosixFileAttributes attrs = readAttributes();
|
PosixFileAttributes attrs = readAttributes();
|
||||||
addBasicAttributesToBuilder(attrs, builder);
|
addBasicAttributesToBuilder(attrs, builder);
|
||||||
addPosixAttributesToBuilder(attrs, builder);
|
addPosixAttributesToBuilder(attrs, builder);
|
||||||
@ -297,6 +293,7 @@ class UnixFileAttributeViews {
|
|||||||
private static final String INO_NAME = "ino";
|
private static final String INO_NAME = "ino";
|
||||||
private static final String DEV_NAME = "dev";
|
private static final String DEV_NAME = "dev";
|
||||||
private static final String RDEV_NAME = "rdev";
|
private static final String RDEV_NAME = "rdev";
|
||||||
|
private static final String NLINK_NAME = "nlink";
|
||||||
private static final String UID_NAME = "uid";
|
private static final String UID_NAME = "uid";
|
||||||
private static final String GID_NAME = "gid";
|
private static final String GID_NAME = "gid";
|
||||||
private static final String CTIME_NAME = "ctime";
|
private static final String CTIME_NAME = "ctime";
|
||||||
@ -320,6 +317,8 @@ class UnixFileAttributeViews {
|
|||||||
return readAttributes().dev();
|
return readAttributes().dev();
|
||||||
if (attribute.equals(RDEV_NAME))
|
if (attribute.equals(RDEV_NAME))
|
||||||
return readAttributes().rdev();
|
return readAttributes().rdev();
|
||||||
|
if (attribute.equals(NLINK_NAME))
|
||||||
|
return readAttributes().nlink();
|
||||||
if (attribute.equals(UID_NAME))
|
if (attribute.equals(UID_NAME))
|
||||||
return readAttributes().uid();
|
return readAttributes().uid();
|
||||||
if (attribute.equals(GID_NAME))
|
if (attribute.equals(GID_NAME))
|
||||||
@ -349,10 +348,10 @@ class UnixFileAttributeViews {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,?> readAttributes(String first, String[] rest)
|
public Map<String,?> readAttributes(String[] attributes)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
AttributesBuilder builder = AttributesBuilder.create(first, rest);
|
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||||
UnixFileAttributes attrs = readAttributes();
|
UnixFileAttributes attrs = readAttributes();
|
||||||
addBasicAttributesToBuilder(attrs, builder);
|
addBasicAttributesToBuilder(attrs, builder);
|
||||||
addPosixAttributesToBuilder(attrs, builder);
|
addPosixAttributesToBuilder(attrs, builder);
|
||||||
@ -364,6 +363,8 @@ class UnixFileAttributeViews {
|
|||||||
builder.add(DEV_NAME, attrs.dev());
|
builder.add(DEV_NAME, attrs.dev());
|
||||||
if (builder.match(RDEV_NAME))
|
if (builder.match(RDEV_NAME))
|
||||||
builder.add(RDEV_NAME, attrs.rdev());
|
builder.add(RDEV_NAME, attrs.rdev());
|
||||||
|
if (builder.match(NLINK_NAME))
|
||||||
|
builder.add(NLINK_NAME, attrs.nlink());
|
||||||
if (builder.match(UID_NAME))
|
if (builder.match(UID_NAME))
|
||||||
builder.add(UID_NAME, attrs.uid());
|
builder.add(UID_NAME, attrs.uid());
|
||||||
if (builder.match(GID_NAME))
|
if (builder.match(GID_NAME))
|
||||||
@ -374,19 +375,19 @@ class UnixFileAttributeViews {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BasicFileAttributeView createBasicView(UnixPath file, boolean followLinks) {
|
static Basic createBasicView(UnixPath file, boolean followLinks) {
|
||||||
return new Basic(file, followLinks);
|
return new Basic(file, followLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PosixFileAttributeView createPosixView(UnixPath file, boolean followLinks) {
|
static Posix createPosixView(UnixPath file, boolean followLinks) {
|
||||||
return new Posix(file, followLinks);
|
return new Posix(file, followLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PosixFileAttributeView createUnixView(UnixPath file, boolean followLinks) {
|
static Unix createUnixView(UnixPath file, boolean followLinks) {
|
||||||
return new Unix(file, followLinks);
|
return new Unix(file, followLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileOwnerAttributeView createOwnerView(UnixPath file, boolean followLinks) {
|
static FileOwnerAttributeViewImpl createOwnerView(UnixPath file, boolean followLinks) {
|
||||||
return new FileOwnerAttributeViewImpl(createPosixView(file, followLinks));
|
return new FileOwnerAttributeViewImpl(createPosixView(file, followLinks));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,9 +97,13 @@ class UnixFileAttributes
|
|||||||
long ino() { return st_ino; }
|
long ino() { return st_ino; }
|
||||||
long dev() { return st_dev; }
|
long dev() { return st_dev; }
|
||||||
long rdev() { return st_rdev; }
|
long rdev() { return st_rdev; }
|
||||||
|
int nlink() { return st_nlink; }
|
||||||
int uid() { return st_uid; }
|
int uid() { return st_uid; }
|
||||||
int gid() { return st_gid; }
|
int gid() { return st_gid; }
|
||||||
long ctime() { return st_ctime; }
|
|
||||||
|
FileTime ctime() {
|
||||||
|
return FileTime.from(st_ctime, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
boolean isDevice() {
|
boolean isDevice() {
|
||||||
int type = st_mode & UnixConstants.S_IFMT;
|
int type = st_mode & UnixConstants.S_IFMT;
|
||||||
@ -109,23 +113,18 @@ class UnixFileAttributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long lastModifiedTime() {
|
public FileTime lastModifiedTime() {
|
||||||
return st_mtime;
|
return FileTime.from(st_mtime, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long lastAccessTime() {
|
public FileTime lastAccessTime() {
|
||||||
return st_atime;
|
return FileTime.from(st_atime, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long creationTime() {
|
public FileTime creationTime() {
|
||||||
return -1L;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TimeUnit resolution() {
|
|
||||||
return TimeUnit.MILLISECONDS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -156,11 +155,6 @@ class UnixFileAttributes
|
|||||||
return st_size;
|
return st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int linkCount() {
|
|
||||||
return st_nlink;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnixFileKey fileKey() {
|
public UnixFileKey fileKey() {
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
@ -260,22 +254,18 @@ class UnixFileAttributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long lastModifiedTime() {
|
public FileTime lastModifiedTime() {
|
||||||
return attrs.lastModifiedTime();
|
return attrs.lastModifiedTime();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long lastAccessTime() {
|
public FileTime lastAccessTime() {
|
||||||
return attrs.lastAccessTime();
|
return attrs.lastAccessTime();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long creationTime() {
|
public FileTime creationTime() {
|
||||||
return attrs.creationTime();
|
return attrs.creationTime();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public TimeUnit resolution() {
|
|
||||||
return attrs.resolution();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean isRegularFile() {
|
public boolean isRegularFile() {
|
||||||
return attrs.isRegularFile();
|
return attrs.isRegularFile();
|
||||||
}
|
}
|
||||||
@ -296,10 +286,6 @@ class UnixFileAttributes
|
|||||||
return attrs.size();
|
return attrs.size();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int linkCount() {
|
|
||||||
return attrs.linkCount();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Object fileKey() {
|
public Object fileKey() {
|
||||||
return attrs.fileKey();
|
return attrs.fileKey();
|
||||||
}
|
}
|
||||||
|
@ -53,4 +53,15 @@ class UnixFileKey {
|
|||||||
UnixFileKey other = (UnixFileKey)obj;
|
UnixFileKey other = (UnixFileKey)obj;
|
||||||
return (this.st_dev == other.st_dev) && (this.st_ino == other.st_ino);
|
return (this.st_dev == other.st_dev) && (this.st_ino == other.st_ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("(dev=")
|
||||||
|
.append(Long.toHexString(st_dev))
|
||||||
|
.append(",ino=")
|
||||||
|
.append(st_ino)
|
||||||
|
.append(')');
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,10 +42,7 @@ class UnixFileModeAttribute {
|
|||||||
static final int TEMPFILE_PERMISSIONS =
|
static final int TEMPFILE_PERMISSIONS =
|
||||||
UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR;
|
UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR;
|
||||||
|
|
||||||
private Set<PosixFilePermission> perms;
|
private UnixFileModeAttribute() {
|
||||||
|
|
||||||
UnixFileModeAttribute() {
|
|
||||||
perms = Collections.emptySet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int toUnixMode(Set<PosixFilePermission> perms) {
|
static int toUnixMode(Set<PosixFilePermission> perms) {
|
||||||
|
@ -78,7 +78,7 @@ abstract class UnixFileStore
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this file store represents a loopback file system that
|
* Returns true if this file store represents a loopback file system that
|
||||||
* will have the same device ID as undelrying file system.
|
* will have the same device ID as underlying file system.
|
||||||
*/
|
*/
|
||||||
abstract boolean isLoopback();
|
abstract boolean isLoopback();
|
||||||
|
|
||||||
@ -111,22 +111,33 @@ abstract class UnixFileStore
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> viewType)
|
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view)
|
||||||
{
|
{
|
||||||
if (viewType == FileStoreSpaceAttributeView.class)
|
if (view == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
if (view == FileStoreSpaceAttributeView.class)
|
||||||
return (V) new UnixFileStoreSpaceAttributeView(this);
|
return (V) new UnixFileStoreSpaceAttributeView(this);
|
||||||
return (V) null;
|
return (V) null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileStoreAttributeView getFileStoreAttributeView(String name) {
|
public Object getAttribute(String attribute) throws IOException {
|
||||||
if (name.equals("space"))
|
if (attribute.equals("space:totalSpace"))
|
||||||
return new UnixFileStoreSpaceAttributeView(this);
|
return new UnixFileStoreSpaceAttributeView(this)
|
||||||
return null;
|
.readAttributes().totalSpace();
|
||||||
|
if (attribute.equals("space:usableSpace"))
|
||||||
|
return new UnixFileStoreSpaceAttributeView(this)
|
||||||
|
.readAttributes().usableSpace();
|
||||||
|
if (attribute.equals("space:unallocatedSpace"))
|
||||||
|
return new UnixFileStoreSpaceAttributeView(this)
|
||||||
|
.readAttributes().unallocatedSpace();
|
||||||
|
throw new UnsupportedOperationException("'" + attribute + "' not recognized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
|
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
|
||||||
|
if (type == null)
|
||||||
|
throw new NullPointerException();
|
||||||
if (type == BasicFileAttributeView.class)
|
if (type == BasicFileAttributeView.class)
|
||||||
return true;
|
return true;
|
||||||
if (type == PosixFileAttributeView.class ||
|
if (type == PosixFileAttributeView.class ||
|
||||||
@ -187,7 +198,7 @@ abstract class UnixFileStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class UnixFileStoreSpaceAttributeView
|
private static class UnixFileStoreSpaceAttributeView
|
||||||
extends AbstractFileStoreSpaceAttributeView
|
implements FileStoreSpaceAttributeView
|
||||||
{
|
{
|
||||||
private final UnixFileStore fs;
|
private final UnixFileStore fs;
|
||||||
|
|
||||||
@ -195,6 +206,11 @@ abstract class UnixFileStore
|
|||||||
this.fs = fs;
|
this.fs = fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "space";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileStoreSpaceAttributes readAttributes()
|
public FileStoreSpaceAttributes readAttributes()
|
||||||
throws IOException
|
throws IOException
|
||||||
@ -275,7 +291,7 @@ abstract class UnixFileStore
|
|||||||
private static Properties loadProperties() {
|
private static Properties loadProperties() {
|
||||||
Properties result = new Properties();
|
Properties result = new Properties();
|
||||||
String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
|
String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
|
||||||
FileRef file = Paths.get(fstypes);
|
Path file = Paths.get(fstypes);
|
||||||
try {
|
try {
|
||||||
ReadableByteChannel rbc = file.newByteChannel();
|
ReadableByteChannel rbc = file.newByteChannel();
|
||||||
try {
|
try {
|
||||||
|
@ -137,13 +137,9 @@ abstract class UnixFileSystem
|
|||||||
* @param tfd
|
* @param tfd
|
||||||
* Open file descriptor to target file
|
* Open file descriptor to target file
|
||||||
*/
|
*/
|
||||||
abstract void copyNonPosixAttributes(int sfd, int tfd);
|
void copyNonPosixAttributes(int sfd, int tfd) {
|
||||||
|
// no-op by default
|
||||||
/**
|
}
|
||||||
* Tells if directory relative system calls (openat, etc.) are available
|
|
||||||
* on this operating system.
|
|
||||||
*/
|
|
||||||
abstract boolean supportsSecureDirectoryStreams();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unix systems only have a single root directory (/)
|
* Unix systems only have a single root directory (/)
|
||||||
@ -340,9 +336,9 @@ abstract class UnixFileSystem
|
|||||||
return Arrays.asList("basic", "posix", "unix", "owner");
|
return Arrays.asList("basic", "posix", "unix", "owner");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FileAttributeView newFileAttributeView(String name,
|
protected DynamicFileAttributeView newFileAttributeView(String name,
|
||||||
UnixPath file,
|
UnixPath file,
|
||||||
LinkOption... options)
|
LinkOption... options)
|
||||||
{
|
{
|
||||||
boolean followLinks = followLinks(options);
|
boolean followLinks = followLinks(options);
|
||||||
if (name.equals("basic"))
|
if (name.equals("basic"))
|
||||||
|
@ -93,7 +93,7 @@ public abstract class UnixFileSystemProvider
|
|||||||
return UnixUriUtils.fromUri(theFileSystem, uri);
|
return UnixUriUtils.fromUri(theFileSystem, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UnixPath checkPath(Path obj) {
|
protected UnixPath checkPath(Path obj) {
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
if (!(obj instanceof UnixPath))
|
if (!(obj instanceof UnixPath))
|
||||||
@ -102,9 +102,9 @@ public abstract class UnixFileSystemProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final FileChannel newFileChannel(Path obj,
|
public FileChannel newFileChannel(Path obj,
|
||||||
Set<? extends OpenOption> options,
|
Set<? extends OpenOption> options,
|
||||||
FileAttribute<?>... attrs)
|
FileAttribute<?>... attrs)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
UnixPath file = checkPath(obj);
|
UnixPath file = checkPath(obj);
|
||||||
@ -119,10 +119,10 @@ public abstract class UnixFileSystemProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AsynchronousFileChannel newAsynchronousFileChannel(Path obj,
|
public AsynchronousFileChannel newAsynchronousFileChannel(Path obj,
|
||||||
Set<? extends OpenOption> options,
|
Set<? extends OpenOption> options,
|
||||||
ExecutorService executor,
|
ExecutorService executor,
|
||||||
FileAttribute<?>... attrs) throws IOException
|
FileAttribute<?>... attrs) throws IOException
|
||||||
{
|
{
|
||||||
UnixPath file = checkPath(obj);
|
UnixPath file = checkPath(obj);
|
||||||
int mode = UnixFileModeAttribute
|
int mode = UnixFileModeAttribute
|
||||||
|
@ -66,7 +66,7 @@ class UnixMountEntry {
|
|||||||
boolean hasOption(String requested) {
|
boolean hasOption(String requested) {
|
||||||
if (optionsAsString == null)
|
if (optionsAsString == null)
|
||||||
optionsAsString = new String(opts);
|
optionsAsString = new String(opts);
|
||||||
for (String opt: optionsAsString.split("\\,", 0)) {
|
for (String opt: Util.split(optionsAsString, ',')) {
|
||||||
if (opt.equals(requested))
|
if (opt.equals(requested))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -542,8 +542,17 @@ class UnixNativeDispatcher {
|
|||||||
*/
|
*/
|
||||||
static native byte[] strerror(int errnum);
|
static native byte[] strerror(int errnum);
|
||||||
|
|
||||||
// initialize field IDs
|
// indicates if openat, unlinkat, etc. is supported
|
||||||
private static native void initIDs();
|
private static final boolean hasAtSysCalls;
|
||||||
|
static boolean supportsAtSysCalls() {
|
||||||
|
return hasAtSysCalls;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize syscalls and fieldIDs
|
||||||
|
private static native int init();
|
||||||
|
|
||||||
|
// flags returned by init to indicate capabilities
|
||||||
|
private static final int HAS_AT_SYSCALLS = 0x1;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||||
@ -551,6 +560,8 @@ class UnixNativeDispatcher {
|
|||||||
System.loadLibrary("nio");
|
System.loadLibrary("nio");
|
||||||
return null;
|
return null;
|
||||||
}});
|
}});
|
||||||
initIDs();
|
int flags = init();
|
||||||
|
|
||||||
|
hasAtSysCalls = (flags & HAS_AT_SYSCALLS) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ package sun.nio.fs;
|
|||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.nio.file.spi.AbstractPath;
|
|
||||||
import java.nio.charset.*;
|
import java.nio.charset.*;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
@ -88,10 +87,9 @@ class UnixPath
|
|||||||
char prevChar = 0;
|
char prevChar = 0;
|
||||||
for (int i=0; i < n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
if (c == '\u0000')
|
|
||||||
throw new InvalidPathException(input, "Nul character not allowed");
|
|
||||||
if ((c == '/') && (prevChar == '/'))
|
if ((c == '/') && (prevChar == '/'))
|
||||||
return normalize(input, n, i - 1);
|
return normalize(input, n, i - 1);
|
||||||
|
checkNotNul(input, c);
|
||||||
prevChar = c;
|
prevChar = c;
|
||||||
}
|
}
|
||||||
if (prevChar == '/')
|
if (prevChar == '/')
|
||||||
@ -99,6 +97,11 @@ class UnixPath
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkNotNul(String input, char c) {
|
||||||
|
if (c == '\u0000')
|
||||||
|
throw new InvalidPathException(input, "Nul character not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
private static String normalize(String input, int len, int off) {
|
private static String normalize(String input, int len, int off) {
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return input;
|
return input;
|
||||||
@ -114,6 +117,7 @@ class UnixPath
|
|||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
if ((c == '/') && (prevChar == '/'))
|
if ((c == '/') && (prevChar == '/'))
|
||||||
continue;
|
continue;
|
||||||
|
checkNotNul(input, c);
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
prevChar = c;
|
prevChar = c;
|
||||||
}
|
}
|
||||||
@ -862,7 +866,7 @@ class UnixPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(boolean failIfNotExists) throws IOException {
|
void implDelete(boolean failIfNotExists) throws IOException {
|
||||||
checkDelete();
|
checkDelete();
|
||||||
|
|
||||||
// need file attributes to know if file is directory
|
// need file attributes to know if file is directory
|
||||||
@ -896,13 +900,14 @@ class UnixPath
|
|||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
checkRead();
|
checkRead();
|
||||||
|
|
||||||
// can't return SecureDirectoryStream on older kernels.
|
// can't return SecureDirectoryStream on kernels that don't support
|
||||||
if (!getFileSystem().supportsSecureDirectoryStreams()) {
|
// openat, etc.
|
||||||
|
if (!supportsAtSysCalls()) {
|
||||||
try {
|
try {
|
||||||
long ptr = opendir(this);
|
long ptr = opendir(this);
|
||||||
return new UnixDirectoryStream(this, ptr, filter);
|
return new UnixDirectoryStream(this, ptr, filter);
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
if (x.errno() == UnixConstants.ENOTDIR)
|
if (x.errno() == ENOTDIR)
|
||||||
throw new NotDirectoryException(getPathForExecptionMessage());
|
throw new NotDirectoryException(getPathForExecptionMessage());
|
||||||
x.rethrowAsIOException(this);
|
x.rethrowAsIOException(this);
|
||||||
}
|
}
|
||||||
@ -959,7 +964,9 @@ class UnixPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileAttributeView getFileAttributeView(String name, LinkOption... options) {
|
public DynamicFileAttributeView getFileAttributeView(String name,
|
||||||
|
LinkOption... options)
|
||||||
|
{
|
||||||
return getFileSystem().newFileAttributeView(name, this, options);
|
return getFileSystem().newFileAttributeView(name, this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,21 +986,9 @@ class UnixPath
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream newInputStream()throws IOException {
|
|
||||||
try {
|
|
||||||
Set<OpenOption> options = Collections.emptySet();
|
|
||||||
FileChannel fc = UnixChannelFactory.newFileChannel(this, options, 0);
|
|
||||||
return Channels.newInputStream(fc);
|
|
||||||
} catch (UnixException x) {
|
|
||||||
x.rethrowAsIOException(this);
|
|
||||||
return null; // keep compiler happy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
|
public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
|
||||||
FileAttribute<?>... attrs)
|
FileAttribute<?>... attrs)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
int mode = UnixFileModeAttribute
|
int mode = UnixFileModeAttribute
|
||||||
@ -1007,29 +1002,7 @@ class UnixPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream newOutputStream(Set<? extends OpenOption> options,
|
public boolean isSameFile(Path obj) throws IOException {
|
||||||
FileAttribute<?>... attrs)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
// need to copy options to add WRITE
|
|
||||||
Set<OpenOption> opts = new HashSet<OpenOption>(options);
|
|
||||||
if (opts.contains(StandardOpenOption.READ))
|
|
||||||
throw new IllegalArgumentException("READ not allowed");
|
|
||||||
opts.add(StandardOpenOption.WRITE);
|
|
||||||
|
|
||||||
int mode = UnixFileModeAttribute
|
|
||||||
.toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
|
|
||||||
try {
|
|
||||||
FileChannel fc = UnixChannelFactory.newFileChannel(this, opts, mode);
|
|
||||||
return Channels.newOutputStream(fc);
|
|
||||||
} catch (UnixException x) {
|
|
||||||
x.rethrowAsIOException(this);
|
|
||||||
return null; // keep compiler happy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSameFile(FileRef obj) throws IOException {
|
|
||||||
if (this.equals(obj))
|
if (this.equals(obj))
|
||||||
return true;
|
return true;
|
||||||
if (!(obj instanceof UnixPath)) // includes null check
|
if (!(obj instanceof UnixPath)) // includes null check
|
||||||
@ -1188,13 +1161,6 @@ class UnixPath
|
|||||||
}
|
}
|
||||||
result = result.resolve(element);
|
result = result.resolve(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally check that file exists
|
|
||||||
try {
|
|
||||||
UnixFileAttributes.get(result, true);
|
|
||||||
} catch (UnixException x) {
|
|
||||||
x.rethrowAsIOException(result);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ import static sun.nio.fs.UnixConstants.*;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class UnixSecureDirectoryStream
|
class UnixSecureDirectoryStream
|
||||||
extends SecureDirectoryStream
|
extends SecureDirectoryStream<Path>
|
||||||
{
|
{
|
||||||
private final UnixDirectoryStream ds;
|
private final UnixDirectoryStream ds;
|
||||||
private final int dfd;
|
private final int dfd;
|
||||||
@ -85,13 +85,13 @@ class UnixSecureDirectoryStream
|
|||||||
* Opens sub-directory in this directory
|
* Opens sub-directory in this directory
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public SecureDirectoryStream newDirectoryStream(Path obj,
|
public SecureDirectoryStream<Path> newDirectoryStream(Path obj,
|
||||||
boolean followLinks,
|
LinkOption... options)
|
||||||
DirectoryStream.Filter<? super Path> filter)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
UnixPath file = getName(obj);
|
UnixPath file = getName(obj);
|
||||||
UnixPath child = ds.directory().resolve(file);
|
UnixPath child = ds.directory().resolve(file);
|
||||||
|
boolean followLinks = file.getFileSystem().followLinks(options);
|
||||||
|
|
||||||
// permission check using name resolved against original path of directory
|
// permission check using name resolved against original path of directory
|
||||||
SecurityManager sm = System.getSecurityManager();
|
SecurityManager sm = System.getSecurityManager();
|
||||||
@ -124,7 +124,7 @@ class UnixSecureDirectoryStream
|
|||||||
throw new NotDirectoryException(file.toString());
|
throw new NotDirectoryException(file.toString());
|
||||||
x.rethrowAsIOException(file);
|
x.rethrowAsIOException(file);
|
||||||
}
|
}
|
||||||
return new UnixSecureDirectoryStream(child, ptr, newdfd2, filter);
|
return new UnixSecureDirectoryStream(child, ptr, newdfd2, null);
|
||||||
} finally {
|
} finally {
|
||||||
ds.readLock().unlock();
|
ds.readLock().unlock();
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ class UnixSecureDirectoryStream
|
|||||||
* Rename/move file in this directory to another (open) directory
|
* Rename/move file in this directory to another (open) directory
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void move(Path fromObj, SecureDirectoryStream dir, Path toObj)
|
public void move(Path fromObj, SecureDirectoryStream<Path> dir, Path toObj)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
UnixPath from = getName(fromObj);
|
UnixPath from = getName(fromObj);
|
||||||
@ -310,14 +310,11 @@ class UnixSecureDirectoryStream
|
|||||||
* A BasicFileAttributeView implementation that using a dfd/name pair.
|
* A BasicFileAttributeView implementation that using a dfd/name pair.
|
||||||
*/
|
*/
|
||||||
private class BasicFileAttributeViewImpl
|
private class BasicFileAttributeViewImpl
|
||||||
extends AbstractBasicFileAttributeView
|
implements BasicFileAttributeView
|
||||||
{
|
{
|
||||||
final UnixPath file;
|
final UnixPath file;
|
||||||
final boolean followLinks;
|
final boolean followLinks;
|
||||||
|
|
||||||
// set to true when binding to another object
|
|
||||||
volatile boolean forwarding;
|
|
||||||
|
|
||||||
BasicFileAttributeViewImpl(UnixPath file, boolean followLinks)
|
BasicFileAttributeViewImpl(UnixPath file, boolean followLinks)
|
||||||
{
|
{
|
||||||
this.file = file;
|
this.file = file;
|
||||||
@ -380,17 +377,11 @@ class UnixSecureDirectoryStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTimes(Long lastModifiedTime,
|
public void setTimes(FileTime lastModifiedTime,
|
||||||
Long lastAccessTime,
|
FileTime lastAccessTime,
|
||||||
Long createTime, // ignore
|
FileTime createTime) // ignore
|
||||||
TimeUnit unit)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// no effect
|
|
||||||
if (lastModifiedTime == null && lastAccessTime == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkWriteAccess();
|
checkWriteAccess();
|
||||||
|
|
||||||
ds.readLock().lock();
|
ds.readLock().lock();
|
||||||
@ -400,47 +391,23 @@ class UnixSecureDirectoryStream
|
|||||||
|
|
||||||
int fd = (file == null) ? dfd : open();
|
int fd = (file == null) ? dfd : open();
|
||||||
try {
|
try {
|
||||||
UnixFileAttributes attrs = null;
|
|
||||||
|
|
||||||
// if not changing both attributes then need existing attributes
|
// if not changing both attributes then need existing attributes
|
||||||
if (lastModifiedTime == null || lastAccessTime == null) {
|
if (lastModifiedTime == null || lastAccessTime == null) {
|
||||||
try {
|
try {
|
||||||
attrs = UnixFileAttributes.get(fd);
|
UnixFileAttributes attrs = UnixFileAttributes.get(fd);
|
||||||
|
if (lastModifiedTime == null)
|
||||||
|
lastModifiedTime = attrs.lastModifiedTime();
|
||||||
|
if (lastAccessTime == null)
|
||||||
|
lastAccessTime = attrs.lastAccessTime();
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
x.rethrowAsIOException(file);
|
x.rethrowAsIOException(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// update times
|
||||||
// modified time = existing, now, or new value
|
|
||||||
long modTime;
|
|
||||||
if (lastModifiedTime == null) {
|
|
||||||
modTime = attrs.lastModifiedTime();
|
|
||||||
} else {
|
|
||||||
if (lastModifiedTime >= 0L) {
|
|
||||||
modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit);
|
|
||||||
} else {
|
|
||||||
if (lastModifiedTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
modTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// access time = existing, now, or new value
|
|
||||||
long accTime;
|
|
||||||
if (lastAccessTime == null) {
|
|
||||||
accTime = attrs.lastAccessTime();
|
|
||||||
} else {
|
|
||||||
if (lastAccessTime >= 0L) {
|
|
||||||
accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit);
|
|
||||||
} else {
|
|
||||||
if (lastAccessTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
accTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
futimes(fd, accTime, modTime);
|
futimes(fd,
|
||||||
|
lastAccessTime.to(TimeUnit.MICROSECONDS),
|
||||||
|
lastModifiedTime.to(TimeUnit.MICROSECONDS));
|
||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
x.rethrowAsIOException(file);
|
x.rethrowAsIOException(file);
|
||||||
}
|
}
|
||||||
@ -460,10 +427,6 @@ class UnixSecureDirectoryStream
|
|||||||
private class PosixFileAttributeViewImpl
|
private class PosixFileAttributeViewImpl
|
||||||
extends BasicFileAttributeViewImpl implements PosixFileAttributeView
|
extends BasicFileAttributeViewImpl implements PosixFileAttributeView
|
||||||
{
|
{
|
||||||
private static final String PERMISSIONS_NAME = "permissions";
|
|
||||||
private static final String OWNER_NAME = "owner";
|
|
||||||
private static final String GROUP_NAME = "group";
|
|
||||||
|
|
||||||
PosixFileAttributeViewImpl(UnixPath file, boolean followLinks) {
|
PosixFileAttributeViewImpl(UnixPath file, boolean followLinks) {
|
||||||
super(file, followLinks);
|
super(file, followLinks);
|
||||||
}
|
}
|
||||||
@ -481,59 +444,6 @@ class UnixSecureDirectoryStream
|
|||||||
return "posix";
|
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)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (attribute.equals(PERMISSIONS_NAME)) {
|
|
||||||
setPermissions((Set<PosixFilePermission>)value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (attribute.equals(OWNER_NAME)) {
|
|
||||||
setOwner((UserPrincipal)value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (attribute.equals(GROUP_NAME)) {
|
|
||||||
setGroup((GroupPrincipal)value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
super.setAttribute(attribute, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
final void addPosixAttributesToBuilder(PosixFileAttributes attrs,
|
|
||||||
AttributesBuilder builder)
|
|
||||||
{
|
|
||||||
if (builder.match(PERMISSIONS_NAME))
|
|
||||||
builder.add(PERMISSIONS_NAME, attrs.permissions());
|
|
||||||
if (builder.match(OWNER_NAME))
|
|
||||||
builder.add(OWNER_NAME, attrs.owner());
|
|
||||||
if (builder.match(GROUP_NAME))
|
|
||||||
builder.add(GROUP_NAME, attrs.group());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String,?> readAttributes(String first, String[] rest)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
AttributesBuilder builder = AttributesBuilder.create(first, rest);
|
|
||||||
PosixFileAttributes attrs = readAttributes();
|
|
||||||
addBasicAttributesToBuilder(attrs, builder);
|
|
||||||
addPosixAttributesToBuilder(attrs, builder);
|
|
||||||
return builder.unmodifiableMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PosixFileAttributes readAttributes() throws IOException {
|
public PosixFileAttributes readAttributes() throws IOException {
|
||||||
SecurityManager sm = System.getSecurityManager();
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
@ -147,8 +147,14 @@ class UnixUserPrincipals {
|
|||||||
} catch (UnixException x) {
|
} catch (UnixException x) {
|
||||||
throw new IOException(name + ": " + x.errorString());
|
throw new IOException(name + ": " + x.errorString());
|
||||||
}
|
}
|
||||||
if (id == -1)
|
if (id == -1) {
|
||||||
throw new UserPrincipalNotFoundException(name);
|
// lookup failed, allow input to be uid or gid
|
||||||
|
try {
|
||||||
|
id = Integer.parseInt(name);
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
|
throw new UserPrincipalNotFoundException(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -92,14 +92,12 @@ typedef int fstatat64_func(int, const char *, struct stat64 *, int);
|
|||||||
typedef int unlinkat_func(int, const char*, int);
|
typedef int unlinkat_func(int, const char*, int);
|
||||||
typedef int renameat_func(int, const char*, int, const char*);
|
typedef int renameat_func(int, const char*, int, const char*);
|
||||||
typedef int futimesat_func(int, const char *, const struct timeval *);
|
typedef int futimesat_func(int, const char *, const struct timeval *);
|
||||||
typedef DIR* fdopendir_func(int);
|
|
||||||
|
|
||||||
static openat64_func* my_openat64_func = NULL;
|
static openat64_func* my_openat64_func = NULL;
|
||||||
static fstatat64_func* my_fstatat64_func = NULL;
|
static fstatat64_func* my_fstatat64_func = NULL;
|
||||||
static unlinkat_func* my_unlinkat_func = NULL;
|
static unlinkat_func* my_unlinkat_func = NULL;
|
||||||
static renameat_func* my_renameat_func = NULL;
|
static renameat_func* my_renameat_func = NULL;
|
||||||
static futimesat_func* my_futimesat_func = NULL;
|
static futimesat_func* my_futimesat_func = NULL;
|
||||||
static fdopendir_func* my_fdopendir_func = NULL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fstatat missing from glibc on Linux. Temporary workaround
|
* fstatat missing from glibc on Linux. Temporary workaround
|
||||||
@ -142,16 +140,17 @@ static void throwUnixException(JNIEnv* env, int errnum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize jfieldIDs
|
* Initialization
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this)
|
Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
|
||||||
{
|
{
|
||||||
|
jint flags = 0;
|
||||||
jclass clazz;
|
jclass clazz;
|
||||||
|
|
||||||
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileAttributes");
|
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileAttributes");
|
||||||
if (clazz == NULL) {
|
if (clazz == NULL) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
attrs_st_mode = (*env)->GetFieldID(env, clazz, "st_mode", "I");
|
attrs_st_mode = (*env)->GetFieldID(env, clazz, "st_mode", "I");
|
||||||
attrs_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J");
|
attrs_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J");
|
||||||
@ -167,7 +166,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this)
|
|||||||
|
|
||||||
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
|
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
|
||||||
if (clazz == NULL) {
|
if (clazz == NULL) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J");
|
attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J");
|
||||||
attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J");
|
attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J");
|
||||||
@ -176,7 +175,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this)
|
|||||||
|
|
||||||
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
|
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
|
||||||
if (clazz == NULL) {
|
if (clazz == NULL) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
|
entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
|
||||||
entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
|
entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
|
||||||
@ -197,13 +196,21 @@ Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this)
|
|||||||
my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
|
my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
|
||||||
my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
|
my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
|
||||||
my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
|
my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
|
||||||
my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir");
|
|
||||||
|
|
||||||
#if defined(FSTATAT64_SYSCALL_AVAILABLE)
|
#if defined(FSTATAT64_SYSCALL_AVAILABLE)
|
||||||
/* fstatat64 missing from glibc */
|
/* fstatat64 missing from glibc */
|
||||||
if (my_fstatat64_func == NULL)
|
if (my_fstatat64_func == NULL)
|
||||||
my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
|
my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (my_openat64_func != NULL && my_fstatat64_func != NULL &&
|
||||||
|
my_unlinkat_func != NULL && my_renameat_func != NULL &&
|
||||||
|
my_futimesat_func != NULL)
|
||||||
|
{
|
||||||
|
flags |= sun_nio_fs_UnixNativeDispatcher_HAS_AT_SYSCALLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jbyteArray JNICALL
|
JNIEXPORT jbyteArray JNICALL
|
||||||
@ -364,9 +371,9 @@ static void prepAttributes(JNIEnv* env, struct stat64* buf, jobject attrs) {
|
|||||||
(*env)->SetIntField(env, attrs, attrs_st_uid, (jint)buf->st_uid);
|
(*env)->SetIntField(env, attrs, attrs_st_uid, (jint)buf->st_uid);
|
||||||
(*env)->SetIntField(env, attrs, attrs_st_gid, (jint)buf->st_gid);
|
(*env)->SetIntField(env, attrs, attrs_st_gid, (jint)buf->st_gid);
|
||||||
(*env)->SetLongField(env, attrs, attrs_st_size, (jlong)buf->st_size);
|
(*env)->SetLongField(env, attrs, attrs_st_size, (jlong)buf->st_size);
|
||||||
(*env)->SetLongField(env, attrs, attrs_st_atime, (jlong)buf->st_atime * 1000);
|
(*env)->SetLongField(env, attrs, attrs_st_atime, (jlong)buf->st_atime);
|
||||||
(*env)->SetLongField(env, attrs, attrs_st_mtime, (jlong)buf->st_mtime * 1000);
|
(*env)->SetLongField(env, attrs, attrs_st_mtime, (jlong)buf->st_mtime);
|
||||||
(*env)->SetLongField(env, attrs, attrs_st_ctime, (jlong)buf->st_ctime * 1000);
|
(*env)->SetLongField(env, attrs, attrs_st_ctime, (jlong)buf->st_ctime);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
@ -506,11 +513,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this,
|
|||||||
struct timeval times[2];
|
struct timeval times[2];
|
||||||
const char* path = (const char*)jlong_to_ptr(pathAddress);
|
const char* path = (const char*)jlong_to_ptr(pathAddress);
|
||||||
|
|
||||||
times[0].tv_sec = accessTime / 1000;
|
times[0].tv_sec = accessTime / 1000000;
|
||||||
times[0].tv_usec = (accessTime % 1000) * 1000;
|
times[0].tv_usec = accessTime % 1000000;
|
||||||
|
|
||||||
times[1].tv_sec = modificationTime / 1000;
|
times[1].tv_sec = modificationTime / 1000000;
|
||||||
times[1].tv_usec = (modificationTime % 1000) * 1000;
|
times[1].tv_usec = modificationTime % 1000000;
|
||||||
|
|
||||||
RESTARTABLE(utimes(path, ×[0]), err);
|
RESTARTABLE(utimes(path, ×[0]), err);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
@ -525,11 +532,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint file
|
|||||||
struct timeval times[2];
|
struct timeval times[2];
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
times[0].tv_sec = accessTime / 1000;
|
times[0].tv_sec = accessTime / 1000000;
|
||||||
times[0].tv_usec = (accessTime % 1000) * 1000;
|
times[0].tv_usec = accessTime % 1000000;
|
||||||
|
|
||||||
times[1].tv_sec = modificationTime / 1000;
|
times[1].tv_sec = modificationTime / 1000000;
|
||||||
times[1].tv_usec = (modificationTime % 1000) * 1000;
|
times[1].tv_usec = modificationTime % 1000000;
|
||||||
|
|
||||||
if (my_futimesat_func != NULL) {
|
if (my_futimesat_func != NULL) {
|
||||||
RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err);
|
RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err);
|
||||||
@ -558,13 +565,8 @@ JNIEXPORT jlong JNICALL
|
|||||||
Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) {
|
Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) {
|
||||||
DIR* dir;
|
DIR* dir;
|
||||||
|
|
||||||
if (my_fdopendir_func == NULL) {
|
|
||||||
JNU_ThrowInternalError(env, "should not reach here");
|
|
||||||
return (jlong)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EINTR not listed as a possible error */
|
/* EINTR not listed as a possible error */
|
||||||
dir = (*my_fdopendir_func)((int)dfd);
|
dir = fdopendir((int)dfd);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
throwUnixException(env, errno);
|
throwUnixException(env, errno);
|
||||||
}
|
}
|
||||||
|
@ -66,16 +66,6 @@ int main(int argc, const char* argv[]) {
|
|||||||
DEFX(O_DSYNC);
|
DEFX(O_DSYNC);
|
||||||
DEFX(O_NOFOLLOW);
|
DEFX(O_NOFOLLOW);
|
||||||
|
|
||||||
// flags used with openat/unlinkat/etc.
|
|
||||||
#ifdef __solaris__
|
|
||||||
DEFX(AT_SYMLINK_NOFOLLOW);
|
|
||||||
DEFX(AT_REMOVEDIR);
|
|
||||||
#endif
|
|
||||||
#ifdef __linux__
|
|
||||||
emitX("AT_SYMLINK_NOFOLLOW", 0x100); // since 2.6.16
|
|
||||||
emitX("AT_REMOVEDIR", 0x200);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// mode masks
|
// mode masks
|
||||||
emitX("S_IAMB",
|
emitX("S_IAMB",
|
||||||
(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH));
|
(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH));
|
||||||
@ -119,6 +109,16 @@ int main(int argc, const char* argv[]) {
|
|||||||
DEF(ENODATA);
|
DEF(ENODATA);
|
||||||
DEF(ERANGE);
|
DEF(ERANGE);
|
||||||
|
|
||||||
|
// flags used with openat/unlinkat/etc.
|
||||||
|
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
|
||||||
|
DEFX(AT_SYMLINK_NOFOLLOW)
|
||||||
|
DEFX(AT_REMOVEDIR);
|
||||||
|
#else
|
||||||
|
// not supported (dummy values will not be used at runtime).
|
||||||
|
emitX("AT_SYMLINK_NOFOLLOW", 0x0);
|
||||||
|
emitX("AT_REMOVEDIR", 0x0);
|
||||||
|
#endif
|
||||||
|
|
||||||
out("} ");
|
out("} ");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -93,6 +93,7 @@ class WindowsConstants {
|
|||||||
public static final int ERROR_NOT_SAME_DEVICE = 17;
|
public static final int ERROR_NOT_SAME_DEVICE = 17;
|
||||||
public static final int ERROR_NOT_READY = 21;
|
public static final int ERROR_NOT_READY = 21;
|
||||||
public static final int ERROR_FILE_EXISTS = 80;
|
public static final int ERROR_FILE_EXISTS = 80;
|
||||||
|
public static final int ERROR_INVALID_PARAMATER = 87;
|
||||||
public static final int ERROR_DISK_FULL = 112;
|
public static final int ERROR_DISK_FULL = 112;
|
||||||
public static final int ERROR_INSUFFICIENT_BUFFER = 122;
|
public static final int ERROR_INSUFFICIENT_BUFFER = 122;
|
||||||
public static final int ERROR_INVALID_LEVEL = 124;
|
public static final int ERROR_INVALID_LEVEL = 124;
|
||||||
|
@ -152,11 +152,13 @@ class WindowsDirectoryStream
|
|||||||
}
|
}
|
||||||
Path entry = WindowsPath
|
Path entry = WindowsPath
|
||||||
.createFromNormalizedPath(dir.getFileSystem(), s, attrs);
|
.createFromNormalizedPath(dir.getFileSystem(), s, attrs);
|
||||||
if (filter.accept(entry)) {
|
try {
|
||||||
return entry;
|
if (filter.accept(entry))
|
||||||
} else {
|
return entry;
|
||||||
return null;
|
} catch (IOException ioe) {
|
||||||
|
throwAsConcurrentModificationException(ioe);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads next directory entry
|
// reads next directory entry
|
||||||
@ -244,7 +246,7 @@ class WindowsDirectoryStream
|
|||||||
prevEntry = null;
|
prevEntry = null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
entry.delete(true);
|
entry.delete();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throwAsConcurrentModificationException(ioe);
|
throwAsConcurrentModificationException(ioe);
|
||||||
} catch (SecurityException se) {
|
} catch (SecurityException se) {
|
||||||
|
@ -28,7 +28,6 @@ package sun.nio.fs;
|
|||||||
|
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static sun.nio.fs.WindowsNativeDispatcher.*;
|
import static sun.nio.fs.WindowsNativeDispatcher.*;
|
||||||
@ -55,10 +54,25 @@ class WindowsFileAttributeViews {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts a Windows time for the FAT epoch.
|
||||||
|
*/
|
||||||
|
private long adjustForFatEpoch(long time) {
|
||||||
|
// 1/1/1980 in Windows Time
|
||||||
|
final long FAT_EPOCH = 119600064000000000L;
|
||||||
|
if (time != -1L && time < FAT_EPOCH) {
|
||||||
|
return FAT_EPOCH;
|
||||||
|
} else {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameter values in Windows times.
|
* Parameter values in Windows times.
|
||||||
*/
|
*/
|
||||||
void setFileTimes(long createTime, long lastAccessTime, long lastWriteTime)
|
void setFileTimes(long createTime,
|
||||||
|
long lastAccessTime,
|
||||||
|
long lastWriteTime)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
long handle = -1L;
|
long handle = -1L;
|
||||||
@ -76,24 +90,43 @@ class WindowsFileAttributeViews {
|
|||||||
x.rethrowAsIOException(file);
|
x.rethrowAsIOException(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update attributes
|
// update times
|
||||||
try {
|
try {
|
||||||
SetFileTime(handle, createTime, lastAccessTime, lastWriteTime);
|
SetFileTime(handle,
|
||||||
|
createTime,
|
||||||
|
lastAccessTime,
|
||||||
|
lastWriteTime);
|
||||||
} catch (WindowsException x) {
|
} catch (WindowsException x) {
|
||||||
x.rethrowAsIOException(file);
|
// If ERROR_INVALID_PARAMATER is returned and the volume is
|
||||||
|
// FAT then adjust to the FAT epoch and retry.
|
||||||
|
if (followLinks && x.lastError() == ERROR_INVALID_PARAMATER) {
|
||||||
|
try {
|
||||||
|
if (WindowsFileStore.create(file).type().equals("FAT")) {
|
||||||
|
SetFileTime(handle,
|
||||||
|
adjustForFatEpoch(createTime),
|
||||||
|
adjustForFatEpoch(lastAccessTime),
|
||||||
|
adjustForFatEpoch(lastWriteTime));
|
||||||
|
// retry succeeded
|
||||||
|
x = null;
|
||||||
|
}
|
||||||
|
} catch (SecurityException ignore) {
|
||||||
|
} catch (WindowsException ignore) {
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
// ignore exceptions to let original exception be thrown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x != null)
|
||||||
|
x.rethrowAsIOException(file);
|
||||||
} finally {
|
} finally {
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTimes(Long lastModifiedTime,
|
public void setTimes(FileTime lastModifiedTime,
|
||||||
Long lastAccessTime,
|
FileTime lastAccessTime,
|
||||||
Long createTime,
|
FileTime createTime) throws IOException
|
||||||
TimeUnit unit) throws IOException
|
|
||||||
{
|
{
|
||||||
file.checkWrite();
|
|
||||||
|
|
||||||
// if all null then do nothing
|
// if all null then do nothing
|
||||||
if (lastModifiedTime == null && lastAccessTime == null &&
|
if (lastModifiedTime == null && lastAccessTime == null &&
|
||||||
createTime == null)
|
createTime == null)
|
||||||
@ -102,42 +135,17 @@ class WindowsFileAttributeViews {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// null => no change
|
// permission check
|
||||||
// -1 => change to current time
|
file.checkWrite();
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
long modTime = 0L, accTime = 0L, crTime = 0L;
|
|
||||||
if (lastModifiedTime != null) {
|
|
||||||
if (lastModifiedTime < 0L) {
|
|
||||||
if (lastModifiedTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
modTime = now;
|
|
||||||
} else {
|
|
||||||
modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit);
|
|
||||||
}
|
|
||||||
modTime = WindowsFileAttributes.toWindowsTime(modTime);
|
|
||||||
}
|
|
||||||
if (lastAccessTime != null) {
|
|
||||||
if (lastAccessTime < 0L) {
|
|
||||||
if (lastAccessTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
accTime = now;
|
|
||||||
} else {
|
|
||||||
accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit);
|
|
||||||
}
|
|
||||||
accTime = WindowsFileAttributes.toWindowsTime(accTime);
|
|
||||||
}
|
|
||||||
if (createTime != null) {
|
|
||||||
if (createTime < 0L) {
|
|
||||||
if (createTime != -1L)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
crTime = now;
|
|
||||||
} else {
|
|
||||||
crTime = TimeUnit.MILLISECONDS.convert(createTime, unit);
|
|
||||||
}
|
|
||||||
crTime = WindowsFileAttributes.toWindowsTime(crTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFileTimes(crTime, accTime, modTime);
|
// update times
|
||||||
|
long t1 = (createTime == null) ? -1L :
|
||||||
|
WindowsFileAttributes.toWindowsTime(createTime);
|
||||||
|
long t2 = (lastAccessTime == null) ? -1L :
|
||||||
|
WindowsFileAttributes.toWindowsTime(lastAccessTime);
|
||||||
|
long t3 = (lastModifiedTime == null) ? -1L :
|
||||||
|
WindowsFileAttributes.toWindowsTime(lastModifiedTime);
|
||||||
|
setFileTimes(t1, t2, t3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,10 +205,10 @@ class WindowsFileAttributeViews {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,?> readAttributes(String first, String[] rest)
|
public Map<String,?> readAttributes(String[] attributes)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
AttributesBuilder builder = AttributesBuilder.create(first, rest);
|
AttributesBuilder builder = AttributesBuilder.create(attributes);
|
||||||
WindowsFileAttributes attrs = readAttributes();
|
WindowsFileAttributes attrs = readAttributes();
|
||||||
addBasicAttributesToBuilder(attrs, builder);
|
addBasicAttributesToBuilder(attrs, builder);
|
||||||
if (builder.match(READONLY_NAME))
|
if (builder.match(READONLY_NAME))
|
||||||
@ -286,11 +294,11 @@ class WindowsFileAttributeViews {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BasicFileAttributeView createBasicView(WindowsPath file, boolean followLinks) {
|
static Basic createBasicView(WindowsPath file, boolean followLinks) {
|
||||||
return new Basic(file, followLinks);
|
return new Basic(file, followLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WindowsFileAttributeViews.Dos createDosView(WindowsPath file, boolean followLinks) {
|
static Dos createDosView(WindowsPath file, boolean followLinks) {
|
||||||
return new Dos(file, followLinks);
|
return new Dos(file, followLinks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,6 @@ class WindowsFileAttributes
|
|||||||
private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM = 28;
|
private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM = 28;
|
||||||
private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH = 32;
|
private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH = 32;
|
||||||
private static final short OFFSETOF_FILE_INFORMATION_SIZELOW = 36;
|
private static final short OFFSETOF_FILE_INFORMATION_SIZELOW = 36;
|
||||||
private static final short OFFSETOF_FILE_INFORMATION_NUMLINKS = 40;
|
|
||||||
private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH = 44;
|
private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH = 44;
|
||||||
private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW = 48;
|
private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW = 48;
|
||||||
|
|
||||||
@ -110,6 +109,9 @@ class WindowsFileAttributes
|
|||||||
private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;
|
private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;
|
||||||
private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;
|
private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;
|
||||||
|
|
||||||
|
// used to adjust values between Windows and java epoch
|
||||||
|
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
|
||||||
|
|
||||||
// indicates if accurate metadata is required (interesting on NTFS only)
|
// indicates if accurate metadata is required (interesting on NTFS only)
|
||||||
private static final boolean ensureAccurateMetadata;
|
private static final boolean ensureAccurateMetadata;
|
||||||
static {
|
static {
|
||||||
@ -128,29 +130,33 @@ class WindowsFileAttributes
|
|||||||
private final int reparseTag;
|
private final int reparseTag;
|
||||||
|
|
||||||
// additional attributes when using GetFileInformationByHandle
|
// additional attributes when using GetFileInformationByHandle
|
||||||
private final int linkCount;
|
|
||||||
private final int volSerialNumber;
|
private final int volSerialNumber;
|
||||||
private final int fileIndexHigh;
|
private final int fileIndexHigh;
|
||||||
private final int fileIndexLow;
|
private final int fileIndexLow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert 64-bit value representing the number of 100-nanosecond intervals
|
* Convert 64-bit value representing the number of 100-nanosecond intervals
|
||||||
* since January 1, 1601 to java time.
|
* since January 1, 1601 to a FileTime.
|
||||||
*/
|
*/
|
||||||
private static long toJavaTime(long time) {
|
static FileTime toFileTime(long time) {
|
||||||
time /= 10000L;
|
// 100ns -> us
|
||||||
time -= 11644473600000L;
|
time /= 10L;
|
||||||
return time;
|
// adjust to java epoch
|
||||||
|
time += WINDOWS_EPOCH_IN_MICROSECONDS;
|
||||||
|
return FileTime.from(time, TimeUnit.MICROSECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert java time to 64-bit value representing the number of 100-nanosecond
|
* Convert FileTime to 64-bit value representing the number of 100-nanosecond
|
||||||
* intervals since January 1, 1601.
|
* intervals since January 1, 1601.
|
||||||
*/
|
*/
|
||||||
static long toWindowsTime(long time) {
|
static long toWindowsTime(FileTime time) {
|
||||||
time += 11644473600000L;
|
long value = time.to(TimeUnit.MICROSECONDS);
|
||||||
time *= 10000L;
|
// adjust to Windows epoch+= 11644473600000000L;
|
||||||
return time;
|
value -= WINDOWS_EPOCH_IN_MICROSECONDS;
|
||||||
|
// us -> 100ns
|
||||||
|
value *= 10L;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,7 +168,6 @@ class WindowsFileAttributes
|
|||||||
long lastWriteTime,
|
long lastWriteTime,
|
||||||
long size,
|
long size,
|
||||||
int reparseTag,
|
int reparseTag,
|
||||||
int linkCount,
|
|
||||||
int volSerialNumber,
|
int volSerialNumber,
|
||||||
int fileIndexHigh,
|
int fileIndexHigh,
|
||||||
int fileIndexLow)
|
int fileIndexLow)
|
||||||
@ -173,7 +178,6 @@ class WindowsFileAttributes
|
|||||||
this.lastWriteTime = lastWriteTime;
|
this.lastWriteTime = lastWriteTime;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.reparseTag = reparseTag;
|
this.reparseTag = reparseTag;
|
||||||
this.linkCount = linkCount;
|
|
||||||
this.volSerialNumber = volSerialNumber;
|
this.volSerialNumber = volSerialNumber;
|
||||||
this.fileIndexHigh = fileIndexHigh;
|
this.fileIndexHigh = fileIndexHigh;
|
||||||
this.fileIndexLow = fileIndexLow;
|
this.fileIndexLow = fileIndexLow;
|
||||||
@ -184,15 +188,11 @@ class WindowsFileAttributes
|
|||||||
*/
|
*/
|
||||||
private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) {
|
private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) {
|
||||||
int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
|
||||||
long creationTime =
|
long creationTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME);
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME));
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME);
|
||||||
long lastAccessTime =
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME);
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME));
|
|
||||||
long lastWriteTime =
|
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME));
|
|
||||||
long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32)
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32)
|
||||||
+ (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL);
|
+ (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL);
|
||||||
int linkCount = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_NUMLINKS);
|
|
||||||
int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM);
|
int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM);
|
||||||
int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH);
|
int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH);
|
||||||
int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW);
|
int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW);
|
||||||
@ -202,7 +202,6 @@ class WindowsFileAttributes
|
|||||||
lastWriteTime,
|
lastWriteTime,
|
||||||
size,
|
size,
|
||||||
reparseTag,
|
reparseTag,
|
||||||
linkCount,
|
|
||||||
volSerialNumber,
|
volSerialNumber,
|
||||||
fileIndexHigh,
|
fileIndexHigh,
|
||||||
fileIndexLow);
|
fileIndexLow);
|
||||||
@ -213,12 +212,9 @@ class WindowsFileAttributes
|
|||||||
*/
|
*/
|
||||||
private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) {
|
private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) {
|
||||||
int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
|
||||||
long creationTime =
|
long creationTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME);
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME));
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME);
|
||||||
long lastAccessTime =
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME);
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME));
|
|
||||||
long lastWriteTime =
|
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME));
|
|
||||||
long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32)
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32)
|
||||||
+ (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL);
|
+ (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL);
|
||||||
return new WindowsFileAttributes(fileAttrs,
|
return new WindowsFileAttributes(fileAttrs,
|
||||||
@ -227,7 +223,6 @@ class WindowsFileAttributes
|
|||||||
lastWriteTime,
|
lastWriteTime,
|
||||||
size,
|
size,
|
||||||
reparseTag,
|
reparseTag,
|
||||||
1, // linkCount
|
|
||||||
0, // volSerialNumber
|
0, // volSerialNumber
|
||||||
0, // fileIndexHigh
|
0, // fileIndexHigh
|
||||||
0); // fileIndexLow
|
0); // fileIndexLow
|
||||||
@ -246,12 +241,9 @@ class WindowsFileAttributes
|
|||||||
*/
|
*/
|
||||||
static WindowsFileAttributes fromFindData(long address) {
|
static WindowsFileAttributes fromFindData(long address) {
|
||||||
int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES);
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES);
|
||||||
long creationTime =
|
long creationTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME);
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME));
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME);
|
||||||
long lastAccessTime =
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME);
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME));
|
|
||||||
long lastWriteTime =
|
|
||||||
toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME));
|
|
||||||
long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)
|
||||||
+ (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);
|
+ (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);
|
||||||
int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ?
|
int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ?
|
||||||
@ -262,7 +254,6 @@ class WindowsFileAttributes
|
|||||||
lastWriteTime,
|
lastWriteTime,
|
||||||
size,
|
size,
|
||||||
reparseTag,
|
reparseTag,
|
||||||
1, // linkCount
|
|
||||||
0, // volSerialNumber
|
0, // volSerialNumber
|
||||||
0, // fileIndexHigh
|
0, // fileIndexHigh
|
||||||
0); // fileIndexLow
|
0); // fileIndexLow
|
||||||
@ -375,28 +366,18 @@ class WindowsFileAttributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long lastModifiedTime() {
|
public FileTime lastModifiedTime() {
|
||||||
return (lastWriteTime >= 0L) ? lastWriteTime : 0L;
|
return toFileTime(lastWriteTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long lastAccessTime() {
|
public FileTime lastAccessTime() {
|
||||||
return (lastAccessTime >= 0L) ? lastAccessTime : 0L;
|
return toFileTime(lastAccessTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long creationTime() {
|
public FileTime creationTime() {
|
||||||
return (creationTime >= 0L) ? creationTime : 0L;
|
return toFileTime(creationTime);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TimeUnit resolution() {
|
|
||||||
return TimeUnit.MILLISECONDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int linkCount() {
|
|
||||||
return linkCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,7 +27,6 @@ package sun.nio.fs;
|
|||||||
|
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.util.*;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static sun.nio.fs.WindowsConstants.*;
|
import static sun.nio.fs.WindowsConstants.*;
|
||||||
@ -120,23 +119,40 @@ class WindowsFileStore
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view) {
|
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
|
||||||
if (view == FileStoreSpaceAttributeView.class)
|
if (type == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
if (type == FileStoreSpaceAttributeView.class)
|
||||||
return (V) new WindowsFileStoreAttributeView(this);
|
return (V) new WindowsFileStoreAttributeView(this);
|
||||||
return (V) null;
|
return (V) null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileStoreAttributeView getFileStoreAttributeView(String name) {
|
public Object getAttribute(String attribute) throws IOException {
|
||||||
if (name.equals("space"))
|
// standard
|
||||||
return new WindowsFileStoreAttributeView(this);
|
if (attribute.equals("space:totalSpace"))
|
||||||
if (name.equals("volume"))
|
return new WindowsFileStoreAttributeView(this)
|
||||||
return new VolumeFileStoreAttributeView(this);
|
.readAttributes().totalSpace();
|
||||||
return null;
|
if (attribute.equals("space:usableSpace"))
|
||||||
|
return new WindowsFileStoreAttributeView(this)
|
||||||
|
.readAttributes().usableSpace();
|
||||||
|
if (attribute.equals("space:unallocatedSpace"))
|
||||||
|
return new WindowsFileStoreAttributeView(this)
|
||||||
|
.readAttributes().unallocatedSpace();
|
||||||
|
// windows specific for testing purposes
|
||||||
|
if (attribute.equals("volume:vsn"))
|
||||||
|
return volInfo.volumeSerialNumber();
|
||||||
|
if (attribute.equals("volume:isRemovable"))
|
||||||
|
return volType == DRIVE_REMOVABLE;
|
||||||
|
if (attribute.equals("volume:isCdrom"))
|
||||||
|
return volType == DRIVE_CDROM;
|
||||||
|
throw new UnsupportedOperationException("'" + attribute + "' not recognized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
|
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
|
||||||
|
if (type == null)
|
||||||
|
throw new NullPointerException();
|
||||||
if (type == BasicFileAttributeView.class)
|
if (type == BasicFileAttributeView.class)
|
||||||
return true;
|
return true;
|
||||||
if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class)
|
if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class)
|
||||||
@ -154,7 +170,7 @@ class WindowsFileStore
|
|||||||
return supportsFileAttributeView(AclFileAttributeView.class);
|
return supportsFileAttributeView(AclFileAttributeView.class);
|
||||||
if (name.equals("owner"))
|
if (name.equals("owner"))
|
||||||
return supportsFileAttributeView(FileOwnerAttributeView.class);
|
return supportsFileAttributeView(FileOwnerAttributeView.class);
|
||||||
if (name.equals("xattr"))
|
if (name.equals("user"))
|
||||||
return supportsFileAttributeView(UserDefinedFileAttributeView.class);
|
return supportsFileAttributeView(UserDefinedFileAttributeView.class);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -188,7 +204,7 @@ class WindowsFileStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class WindowsFileStoreAttributeView
|
static class WindowsFileStoreAttributeView
|
||||||
extends AbstractFileStoreSpaceAttributeView
|
implements FileStoreSpaceAttributeView
|
||||||
{
|
{
|
||||||
private final WindowsFileStore fs;
|
private final WindowsFileStore fs;
|
||||||
|
|
||||||
@ -196,6 +212,11 @@ class WindowsFileStore
|
|||||||
this.fs = fs;
|
this.fs = fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "space";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileStoreSpaceAttributes readAttributes()
|
public FileStoreSpaceAttributes readAttributes()
|
||||||
throws IOException
|
throws IOException
|
||||||
@ -225,113 +246,4 @@ class WindowsFileStore
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Windows-specific attribute view to allow access to volume information.
|
|
||||||
*/
|
|
||||||
static class VolumeFileStoreAttributeView
|
|
||||||
implements FileStoreAttributeView
|
|
||||||
{
|
|
||||||
private static final String VSN_NAME = "vsn";
|
|
||||||
private static final String COMPRESSED_NAME = "compressed";
|
|
||||||
private static final String REMOVABLE_NAME = "removable";
|
|
||||||
private static final String CDROM_NAME = "cdrom";
|
|
||||||
|
|
||||||
private final WindowsFileStore fs;
|
|
||||||
|
|
||||||
VolumeFileStoreAttributeView(WindowsFileStore fs) {
|
|
||||||
this.fs = fs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return "volume";
|
|
||||||
}
|
|
||||||
|
|
||||||
private int vsn() {
|
|
||||||
return fs.volumeInformation().volumeSerialNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCompressed() {
|
|
||||||
return (fs.volumeInformation().flags() &
|
|
||||||
FILE_VOLUME_IS_COMPRESSED) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isRemovable() {
|
|
||||||
return fs.volumeType() == DRIVE_REMOVABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCdrom() {
|
|
||||||
return fs.volumeType() == DRIVE_CDROM;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getAttribute(String attribute) throws IOException {
|
|
||||||
if (attribute.equals(VSN_NAME))
|
|
||||||
return vsn();
|
|
||||||
if (attribute.equals(COMPRESSED_NAME))
|
|
||||||
return isCompressed();
|
|
||||||
if (attribute.equals(REMOVABLE_NAME))
|
|
||||||
return isRemovable();
|
|
||||||
if (attribute.equals(CDROM_NAME))
|
|
||||||
return isCdrom();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAttribute(String attribute, Object value)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String,?> readAttributes(String first, String... rest)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
boolean all = false;
|
|
||||||
boolean vsn = false;
|
|
||||||
boolean compressed = false;
|
|
||||||
boolean removable = false;
|
|
||||||
boolean cdrom = false;
|
|
||||||
|
|
||||||
if (first.equals(VSN_NAME)) vsn = true;
|
|
||||||
else if (first.equals(COMPRESSED_NAME)) compressed = true;
|
|
||||||
else if (first.equals(REMOVABLE_NAME)) removable = true;
|
|
||||||
else if (first.equals(CDROM_NAME)) cdrom = true;
|
|
||||||
else if (first.equals("*")) all = true;
|
|
||||||
|
|
||||||
if (!all) {
|
|
||||||
for (String attribute: rest) {
|
|
||||||
if (attribute.equals("*")) {
|
|
||||||
all = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (attribute.equals(VSN_NAME)) {
|
|
||||||
vsn = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (attribute.equals(COMPRESSED_NAME)) {
|
|
||||||
compressed = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (attribute.equals(REMOVABLE_NAME)) {
|
|
||||||
removable = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String,Object> result = new HashMap<String,Object>();
|
|
||||||
if (all || vsn)
|
|
||||||
result.put(VSN_NAME, vsn());
|
|
||||||
if (all || compressed)
|
|
||||||
result.put(COMPRESSED_NAME, isCompressed());
|
|
||||||
if (all || removable)
|
|
||||||
result.put(REMOVABLE_NAME, isRemovable());
|
|
||||||
if (all || cdrom)
|
|
||||||
result.put(CDROM_NAME, isCdrom());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -63,7 +63,7 @@ class WindowsFileSystem
|
|||||||
|
|
||||||
PrivilegedAction<String> pa = new GetPropertyAction("os.version");
|
PrivilegedAction<String> pa = new GetPropertyAction("os.version");
|
||||||
String osversion = AccessController.doPrivileged(pa);
|
String osversion = AccessController.doPrivileged(pa);
|
||||||
String[] vers = osversion.split("\\.", 0);
|
String[] vers = Util.split(osversion, '.');
|
||||||
int major = Integer.parseInt(vers[0]);
|
int major = Integer.parseInt(vers[0]);
|
||||||
int minor = Integer.parseInt(vers[1]);
|
int minor = Integer.parseInt(vers[1]);
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ class WindowsFileSystem
|
|||||||
|
|
||||||
// supported views
|
// supported views
|
||||||
private static final Set<String> supportedFileAttributeViews = Collections
|
private static final Set<String> supportedFileAttributeViews = Collections
|
||||||
.unmodifiableSet(new HashSet<String>(Arrays.asList("basic", "dos", "acl", "owner", "xattr")));
|
.unmodifiableSet(new HashSet<String>(Arrays.asList("basic", "dos", "acl", "owner", "user")));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> supportedFileAttributeViews() {
|
public Set<String> supportedFileAttributeViews() {
|
||||||
|
@ -76,7 +76,7 @@ class WindowsLinkSupport {
|
|||||||
if (!followLinks || !fs.supportsLinks())
|
if (!followLinks || !fs.supportsLinks())
|
||||||
return input.getPathForWin32Calls();
|
return input.getPathForWin32Calls();
|
||||||
|
|
||||||
// if file is a sym link then don't need final path
|
// if file is not a sym link then don't need final path
|
||||||
if (!WindowsFileAttributes.get(input, false).isSymbolicLink()) {
|
if (!WindowsFileAttributes.get(input, false).isSymbolicLink()) {
|
||||||
return input.getPathForWin32Calls();
|
return input.getPathForWin32Calls();
|
||||||
}
|
}
|
||||||
|
@ -379,8 +379,11 @@ class WindowsNativeDispatcher {
|
|||||||
* CONST FILETIME *lpLastWriteTime
|
* CONST FILETIME *lpLastWriteTime
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
static native void SetFileTime(long handle, long createTime,
|
static native void SetFileTime(long handle,
|
||||||
long lastAccessTime, long lastWriteTime) throws WindowsException;
|
long createTime,
|
||||||
|
long lastAccessTime,
|
||||||
|
long lastWriteTime)
|
||||||
|
throws WindowsException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SetEndOfFile(
|
* SetEndOfFile(
|
||||||
|
@ -27,7 +27,6 @@ package sun.nio.fs;
|
|||||||
|
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.nio.file.spi.AbstractPath;
|
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@ -166,6 +165,8 @@ class WindowsPath extends AbstractPath {
|
|||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
ref.clear();
|
ref.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no need to override equals/hashCode.
|
||||||
}
|
}
|
||||||
|
|
||||||
// use this message when throwing exceptions
|
// use this message when throwing exceptions
|
||||||
@ -948,7 +949,7 @@ class WindowsPath extends AbstractPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(boolean failIfNotExists) throws IOException {
|
void implDelete(boolean failIfNotExists) throws IOException {
|
||||||
checkDelete();
|
checkDelete();
|
||||||
|
|
||||||
WindowsFileAttributes attrs = null;
|
WindowsFileAttributes attrs = null;
|
||||||
@ -1040,7 +1041,7 @@ class WindowsPath extends AbstractPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileAttributeView getFileAttributeView(String name, LinkOption... options) {
|
public DynamicFileAttributeView getFileAttributeView(String name, LinkOption... options) {
|
||||||
boolean followLinks = followLinks(options);
|
boolean followLinks = followLinks(options);
|
||||||
if (name.equals("basic"))
|
if (name.equals("basic"))
|
||||||
return WindowsFileAttributeViews.createBasicView(this, followLinks);
|
return WindowsFileAttributeViews.createBasicView(this, followLinks);
|
||||||
@ -1051,7 +1052,7 @@ class WindowsPath extends AbstractPath {
|
|||||||
if (name.equals("owner"))
|
if (name.equals("owner"))
|
||||||
return new FileOwnerAttributeViewImpl(
|
return new FileOwnerAttributeViewImpl(
|
||||||
new WindowsAclFileAttributeView(this, followLinks));
|
new WindowsAclFileAttributeView(this, followLinks));
|
||||||
if (name.equals("xattr"))
|
if (name.equals("user"))
|
||||||
return new WindowsUserDefinedFileAttributeView(this, followLinks);
|
return new WindowsUserDefinedFileAttributeView(this, followLinks);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1072,22 +1073,6 @@ class WindowsPath extends AbstractPath {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream newInputStream()throws IOException {
|
|
||||||
try {
|
|
||||||
Set<OpenOption> options = Collections.emptySet();
|
|
||||||
FileChannel fc = WindowsChannelFactory
|
|
||||||
.newFileChannel(getPathForWin32Calls(),
|
|
||||||
getPathForPermissionCheck(),
|
|
||||||
options,
|
|
||||||
0L);
|
|
||||||
return Channels.newInputStream(fc);
|
|
||||||
} catch (WindowsException x) {
|
|
||||||
x.rethrowAsIOException(this);
|
|
||||||
return null; // keep compiler happy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
|
public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
|
||||||
FileAttribute<?>... attrs)
|
FileAttribute<?>... attrs)
|
||||||
@ -1110,36 +1095,7 @@ class WindowsPath extends AbstractPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream newOutputStream(Set<? extends OpenOption> options,
|
public boolean isSameFile(Path obj) throws IOException {
|
||||||
FileAttribute<?>... attrs)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
// need to copy options to add WRITE
|
|
||||||
Set<OpenOption> opts = new HashSet<OpenOption>(options);
|
|
||||||
if (opts.contains(StandardOpenOption.READ))
|
|
||||||
throw new IllegalArgumentException("READ not allowed");
|
|
||||||
opts.add(StandardOpenOption.WRITE);
|
|
||||||
|
|
||||||
WindowsSecurityDescriptor sd =
|
|
||||||
WindowsSecurityDescriptor.fromAttribute(attrs);
|
|
||||||
FileChannel fc;
|
|
||||||
try {
|
|
||||||
fc = WindowsChannelFactory
|
|
||||||
.newFileChannel(getPathForWin32Calls(),
|
|
||||||
getPathForPermissionCheck(),
|
|
||||||
opts,
|
|
||||||
sd.address());
|
|
||||||
return Channels.newOutputStream(fc);
|
|
||||||
} catch (WindowsException x) {
|
|
||||||
x.rethrowAsIOException(this);
|
|
||||||
return null; // keep compiler happy
|
|
||||||
} finally {
|
|
||||||
sd.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSameFile(FileRef obj) throws IOException {
|
|
||||||
if (this.equals(obj))
|
if (this.equals(obj))
|
||||||
return true;
|
return true;
|
||||||
if (!(obj instanceof WindowsPath)) // includes null check
|
if (!(obj instanceof WindowsPath)) // includes null check
|
||||||
@ -1216,7 +1172,7 @@ class WindowsPath extends AbstractPath {
|
|||||||
* creates a link with the resolved target for this case.
|
* creates a link with the resolved target for this case.
|
||||||
*/
|
*/
|
||||||
if (target.type == WindowsPathType.DRIVE_RELATIVE) {
|
if (target.type == WindowsPathType.DRIVE_RELATIVE) {
|
||||||
throw new IOException("Cannot create symbolic link to drive-relative target");
|
throw new IOException("Cannot create symbolic link to working directory relative target");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -560,9 +560,9 @@ Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this,
|
|||||||
HANDLE h = (HANDLE)jlong_to_ptr(handle);
|
HANDLE h = (HANDLE)jlong_to_ptr(handle);
|
||||||
|
|
||||||
if (SetFileTime(h,
|
if (SetFileTime(h,
|
||||||
(createTime == (jlong)0) ? NULL : (CONST FILETIME *)&createTime,
|
(createTime == (jlong)-1) ? NULL : (CONST FILETIME *)&createTime,
|
||||||
(lastAccessTime == (jlong)0) ? NULL : (CONST FILETIME *)&lastAccessTime,
|
(lastAccessTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastAccessTime,
|
||||||
(lastWriteTime == (jlong)0) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0)
|
(lastWriteTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0)
|
||||||
{
|
{
|
||||||
throwWindowsException(env, GetLastError());
|
throwWindowsException(env, GetLastError());
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4313887
|
* @bug 4313887 6838333
|
||||||
* @summary Unit test for java.nio.file.DirectoryStream
|
* @summary Unit test for java.nio.file.DirectoryStream
|
||||||
* @library ..
|
* @library ..
|
||||||
*/
|
*/
|
||||||
@ -38,20 +38,23 @@ public class Basic {
|
|||||||
DirectoryStream<Path> stream;
|
DirectoryStream<Path> stream;
|
||||||
|
|
||||||
// test that directory is empty
|
// test that directory is empty
|
||||||
Files.withDirectory(dir, new FileAction<FileRef>() {
|
stream = dir.newDirectoryStream();
|
||||||
public void invoke(FileRef entry) {
|
try {
|
||||||
|
if (stream.iterator().hasNext())
|
||||||
throw new RuntimeException("directory not empty");
|
throw new RuntimeException("directory not empty");
|
||||||
}
|
} finally {
|
||||||
});
|
stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
// create file in directory
|
// create file in directory
|
||||||
final Path foo = Paths.get("foo");
|
final Path foo = Paths.get("foo");
|
||||||
dir.resolve(foo).createFile();
|
dir.resolve(foo).createFile();
|
||||||
|
|
||||||
// iterate over directory and check there is one entry
|
// iterate over directory and check there is one entry
|
||||||
|
stream = dir.newDirectoryStream();
|
||||||
found = false;
|
found = false;
|
||||||
Files.withDirectory(dir, new FileAction<Path>() {
|
try {
|
||||||
public void invoke(Path entry) {
|
for (Path entry: stream) {
|
||||||
if (entry.getName().equals(foo)) {
|
if (entry.getName().equals(foo)) {
|
||||||
if (found)
|
if (found)
|
||||||
throw new RuntimeException("entry already found");
|
throw new RuntimeException("entry already found");
|
||||||
@ -61,7 +64,9 @@ public class Basic {
|
|||||||
" not expected");
|
" not expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
throw new RuntimeException("entry not found");
|
throw new RuntimeException("entry not found");
|
||||||
|
|
||||||
@ -73,12 +78,15 @@ public class Basic {
|
|||||||
return matcher.matches(file);
|
return matcher.matches(file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Files.withDirectory(dir, filter, new FileAction<Path>() {
|
stream = dir.newDirectoryStream(filter);
|
||||||
public void invoke(Path entry) {
|
try {
|
||||||
|
for (Path entry: stream) {
|
||||||
if (!entry.getName().equals(foo))
|
if (!entry.getName().equals(foo))
|
||||||
throw new RuntimeException("entry not expected");
|
throw new RuntimeException("entry not expected");
|
||||||
}
|
}
|
||||||
});
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
// check filtering: z* should not match any files
|
// check filtering: z* should not match any files
|
||||||
filter = new DirectoryStream.Filter<Path>() {
|
filter = new DirectoryStream.Filter<Path>() {
|
||||||
@ -88,11 +96,31 @@ public class Basic {
|
|||||||
return matcher.matches(file);
|
return matcher.matches(file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Files.withDirectory(dir, filter, new FileAction<FileRef>() {
|
stream = dir.newDirectoryStream(filter);
|
||||||
public void invoke(FileRef entry) {
|
try {
|
||||||
|
if (stream.iterator().hasNext())
|
||||||
throw new RuntimeException("no matching entries expected");
|
throw new RuntimeException("no matching entries expected");
|
||||||
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that IOExceptions throws by filters are propagated
|
||||||
|
filter = new DirectoryStream.Filter<Path>() {
|
||||||
|
public boolean accept(Path file) throws IOException {
|
||||||
|
throw new IOException();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
stream = dir.newDirectoryStream(filter);
|
||||||
|
try {
|
||||||
|
stream.iterator().hasNext();
|
||||||
|
throw new RuntimeException("ConcurrentModificationException expected");
|
||||||
|
} catch (ConcurrentModificationException x) {
|
||||||
|
Throwable t = x.getCause();
|
||||||
|
if (!(t instanceof IOException))
|
||||||
|
throw new RuntimeException("Cause is not IOException as expected");
|
||||||
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
// check that exception or error thrown by filter is not thrown
|
// check that exception or error thrown by filter is not thrown
|
||||||
// by newDirectoryStream or iterator method.
|
// by newDirectoryStream or iterator method.
|
||||||
|
@ -1,241 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008-2009 Sun Microsystems, Inc. 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.
|
|
||||||
*
|
|
||||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
||||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
||||||
* have any questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @test
|
|
||||||
* @bug 4313887
|
|
||||||
* @summary Unit test for java.nio.file.DirectoryStreamFilters
|
|
||||||
* @library ..
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.nio.file.*;
|
|
||||||
import static java.nio.file.DirectoryStreamFilters.*;
|
|
||||||
import java.nio.file.attribute.Attributes;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class Filters {
|
|
||||||
static final Random rand = new Random();
|
|
||||||
|
|
||||||
// returns a filter that only accepts files that are larger than a given size
|
|
||||||
static DirectoryStream.Filter<FileRef> newMinimumSizeFilter(final long min) {
|
|
||||||
return new DirectoryStream.Filter<FileRef>() {
|
|
||||||
public boolean accept(FileRef file) {
|
|
||||||
try {
|
|
||||||
long size = Attributes.readBasicFileAttributes(file).size();
|
|
||||||
return size >= min;
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IOError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns a filter that only accepts files that are matched by a given glob
|
|
||||||
static DirectoryStream.Filter<Path> newGlobFilter(final String glob) {
|
|
||||||
return new DirectoryStream.Filter<Path>() {
|
|
||||||
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:"+ glob);
|
|
||||||
public boolean accept(Path file) {
|
|
||||||
return matcher.matches(file.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static final int BIG_FILE_THRESHOLD = 8192;
|
|
||||||
|
|
||||||
static int totalCount;
|
|
||||||
static int htmlCount;
|
|
||||||
static int bigAndHtmlCount;
|
|
||||||
static int bigOrHtmlCount;
|
|
||||||
|
|
||||||
// generates random files in the test directory and initializes the counts
|
|
||||||
static void setup(Path dir) throws IOException {
|
|
||||||
// create 10-26 files.
|
|
||||||
totalCount = 10 + rand.nextInt(17);
|
|
||||||
char firstChar = 'A';
|
|
||||||
for (int i=0; i<totalCount; i++) {
|
|
||||||
boolean isHtml = rand.nextBoolean();
|
|
||||||
boolean isBig = rand.nextBoolean();
|
|
||||||
if (isHtml) {
|
|
||||||
htmlCount++;
|
|
||||||
if (isBig) bigAndHtmlCount++;
|
|
||||||
}
|
|
||||||
if (isHtml || isBig)
|
|
||||||
bigOrHtmlCount++;
|
|
||||||
String name;
|
|
||||||
if (isHtml) {
|
|
||||||
name = firstChar + ".html";
|
|
||||||
} else {
|
|
||||||
name = firstChar + ".tmp";
|
|
||||||
}
|
|
||||||
firstChar++;
|
|
||||||
int size = rand.nextInt(BIG_FILE_THRESHOLD);
|
|
||||||
if (isBig)
|
|
||||||
size += BIG_FILE_THRESHOLD;
|
|
||||||
Path file = dir.resolve(name);
|
|
||||||
OutputStream out = file.newOutputStream();
|
|
||||||
try {
|
|
||||||
if (size > 0)
|
|
||||||
out.write(new byte[size]);
|
|
||||||
} finally {
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
System.out.format("Created %s, size %d byte(s)\n", name, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isHtml(Path file) {
|
|
||||||
return file.toString().endsWith(".html");
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isBig(Path file) throws IOException {
|
|
||||||
long size = Attributes.readBasicFileAttributes(file).size();
|
|
||||||
return size >= BIG_FILE_THRESHOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void checkCount(int expected, int actual) {
|
|
||||||
if (actual != expected)
|
|
||||||
throw new RuntimeException("'" + expected +
|
|
||||||
"' entries expected, actual: " + actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void doTests(Path dir) throws IOException {
|
|
||||||
final List<DirectoryStream.Filter<Path>> emptyList = Collections.emptyList();
|
|
||||||
|
|
||||||
// list containing two filters
|
|
||||||
List<DirectoryStream.Filter<? super Path>> filters =
|
|
||||||
new ArrayList<DirectoryStream.Filter<? super Path>>();
|
|
||||||
filters.add(newMinimumSizeFilter(BIG_FILE_THRESHOLD));
|
|
||||||
filters.add(newGlobFilter("*.html"));
|
|
||||||
|
|
||||||
int accepted;
|
|
||||||
DirectoryStream<Path> stream;
|
|
||||||
|
|
||||||
System.out.println("Test: newContentTypeFilter");
|
|
||||||
accepted = 0;
|
|
||||||
stream = dir.newDirectoryStream(newContentTypeFilter("text/html"));
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
if (!isHtml(entry))
|
|
||||||
throw new RuntimeException("html file expected");
|
|
||||||
accepted++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
checkCount(htmlCount, accepted);
|
|
||||||
|
|
||||||
System.out.println("Test: allOf with list of filters");
|
|
||||||
accepted = 0;
|
|
||||||
stream = dir.newDirectoryStream(allOf(filters));
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
if (!isHtml(entry))
|
|
||||||
throw new RuntimeException("html file expected");
|
|
||||||
if (!isBig(entry))
|
|
||||||
throw new RuntimeException("big file expected");
|
|
||||||
accepted++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
checkCount(bigAndHtmlCount, accepted);
|
|
||||||
|
|
||||||
System.out.println("Test: allOf with empty list");
|
|
||||||
accepted = 0;
|
|
||||||
stream = dir.newDirectoryStream(allOf(emptyList));
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
accepted++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
checkCount(totalCount, accepted);
|
|
||||||
|
|
||||||
System.out.println("Test: anyOf with list of filters");
|
|
||||||
accepted = 0;
|
|
||||||
stream = dir.newDirectoryStream(anyOf(filters));
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
if (!isHtml(entry) && !isBig(entry))
|
|
||||||
throw new RuntimeException("html or big file expected");
|
|
||||||
accepted++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
checkCount(bigOrHtmlCount, accepted);
|
|
||||||
|
|
||||||
System.out.println("Test: anyOf with empty list");
|
|
||||||
accepted = 0;
|
|
||||||
stream = dir.newDirectoryStream(anyOf(emptyList));
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
accepted++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
checkCount(0, accepted);
|
|
||||||
|
|
||||||
System.out.println("Test: complementOf");
|
|
||||||
accepted = 0;
|
|
||||||
stream = dir.newDirectoryStream(complementOf(newGlobFilter("*.html")));
|
|
||||||
try {
|
|
||||||
for (Path entry: stream) {
|
|
||||||
accepted++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
checkCount(totalCount-htmlCount, accepted);
|
|
||||||
|
|
||||||
System.out.println("Test: nulls");
|
|
||||||
try {
|
|
||||||
newContentTypeFilter(null);
|
|
||||||
throw new RuntimeException("NullPointerException expected");
|
|
||||||
} catch (NullPointerException npe) { }
|
|
||||||
try {
|
|
||||||
allOf(null);
|
|
||||||
throw new RuntimeException("NullPointerException expected");
|
|
||||||
} catch (NullPointerException npe) { }
|
|
||||||
try {
|
|
||||||
anyOf(null);
|
|
||||||
throw new RuntimeException("NullPointerException expected");
|
|
||||||
} catch (NullPointerException npe) { }
|
|
||||||
try {
|
|
||||||
complementOf(null);
|
|
||||||
throw new RuntimeException("NullPointerException expected");
|
|
||||||
} catch (NullPointerException npe) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
|
||||||
Path dir = TestUtil.createTemporaryDirectory();
|
|
||||||
try {
|
|
||||||
setup(dir);
|
|
||||||
doTests(dir);
|
|
||||||
} finally {
|
|
||||||
TestUtil.removeAll(dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4313887
|
* @bug 4313887 6838333
|
||||||
* @summary Unit test for java.nio.file.SecureDirectoryStream
|
* @summary Unit test for java.nio.file.SecureDirectoryStream
|
||||||
* @library ..
|
* @library ..
|
||||||
*/
|
*/
|
||||||
@ -41,7 +41,7 @@ public class SecureDS {
|
|||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
Path dir = TestUtil.createTemporaryDirectory();
|
Path dir = TestUtil.createTemporaryDirectory();
|
||||||
try {
|
try {
|
||||||
DirectoryStream stream = dir.newDirectoryStream();
|
DirectoryStream<Path> stream = dir.newDirectoryStream();
|
||||||
stream.close();
|
stream.close();
|
||||||
if (!(stream instanceof SecureDirectoryStream)) {
|
if (!(stream instanceof SecureDirectoryStream)) {
|
||||||
System.out.println("SecureDirectoryStream not supported.");
|
System.out.println("SecureDirectoryStream not supported.");
|
||||||
@ -81,8 +81,8 @@ public class SecureDS {
|
|||||||
|
|
||||||
// open directory and then move it so that it is no longer accessible
|
// open directory and then move it so that it is no longer accessible
|
||||||
// via its original path.
|
// via its original path.
|
||||||
SecureDirectoryStream stream =
|
SecureDirectoryStream<Path> stream =
|
||||||
(SecureDirectoryStream)dir1.newDirectoryStream();
|
(SecureDirectoryStream<Path>)dir1.newDirectoryStream();
|
||||||
dir1.moveTo(dir2);
|
dir1.moveTo(dir2);
|
||||||
|
|
||||||
// Test: iterate over all entries
|
// Test: iterate over all entries
|
||||||
@ -96,18 +96,6 @@ public class SecureDS {
|
|||||||
.readAttributes()
|
.readAttributes()
|
||||||
.isDirectory());
|
.isDirectory());
|
||||||
|
|
||||||
// Test: dynamic access to directory's attributes
|
|
||||||
BasicFileAttributeView view = stream.
|
|
||||||
getFileAttributeView(BasicFileAttributeView.class);
|
|
||||||
Map<String,?> attrs = view.readAttributes("*");
|
|
||||||
assertTrue((Boolean)attrs.get("isDirectory"));
|
|
||||||
attrs = view.readAttributes("isRegularFile", "size");
|
|
||||||
assertTrue(!(Boolean)attrs.get("isRegularFile"));
|
|
||||||
assertTrue((Long)attrs.get("size") >= 0);
|
|
||||||
int linkCount = (Integer)view.getAttribute("linkCount");
|
|
||||||
assertTrue(linkCount > 0);
|
|
||||||
view.setAttribute("lastModifiedTime", 0L);
|
|
||||||
|
|
||||||
// Test: getFileAttributeView to access attributes of entries
|
// Test: getFileAttributeView to access attributes of entries
|
||||||
assertTrue(stream
|
assertTrue(stream
|
||||||
.getFileAttributeView(fileEntry, BasicFileAttributeView.class)
|
.getFileAttributeView(fileEntry, BasicFileAttributeView.class)
|
||||||
@ -144,17 +132,6 @@ public class SecureDS {
|
|||||||
.isSymbolicLink());
|
.isSymbolicLink());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test: dynamic access to entry attributes
|
|
||||||
view = stream
|
|
||||||
.getFileAttributeView(fileEntry, PosixFileAttributeView.class, NOFOLLOW_LINKS);
|
|
||||||
if (view != null) {
|
|
||||||
attrs = view.readAttributes("owner", "size");
|
|
||||||
UserPrincipal owner = (UserPrincipal)attrs.get("owner");
|
|
||||||
assertTrue(owner != null);
|
|
||||||
assertTrue((Long)attrs.get("size") >= 0L);
|
|
||||||
view.setAttribute("lastAccessTime", 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test: newByteChannel
|
// Test: newByteChannel
|
||||||
Set<StandardOpenOption> opts = Collections.emptySet();
|
Set<StandardOpenOption> opts = Collections.emptySet();
|
||||||
stream.newByteChannel(fileEntry, opts).close();
|
stream.newByteChannel(fileEntry, opts).close();
|
||||||
@ -170,12 +147,13 @@ public class SecureDS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test: newDirectoryStream
|
// Test: newDirectoryStream
|
||||||
stream.newDirectoryStream(dirEntry, true, null).close();
|
stream.newDirectoryStream(dirEntry).close();
|
||||||
stream.newDirectoryStream(dirEntry, false, null).close();
|
stream.newDirectoryStream(dirEntry, LinkOption.NOFOLLOW_LINKS).close();
|
||||||
if (supportsLinks) {
|
if (supportsLinks) {
|
||||||
stream.newDirectoryStream(link2Entry, true, null).close();
|
stream.newDirectoryStream(link2Entry).close();
|
||||||
try {
|
try {
|
||||||
stream.newDirectoryStream(link2Entry, false, null).close();
|
stream.newDirectoryStream(link2Entry, LinkOption.NOFOLLOW_LINKS)
|
||||||
|
.close();
|
||||||
shouldNotGetHere();
|
shouldNotGetHere();
|
||||||
} catch (IOException x) { }
|
} catch (IOException x) { }
|
||||||
}
|
}
|
||||||
@ -193,7 +171,7 @@ public class SecureDS {
|
|||||||
stream.close();
|
stream.close();
|
||||||
dir2.moveTo(dir1);
|
dir2.moveTo(dir1);
|
||||||
dir1.resolve(fileEntry).createFile();
|
dir1.resolve(fileEntry).createFile();
|
||||||
stream = (SecureDirectoryStream)dir1.newDirectoryStream();
|
stream = (SecureDirectoryStream<Path>)dir1.newDirectoryStream();
|
||||||
dir1.moveTo(dir2);
|
dir1.moveTo(dir2);
|
||||||
Iterator<Path> iter = stream.iterator();
|
Iterator<Path> iter = stream.iterator();
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
@ -227,10 +205,10 @@ public class SecureDS {
|
|||||||
Path target = Paths.get("newfile");
|
Path target = Paths.get("newfile");
|
||||||
|
|
||||||
// open stream to both directories
|
// open stream to both directories
|
||||||
SecureDirectoryStream stream1 =
|
SecureDirectoryStream<Path> stream1 =
|
||||||
(SecureDirectoryStream)dir1.newDirectoryStream();
|
(SecureDirectoryStream<Path>)dir1.newDirectoryStream();
|
||||||
SecureDirectoryStream stream2 =
|
SecureDirectoryStream<Path> stream2 =
|
||||||
(SecureDirectoryStream)dir2.newDirectoryStream();
|
(SecureDirectoryStream<Path>)dir2.newDirectoryStream();
|
||||||
|
|
||||||
// Test: move dir1/myfile -> dir2/newfile
|
// Test: move dir1/myfile -> dir2/newfile
|
||||||
stream1.move(fileEntry, stream2, target);
|
stream1.move(fileEntry, stream2, target);
|
||||||
@ -259,8 +237,8 @@ public class SecureDS {
|
|||||||
if (testDirAsString != null) {
|
if (testDirAsString != null) {
|
||||||
Path testDir = Paths.get(testDirAsString);
|
Path testDir = Paths.get(testDirAsString);
|
||||||
if (!dir1.getFileStore().equals(testDir.getFileStore())) {
|
if (!dir1.getFileStore().equals(testDir.getFileStore())) {
|
||||||
SecureDirectoryStream ts =
|
SecureDirectoryStream<Path> ts =
|
||||||
(SecureDirectoryStream)testDir.newDirectoryStream();
|
(SecureDirectoryStream<Path>)testDir.newDirectoryStream();
|
||||||
dir1.resolve(fileEntry).createFile();
|
dir1.resolve(fileEntry).createFile();
|
||||||
try {
|
try {
|
||||||
stream1.move(fileEntry, ts, target);
|
stream1.move(fileEntry, ts, target);
|
||||||
@ -281,8 +259,8 @@ public class SecureDS {
|
|||||||
Path file = Paths.get("file");
|
Path file = Paths.get("file");
|
||||||
dir.resolve(file).createFile();
|
dir.resolve(file).createFile();
|
||||||
|
|
||||||
SecureDirectoryStream stream =
|
SecureDirectoryStream<Path> stream =
|
||||||
(SecureDirectoryStream)dir.newDirectoryStream();
|
(SecureDirectoryStream<Path>)dir.newDirectoryStream();
|
||||||
|
|
||||||
// NullPointerException
|
// NullPointerException
|
||||||
try {
|
try {
|
||||||
@ -322,7 +300,7 @@ public class SecureDS {
|
|||||||
shouldNotGetHere();
|
shouldNotGetHere();
|
||||||
} catch (NullPointerException x) { }
|
} catch (NullPointerException x) { }
|
||||||
try {
|
try {
|
||||||
stream.newDirectoryStream(null, true, null);
|
stream.newDirectoryStream(null);
|
||||||
shouldNotGetHere();
|
shouldNotGetHere();
|
||||||
} catch (NullPointerException x) { }
|
} catch (NullPointerException x) { }
|
||||||
try {
|
try {
|
||||||
@ -340,7 +318,7 @@ public class SecureDS {
|
|||||||
|
|
||||||
// ClosedDirectoryStreamException
|
// ClosedDirectoryStreamException
|
||||||
try {
|
try {
|
||||||
stream.newDirectoryStream(file, true, null);
|
stream.newDirectoryStream(file);
|
||||||
shouldNotGetHere();
|
shouldNotGetHere();
|
||||||
} catch (ClosedDirectoryStreamException x) { }
|
} catch (ClosedDirectoryStreamException x) { }
|
||||||
try {
|
try {
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4313887
|
* @bug 4313887 6838333
|
||||||
* @summary Unit test for java.nio.file.FileSystem
|
* @summary Unit test for java.nio.file.FileSystem
|
||||||
* @library ..
|
* @library ..
|
||||||
*/
|
*/
|
||||||
@ -73,10 +73,10 @@ public class Basic {
|
|||||||
checkSupported(fs, "basic");
|
checkSupported(fs, "basic");
|
||||||
String os = System.getProperty("os.name");
|
String os = System.getProperty("os.name");
|
||||||
if (os.equals("SunOS"))
|
if (os.equals("SunOS"))
|
||||||
checkSupported(fs, "posix", "unix", "owner", "acl", "xattr");
|
checkSupported(fs, "posix", "unix", "owner", "acl", "user");
|
||||||
if (os.equals("Linux"))
|
if (os.equals("Linux"))
|
||||||
checkSupported(fs, "posix", "unix", "owner", "dos", "xattr");
|
checkSupported(fs, "posix", "unix", "owner", "dos", "user");
|
||||||
if (os.equals("Windows"))
|
if (os.equals("Windows"))
|
||||||
checkSupported(fs, "owner", "dos", "acl", "xattr");
|
checkSupported(fs, "owner", "dos", "acl", "user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,13 @@
|
|||||||
* have any questions.
|
* have any questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* @test
|
||||||
|
* @bug 4313887
|
||||||
|
* @summary Unit test for probeContentType method
|
||||||
|
* @library ..
|
||||||
|
* @build ContentType SimpleFileTypeDetector
|
||||||
|
*/
|
||||||
|
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
@ -30,7 +37,7 @@ import java.io.*;
|
|||||||
|
|
||||||
public class ContentType {
|
public class ContentType {
|
||||||
|
|
||||||
static FileRef createHtmlFile() throws IOException {
|
static Path createHtmlFile() throws IOException {
|
||||||
Path file = File.createTempFile("foo", ".html").toPath();
|
Path file = File.createTempFile("foo", ".html").toPath();
|
||||||
OutputStream out = file.newOutputStream();
|
OutputStream out = file.newOutputStream();
|
||||||
try {
|
try {
|
||||||
@ -42,18 +49,14 @@ public class ContentType {
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileRef createUnknownFile() throws IOException {
|
static Path createGrapeFile() throws IOException {
|
||||||
return File.createTempFile("unknown", "unknown-file-type-789").toPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
static FileRef createGrapeFile() throws IOException {
|
|
||||||
return File.createTempFile("red", ".grape").toPath();
|
return File.createTempFile("red", ".grape").toPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
// exercise default file type detector
|
// exercise default file type detector
|
||||||
FileRef file = createHtmlFile();
|
Path file = createHtmlFile();
|
||||||
try {
|
try {
|
||||||
String type = Files.probeContentType(file);
|
String type = Files.probeContentType(file);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
@ -63,16 +66,7 @@ public class ContentType {
|
|||||||
throw new RuntimeException("Unexpected type: " + type);
|
throw new RuntimeException("Unexpected type: " + type);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
TestUtil.deleteUnchecked(file);
|
file.delete();
|
||||||
}
|
|
||||||
file = createUnknownFile();
|
|
||||||
try {
|
|
||||||
String type = Files.probeContentType(file);
|
|
||||||
if (type != null)
|
|
||||||
throw new RuntimeException(file + " should not be recognized as:" +
|
|
||||||
type);
|
|
||||||
} finally {
|
|
||||||
TestUtil.deleteUnchecked(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// exercise custom file type detector
|
// exercise custom file type detector
|
||||||
@ -84,7 +78,7 @@ public class ContentType {
|
|||||||
if (!type.equals("grape/unknown"))
|
if (!type.equals("grape/unknown"))
|
||||||
throw new RuntimeException("Unexpected type: " + type);
|
throw new RuntimeException("Unexpected type: " + type);
|
||||||
} finally {
|
} finally {
|
||||||
TestUtil.deleteUnchecked(file);
|
file.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4313887
|
* @bug 4313887 6838333
|
||||||
* @summary Unit test for java.nio.file.Files for miscellenous cases not
|
* @summary Unit test for java.nio.file.Files for miscellenous cases not
|
||||||
* covered by other tests
|
* covered by other tests
|
||||||
* @library ..
|
* @library ..
|
||||||
@ -39,74 +39,66 @@ public class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
|
// -- Files.createDirectories --
|
||||||
|
|
||||||
|
Path dir = TestUtil.createTemporaryDirectory();
|
||||||
|
try {
|
||||||
|
// no-op
|
||||||
|
Files.createDirectories(dir);
|
||||||
|
|
||||||
|
// create one directory
|
||||||
|
Path subdir = dir.resolve("a");
|
||||||
|
Files.createDirectories(subdir);
|
||||||
|
if (!subdir.exists())
|
||||||
|
throw new RuntimeException("directory not created");
|
||||||
|
|
||||||
|
// create parents
|
||||||
|
subdir = subdir.resolve("b/c/d");
|
||||||
|
Files.createDirectories(subdir);
|
||||||
|
if (!subdir.exists())
|
||||||
|
throw new RuntimeException("directory not created");
|
||||||
|
|
||||||
|
// existing file is not a directory
|
||||||
|
Path file = dir.resolve("x").createFile();
|
||||||
|
try {
|
||||||
|
Files.createDirectories(file);
|
||||||
|
throw new RuntimeException("failure expected");
|
||||||
|
} catch (FileAlreadyExistsException x) { }
|
||||||
|
try {
|
||||||
|
Files.createDirectories(file.resolve("y"));
|
||||||
|
throw new RuntimeException("failure expected");
|
||||||
|
} catch (IOException x) { }
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
TestUtil.removeAll(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- NullPointerException --
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.probeContentType(null);
|
Files.probeContentType(null);
|
||||||
npeExpected();
|
npeExpected();
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
Files.withDirectory(null, "*", new FileAction<Path>() {
|
|
||||||
public void invoke(Path entry) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
npeExpected();
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Files.withDirectory(Paths.get("."), (String)null, new FileAction<Path>() {
|
|
||||||
public void invoke(Path entry) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
npeExpected();
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Files.withDirectory(Paths.get("."), "*", null);
|
|
||||||
npeExpected();
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// test propogation of IOException
|
|
||||||
Path tmpdir = TestUtil.createTemporaryDirectory();
|
|
||||||
try {
|
|
||||||
tmpdir.resolve("foo").createFile();
|
|
||||||
try {
|
|
||||||
Files.withDirectory(tmpdir, new FileAction<Path>() {
|
|
||||||
public void invoke(Path entry) throws IOException {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
throw new RuntimeException("IOException expected");
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
TestUtil.removeAll(tmpdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.walkFileTree(null, EnumSet.noneOf(FileVisitOption.class),
|
Files.walkFileTree(null, EnumSet.noneOf(FileVisitOption.class),
|
||||||
Integer.MAX_VALUE, new SimpleFileVisitor<Path>(){});
|
Integer.MAX_VALUE, new SimpleFileVisitor<Path>(){});
|
||||||
npeExpected();
|
npeExpected();
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE,
|
Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE,
|
||||||
new SimpleFileVisitor<Path>(){});
|
new SimpleFileVisitor<Path>(){});
|
||||||
npeExpected();
|
npeExpected();
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class),
|
Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class),
|
||||||
-1, new SimpleFileVisitor<Path>(){});
|
-1, new SimpleFileVisitor<Path>(){});
|
||||||
throw new RuntimeException("IllegalArgumentExpected expected");
|
throw new RuntimeException("IllegalArgumentExpected expected");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Set<FileVisitOption> opts = new HashSet<FileVisitOption>(1);
|
Set<FileVisitOption> opts = new HashSet<FileVisitOption>(1);
|
||||||
opts.add(null);
|
opts.add(null);
|
||||||
@ -115,7 +107,6 @@ public class Misc {
|
|||||||
npeExpected();
|
npeExpected();
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class),
|
Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class),
|
||||||
Integer.MAX_VALUE, null);
|
Integer.MAX_VALUE, null);
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2008-2009 Sun Microsystems, Inc. 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.
|
|
||||||
#
|
|
||||||
# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
||||||
# CA 95054 USA or visit www.sun.com if you need additional information or
|
|
||||||
# have any questions.
|
|
||||||
#
|
|
||||||
|
|
||||||
# @test
|
|
||||||
# @bug 4313887
|
|
||||||
# @summary Unit test for probeContentType method
|
|
||||||
# @library ..
|
|
||||||
# @build ContentType SimpleFileTypeDetector
|
|
||||||
# @run shell content_type.sh
|
|
||||||
|
|
||||||
# if TESTJAVA isn't set then we assume an interactive run.
|
|
||||||
|
|
||||||
if [ -z "$TESTJAVA" ]; then
|
|
||||||
TESTSRC=.
|
|
||||||
TESTCLASSES=.
|
|
||||||
JAVA=java
|
|
||||||
else
|
|
||||||
JAVA="${TESTJAVA}/bin/java"
|
|
||||||
fi
|
|
||||||
|
|
||||||
OS=`uname -s`
|
|
||||||
case "$OS" in
|
|
||||||
Windows_* )
|
|
||||||
CLASSPATH="${TESTCLASSES};${TESTSRC}"
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
CLASSPATH=${TESTCLASSES}:${TESTSRC}
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
export CLASSPATH
|
|
||||||
|
|
||||||
failures=0
|
|
||||||
|
|
||||||
go() {
|
|
||||||
echo ''
|
|
||||||
$JAVA $1 $2 $3 2>&1
|
|
||||||
if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run the test
|
|
||||||
|
|
||||||
go ContentType
|
|
||||||
|
|
||||||
#
|
|
||||||
# Results
|
|
||||||
#
|
|
||||||
echo ''
|
|
||||||
if [ $failures -gt 0 ];
|
|
||||||
then echo "$failures test(s) failed";
|
|
||||||
else echo "All test(s) passed"; fi
|
|
||||||
exit $failures
|
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4313887
|
* @bug 4313887 6838333
|
||||||
* @summary Unit test for java.nio.file.Path copyTo/moveTo methods
|
* @summary Unit test for java.nio.file.Path copyTo/moveTo methods
|
||||||
* @library ..
|
* @library ..
|
||||||
*/
|
*/
|
||||||
@ -69,9 +69,9 @@ public class CopyAndMove {
|
|||||||
assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink());
|
assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink());
|
||||||
assertTrue(attrs1.isOther() == attrs2.isOther());
|
assertTrue(attrs1.isOther() == attrs2.isOther());
|
||||||
|
|
||||||
// check last modified time (assume millisecond precision)
|
// check last modified time
|
||||||
long time1 = attrs1.resolution().toMillis(attrs1.lastModifiedTime());
|
long time1 = attrs1.lastModifiedTime().toMillis();
|
||||||
long time2 = attrs1.resolution().toMillis(attrs2.lastModifiedTime());
|
long time2 = attrs2.lastModifiedTime().toMillis();
|
||||||
assertTrue(time1 == time2);
|
assertTrue(time1 == time2);
|
||||||
|
|
||||||
// check size
|
// check size
|
||||||
|
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