提交 682dcc8a 编写于 作者: O ohair

Merge

...@@ -412,6 +412,7 @@ JAVA_JAVA_java = \ ...@@ -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 = \ ...@@ -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 = \ ...@@ -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 = \ ...@@ -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 = \ ...@@ -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 = \ ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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,&nbsp;suffix,&nbsp;null)}</code>. * createTempFile(prefix,&nbsp;suffix,&nbsp;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 ...@@ -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,&nbsp;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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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;
} }
} }
/*
* 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; ...@@ -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 { ...@@ -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 @@ ...@@ -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 ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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> ...@@ -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> ...@@ -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;
} }
/** /**
......
/*
* 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&nbsp;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>'&#92;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&lt;FileRef&gt; 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&lt;DirectoryStream.Filter&lt;? super Path&gt;&gt; filters = ...
* DirectoryStream.Filter&lt;Path&gt; 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,12 +26,13 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -42,9 +42,9 @@ import java.io.IOException;
* &#64;Override * &#64;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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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.
......
...@@ -35,7 +35,7 @@ import java.net.URI; ...@@ -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 { ...@@ -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; ...@@ -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; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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; ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 @@ ...@@ -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 { ...@@ -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; ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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; ...@@ -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; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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
*/ */
......
/*
* 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&nbsp;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; ...@@ -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.*; ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 ...@@ -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 { ...@@ -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
......
...@@ -270,7 +270,9 @@ public abstract class FileSystemProvider { ...@@ -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 { ...@@ -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> { ...@@ -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> { ...@@ -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 @@ ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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; ...@@ -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 ...@@ -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 @@ ...@@ -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 ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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();
} }
......
/*
* 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; ...@@ -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 ...@@ -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 ...@@ -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;
}
} }
...@@ -31,11 +31,11 @@ import java.io.IOException; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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>();
......
/* /*
* 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 @@ ...@@ -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&lt;Path&gt;() {
* public void invoke(Path entry) {
* :
* }
* });
* </pre>
*
* @param <T> the type of file reference
*
* @since 1.7
*/ */
public interface FileAction<T extends FileRef> { interface DynamicFileAttributeView {
/**
* Reads the value of an attribute.
*/
Object getAttribute(String attribute) throws IOException;
/**
* Sets/updates the value of an attribute.
*/
void setAttribute(String attribute, Object value) throws IOException;
/** /**
* Invoked for a file. * Reads a set of file attributes as a bulk operation.
*
* @param file
* the file
*
* @throws IOException
* if the block terminates due an uncaught I/O exception
*/ */
void invoke(T file) throws IOException; Map<String,?> readAttributes(String[] attributes) throws IOException;
} }
...@@ -34,7 +34,9 @@ import java.io.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 { ...@@ -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;
......
...@@ -265,7 +265,7 @@ class PollingWatchService ...@@ -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 ...@@ -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
......
/* /*
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * Copyright 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
...@@ -26,48 +26,34 @@ ...@@ -26,48 +26,34 @@
package sun.nio.fs; package sun.nio.fs;
/** /**
* Represents a MIME type for the purposes of validation and matching. For * Utility methods
* now this class is implemented using the javax.activation.MimeType class but
* this dependency can easily be eliminated when required.
*/ */
public class MimeType { class Util {
private final javax.activation.MimeType type; private Util() { }
private MimeType(javax.activation.MimeType type) {
this.type = type;
}
/** /**
* Parses the given string as a MIME type. * Splits a string around the given character. The array returned by this
* * method contains each substring that is terminated by the character. Use
* @throws IllegalArgumentException * for simple string spilting cases when needing to avoid loading regex.
* If the string is not a valid MIME type
*/ */
public static MimeType parse(String type) { static String[] split(String s, char c) {
try { int count = 0;
return new MimeType(new javax.activation.MimeType(type)); for (int i=0; i<s.length(); i++) {
} catch (javax.activation.MimeTypeParseException x) { if (s.charAt(i) == c)
throw new IllegalArgumentException(x); count++;
} }
} String[] result = new String[count+1];
int n = 0;
/** int last = 0;
* Returns {@code true} if this MIME type has parameters. for (int i=0; i<s.length(); i++) {
*/ if (s.charAt(i) == c) {
public boolean hasParameters() { result[n++] = s.substring(last, i);
return !type.getParameters().isEmpty(); last = i + 1;
} }
/**
* 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;
} }
result[n] = s.substring(last, s.length());
return result;
} }
} }
...@@ -127,8 +127,7 @@ public class Copy { ...@@ -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 { ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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.*; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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
*/ */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册