diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 83f3af7d968..58c7b13608c 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -412,6 +412,7 @@ JAVA_JAVA_java = \ java/io/FileReader.java \ java/io/PipedReader.java \ java/io/StringReader.java \ + java/io/TempFileHelper.java \ java/io/Writer.java \ java/io/BufferedWriter.java \ java/io/PrintWriter.java \ diff --git a/jdk/make/java/nio/FILES_java.gmk b/jdk/make/java/nio/FILES_java.gmk index 637b8dc4f96..4fb524a7dd4 100644 --- a/jdk/make/java/nio/FILES_java.gmk +++ b/jdk/make/java/nio/FILES_java.gmk @@ -86,8 +86,6 @@ FILES_src = \ java/nio/file/CopyOption.java \ java/nio/file/DirectoryNotEmptyException.java \ java/nio/file/DirectoryStream.java \ - java/nio/file/DirectoryStreamFilters.java \ - java/nio/file/FileAction.java \ java/nio/file/FileAlreadyExistsException.java \ java/nio/file/FileRef.java \ java/nio/file/FileStore.java \ @@ -141,6 +139,7 @@ FILES_src = \ java/nio/file/attribute/FileStoreAttributeView.java \ java/nio/file/attribute/FileStoreSpaceAttributeView.java \ java/nio/file/attribute/FileStoreSpaceAttributes.java \ + java/nio/file/attribute/FileTime.java \ java/nio/file/attribute/GroupPrincipal.java \ java/nio/file/attribute/UserDefinedFileAttributeView.java \ java/nio/file/attribute/PosixFileAttributeView.java \ @@ -151,7 +150,6 @@ FILES_src = \ java/nio/file/attribute/UserPrincipalLookupService.java \ java/nio/file/attribute/UserPrincipalNotFoundException.java \ \ - java/nio/file/spi/AbstractPath.java \ java/nio/file/spi/FileSystemProvider.java \ java/nio/file/spi/FileTypeDetector.java \ \ @@ -248,8 +246,8 @@ FILES_src = \ \ sun/nio/fs/AbstractAclFileAttributeView.java \ sun/nio/fs/AbstractBasicFileAttributeView.java \ - sun/nio/fs/AbstractFileStoreSpaceAttributeView.java \ sun/nio/fs/AbstractFileTypeDetector.java \ + sun/nio/fs/AbstractPath.java \ sun/nio/fs/AbstractPoller.java \ sun/nio/fs/AbstractUserDefinedFileAttributeView.java \ sun/nio/fs/AbstractWatchKey.java \ @@ -258,12 +256,13 @@ FILES_src = \ sun/nio/fs/Cancellable.java \ sun/nio/fs/DefaultFileSystemProvider.java \ sun/nio/fs/DefaultFileTypeDetector.java \ + sun/nio/fs/DynamicFileAttributeView.java \ sun/nio/fs/FileOwnerAttributeViewImpl.java \ sun/nio/fs/Globs.java \ - sun/nio/fs/MimeType.java \ sun/nio/fs/NativeBuffer.java \ sun/nio/fs/NativeBuffers.java \ sun/nio/fs/Reflect.java \ + sun/nio/fs/Util.java \ \ java/net/DatagramSocket.java \ java/net/DatagramSocketImpl.java \ diff --git a/jdk/make/java/nio/mapfile-linux b/jdk/make/java/nio/mapfile-linux index 13353edcdb7..79bdd1e5128 100644 --- a/jdk/make/java/nio/mapfile-linux +++ b/jdk/make/java/nio/mapfile-linux @@ -142,7 +142,7 @@ SUNWprivate_1.1 { Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0; Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0; 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_strerror; Java_sun_nio_fs_UnixNativeDispatcher_dup; diff --git a/jdk/make/java/nio/mapfile-solaris b/jdk/make/java/nio/mapfile-solaris index 129eaf477c0..b63fe38b8b5 100644 --- a/jdk/make/java/nio/mapfile-solaris +++ b/jdk/make/java/nio/mapfile-solaris @@ -120,7 +120,7 @@ SUNWprivate_1.1 { Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio; Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs; 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_strerror; Java_sun_nio_fs_UnixNativeDispatcher_dup; diff --git a/jdk/src/share/classes/java/io/File.java b/jdk/src/share/classes/java/io/File.java index 6e58efbbd6b..4f7a413839a 100644 --- a/jdk/src/share/classes/java/io/File.java +++ b/jdk/src/share/classes/java/io/File.java @@ -30,15 +30,15 @@ import java.net.URI; import java.net.URL; import java.net.MalformedURLException; import java.net.URISyntaxException; -import java.util.*; -import java.nio.file.*; -import java.nio.file.attribute.*; +import java.util.List; +import java.util.ArrayList; import java.security.AccessController; -import java.security.PrivilegedAction; 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; - /** * An abstract representation of file and directory pathnames. * @@ -787,7 +787,7 @@ public class File * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file * - * @see Attributes#readBasicFileAttributes + * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public boolean isDirectory() { SecurityManager security = System.getSecurityManager(); @@ -813,7 +813,7 @@ public class File * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file * - * @see Attributes#readBasicFileAttributes + * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public boolean isFile() { SecurityManager security = System.getSecurityManager(); @@ -863,7 +863,7 @@ public class File * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file * - * @see Attributes#readBasicFileAttributes + * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public long lastModified() { SecurityManager security = System.getSecurityManager(); @@ -887,7 +887,7 @@ public class File * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file * - * @see Attributes#readBasicFileAttributes + * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public long length() { SecurityManager security = System.getSecurityManager(); @@ -1369,9 +1369,10 @@ public class File * Sets the owner's or everybody's write permission for this abstract * pathname. * - *

The {@link Attributes Attributes} class defines methods that operate - * on file attributes including file permissions. This may be used when - * finer manipulation of file permissions is required. + *

The {@link java.nio.file.attribute.Attributes Attributes} class + * defines methods that operate on file attributes including file + * permissions. This may be used when finer manipulation of file permissions + * is required. * * @param writable * If true, sets the access permission to allow write @@ -1436,9 +1437,10 @@ public class File * Sets the owner's or everybody's read permission for this abstract * pathname. * - *

The {@link Attributes Attributes} class defines methods that operate - * on file attributes including file permissions. This may be used when - * finer manipulation of file permissions is required. + *

The {@link java.nio.file.attribute.Attributes Attributes} class + * defines methods that operate on file attributes including file + * permissions. This may be used when finer manipulation of file permissions + * is required. * * @param readable * If true, sets the access permission to allow read @@ -1509,9 +1511,10 @@ public class File * Sets the owner's or everybody's execute permission for this abstract * pathname. * - *

The {@link Attributes Attributes} class defines methods that operate - * on file attributes including file permissions. This may be used when - * finer manipulation of file permissions is required. + *

The {@link java.nio.file.attribute.Attributes Attributes} class + * defines methods that operate on file attributes including file + * permissions. This may be used when finer manipulation of file permissions + * is required. * * @param executable * If true, sets the access permission to allow execute @@ -1748,16 +1751,17 @@ public class File return fs.getSpace(this, FileSystem.SPACE_USABLE); } - /* -- Temporary files -- */ - private static class TemporaryDirectory { - private TemporaryDirectory() { } + static class TempDirectory { + private TempDirectory() { } - static final String valueAsString = fs.normalize( - AccessController.doPrivileged(new GetPropertyAction("java.io.tmpdir"))); - static final File valueAsFile = - new File(valueAsString, fs.prefixLength(valueAsString)); + // temporary directory location + private static final File tmpdir = new File(fs.normalize(AccessController + .doPrivileged(new GetPropertyAction("java.io.tmpdir")))); + static File location() { + return tmpdir; + } // file name generation private static final SecureRandom random = new SecureRandom(); @@ -1770,25 +1774,6 @@ public class File } return new File(dir, prefix + Long.toString(n) + suffix); } - - // default file permissions - static final FileAttribute> defaultPosixFilePermissions = - PosixFilePermissions.asFileAttribute(EnumSet - .of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)); - static final boolean isPosix = isPosix(); - static boolean isPosix() { - return AccessController.doPrivileged( - new PrivilegedAction() { - public Boolean run() { - try { - return FileSystems.getDefault().getPath(valueAsString) - .getFileStore().supportsFileAttributeView("posix"); - } catch (IOException e) { - throw new IOError(e); - } - } - }); - } } /** @@ -1869,12 +1854,11 @@ public class File if (suffix == null) suffix = ".tmp"; - File tmpdir = (directory != null) ? - directory : TemporaryDirectory.valueAsFile; + File tmpdir = (directory != null) ? directory : TempDirectory.location(); SecurityManager sm = System.getSecurityManager(); File f; do { - f = TemporaryDirectory.generateFile(prefix, suffix, tmpdir); + f = TempDirectory.generateFile(prefix, suffix, tmpdir); if (sm != null) { try { sm.checkWrite(f.getPath()); @@ -1891,11 +1875,17 @@ public class File /** * 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 {@link #createTempFile(java.lang.String, * java.lang.String, java.io.File) * createTempFile(prefix, suffix, null)}. * + *

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 * name; must be at least three characters long * @@ -1926,17 +1916,7 @@ public class File /** * Creates an empty file in the default temporary-file directory, using - * the given prefix and suffix to generate its name. This method is - * equivalent to invoking the {@link #createTempFile(String,String) - * createTempFile(prefix, suffix)} method with the addition that the - * resulting pathname may be requested to be deleted when the Java virtual - * machine terminates, and the initial file attributes to set atomically - * when creating the file may be specified. - * - *

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. + * the given prefix and suffix to generate its name. * *

The {@code attrs} parameter is an optional array of {@link FileAttribute * attributes} to set atomically when creating the file. Each attribute is @@ -1944,6 +1924,12 @@ public class File * of the same name is included in the array then all but the last occurrence * is ignored. * + *

Where the {@code attrs} parameter does not specify access + * permissions to set atomically when creating the file, then the + * resulting file may have more restrictive access permissions than files + * created by the {@link #createTempFile(java.lang.String, java.lang.String)} + * method. + * * @param prefix * The prefix string to be used in generating the file's * name; must be at least three characters long @@ -1951,9 +1937,6 @@ public class File * The suffix string to be used in generating the file's * name; may be {@code null}, in which case the suffix * {@code ".tmp"} will be used - * @param deleteOnExit - * {@code true} if the file denoted by resulting pathname be - * deleted when the Java virtual machine terminates * @param attrs * An optional list of file attributes to set atomically when creating * the file @@ -1961,7 +1944,7 @@ public class File * @return An abstract pathname denoting a newly-created empty file * * @throws IllegalArgumentException - * If the prefix argument contains fewer than three + * If the {@code prefix} argument contains fewer than three * characters * @throws UnsupportedOperationException * If the array contains an attribute that cannot be set atomically @@ -1971,74 +1954,19 @@ public class File * @throws SecurityException * If a security manager exists and its {@link * java.lang.SecurityManager#checkWrite(java.lang.String)} - * method does not allow a file to be created. When the {@code - * 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. + * method does not allow a file to be created. + * * @since 1.7 */ - public static File createTempFile(String prefix, - String suffix, - boolean deleteOnExit, - FileAttribute... attrs) + public static File createTemporaryFile(String prefix, + String suffix, + FileAttribute... attrs) throws IOException { if (prefix.length() < 3) throw new IllegalArgumentException("Prefix string too short"); suffix = (suffix == null) ? ".tmp" : suffix; - - // 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[] 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 - } - } + return TempFileHelper.createFile(prefix, suffix, attrs); } /* -- Basic infrastructure -- */ @@ -2153,40 +2081,45 @@ public class File /** * Returns a {@link Path java.nio.file.Path} object constructed from the - * this abstract path. The first invocation of this method works as if - * invoking it were equivalent to evaluating the expression: + * this abstract path. The resulting {@code Path} is associated with the + * {@link java.nio.file.FileSystems#getDefault default-filesystem}. + * + *

The first invocation of this method works as if invoking it were + * equivalent to evaluating the expression: *

-     * {@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}());
      * 
* Subsequent invocations of this method return the same {@code Path}. * *

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. * - * @return A {@code Path} constructed from this abstract path. The resulting - * {@code Path} is associated with the {@link FileSystems#getDefault - * default-filesystem}. + * @return a {@code Path} constructed from this abstract path * * @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}) * * @since 1.7 */ public Path toPath() { - if (filePath == null) { + Path result = filePath; + if (result == null) { synchronized (this) { - if (filePath == null) { + result = filePath; + if (result == null) { if (path.length() == 0) { // assume default file system treats "." as current directory - filePath = Paths.get("."); + result = Paths.get("."); } else { - filePath = Paths.get(path); + result = Paths.get(path); } + filePath = result; } } } - return filePath; + return result; } } diff --git a/jdk/src/share/classes/java/io/TempFileHelper.java b/jdk/src/share/classes/java/io/TempFileHelper.java new file mode 100644 index 00000000000..f3b518a2690 --- /dev/null +++ b/jdk/src/share/classes/java/io/TempFileHelper.java @@ -0,0 +1,139 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.io; + +import java.nio.file.FileSystems; +import java.nio.file.InvalidPathException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import static java.nio.file.attribute.PosixFilePermission.*; +import java.util.Set; +import java.util.EnumSet; + +/** + * Helper class to support creation of temporary files and directory with + * initial attributes. + */ + +class TempFileHelper { + private TempFileHelper() { } + + // default file and directory permissions (lazily initialized) + private static class PermissionsHolder { + static final boolean hasPosixPermissions = FileSystems.getDefault() + .supportedFileAttributeViews().contains("posix"); + static final FileAttribute> filePermissions = + PosixFilePermissions.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE)); + static final FileAttribute> 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[] 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); + } +} diff --git a/jdk/src/share/classes/java/lang/management/PlatformComponent.java b/jdk/src/share/classes/java/lang/management/PlatformComponent.java index 77c01161c91..3dc5a68400d 100644 --- a/jdk/src/share/classes/java/lang/management/PlatformComponent.java +++ b/jdk/src/share/classes/java/lang/management/PlatformComponent.java @@ -34,7 +34,6 @@ import java.util.logging.LoggingMXBean; import java.util.logging.LogManager; import java.nio.BufferPoolMXBean; import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import com.sun.management.HotSpotDiagnosticMXBean; @@ -198,10 +197,7 @@ enum PlatformComponent { "java.nio", "BufferPool", keyProperties("name"), new MXBeanFetcher() { public List getMXBeans() { - List pools = new ArrayList(2); - pools.add( sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPoolMXBean() ); - pools.add( sun.nio.ch.FileChannelImpl.getMappedBufferPoolMXBean() ); - return pools; + return ManagementFactoryHelper.getBufferPoolMXBeans(); } }), diff --git a/jdk/src/share/classes/java/nio/Bits.java b/jdk/src/share/classes/java/nio/Bits.java index 8627103a531..19f6f10b409 100644 --- a/jdk/src/share/classes/java/nio/Bits.java +++ b/jdk/src/share/classes/java/nio/Bits.java @@ -26,11 +26,8 @@ package java.nio; import java.security.AccessController; -import java.security.PrivilegedAction; import sun.misc.Unsafe; import sun.misc.VM; -import javax.management.ObjectName; -import javax.management.MalformedObjectNameException; /** * Access to bits, native and otherwise. @@ -676,55 +673,34 @@ class Bits { // package-private } } - // -- Management interface for monitoring of direct buffer usage -- + // -- Monitoring of direct buffer usage -- static { // setup access to this package in SharedSecrets sun.misc.SharedSecrets.setJavaNioAccess( new sun.misc.JavaNioAccess() { @Override - public BufferPoolMXBean getDirectBufferPoolMXBean() { - return LazyInitialization.directBufferPoolMXBean; + public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() { + 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 -- diff --git a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java index a977626351e..790a3333f74 100644 --- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java +++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java @@ -30,7 +30,6 @@ package java.nio; import sun.misc.Cleaner; import sun.misc.Unsafe; import sun.nio.ch.DirectBuffer; -import sun.nio.ch.FileChannelImpl; class Direct$Type$Buffer$RW$$BO$ diff --git a/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java index 33efc248861..0334ee7a985 100644 --- a/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java +++ b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java @@ -47,7 +47,7 @@ import java.io.IOException; * so that method invocations on the implementation class can be chained. * * @since 1.7 - * @see java.nio.file.FileRef#newByteChannel + * @see java.nio.file.Path#newByteChannel */ public interface SeekableByteChannel diff --git a/jdk/src/share/classes/java/nio/file/AccessMode.java b/jdk/src/share/classes/java/nio/file/AccessMode.java index 240837681ee..3c18f93fb01 100644 --- a/jdk/src/share/classes/java/nio/file/AccessMode.java +++ b/jdk/src/share/classes/java/nio/file/AccessMode.java @@ -30,7 +30,7 @@ package java.nio.file; * * @since 1.7 * - * @see FileRef#checkAccess + * @see Path#checkAccess */ public enum AccessMode { diff --git a/jdk/src/share/classes/java/nio/file/DirectoryStream.java b/jdk/src/share/classes/java/nio/file/DirectoryStream.java index 589d7b4f5e9..001f22b0723 100644 --- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java @@ -27,6 +27,7 @@ package java.nio.file; import java.util.Iterator; import java.io.Closeable; +import java.io.IOException; /** * An object to iterate over the entries in a directory. A directory stream @@ -50,13 +51,10 @@ import java.io.Closeable; * *

A {@code DirectoryStream} is opened upon creation and is closed by * invoking the {@link #close close} method. Closing the directory stream - * releases any resources associated with the stream. The {@link - * Files#withDirectory Files.withDirectory} utility method is useful for cases - * where a task is performed on entries in a directory. This method automatically - * closes the directory stream when iteration is complete (or an error occurs). - * Once a directory stream is closed, all further method invocations on the - * iterator throw {@link java.util.concurrent.ConcurrentModificationException} - * with cause {@link ClosedDirectoryStreamException}. + * releases any resources associated with the stream. Once a directory stream + * is closed, all further method invocations on the iterator throw {@link + * java.util.concurrent.ConcurrentModificationException} with cause {@link + * ClosedDirectoryStreamException}. * *

A directory stream is not required to be asynchronously closeable. * If a thread is blocked on the directory stream's iterator reading from the @@ -79,7 +77,7 @@ import java.io.Closeable; * *

The iterator's {@link Iterator#remove() remove} method removes the * 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 * thrown with the cause. * @@ -104,10 +102,6 @@ public interface DirectoryStream * newDirectoryStream} method when opening a directory to iterate over the * entries in the directory. * - *

The {@link DirectoryStreamFilters} class defines factory methods to - * create filters for a number of common usages and also methods to combine - * filters. - * * @param the type of the directory entry * * @since 1.7 @@ -120,8 +114,11 @@ public interface DirectoryStream * the directory entry to be tested * * @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; } /** diff --git a/jdk/src/share/classes/java/nio/file/DirectoryStreamFilters.java b/jdk/src/share/classes/java/nio/file/DirectoryStreamFilters.java deleted file mode 100644 index b582bbf93bc..00000000000 --- a/jdk/src/share/classes/java/nio/file/DirectoryStreamFilters.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.nio.file; - -import java.io.IOException; -import java.io.IOError; -import sun.nio.fs.MimeType; - -/** - * This class consists exclusively of static methods that construct or combine - * filters. - * - * @since 1.7 - */ - -public final class DirectoryStreamFilters { - private DirectoryStreamFilters() { } - - /** - * Constructs a directory stream filter that filters directory entries by - * their MIME 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. - * - *

The {@code type} parameter is the value of a Multipurpose Internet - * Mail Extension (MIME) content type as defined by RFC 2045: Multipurpose - * Internet Mail Extensions (MIME) Part One: Format of Internet Message - * Bodies. It is parsable according to the grammar in the RFC. Any - * space characters ('\u0020') 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. - * - *

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. - * - *

Usage Example: - * Suppose we require to list only the HTML files in a directory. - *

-     *     DirectoryStream.Filter<FileRef> filter =
-     *         DirectoryStreamFilters.newContentTypeFilter("text/html");
-     * 
- * - * @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 DirectoryStream.Filter - newContentTypeFilter(String type) - { - final MimeType matchType = MimeType.parse(type); - if (matchType.hasParameters()) - throw new IllegalArgumentException("Parameters not allowed"); - return new DirectoryStream.Filter() { - @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. - * - *

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. - * - *

Usage Example: - *

-     *     List<DirectoryStream.Filter<? super Path>> filters = ...
-     *     DirectoryStream.Filter<Path> filter = DirectoryStreamFilters.allOf(filters);
-     * 
- * - * @param filters - * the sequence of filters - * - * @return the resulting filter - */ - public static DirectoryStream.Filter - allOf(final Iterable> filters) - { - if (filters == null) - throw new NullPointerException("'filters' is null"); - return new DirectoryStream.Filter() { - @Override - public boolean accept(T entry) { - for (DirectoryStream.Filter 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. - * - *

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 DirectoryStream.Filter - anyOf(final Iterable> filters) - { - if (filters == null) - throw new NullPointerException("'filters' is null"); - return new DirectoryStream.Filter() { - @Override - public boolean accept(T entry) { - for (DirectoryStream.Filter filter: filters) { - if (filter.accept(entry)) - return true; - } - return false; - } - }; - } - - /** - * Returns a directory stream filter that is the complement 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 DirectoryStream.Filter - complementOf(final DirectoryStream.Filter filter) - { - if (filter == null) - throw new NullPointerException("'filter' is null"); - return new DirectoryStream.Filter() { - @Override - public boolean accept(T entry) { - return !filter.accept(entry); - } - }; - } -} diff --git a/jdk/src/share/classes/java/nio/file/FileRef.java b/jdk/src/share/classes/java/nio/file/FileRef.java index 2606a879c75..8a19ce285c2 100644 --- a/jdk/src/share/classes/java/nio/file/FileRef.java +++ b/jdk/src/share/classes/java/nio/file/FileRef.java @@ -26,225 +26,85 @@ package java.nio.file; import java.nio.file.attribute.*; -import java.nio.channels.SeekableByteChannel; +import java.util.Map; +import java.io.InputStream; +import java.io.OutputStream; import java.io.IOException; /** * A reference to a file. * *

A {@code FileRef} is an object that locates a file and defines methods to - * access the file. The means by which the file is located depends on the - * implementation. In many cases, a file is located by a {@link Path} but it may - * be located by other means such as a file-system identifier. - * - *

This interface defines the following operations: - *

    - *
  • The {@link #newByteChannel newByteChannel} method - * may be used to open a file and obtain a byte channel for reading or - * writing.

  • - *
  • The {@link #delete delete} method may be used to delete a file. - *

  • - *
  • The {@link #checkAccess checkAccess} method may be used to check - * the existence or accessibility of a file.

  • - *
  • The {@link #isSameFile isSameFile} method may be used to test if - * two file references locate the same file.

  • - *
  • The {@link #getFileStore getFileStore} method may be used to - * obtain the {@link FileStore} representing the storage where a file is - * located.

  • - *
- * - *

Access to associated metadata or file attributes requires an appropriate - * {@link FileAttributeView FileAttributeView}. The {@link - * #getFileAttributeView(Class,LinkOption[]) getFileAttributeView(Class,LinkOption[])} - * method may be used to obtain a file attribute view that defines type-safe - * methods to read or update file attributes. The {@link - * #getFileAttributeView(String,LinkOption[]) getFileAttributeView(String,LinkOption[])} - * method may be used to obtain a file attribute view where dynamic access to - * file attributes where required. - * - *

A {@code FileRef} is immutable and safe for use by multiple concurrent - * threads. + * open the file for reading or writing. It also provides access to associated + * metadata or file attributes. * * @since 1.7 + * @see java.io.Inputs + * @see java.io.Outputs + * @see java.nio.file.attribute.Attributes + * @see java.io.File#toPath */ public interface FileRef { /** - * Opens the file referenced by this object, returning a seekable byte - * channel to access the file. + * Opens the file referenced by this object, returning an input stream to + * read from the file. The stream will not be buffered, and is not required + * to support the {@link InputStream#mark mark} or {@link InputStream#reset + * reset} methods. The stream will be safe for access by multiple concurrent + * threads. Reading commences at the beginning of the file. * *

The {@code options} parameter determines how the file is opened. - * The {@link StandardOpenOption#READ READ} and {@link StandardOpenOption#WRITE - * WRITE} options determine if the file should be opened for reading and/or - * writing. If neither option (or the {@link StandardOpenOption#APPEND APPEND} - * option) is contained in the array then the file is opened for reading. - * By default reading or writing commences at the beginning of the file. + * If no options are present then it is equivalent to opening the file with + * the {@link StandardOpenOption#READ READ} option. In addition to the {@code + * READ} option, an implementation may also support additional implementation + * specific options. * - *

In the addition to {@code READ} and {@code WRITE}, the following - * options may be present: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Option Description
{@link StandardOpenOption#APPEND APPEND} If this option is present then the file is opened for writing and - * each invocation of the channel's {@code write} method first advances - * the position to the end of the file and then writes the requested - * data. Whether the advancement of the position and the writing of the - * data are done in a single atomic operation is system-dependent and - * therefore unspecified. This option may not be used in conjunction - * with the {@code READ} or {@code TRUNCATE_EXISTING} options.
{@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} If this option is present then the existing file is truncated to - * a size of 0 bytes. This option is ignored when the file is opened only - * for reading.
{@link StandardOpenOption#SYNC SYNC} Requires that every update to the file's content or metadata be - * written synchronously to the underlying storage device. (see Synchronized I/O file - * integrity).
{@link StandardOpenOption#DSYNC DSYNC} Requires that every update to the file's content be written - * synchronously to the underlying storage device. (see Synchronized I/O file - * integrity).
- * - *

An implementation of this interface may support additional options - * defined by the {@link StandardOpenOption} enumeration type or other - * implementation specific options. - * - *

The {@link java.nio.channels.Channels} utility classes defines methods - * to construct input and output streams where inter-operation with the - * {@link java.io} package is required. - * - * @param options - * Options specifying how the file is opened - * - * @return a new seekable byte channel + * @return an input stream to read bytes from the file * * @throws IllegalArgumentException - * If an invalid combination of options is specified + * if an invalid combination of options is specified * @throws UnsupportedOperationException - * If an unsupported open option is specified + * if an unsupported option is specified * @throws IOException - * If an I/O error occurs + * if an I/O error occurs * @throws SecurityException * In the case of the default provider, and a security manager is * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the path if the file is - * opened for reading. The {@link SecurityManager#checkWrite(String) - * checkWrite} method is invoked to check write access to the path - * if the file is opened for writing. + * method is invoked to check read access to the file. */ - SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException; + InputStream newInputStream(OpenOption... options) throws IOException; /** - * Returns the {@link FileStore} representing the file store where the file - * referenced by this object is stored. + * Opens or creates the file located by this object for writing, returning + * an output stream to write bytes to the file. * - *

Once a reference to the {@code FileStore} is obtained it is - * implementation specific if operations on the returned {@code FileStore}, - * or {@link FileStoreAttributeView} objects obtained from it, continue - * to depend on the existence of the file. In particular the behavior is not - * defined for the case that the file is deleted or moved to a different - * file store. + *

The {@code options} parameter determines how the file is opened. + * If no options are present then this method creates a new file for writing + * or truncates an existing file. In addition to the {@link StandardOpenOption + * standard} options, an implementation may also support additional + * implementation specific options. * - * @return The file store where the file is stored + *

The resulting stream will not be buffered. The stream will be safe + * for access by multiple concurrent threads. * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the file, and in - * addition it checks {@link RuntimePermission} - * ("getFileStoreAttributes") - */ - FileStore getFileStore() throws IOException; - - /** - * Checks the existence and optionally the accessibility of the file - * referenced by this object. + * @param options + * options specifying how the file is opened * - *

This method checks the existence of a file and that this Java virtual - * machine has appropriate privileges that would allow it access the file - * according to all of access modes specified in the {@code modes} parameter - * as follows: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Value Description
{@link AccessMode#READ READ} Checks that the file exists and that the Java virtual machine has - * permission to read the file.
{@link AccessMode#WRITE WRITE} Checks that the file exists and that the Java virtual machine has - * permission to write to the file,
{@link AccessMode#EXECUTE EXECUTE} Checks that the file exists and that the Java virtual machine has - * permission to {@link Runtime#exec execute} the file. The semantics - * may differ when checking access to a directory. For example, on UNIX - * systems, checking for {@code EXECUTE} access checks that the Java - * virtual machine has permission to search the directory in order to - * access file or subdirectories.
- * - *

If the {@code modes} parameter is of length zero, then the existence - * of the file is checked. - * - *

This method follows symbolic links if the file referenced by this - * object is a symbolic link. Depending on the implementation, this method - * may require to read file permissions, access control lists, or other - * file attributes in order to check the effective access to the file. To - * determine the effective access to a file may require access to several - * attributes and so in some implementations this method may not be atomic - * with respect to other file system operations. Furthermore, as the result - * of this method is immediately outdated, there is no guarantee that a - * subsequence access will succeed (or even that it will access the same - * file). Care should be taken when using this method in security sensitive - * applications. - * - * @param modes - * The access modes to check; may have zero elements + * @return a new output stream * + * @throws IllegalArgumentException + * if {@code options} contains an invalid combination of options * @throws UnsupportedOperationException - * An implementation is required to support checking for - * {@code READ}, {@code WRITE}, and {@code EXECUTE} access. This - * exception is specified to allow for the {@code Access} enum to - * be extended in future releases. - * @throws NoSuchFileException - * If a file does not exist (optional specific exception) - * @throws AccessDeniedException - * The requested access would be denied or the access cannot be - * determined because the Java virtual machine has insufficient - * privileges or other reasons. (optional specific exception) + * if an unsupported option is specified * @throws IOException - * If an I/O error occurs + * if an I/O error occurs * @throws SecurityException * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * is invoked when checking read access to the file or only the - * existence of the file, the {@link SecurityManager#checkWrite(String) - * checkWrite} is invoked when checking write access to the file, - * and {@link SecurityManager#checkExec(String) checkExec} is invoked - * when checking execute access. + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. */ - void checkAccess(AccessMode... modes) throws IOException; + OutputStream newOutputStream(OpenOption... options) throws IOException; /** * Returns a file attribute view of a given type. @@ -266,11 +126,11 @@ public interface FileRef { * that do not support symbolic links. * * @param type - * The {@code Class} object corresponding to the file attribute view + * the {@code Class} object corresponding to the file attribute view * @param options - * Options indicating how symbolic links are handled + * options indicating how symbolic links are handled * - * @return A file attribute view of the specified type, or {@code null} if + * @return a file attribute view of the specified type, or {@code null} if * the attribute view type is not available * * @throws UnsupportedOperationException @@ -280,145 +140,185 @@ public interface FileRef { * * @see Attributes#readBasicFileAttributes */ - V getFileAttributeView(Class type, LinkOption... options); + V getFileAttributeView(Class type, + LinkOption... options); /** - * Returns a file attribute view of the given name. + * Sets the value of a file attribute. * - *

A file attribute view provides a read-only or updatable view of a - * set of file attributes. This method is intended to be used where - * dynamic access to the file attributes is required. The {@code - * name} parameter specifies the {@link FileAttributeView#name name} of the - * file attribute view and this method returns an instance of that view if - * supported. The {@link BasicFileAttributeView} type supports access to the - * basic attributes of a file and is name {@code "basic"}. Invoking this - * method to select a file attribute view named {@code "basic"} will always - * return an instance of that class. + *

The {@code attribute} parameter identifies the attribute to be set + * and takes the form: + *

+ * [view-name:]attribute-name + *
+ * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + *

view-name 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. attribute-name is the name of the attribute + * within the set. + * + *

Usage Example: + * Suppose we want to set the DOS "hidden" attribute: + *

+     *    file.setAttribute("dos:hidden", true);
+     * 
+ * + * @param attribute + * the attribute to set + * @param value + * the attribute value + * @param options + * options indicating how symbolic links are handled + * + * @throws UnsupportedOperationException + * if the attribute view is not available or it does not support + * updating the attribute + * @throws IllegalArgumentException + * if the attribute value is of the correct type but has an + * inappropriate value + * @throws ClassCastException + * If the attribute value is not of the expected type or is a + * collection containing elements that are not of the expected + * type + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the file. If this method is invoked + * to set security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + void setAttribute(String attribute, Object value, LinkOption... options) + throws IOException; + + /** + * Reads the value of a file attribute. + * + *

The {@code attribute} parameter identifies the attribute to be read + * and takes the form: + *

+ * [view-name:]attribute-name + *
+ * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + *

view-name 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. attribute-name is the name of the attribute. * *

The {@code options} array may be used to indicate how symbolic links - * are handled by the resulting file attribute view for the case that the - * file is a symbolic link. By default, symbolic links are followed. If the - * option {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} is present then - * symbolic links are not followed. This option is ignored by implementations - * that do not support symbolic links. + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed and so + * the method returns the file attribute of the symbolic link. * - * @param name - * The name of the file attribute view + *

Usage Example: + * Suppose we require the user ID of the file owner on a system that + * supports a "{@code unix}" view: + *

+     *    int uid = (Integer)file.getAttribute("unix:uid");
+     * 
+ * + * @param attribute + * the attribute to read + * @param options + * options indicating how symbolic links are handled + * @return the attribute value or {@code null} if the attribute view + * is not available or it does not support reading the attribute + * + * reading the attribute + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. If this method is invoked + * to read security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + Object getAttribute(String attribute, LinkOption... options) throws IOException; + + /** + * Reads a set of file attributes as a bulk operation. + * + *

The {@code attributes} parameter identifies the attributes to be read + * and takes the form: + *

+ * [view-name:]attribute-list + *
+ * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + *

view-name 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. + * + *

The attribute-list 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. + * + *

The following examples demonstrate possible values for the {@code + * attributes} parameter: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
{@code "*"} Read all {@link BasicFileAttributes basic-file-attributes}.
{@code "size,lastModifiedTime,lastAccessTime"} Reads the file size, last modified time, and last access time + * attributes.
{@code "posix:*"} Read all {@link PosixFileAttributes POSIX-file-attributes}..
{@code "posix:permissions,owner,size"} Reads the POSX file permissions, owner, and file size.
+ *
+ * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed and so + * the method returns the file attribute of the symbolic link. + * + * @param attributes + * The attributes to read * @param options * Options indicating how symbolic links are handled * - * @return A file attribute view of the given name, or {@code null} if - * the attribute view is not available - * - * @throws UnsupportedOperationException - * If options contains an unsupported option. This exception is - * specified to allow the {@code LinkOption} enum be extended - * in future releases. - */ - FileAttributeView getFileAttributeView(String name, LinkOption... options); - - /** - * Tests if the file referenced by this object is the same file referenced - * by another object. - * - *

If this {@code FileRef} and the given {@code FileRef} are {@link - * #equals(Object) equal} then this method returns {@code true} without checking - * if the file exists. If the {@code FileRef} and the given {@code FileRef} - * are associated with different providers, or the given {@code FileRef} is - * {@code null} then this method returns {@code false}. Otherwise, this method - * checks if both {@code FileRefs} locate the same file, and depending on the - * implementation, may require to open or access both files. - * - *

If the file system and files remain static, then this method implements - * an equivalence relation for non-null {@code FileRefs}. - *

    - *
  • It is reflexive: for a non-null {@code FileRef} {@code f}, - * {@code f.isSameFile(f)} should return {@code true}. - *
  • It is symmetric: for two non-null {@code FileRefs} - * {@code f} and {@code g}, {@code f.isSameFile(g)} will equal - * {@code g.isSameFile(f)}. - *
  • It is transitive: for three {@code FileRefs} - * {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns - * {@code true} and {@code g.isSameFile(h)} returns {@code true}, then - * {@code f.isSameFile(h)} will return return {@code true}. - *
- * - * @param other - * The other file reference - * - * @return {@code true} if, and only if, this object and the given object - * locate the same file + * @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, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to both files. - * - * @see java.nio.file.attribute.BasicFileAttributes#fileKey + * 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. */ - boolean isSameFile(FileRef other) throws IOException; - - /** - * Deletes the file referenced by this object. - * - *

An implementation may require to examine the file to determine if the - * file is a directory. Consequently this method may not be atomic with respect - * to other file system operations. If the file is a symbolic-link then the - * link is deleted and not the final target of the link. - * - *

If the file is a directory then the directory must be empty. In some - * implementations a directory has entries for special files or links that - * are created when the directory is created. In such implementations a - * directory is considered empty when only the special entries exist. - * - *

On some operating systems it may not be possible to remove a file when - * it is open and in use by this Java virtual machine or other programs. - * - * @throws NoSuchFileException - * If the file does not exist (optional specific exception) - * @throws DirectoryNotEmptyException - * If the file is a directory and could not otherwise be deleted - * because the directory is not empty (optional specific - * exception) - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkDelete(String)} method - * is invoked to check delete access to the file - */ - void delete() throws IOException; - - /** - * Tests this object for equality with another object. - * - *

If the given object is not a {@code FileRef} then this method - * immediately returns {@code false}. - * - *

For two file references to be considered equal requires that they - * are both the same type of {@code FileRef} and encapsulate components - * to locate the same file. This method does not access the file system and - * the file may not exist. - * - *

This method satisfies the general contract of the {@link - * java.lang.Object#equals(Object) Object.equals} method.

- * - * @param ob The object to which this object is to be compared - * - * @return {@code true} if, and only if, the given object is a {@code FileRef} - * that is identical to this {@code FileRef} - * - * @see #isSameFile - */ - boolean equals(Object ob); - - /** - * Returns the hash-code value for this object. - * - *

This method satisfies the general contract of the - * {@link java.lang.Object#hashCode() Object.hashCode} method. - */ - int hashCode(); + Map readAttributes(String attributes, LinkOption... options) + throws IOException; } diff --git a/jdk/src/share/classes/java/nio/file/FileStore.java b/jdk/src/share/classes/java/nio/file/FileStore.java index 3f8df103129..f837a532d83 100644 --- a/jdk/src/share/classes/java/nio/file/FileStore.java +++ b/jdk/src/share/classes/java/nio/file/FileStore.java @@ -26,12 +26,13 @@ package java.nio.file; import java.nio.file.attribute.*; +import java.io.IOException; /** * Storage for files. A {@code FileStore} represents a storage pool, device, * partition, volume, concrete file system or other implementation specific means * of file storage. The {@code FileStore} for where a file is stored is obtained - * by invoking the {@link 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 * getFileStores} method. * @@ -146,24 +147,41 @@ public abstract class FileStore { getFileStoreAttributeView(Class type); /** - * Returns a {@code FileStoreAttributeView} of the given name. + * Reads the value of a file store attribute. * - *

This method is intended to be used where dynamic access to - * file store attributes is required. The {@code name} parameter specifies - * the {@link FileAttributeView#name name} of the file store attribute view - * and this method returns an instance of that view if supported. + *

The {@code attribute} parameter identifies the attribute to be read + * and takes the form: + *

+ * view-name:attribute-name + *
+ * where the character {@code ':'} stands for itself. + * + *

view-name is the {@link FileStoreAttributeView#name name} of + * a {@link FileStore AttributeView} that identifies a set of file attributes. + * attribute-name is the name of the attribute. * *

For {@code FileStore} objects created by the default provider, then * the file stores support the {@link FileStoreSpaceAttributeView} that - * provides access to space attributes. In that case invoking this method - * with a parameter value of {@code "space"} will always return an instance - * of that class. + * provides access to space attributes. * - * @param name - * the name of the attribute view + *

Usage Example: + * Suppose we want to know if ZFS compression is enabled (assuming the "zfs" + * view is supported): + *

+     *    boolean compression = (Boolean)fs.getAttribute("zfs:compression");
+     * 
* - * @return a file store attribute view of the given name, or {@code null} - * if the attribute view is not available + * @param attribute + * 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; } diff --git a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java index 95148a5b50d..71cb86eb88a 100644 --- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java +++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java @@ -50,8 +50,6 @@ class FileTreeWalker { case FOLLOW_LINKS : fl = true; break; case DETECT_CYCLES : dc = true; break; default: - if (option == null) - throw new NullPointerException("Visit options contains 'null'"); throw new AssertionError("Should not get here"); } } @@ -239,13 +237,13 @@ class FileTreeWalker { } private static class AncestorDirectory { - private final FileRef dir; + private final Path dir; private final Object key; - AncestorDirectory(FileRef dir, Object key) { + AncestorDirectory(Path dir, Object key) { this.dir = dir; this.key = key; } - FileRef file() { + Path file() { return dir; } Object fileKey() { diff --git a/jdk/src/share/classes/java/nio/file/FileVisitor.java b/jdk/src/share/classes/java/nio/file/FileVisitor.java index 6d65eba27a9..26e5abbeed0 100644 --- a/jdk/src/share/classes/java/nio/file/FileVisitor.java +++ b/jdk/src/share/classes/java/nio/file/FileVisitor.java @@ -42,9 +42,9 @@ import java.io.IOException; * @Override * public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { * try { - * file.delete(false); + * file.delete(); * } catch (IOException exc) { - * // failed to delete + * // failed to delete, do error handling here * } * return FileVisitResult.CONTINUE; * } @@ -52,9 +52,9 @@ import java.io.IOException; * public FileVisitResult postVisitDirectory(Path dir, IOException e) { * if (e == null) { * try { - * dir.delete(false); + * dir.delete(); * } catch (IOException exc) { - * // failed to delete + * // failed to delete, do error handling here * } * } else { * // directory iteration failed @@ -80,7 +80,8 @@ import java.io.IOException; * } catch (FileAlreadyExistsException e) { * // ignore * } 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 CONTINUE; @@ -90,7 +91,7 @@ import java.io.IOException; * try { * file.copyTo(target.resolve(source.relativize(file))); * } catch (IOException e) { - * // copy failed + * // copy failed, do error handling here * } * return CONTINUE; * } @@ -100,7 +101,7 @@ import java.io.IOException; * @since 1.7 */ -public interface FileVisitor { +public interface FileVisitor { /** * Invoked for a directory before entries in the directory are visited. diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java index 42fdad823b3..00e1014526c 100644 --- a/jdk/src/share/classes/java/nio/file/Files.java +++ b/jdk/src/share/classes/java/nio/file/Files.java @@ -26,13 +26,15 @@ package java.nio.file; import java.nio.file.spi.FileTypeDetector; +import java.nio.file.attribute.*; import java.io.IOException; import java.util.*; import java.security.AccessController; 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 */ @@ -109,8 +111,6 @@ public final class Files { * @throws SecurityException * If a security manager is installed and it denies an unspecified * permission required by a file type detector implementation. - * - * @see DirectoryStreamFilters#newContentTypeFilter */ public static String probeContentType(FileRef file) throws IOException @@ -127,158 +127,6 @@ public final class Files { .probeContentType(file); } - /** - * Invokes a {@link FileAction} for each entry in a directory accepted - * by a given {@link java.nio.file.DirectoryStream.Filter filter}. - * - *

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. - * - *

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 (optional - * specific exception) - * @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 filter, - FileAction action) - throws IOException - { - // explicit null check required in case directory is empty - if (action == null) - throw new NullPointerException(); - - DirectoryStream 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. - * - *

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. - * - *

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. - * - *

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 (optional - * specific exception) - * @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 action) - throws IOException - { - if (glob == null) - throw new NullPointerException("'glob' is null"); - final PathMatcher matcher = dir.getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter filter = new DirectoryStream.Filter() { - @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. - * - *

This method works as if invoking it were equivalent to evaluating the - * expression: - *

-     * withDirectory(dir, "*", action)
-     * 
- * - * @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 (optional - * specific exception) - * @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 action) - throws IOException - { - withDirectory(dir, "*", action); - } - /** * Walks a file tree. * @@ -328,7 +176,7 @@ public final class Files { * arises when there is an entry in a directory that is an ancestor of the * directory. Cycle detection is done by recording the {@link * 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 * ancestor. When a cycle is detected the {@link FileVisitor#visitFile * visitFile} is invoked with the attributes of the directory. The {@link @@ -403,4 +251,108 @@ public final class Files { Integer.MAX_VALUE, visitor); } + + /** + * Creates a directory by creating all nonexistent parent directories first. + * + *

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. + * + *

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 (optional specific + * exception) + * @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; + } + } } diff --git a/jdk/src/share/classes/java/nio/file/LinkPermission.java b/jdk/src/share/classes/java/nio/file/LinkPermission.java index d17788fd029..01949114761 100644 --- a/jdk/src/share/classes/java/nio/file/LinkPermission.java +++ b/jdk/src/share/classes/java/nio/file/LinkPermission.java @@ -95,7 +95,7 @@ public final class LinkPermission extends BasicPermission { * {@code null} * * @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) { super(name); diff --git a/jdk/src/share/classes/java/nio/file/OpenOption.java b/jdk/src/share/classes/java/nio/file/OpenOption.java index c525307e7dc..b19bffb0c37 100644 --- a/jdk/src/share/classes/java/nio/file/OpenOption.java +++ b/jdk/src/share/classes/java/nio/file/OpenOption.java @@ -30,7 +30,7 @@ package java.nio.file; * *

Objects of this type are used by methods such as {@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.AsynchronousFileChannel#open AsynchronousFileChannel.open} * when opening or creating a file. diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java index 8f796b6c32e..e00c96144d9 100644 --- a/jdk/src/share/classes/java/nio/file/Path.java +++ b/jdk/src/share/classes/java/nio/file/Path.java @@ -26,10 +26,12 @@ package java.nio.file; import java.nio.file.attribute.*; -import java.nio.channels.*; -import java.io.*; +import java.nio.channels.SeekableByteChannel; +import java.io.IOException; +import java.io.OutputStream; import java.net.URI; -import java.util.*; +import java.util.Iterator; +import java.util.Set; /** * A file reference that locates a file using a system dependent path. The file @@ -70,19 +72,27 @@ import java.util.*; * this class defines the following operations: * *

    + *
  • The {@link #newByteChannel newByteChannel} method + * may be used to open a file and obtain a byte channel for reading or + * writing.

  • *
  • Files may be {@link #createFile(FileAttribute[]) created}, or * directories may be {@link #createDirectory(FileAttribute[]) created}. *

  • + *
  • The {@link #delete delete} method may be used to delete a file. + *

  • + *
  • The {@link #checkAccess checkAccess} method may be used to check + * the existence or accessibility of a file.

  • + *
  • The {@link #isSameFile isSameFile} method may be used to test if + * two file references locate the same file.

  • + *
  • The {@link #getFileStore getFileStore} method may be used to + * obtain the {@link FileStore} representing the storage where a file is + * located.

  • *
  • Directories can be {@link #newDirectoryStream opened} so as to * iterate over the entries in the directory.

  • *
  • Files can be {@link #copyTo(Path,CopyOption[]) copied} or * {@link #moveTo(Path,CopyOption[]) moved}.

  • *
  • Symbolic-links may be {@link #createSymbolicLink created}, or the * target of a link may be {@link #readSymbolicLink read}.

  • - *
  • {@link #newInputStream InputStream} or {@link #newOutputStream - * OutputStream} streams can be created to allow for interoperation with the - * {@code java.io} package - * where required.

  • *
  • The {@link #toRealPath real} path of an existing file may be * obtained.

  • *
@@ -93,13 +103,14 @@ import java.util.*; * *

File attributes

* - * The {@code java.nio.file.attribute} - * package provides access to file attributes or meta-data associated - * with files. The {@link Attributes Attributes} class defines methods that - * operate on or return file attributes. For example, the file type, size, - * timestamps, and other basic meta-data are obtained, in bulk, by - * invoking the {@link Attributes#readBasicFileAttributes - * Attributes.readBasicFileAttributes} method: + * In addition to the {@link #setAttribute setAttribute} and {@link #getAttribute + * getAttribute} methods, the {@code + * java.nio.file.attribute} package provides type-safe and efficient access + * to file attributes or meta-data associated with files. The {@link + * Attributes Attributes} class defines methods that operate on or return file + * attributes. For example, the file type, size, timestamps, and other + * basic meta-data are obtained, in bulk, by invoking the {@link + * Attributes#readBasicFileAttributes Attributes.readBasicFileAttributes} method: *
  *     Path file = ...
  *     BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
@@ -417,12 +428,38 @@ public abstract class Path
     /**
      * Deletes the file located by this path.
      *
-     * 

The {@code failIfNotExists} parameter determines how the method - * behaves when the file does not exist. When {@code true}, and the file - * does not exist, then the method fails. When {@code false} then the method - * does not fail. + *

An implementation may require to examine the file to determine if the + * file is a directory. Consequently this method may not be atomic with respect + * to other file system operations. If the file is a symbolic-link then the + * link is deleted and not the final target of the link. * - *

As with the {@link FileRef#delete delete()} method, an implementation + *

If the file is a directory then the directory must be empty. In some + * implementations a directory has entries for special files or links that + * are created when the directory is created. In such implementations a + * directory is considered empty when only the special entries exist. + * + *

On some operating systems it may not be possible to remove a file when + * it is open and in use by this Java virtual machine or other programs. + * + * @throws NoSuchFileException + * if the file does not exist (optional specific exception) + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkDelete(String)} method + * is invoked to check delete access to the file + */ + public abstract void delete() throws IOException; + + /** + * Deletes the file located by this path, if it exists. + * + *

As with the {@link #delete delete()} method, an implementation * may require to examine the file to determine if the file is a directory. * Consequently this method may not be atomic with respect to other file * system operations. If the file is a symbolic-link then the link is @@ -436,13 +473,6 @@ public abstract class Path *

On some operating systems it may not be possible to remove a file when * it is open and in use by this Java virtual machine or other programs. * - * @param failIfNotExists - * {@code true} if the method should fail when the file does not - * exist - * - * @throws NoSuchFileException - * if the value of the {@code failIfNotExists} is {@code true} and - * the file does not exist (optional specific exception) * @throws DirectoryNotEmptyException * if the file is a directory and could not otherwise be deleted * because the directory is not empty (optional specific @@ -454,7 +484,7 @@ public abstract class Path * installed, the {@link SecurityManager#checkDelete(String)} method * is invoked to check delete access to the file. */ - public abstract void delete(boolean failIfNotExists) throws IOException; + public abstract void deleteIfExists() throws IOException; /** * Creates a symbolic link to a target (optional operation). @@ -536,8 +566,6 @@ public abstract class Path * or its {@link SecurityManager#checkWrite(String) checkWrite} * method denies write access to both this path and the path of the * existing file. - * - * @see BasicFileAttributes#linkCount */ public abstract Path createLink(Path existing) throws IOException; @@ -608,7 +636,7 @@ public abstract class Path * * @return an absolute, hierarchical URI with a non-empty path component * - * @throws IOError + * @throws java.io.IOError * if an I/O error occurs obtaining the absolute path, or where a * file system is constructed to access the contents of a file as * a file system, and the URI of the enclosing file system cannot be @@ -636,8 +664,9 @@ public abstract class Path * @throws IOError * if an I/O error occurs * @throws SecurityException - * In the case of the default provider, and a security manager - * is installed, its {@link SecurityManager#checkPropertyAccess(String) + * In the case of the default provider, a security manager + * is installed, and this path is not absolute, then the security + * manager's {@link SecurityManager#checkPropertyAccess(String) * checkPropertyAccess} method is invoked to check access to the * system property {@code user.dir} */ @@ -720,7 +749,9 @@ public abstract class Path * the target file. The exact file attributes that are copied is platform * and file system dependent and therefore unspecified. Minimally, the * {@link BasicFileAttributes#lastModifiedTime last-modified-time} is - * copied to the target file. + * copied to the target file if supported by both the source and target + * file store. Copying of file timestamps may result in precision + * loss. * * * {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} @@ -867,10 +898,7 @@ public abstract class Path * *

The directory stream's {@code close} method should be invoked after * iteration is completed so as to free any resources held for the open - * directory. The {@link Files#withDirectory Files.withDirectory} utility - * method is useful for cases where a task is performed on each accepted - * entry in a directory. This method closes the directory when iteration is - * complete (or an error occurs). + * directory. * *

When an implementation supports operations on entries in the * directory that execute in a race-free manner then the returned directory @@ -927,8 +955,6 @@ public abstract class Path * * @throws java.util.regex.PatternSyntaxException * if the pattern is invalid - * @throws UnsupportedOperationException - * if the pattern syntax is not known to the implementation * @throws NotDirectoryException * if the file could not otherwise be opened because it is not * a directory (optional specific exception) @@ -950,19 +976,18 @@ public abstract class Path * directory. The {@code Path} objects are obtained as if by {@link * #resolve(Path) resolving} the name of the directory entry against this * path. The entries returned by the iterator are filtered by the given - * {@link DirectoryStream.Filter filter}. The {@link DirectoryStreamFilters} - * class defines factory methods that create useful filters. + * {@link DirectoryStream.Filter filter}. * *

The directory stream's {@code close} method should be invoked after * iteration is completed so as to free any resources held for the open - * directory. The {@link Files#withDirectory Files.withDirectory} utility - * method is useful for cases where a task is performed on each accepted - * entry in a directory. This method closes the directory when iteration is - * complete (or an error occurs). + * directory. * *

Where the filter terminates due to an uncaught error or runtime - * exception then it propogated to the caller of the iterator's {@link - * Iterator#hasNext() hasNext} or {@link Iterator#next() next} methods. + * exception then it is propogated to the iterator's {@link Iterator#hasNext() + * hasNext} or {@link Iterator#next() next} method. Where an {@code + * IOException} is thrown, it is propogated as a {@link + * java.util.concurrent.ConcurrentModificationException} with the {@code + * IOException} as the cause. * *

When an implementation supports operations on entries in the * directory that execute in a race-free manner then the returned directory @@ -973,14 +998,9 @@ public abstract class Path * larger than 8K. *

      *     DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
-     *         public boolean accept(Path file) {
-     *             try {
-     *                 long size = Attributes.readBasicFileAttributes(file).size();
-     *                 return (size > 8192L);
-     *             } catch (IOException e) {
-     *                 // failed to get size
-     *                 return false;
-     *             }
+     *         public boolean accept(Path file) throws IOException {
+     *             long size = Attributes.readBasicFileAttributes(file).size();
+     *             return (size > 8192L);
      *         }
      *     };
      *     Path dir = ...
@@ -1071,6 +1091,8 @@ public abstract class Path
      *          In the case of the default provider, and a security manager is
      *          installed, the {@link SecurityManager#checkWrite(String) checkWrite}
      *          method is invoked to check write access to the new directory.
+     *
+     * @see Files#createDirectories
      */
     public abstract Path createDirectory(FileAttribute... attrs)
         throws IOException;
@@ -1159,7 +1181,7 @@ public abstract class Path
      * FileAttribute file-attributes} to set atomically when a new file is created.
      *
      * 

In the case of the default provider, the returned seekable byte channel - * is a {@link FileChannel}. + * is a {@link java.nio.channels.FileChannel}. * *

Usage Examples: *

@@ -1212,12 +1234,9 @@ public abstract class Path
      * Opens or creates a file, returning a seekable byte channel to access the
      * file.
      *
-     * 

This method extends the options defined by the {@code FileRef} - * interface and to the options specified by the {@link - * #newByteChannel(Set,FileAttribute[]) newByteChannel} method - * except that the options are specified by an array. In the case of the - * default provider, the returned seekable byte channel is a {@link - * FileChannel}. + *

This method opens or creates a file in exactly the manner specified + * by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel} + * method. * * @param options * options specifying how the file is opened @@ -1232,108 +1251,40 @@ public abstract class Path * if a file of that name already exists and the {@link * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified * (optional specific exception) - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public abstract SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException; - - /** - * Opens the file located by this path for reading, returning an input - * stream to read bytes from the file. The stream will not be buffered, and - * is not required to support the {@link InputStream#mark mark} or {@link - * InputStream#reset reset} methods. The stream will be safe for access by - * multiple concurrent threads. Reading commences at the beginning of the file. - * - * @return an input stream to read bytes from the file - * * @throws IOException * if an I/O error occurs * @throws SecurityException * In the case of the default provider, and a security manager is * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the file. + * method is invoked to check read access to the path if the file is + * opened for reading. The {@link SecurityManager#checkWrite(String) + * checkWrite} method is invoked to check write access to the path + * if the file is opened for writing. */ - public abstract InputStream newInputStream() throws IOException; + public abstract SeekableByteChannel newByteChannel(OpenOption... options) + throws IOException; /** - * Opens or creates the file located by this path for writing, returning an - * output stream to write bytes to the file. + * Opens or creates the file located by this object for writing, returning + * an output stream to write bytes to the file. * *

This method opens or creates a file in exactly the manner specified * by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel} * method except that the {@link StandardOpenOption#READ READ} option may not - * be present in the array of open options. If no open options are present - * then this method creates a new file for writing or truncates an existing - * file. - * - *

The resulting stream will not be buffered. The stream will be safe - * for access by multiple concurrent threads. - * - *

Usage Example: - * Suppose we wish to open a log file for writing so that we append to the - * file if it already exists, or create it when it doesn't exist. - *

-     *     Path logfile = ...
-     *     OutputStream out = new BufferedOutputStream(logfile.newOutputStream(CREATE, APPEND));
-     * 
+ * be present in the array of open options. * * @param options * options specifying how the file is opened * - * @return a new seekable byte channel - * - * @throws IllegalArgumentException - * if {@code options} contains an invalid combination of options - * @throws UnsupportedOperationException - * if an unsupported open option is specified - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to the file. - */ - public abstract OutputStream newOutputStream(OpenOption... options) - throws IOException; - - /** - * Opens or creates the file located by this path for writing, returning an - * output stream to write bytes to the file. - * - *

This method opens or creates a file in exactly the manner specified - * by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel} - * method except that {@code options} parameter may not contain the {@link - * StandardOpenOption#READ READ} option. If no open options are present - * then this method creates a new file for writing or truncates an existing - * file. - * - *

The resulting stream will not be buffered. The stream will be safe - * for access by multiple concurrent threads. - * - * @param options - * options specifying how the file is opened - * @param attrs - * an optional list of file attributes to set atomically when - * creating the file - * * @return a new output stream * - * @throws IllegalArgumentException - * if the set contains an invalid combination of options - * @throws UnsupportedOperationException - * if an unsupported open option is specified or the array contains - * attributes that cannot be set atomically when creating the file - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to the file. + * @throws IllegalArgumentException {@inheritDoc} + * @throws UnsupportedOperationException {@inheritDoc} + * @throws IOException {@inheritDoc} + * @throws SecurityException {@inheritDoc} */ - public abstract OutputStream newOutputStream(Set options, - FileAttribute... attrs) + @Override + public abstract OutputStream newOutputStream(OpenOption... options) throws IOException; /** @@ -1358,6 +1309,80 @@ public abstract class Path */ public abstract boolean isHidden() throws IOException; + /** + * Checks the existence and optionally the accessibility of the file + * located by this path. + * + *

This method checks the existence of a file and that this Java virtual + * machine has appropriate privileges that would allow it access the file + * according to all of access modes specified in the {@code modes} parameter + * as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Value Description
{@link AccessMode#READ READ} Checks that the file exists and that the Java virtual machine has + * permission to read the file.
{@link AccessMode#WRITE WRITE} Checks that the file exists and that the Java virtual machine has + * permission to write to the file,
{@link AccessMode#EXECUTE EXECUTE} Checks that the file exists and that the Java virtual machine has + * permission to {@link Runtime#exec execute} the file. The semantics + * may differ when checking access to a directory. For example, on UNIX + * systems, checking for {@code EXECUTE} access checks that the Java + * virtual machine has permission to search the directory in order to + * access file or subdirectories.
+ * + *

If the {@code modes} parameter is of length zero, then the existence + * of the file is checked. + * + *

This method follows symbolic links if the file referenced by this + * object is a symbolic link. Depending on the implementation, this method + * may require to read file permissions, access control lists, or other + * file attributes in order to check the effective access to the file. To + * determine the effective access to a file may require access to several + * attributes and so in some implementations this method may not be atomic + * with respect to other file system operations. Furthermore, as the result + * of this method is immediately outdated, there is no guarantee that a + * subsequence access will succeed (or even that it will access the same + * file). Care should be taken when using this method in security sensitive + * applications. + * + * @param modes + * The access modes to check; may have zero elements + * + * @throws UnsupportedOperationException + * an implementation is required to support checking for + * {@code READ}, {@code WRITE}, and {@code EXECUTE} access. This + * exception is specified to allow for the {@code Access} enum to + * be extended in future releases. + * @throws NoSuchFileException + * if a file does not exist (optional specific exception) + * @throws AccessDeniedException + * the requested access would be denied or the access cannot be + * determined because the Java virtual machine has insufficient + * privileges or other reasons. (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * is invoked when checking read access to the file or only the + * existence of the file, the {@link SecurityManager#checkWrite(String) + * checkWrite} is invoked when checking write access to the file, + * and {@link SecurityManager#checkExec(String) checkExec} is invoked + * when checking execute access. + */ + public abstract void checkAccess(AccessMode... modes) throws IOException; + /** * Tests whether the file located by this path exists. * @@ -1414,6 +1439,30 @@ public abstract class Path */ public abstract boolean notExists(); + /** + * Returns the {@link FileStore} representing the file store where an + * existing file, located by this path, is stored. + * + *

Once a reference to the {@code FileStore} is obtained it is + * implementation specific if operations on the returned {@code FileStore}, + * or {@link FileStoreAttributeView} objects obtained from it, continue + * to depend on the existence of the file. In particular the behavior is not + * defined for the case that the file is deleted or moved to a different + * file store. + * + * @return the file store where the file is stored + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file, and in + * addition it checks {@link RuntimePermission} + * ("getFileStoreAttributes") + */ + public abstract FileStore getFileStore() throws IOException; + // -- watchable -- /** @@ -1561,6 +1610,49 @@ public abstract class Path @Override public abstract int compareTo(Path other); + /** + * Tests if the file referenced by this object is the same file referenced + * by another object. + * + *

If this {@code FileRef} and the given {@code FileRef} are {@link + * #equals(Object) equal} then this method returns {@code true} without checking + * if the file exists. If the {@code FileRef} and the given {@code FileRef} + * are associated with different providers, or the given {@code FileRef} is + * {@code null} then this method returns {@code false}. Otherwise, this method + * checks if both {@code FileRefs} locate the same file, and depending on the + * implementation, may require to open or access both files. + * + *

If the file system and files remain static, then this method implements + * an equivalence relation for non-null {@code FileRefs}. + *

    + *
  • It is reflexive: for a non-null {@code FileRef} {@code f}, + * {@code f.isSameFile(f)} should return {@code true}. + *
  • It is symmetric: for two non-null {@code FileRefs} + * {@code f} and {@code g}, {@code f.isSameFile(g)} will equal + * {@code g.isSameFile(f)}. + *
  • It is transitive: for three {@code FileRefs} + * {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns + * {@code true} and {@code g.isSameFile(h)} returns {@code true}, then + * {@code f.isSameFile(h)} will return return {@code true}. + *
+ * + * @param other + * the other file reference + * + * @return {@code true} if, and only if, this object and the given object + * locate the same file + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to both files. + * + * @see java.nio.file.attribute.BasicFileAttributes#fileKey + */ + public abstract boolean isSameFile(Path other) throws IOException; + /** * Tests this path for equality with the given object. * diff --git a/jdk/src/share/classes/java/nio/file/Paths.java b/jdk/src/share/classes/java/nio/file/Paths.java index 2cd7a091213..8f456846f16 100644 --- a/jdk/src/share/classes/java/nio/file/Paths.java +++ b/jdk/src/share/classes/java/nio/file/Paths.java @@ -35,7 +35,7 @@ import java.net.URI; * @since 1.7 */ -public class Paths { +public final class Paths { private Paths() { } /** @@ -106,8 +106,9 @@ public class Paths { * if preconditions on the {@code uri} parameter do not hold. The * format of the URI is provider specific. * @throws FileSystemNotFoundException - * if the file system identified by the URI does not exist or the - * provider identified by the URI's scheme component is not installed + * The file system, identified by the URI, does not exist and + * cannot be created automatically, or the provider identified by + * the URI's scheme component is not installed * @throws SecurityException * if a security manager is installed and it denies an unspecified * permission to access the file system diff --git a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java index 7268c41c54d..9655695d301 100644 --- a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java @@ -36,7 +36,7 @@ import java.io.IOException; * 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 * 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 * by an attacker while the directory is open. A {@code SecureDirectoryStream} * may also be used as a virtual working directory. @@ -65,8 +65,8 @@ import java.io.IOException; * @since 1.7 */ -public abstract class SecureDirectoryStream - implements DirectoryStream +public abstract class SecureDirectoryStream + implements DirectoryStream { /** * Initialize a new instance of this class. @@ -78,13 +78,12 @@ public abstract class SecureDirectoryStream * SecureDirectoryStream} to iterate over the entries in the directory. * *

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. * When the parameter is a relative path then the directory to open is - * relative to this open directory. The {@code followLinks} parameter - * determines if links should be followed. If this parameter is {@code - * false} and the file is a symbolic link then this method fails (by - * throwing an I/O exception). + * relative to this open directory. The {@link + * LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} option may be used to + * ensure that this method fails if the file is a symbolic link. * *

The new directory stream, once created, is not dependent upon the * directory stream used to create it. Closing this directory stream has no @@ -92,10 +91,8 @@ public abstract class SecureDirectoryStream * * @param path * the path to the directory to open - * @param followLinks - * {@code true} if the links should be followed - * @param filter - * the directory stream filter or {@code null}. + * @param options + * options indicating how symbolic links are handled * * @return a new and open {@code SecureDirectoryStream} object * @@ -111,9 +108,8 @@ public abstract class SecureDirectoryStream * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the directory. */ - public abstract SecureDirectoryStream newDirectoryStream(Path path, - boolean followLinks, - DirectoryStream.Filter filter) + public abstract SecureDirectoryStream newDirectoryStream(T path, + LinkOption... options) throws IOException; /** @@ -162,7 +158,7 @@ public abstract class SecureDirectoryStream * checkWrite} method is invoked to check write access to the path * if the file is opened for writing. */ - public abstract SeekableByteChannel newByteChannel(Path path, + public abstract SeekableByteChannel newByteChannel(T path, Set options, FileAttribute... attrs) throws IOException; @@ -170,7 +166,7 @@ public abstract class SecureDirectoryStream /** * Deletes a file. * - *

Unlike the {@link FileRef#delete delete()} method, this method + *

Unlike the {@link Path#delete delete()} method, this method * does not first examine the file to determine if the file is a directory. * Whether a directory is deleted by this method is system dependent and * therefore not specified. If the file is a symbolic-link then the link is @@ -191,12 +187,12 @@ public abstract class SecureDirectoryStream * installed, the {@link SecurityManager#checkDelete(String) checkDelete} * 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. * - *

Unlike the {@link FileRef#delete delete()} method, this method + *

Unlike the {@link Path#delete delete()} method, this method * does not first examine the file to determine if the file is a directory. * Whether non-directories are deleted by this method is system dependent and * therefore not specified. When the parameter is a relative path then the @@ -219,7 +215,7 @@ public abstract class SecureDirectoryStream * installed, the {@link SecurityManager#checkDelete(String) checkDelete} * 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. @@ -259,7 +255,7 @@ public abstract class SecureDirectoryStream * method is invoked to check write access to both the source and * target file. */ - public abstract void move(Path srcpath, SecureDirectoryStream targetdir, Path targetpath) + public abstract void move(T srcpath, SecureDirectoryStream targetdir, T targetpath) throws IOException; /** @@ -318,7 +314,7 @@ public abstract class SecureDirectoryStream * type is not available * */ - public abstract V getFileAttributeView(Path path, + public abstract V getFileAttributeView(T path, Class type, LinkOption... options); } diff --git a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java index d9557d024a4..36852392327 100644 --- a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java +++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java @@ -40,7 +40,7 @@ import java.io.IOError; * @since 1.7 */ -public class SimpleFileVisitor implements FileVisitor { +public class SimpleFileVisitor implements FileVisitor { /** * Initializes a new instance of this class. */ diff --git a/jdk/src/share/classes/java/nio/file/StandardWatchEventKind.java b/jdk/src/share/classes/java/nio/file/StandardWatchEventKind.java index 6cc937e9943..a7268ed2f7d 100644 --- a/jdk/src/share/classes/java/nio/file/StandardWatchEventKind.java +++ b/jdk/src/share/classes/java/nio/file/StandardWatchEventKind.java @@ -31,7 +31,7 @@ package java.nio.file; * @since 1.7 */ -public class StandardWatchEventKind { +public final class StandardWatchEventKind { private StandardWatchEventKind() { } /** diff --git a/jdk/src/share/classes/java/nio/file/WatchKey.java b/jdk/src/share/classes/java/nio/file/WatchKey.java index d065585d87d..a990e40eb90 100644 --- a/jdk/src/share/classes/java/nio/file/WatchKey.java +++ b/jdk/src/share/classes/java/nio/file/WatchKey.java @@ -103,7 +103,7 @@ public abstract class WatchKey { * *

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> pollEvents(); @@ -128,7 +128,7 @@ public abstract class WatchKey { * 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 * 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. * *

If this watch key has already been cancelled then invoking this diff --git a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java index c3d28c914a7..4127a78e942 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java @@ -110,13 +110,13 @@ import java.io.IOException; * * * - *

The {@link #getAttribute getAttribute} or {@link #readAttributes - * readAttributes} methods may be used to read the ACL or owner attributes as if - * by invoking the {@link #getAcl getAcl} or {@link #getOwner getOwner} methods. + *

The {@link FileRef#getAttribute getAttribute} method may be used to read + * the ACL or owner attributes as if by invoking the {@link #getAcl getAcl} or + * {@link #getOwner getOwner} methods. * - *

The {@link #setAttribute setAttribute} method may be used to update the - * ACL or owner attributes as if by invoking the {@link #setAcl setAcl} or {@link - * #setOwner setOwner} methods. + *

The {@link FileRef#setAttribute setAttribute} method may be used to + * update the ACL or owner attributes as if by invoking the {@link #setAcl setAcl} + * or {@link #setOwner setOwner} methods. * *

Setting the ACL when creating a file

* diff --git a/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java index 6b0934e7af0..0e10f3341ac 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java @@ -25,20 +25,12 @@ package java.nio.file.attribute; -import java.util.*; -import java.io.IOException; - /** * An object that provides a read-only or updatable view of non-opaque * values associated with an object in a filesystem. This interface is extended * or implemented by specific attribute views that define the attributes * 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 - * provides dynamic access 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. + * type-safe methods to read or update the attributes that it supports. * * @since 1.7 */ @@ -48,71 +40,4 @@ public interface AttributeView { * Returns the name of the attribute view. */ 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. - * - *

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 readAttributes(String first, String... rest) throws IOException; } diff --git a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java b/jdk/src/share/classes/java/nio/file/attribute/Attributes.java index b3fe130d5ba..3ffa6389b43 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/Attributes.java @@ -28,7 +28,6 @@ package java.nio.file.attribute; import java.nio.file.*; import java.io.IOException; import java.util.*; -import java.util.concurrent.TimeUnit; /** * This class consists exclusively of static methods that operate on or return @@ -39,245 +38,7 @@ import java.util.concurrent.TimeUnit; */ public final class Attributes { - 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. - * - *

The {@code attribute} parameter identifies the attribute to be set - * and takes the form: - *

- * [view-name:]attribute-name - *
- * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - *

view-name 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. attribute-name is the name of the attribute - * within the set. - * - *

Usage Example: - * Suppose we want to set the DOS "hidden" attribute: - *

-     *    Attributes.setAttribute(file, "dos:hidden", true);
-     * 
- * - * @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. - * - *

The {@code attribute} parameter identifies the attribute to be read - * and takes the form: - *

- * [view-name:]attribute-name - *
- * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - *

view-name 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. attribute-name is the name of the attribute. - * - *

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. - * - *

Usage Example: - * Suppose we require the user ID of the file owner on a system that - * supports a "{@code unix}" view: - *

-     *    int uid = (Integer)Attributes.getAttribute(file, "unix:uid");
-     * 
- * - * @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. - * - *

The {@code attributes} parameter identifies the attributes to be read - * and takes the form: - *

- * [view-name:]attribute-list - *
- * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - *

view-name 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. - * - *

The attribute-list 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. - * - *

The following examples demonstrate possible values for the {@code - * attributes} parameter: - * - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
{@code "*"} Read all {@link BasicFileAttributes basic-file-attributes}.
{@code "size,lastModifiedTime,lastAccessTime"} Reads the file size, last modified time, and last access time - * attributes.
{@code "posix:*"} Read all {@link PosixFileAttributes POSIX-file-attributes}..
{@code "posix:permissions,owner,size"} Reads the POSX file permissions, owner, and file size.
- *
- * - *

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 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(); - } + private Attributes() { } /** * Reads the basic file attributes of a file. @@ -551,29 +312,28 @@ public final class Attributes { } /** - * Updates the value of a file's last modified time attribute. + * Updates a file's last modified time attribute. The file time is converted + * to the epoch and precision supported by the file system. Converting from + * finer to coarser granularities result in precision loss. The behavior of + * this method when attempting to set a timestamp to a value that is outside + * the range supported by the underlying file store is not defined. It may + * or not fail by throwing an {@code IOException}. * - *

The time value is measured since the epoch - * (00:00:00 GMT, January 1, 1970) and is converted to the precision supported - * by the file system. Converting from finer to coarser granularities result - * in precision loss. + *

If the file system does not support a last modified time attribute + * then this method has no effect. * - *

If the file system does not support a last modified time attribute then - * this method has no effect. + *

Usage Example: + * Suppose we want to set the last modified time to the current time: + *

+     *    FileTime now = FileTime.fromMillis(System.currentTimeMillis());
+     *    Attributes.setLastModifiedTime(file, now);
+     * 
* * @param file * A file reference that locates the file - * * @param lastModifiedTime - * The new last modified time, or {@code -1L} to update it to - * the current time - * @param unit - * A {@code TimeUnit} determining how to interpret the - * {@code lastModifiedTime} parameter + * The new last modified time * - * @throws IllegalArgumentException - * If the {@code lastModifiedime} parameter is a negative value other - * than {@code -1L} * @throws IOException * If an I/O error occurs * @throws SecurityException @@ -584,35 +344,31 @@ public final class Attributes { * @see BasicFileAttributeView#setTimes */ public static void setLastModifiedTime(FileRef file, - long lastModifiedTime, - TimeUnit unit) + FileTime lastModifiedTime) throws IOException { + if (lastModifiedTime == null) + throw new NullPointerException("'lastModifiedTime' is null"); file.getFileAttributeView(BasicFileAttributeView.class) - .setTimes(lastModifiedTime, null, null, unit); + .setTimes(lastModifiedTime, null, null); } /** - * Updates the value of a file's last access time attribute. - * - *

The time value is measured since the epoch - * (00:00:00 GMT, January 1, 1970) and is converted to the precision supported - * by the file system. Converting from finer to coarser granularities result - * in precision loss. + * Updates a file's last access time attribute. The file time is converted + * to the epoch and precision supported by the file system. Converting from + * finer to coarser granularities result in precision loss. The behavior of + * this method when attempting to set a timestamp to a value that is outside + * the range supported by the underlying file store is not defined. It may + * or not fail by throwing an {@code IOException}. * *

If the file system does not support a last access time attribute then * this method has no effect. * + * @param file + * A file reference that locates the file * @param lastAccessTime - * The new last access time, or {@code -1L} to update it to - * the current time - * @param unit - * A {@code TimeUnit} determining how to interpret the - * {@code lastModifiedTime} parameter + * The new last access time * - * @throws IllegalArgumentException - * If the {@code lastAccessTime} parameter is a negative value other - * than {@code -1L} * @throws IOException * If an I/O error occurs * @throws SecurityException @@ -623,12 +379,13 @@ public final class Attributes { * @see BasicFileAttributeView#setTimes */ public static void setLastAccessTime(FileRef file, - long lastAccessTime, - TimeUnit unit) + FileTime lastAccessTime) throws IOException { + if (lastAccessTime == null) + throw new NullPointerException("'lastAccessTime' is null"); file.getFileAttributeView(BasicFileAttributeView.class) - .setTimes(null, lastAccessTime, null, unit); + .setTimes(null, lastAccessTime, null); } /** diff --git a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java index 70100834d8f..45a3b20eb17 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java @@ -25,7 +25,6 @@ package java.nio.file.attribute; -import java.util.concurrent.TimeUnit; import java.io.IOException; /** @@ -49,19 +48,15 @@ import java.io.IOException; * * * "lastModifiedTime" - * {@link Long} + * {@link FileTime} * * * "lastAccessTime" - * {@link Long} + * {@link FileTime} * * * "creationTime" - * {@link Long} - * - * - * "resolution" - * {@link java.util.concurrent.TimeUnit} + * {@link FileTime} * * * "size" @@ -84,26 +79,19 @@ import java.io.IOException; * {@link Boolean} * * - * "linkCount" - * {@link Integer} - * - * * "fileKey" * {@link Object} * * * * - *

The {@link #getAttribute getAttribute} or {@link - * #readAttributes(String,String[]) readAttributes(String,String[])} methods may - * be used to read any of these attributes as if by invoking the {@link + *

The {@link java.nio.file.FileRef#getAttribute getAttribute} method may be + * used to read any of these attributes as if by invoking the {@link * #readAttributes() readAttributes()} method. * - *

The {@link #setAttribute setAttribute} method may be used to update the - * file's last modified time, last access time or create time attributes as if - * by invoking the {@link #setTimes setTimes} method. In that case, the time - * value is interpreted in {@link TimeUnit#MILLISECONDS milliseconds} and - * converted to the precision supported by the file system. + *

The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be + * used to update the file's last modified time, last access time or create time + * attributes as if by invoking the {@link #setTimes setTimes} method. * * @since 1.7 * @see Attributes @@ -141,11 +129,11 @@ public interface BasicFileAttributeView * and create time attributes. * *

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 - * the precision supported by the file system. Converting from finer to - * coarser granularities result in precision loss. If a value is larger - * than the maximum supported by the file system then the corresponding - * timestamp is set to its maximum value. + * 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}. * *

If any of the {@code lastModifiedTime}, {@code lastAccessTime}, * or {@code createTime} parameters has the value {@code null} then the @@ -153,25 +141,19 @@ public interface BasicFileAttributeView * read the existing values of the file attributes when only some, but not * all, of the timestamp attributes are updated. Consequently, this method * 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 * this method has no effect. * * @param lastModifiedTime - * the new last modified time, or {@code -1L} to update it to - * the current time, or {@code null} to not change the attribute + * the new last modified time, or {@code null} to not change the + * value * @param lastAccessTime - * the last access time, or {@code -1L} to update it to - * the current time, or {@code null} to not change the attribute. + * the last access time, or {@code null} to not change the value * @param createTime - * the file's create time, or {@code -1L} to update it to - * the current time, or {@code null} to not change the attribute - * @param unit - * a {@code TimeUnit} determining how to interpret the time values + * the file's create time, or {@code null} to not change the value * - * @throws IllegalArgumentException - * if any of the parameters is a negative value other than {@code - * -1L} * @throws IOException * if an I/O error occurs * @throws SecurityException @@ -179,8 +161,7 @@ public interface BasicFileAttributeView * installed, its {@link SecurityManager#checkWrite(String) checkWrite} * method is invoked to check write access to the file */ - void setTimes(Long lastModifiedTime, - Long lastAccessTime, - Long createTime, - TimeUnit unit) throws IOException; + void setTimes(FileTime lastModifiedTime, + FileTime lastAccessTime, + FileTime createTime) throws IOException; } diff --git a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java index 64c163bc5a1..6fb3bbf7ee9 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java @@ -25,8 +25,6 @@ package java.nio.file.attribute; -import java.util.concurrent.TimeUnit; - /** * Basic attributes associated with a file in a file system. * @@ -50,47 +48,27 @@ public interface BasicFileAttributes { /** * Returns the time of last modification. * - *

The {@link #resolution() resolution} method returns the {@link TimeUnit} - * to interpret the return value of this method. - * - * @return a long 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. + * @return a {@code FileTime} representing the time the file was last + * modified or {@code null} if the attribute is not supported. */ - long lastModifiedTime(); + FileTime lastModifiedTime(); /** * Returns the time of last access if supported. * - *

The {@link #resolution() resolution} method returns the {@link TimeUnit} - * to interpret the return value of this method. - * - * @return a long 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. + * @return a {@code FileTime} representing the time of last access or + * {@code null} if the attribute is not supported. */ - long lastAccessTime(); + FileTime lastAccessTime(); /** * Returns the creation time if supported. The creation time is the time * that the file was created. * - *

The {@link #resolution() resolution} method returns the {@link TimeUnit} - * to interpret the return value of this method. - * - * @return a long 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. + * @return a {@code FileTime} representing the time the file was created + * or {@code null} if the attribute is not supported. */ - long 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(); + FileTime creationTime(); /** * Tells whether the file is a regular file with opaque content. @@ -124,18 +102,6 @@ public interface BasicFileAttributes { */ long size(); - /** - * Returns the number of links to this file. - * - *

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 * null} if a file key is not available. On some platforms or file systems @@ -154,7 +120,7 @@ public interface BasicFileAttributes { * *

File keys returned by this method can be compared for equality and are * suitable for use in collections. If the file system and files remain static, - * and two files are the {@link java.nio.file.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. * * @see java.nio.file.Files#walkFileTree diff --git a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java index c57683999b6..372a4a78060 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java @@ -65,17 +65,17 @@ import java.io.IOException; * * * - *

The {@link #getAttribute getAttribute} or {@link #readAttributes(String,String[]) - * readAttributes(String,String[])} methods may be used to read any of these - * attributes, or any of the attributes defined by {@link BasicFileAttributeView} - * as if by invoking the {@link #readAttributes readAttributes()} method. + *

The {@link java.nio.file.FileRef#getAttribute getAttribute} method may + * be used to read any of these attributes, or any of the attributes defined by + * {@link BasicFileAttributeView} as if by invoking the {@link #readAttributes + * readAttributes()} method. * - *

The {@link #setAttribute setAttribute} method may be used to update the - * file's last modified time, last access time or create time attributes as - * defined by {@link BasicFileAttributeView}. It may also be used to update - * the DOS attributes as if by invoking the {@link #setReadOnly setReadOnly}, - * {@link #setHidden setHidden}, {@link #setSystem setSystem}, and {@link - * #setArchive setArchive} methods respectively. + *

The {@link java.nio.file.FileRef#setAttribute setAttribute} method may + * be used to update the file's last modified time, last access time or create + * time attributes as defined by {@link BasicFileAttributeView}. It may also be + * used to update the DOS attributes as if by invoking the {@link #setReadOnly + * setReadOnly}, {@link #setHidden setHidden}, {@link #setSystem setSystem}, and + * {@link #setArchive setArchive} methods respectively. * * @since 1.7 */ diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java index 78a67b4a4cd..a96f09a387a 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java @@ -34,7 +34,6 @@ package java.nio.file.attribute; * @since 1.7 * * @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 diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java index 0afc19efbff..f13429be634 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java @@ -37,11 +37,11 @@ import java.io.IOException; *

The {@link #getOwner getOwner} or {@link #setOwner setOwner} methods may * be used to read or update the owner of the file. * - *

Where dynamic access to file attributes is required, the owner attribute - * is identified by the name {@code "owner"}, and the value of the attribute is - * a {@link UserPrincipal}. The {@link #readAttributes readAttributes}, {@link - * #getAttribute getAttribute} and {@link #setAttribute setAttributes} methods - * may be used to read or update the file owner. + *

The {@link java.nio.file.FileRef#getAttribute getAttribute} and + * {@link java.nio.file.FileRef#setAttribute setAttribute} methods may also be + * used to read or update the owner. In that case, the owner attribute is + * identified by the name {@code "owner"}, and the value of the attribute is + * a {@link UserPrincipal}. * * @since 1.7 */ diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java index 22d38617cb0..4e9098ab6fb 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java @@ -52,10 +52,8 @@ import java.io.IOException; * * * - *

The {@link #getAttribute getAttribute} or {@link #readAttributes - * readAttributes(String,String[])} methods may be used to read any of these - * attributes as if by invoking the {@link #readAttributes readAttributes()} - * method. + *

The {@link java.nio.file.FileStore#getAttribute getAttribute} method may + * be used to read any of these attributes. * * @since 1.7 */ diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java new file mode 100644 index 00000000000..46b0ab40cad --- /dev/null +++ b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java @@ -0,0 +1,305 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.file.attribute; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Date; +import java.util.Formatter; +import java.util.Locale; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; + +/** + * Represents the value of a file's time stamp attribute. For example, it may + * represent the time that the file was last modified, accessed, or created. + * + *

Instances of this class are immutable. + * + * @since 1.7 + * @see BasicFileAttributes + * @see Attributes#setLastModifiedTime + */ + +public final class FileTime implements Comparable { + 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. + * + *

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. + * + *

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. + * + *

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. + * + *

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 ISO 8601 format: + *

+     *     YYYY-MM-DDThh:mm:ss[.s+]Z
+     * 
+ * 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"}. + * + *

A {@code FileTime} is primarly intended to represent the value of a + * file's time stamp. Where used to represent extreme values, 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; + } +} diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java index 285b8bb7d1c..aeec36a941a 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java @@ -90,14 +90,13 @@ import java.io.IOException; * * * - *

The {@link #getAttribute getAttribute} or {@link - * #readAttributes(String,String[]) readAttributes(String,String[])} methods may - * be used to read any of these attributes, or any of the attributes defined by - * {@link BasicFileAttributeView} as if by invoking the {@link #readAttributes + *

The {@link FileRef#getAttribute getAttribute} method may be used to read + * any of these attributes, or any of the attributes defined by {@link + * BasicFileAttributeView} as if by invoking the {@link #readAttributes * readAttributes()} method. * - *

The {@link #setAttribute setAttribute} method may be used to update the - * file's last modified time, last access time or create time attributes as + *

The {@link FileRef#setAttribute setAttribute} method may be used to update + * the file's last modified time, last access time or create time attributes as * defined by {@link BasicFileAttributeView}. It may also be used to update * the permissions, owner, or group-owner as if by invoking the {@link * #setPermissions setPermissions}, {@link #setOwner setOwner}, and {@link diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java index 97d322c6a59..72570f1243d 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java @@ -35,7 +35,7 @@ import java.util.*; * @since 1.7 */ -public class PosixFilePermissions { +public final class PosixFilePermissions { private PosixFilePermissions() { } // Write string representation of permission bits to {@code sb}. @@ -58,7 +58,9 @@ public class PosixFilePermissions { } /** - * Returns the {@code String} representation of a set of permissions. + * Returns the {@code String} representation of a set of permissions. It + * is guaranteed that the returned {@code String} can be parsed by the + * {@link #fromString} method. * *

If the set contains {@code null} or elements that are not of type * {@code PosixFilePermission} then these elements are ignored. @@ -67,8 +69,6 @@ public class PosixFilePermissions { * the set of permissions * * @return the string representation of the permission set - * - * @see #fromString */ public static String toString(Set perms) { StringBuilder sb = new StringBuilder(9); diff --git a/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java index c0b6896011a..086cd818d86 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java @@ -59,12 +59,11 @@ import java.io.IOException; * attributes. * *

Where dynamic access to file attributes is required, the {@link - * #getAttribute getAttribute} or {@link #readAttributes(String,String[]) - * readAttributes(String,String[])} methods may be used to read the attribute - * value. The attribute value is returned as a byte array (byte[]). The {@link - * #setAttribute setAttribute} method may be used to write the value of a - * user-defined attribute from a buffer (as if by invoking the {@link #write - * write} method), or byte array (byte[]). + * java.nio.file.FileRef#getAttribute getAttribute} method may be used to read + * the attribute value. The attribute value is returned as a byte array (byte[]). + * The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be used + * to write the value of a user-defined attribute from a buffer (as if by + * invoking the {@link #write write} method), or byte array (byte[]). * * @since 1.7 */ @@ -74,7 +73,7 @@ public interface UserDefinedFileAttributeView { /** * Returns the name of this attribute view. Attribute views of this type - * have the name {@code "xattr"}. + * have the name {@code "user"}. */ @Override String name(); diff --git a/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java b/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java index ba74882ce67..79b6a5307ac 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java +++ b/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java @@ -89,7 +89,7 @@ public abstract class UserPrincipalLookupService { * @param group * the string representation of the group to lookup * - * @return a user principal + * @return a group principal * * @throws UserPrincipalNotFoundException * the principal does not exist or is not a group diff --git a/jdk/src/share/classes/java/nio/file/spi/AbstractPath.java b/jdk/src/share/classes/java/nio/file/spi/AbstractPath.java deleted file mode 100644 index 133411e3bf8..00000000000 --- a/jdk/src/share/classes/java/nio/file/spi/AbstractPath.java +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.nio.file.spi; - -import java.nio.file.*; -import static java.nio.file.StandardOpenOption.*; -import java.nio.file.attribute.*; -import java.nio.channels.*; -import java.nio.ByteBuffer; -import java.io.*; -import java.util.*; - -/** - * Base implementation class for a {@code Path}. - * - *

This class is intended to be extended by provider implementors. It - * implements, or provides default implementations for several of the methods - * defined by the {@code Path} class. It implements the {@link #copyTo copyTo} - * and {@link #moveTo moveTo} methods for the case that the source and target - * are not associated with the same provider. - * - * @since 1.7 - */ - -public abstract class AbstractPath extends Path { - - /** - * Initializes a new instance of this class. - */ - protected AbstractPath() { } - - /** - * Deletes the file referenced by this object. - * - *

This method invokes the {@link #delete(boolean) delete(boolean)} - * method with a parameter of {@code true}. It may be overridden where - * required. - * - * @throws NoSuchFileException {@inheritDoc} - * @throws DirectoryNotEmptyException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public void delete() throws IOException { - delete(true); - } - - /** - * Creates a new and empty file, failing if the file already exists. - * - *

This method invokes the {@link #newByteChannel(Set,FileAttribute[]) - * newByteChannel(Set,FileAttribute...)} method to create the file. It may be - * overridden where required. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public Path createFile(FileAttribute... attrs) - throws IOException - { - EnumSet options = EnumSet.of(CREATE_NEW, WRITE); - SeekableByteChannel sbc = newByteChannel(options, attrs); - try { - sbc.close(); - } catch (IOException x) { - // ignore - } - return this; - } - - /** - * Opens or creates a file, returning a seekable byte channel to access the - * file. - * - *

This method invokes the {@link #newByteChannel(Set,FileAttribute[]) - * newByteChannel(Set,FileAttribute...)} method to open or create the file. - * It may be overridden where required. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException - { - Set set = new HashSet(options.length); - Collections.addAll(set, options); - return newByteChannel(set); - } - - /** - * Opens the file located by this path for reading, returning an input - * stream to read bytes from the file. - * - *

This method returns an {@code InputStream} that is constructed by - * invoking the {@link java.nio.channels.Channels#newInputStream - * Channels.newInputStream} method. It may be overridden where a more - * efficient implementation is available. - * - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public InputStream newInputStream() throws IOException { - return Channels.newInputStream(newByteChannel()); - } - - // opts must be modifiable - private OutputStream implNewOutputStream(Set opts, - FileAttribute... attrs) - throws IOException - { - if (opts.isEmpty()) { - opts.add(CREATE); - opts.add(TRUNCATE_EXISTING); - } else { - if (opts.contains(READ)) - throw new IllegalArgumentException("READ not allowed"); - } - opts.add(WRITE); - return Channels.newOutputStream(newByteChannel(opts, attrs)); - } - - /** - * Opens or creates the file located by this path for writing, returning an - * output stream to write bytes to the file. - * - *

This method returns an {@code OutputStream} that is constructed by - * invoking the {@link java.nio.channels.Channels#newOutputStream - * Channels.newOutputStream} method. It may be overridden where a more - * efficient implementation is available. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public OutputStream newOutputStream(OpenOption... options) throws IOException { - int len = options.length; - Set opts = new HashSet(len + 3); - if (len > 0) { - for (OpenOption opt: options) { - opts.add(opt); - } - } - return implNewOutputStream(opts); - } - - /** - * Opens or creates the file located by this path for writing, returning an - * output stream to write bytes to the file. - * - *

This method returns an {@code OutputStream} that is constructed by - * invoking the {@link java.nio.channels.Channels#newOutputStream - * Channels.newOutputStream} method. It may be overridden where a more - * efficient implementation is available. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public OutputStream newOutputStream(Set options, - FileAttribute... attrs) - throws IOException - { - Set opts = new HashSet(options); - return implNewOutputStream(opts, attrs); - } - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over all entries in the directory. - * - *

This method invokes the {@link - * #newDirectoryStream(java.nio.file.DirectoryStream.Filter) - * newDirectoryStream(Filter)} method with a filter that accept all entries. - * It may be overridden where required. - * - * @throws NotDirectoryException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public DirectoryStream newDirectoryStream() throws IOException { - return newDirectoryStream(acceptAllFilter); - } - private static final DirectoryStream.Filter acceptAllFilter = - new DirectoryStream.Filter() { - @Override public boolean accept(Path entry) { return true; } - }; - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over the entries in the directory. The - * entries are filtered by matching the {@code String} representation of - * their file names against a given pattern. - * - *

This method constructs a {@link PathMatcher} by invoking the - * file system's {@link java.nio.file.FileSystem#getPathMatcher - * getPathMatcher} method. This method may be overridden where a more - * efficient implementation is available. - * - * @throws java.util.regex.PatternSyntaxException {@inheritDoc} - * @throws UnsupportedOperationException {@inheritDoc} - * @throws NotDirectoryException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public DirectoryStream newDirectoryStream(String glob) - throws IOException - { - // avoid creating a matcher if all entries are required. - if (glob.equals("*")) - return newDirectoryStream(); - - // create a matcher and return a filter that uses it. - final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter filter = new DirectoryStream.Filter() { - @Override - public boolean accept(Path entry) { - return matcher.matches(entry.getName()); - } - }; - return newDirectoryStream(filter); - } - - /** - * Tests whether the file located by this path exists. - * - *

This method invokes the {@link #checkAccess checkAccess} method to - * check if the file exists. It may be overridden where a more efficient - * implementation is available. - */ - @Override - public boolean exists() { - try { - checkAccess(); - return true; - } catch (IOException x) { - // unable to determine if file exists - } - return false; - } - - /** - * Tests whether the file located by this path does not exist. - * - *

This method invokes the {@link #checkAccess checkAccess} method to - * check if the file exists. It may be overridden where a more efficient - * implementation is available. - */ - @Override - public boolean notExists() { - try { - checkAccess(); - return false; - } catch (NoSuchFileException x) { - // file confirmed not to exist - return true; - } catch (IOException x) { - return false; - } - } - - /** - * Registers the file located by this path with a watch service. - * - *

This method invokes the {@link #register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier[]) - * register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier...)} - * method to register the file. It may be overridden where required. - */ - @Override - public WatchKey register(WatchService watcher, WatchEvent.Kind... events) - throws IOException - { - return register(watcher, events, NO_MODIFIERS); - } - private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0]; - - /** - * Copy the file located by this path to a target location. - * - *

This method is invoked by the {@link #copyTo copyTo} method for - * the case that this {@code Path} and the target {@code Path} are - * associated with the same provider. - * - * @param target - * The target location - * @param options - * Options specifying how the copy should be done - * - * @throws IllegalArgumentException - * If an invalid option is specified - * @throws FileAlreadyExistsException - * The target file exists and cannot be replaced because the - * {@code REPLACE_EXISTING} option is not specified, or the target - * file is a non-empty directory (optional specific exception) - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the source file, the - * {@link SecurityManager#checkWrite(String) checkWrite} is invoked - * to check write access to the target file. If a symbolic link is - * copied the security manager is invoked to check {@link - * LinkPermission}{@code ("symbolic")}. - */ - protected abstract void implCopyTo(Path target, CopyOption... options) - throws IOException; - - /** - * Move the file located by this path to a target location. - * - *

This method is invoked by the {@link #moveTo moveTo} method for - * the case that this {@code Path} and the target {@code Path} are - * associated with the same provider. - * - * @param target - * The target location - * @param options - * Options specifying how the move should be done - * - * @throws IllegalArgumentException - * If an invalid option is specified - * @throws FileAlreadyExistsException - * The target file exists and cannot be replaced because the - * {@code REPLACE_EXISTING} option is not specified, or the target - * file is a non-empty directory - * @throws AtomicMoveNotSupportedException - * The options array contains the {@code ATOMIC_MOVE} option but - * the file cannot be moved as an atomic file system operation. - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to both the source and - * target file. - */ - protected abstract void implMoveTo(Path target, CopyOption... options) - throws IOException; - - /** - * Copy the file located by this path to a target location. - * - *

If this path is associated with the same {@link FileSystemProvider - * provider} as the {@code target} then the {@link #implCopyTo implCopyTo} - * method is invoked to copy the file. Otherwise, this method attempts to - * copy the file to the target location in a manner that may be less - * efficient than would be the case that target is associated with the same - * provider as this path. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public final Path copyTo(Path target, CopyOption... options) - throws IOException - { - if ((getFileSystem().provider() == target.getFileSystem().provider())) { - implCopyTo(target, options); - } else { - xProviderCopyTo(target, options); - } - return target; - } - - /** - * Move or rename the file located by this path to a target location. - * - *

If this path is associated with the same {@link FileSystemProvider - * provider} as the {@code target} then the {@link #implCopyTo implMoveTo} - * method is invoked to move the file. Otherwise, this method attempts to - * copy the file to the target location and delete the source file. This - * implementation may be less efficient than would be the case that - * target is associated with the same provider as this path. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public final Path moveTo(Path target, CopyOption... options) - throws IOException - { - if ((getFileSystem().provider() == target.getFileSystem().provider())) { - implMoveTo(target, options); - } else { - // different providers so copy + delete - xProviderCopyTo(target, convertMoveToCopyOptions(options)); - delete(false); - } - return target; - } - - /** - * Converts the given array of options for moving a file to options suitable - * for copying the file when a move is implemented as copy + delete. - */ - private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) - throws AtomicMoveNotSupportedException - { - int len = options.length; - CopyOption[] newOptions = new CopyOption[len+2]; - for (int i=0; i 0; - buf.flip(); - while (buf.hasRemaining()) { - sbc.write(buf); - } - buf.rewind(); - } - - } finally { - sbc.close(); - } - } finally { - rbc.close(); - } - } -} diff --git a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java index 6b79381bad4..1ad485fbc4c 100644 --- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java +++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java @@ -270,7 +270,9 @@ public abstract class FileSystemProvider { 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. * *

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 @@ -290,7 +292,8 @@ public abstract class FileSystemProvider { * If the URI scheme does not identify this provider or other * preconditions on the uri parameter do not hold * @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 * If a security manager is installed and it denies an unspecified * permission. diff --git a/jdk/src/share/classes/java/util/Scanner.java b/jdk/src/share/classes/java/util/Scanner.java index 3e3806d1ff4..c1032337bd2 100644 --- a/jdk/src/share/classes/java/util/Scanner.java +++ b/jdk/src/share/classes/java/util/Scanner.java @@ -690,7 +690,7 @@ public final class Scanner implements Iterator { public Scanner(FileRef source) throws IOException { - this(source.newByteChannel()); + this(source.newInputStream()); } /** @@ -713,7 +713,7 @@ public final class Scanner implements Iterator { public Scanner(FileRef source, String charsetName) throws IOException { - this(source.newByteChannel(), charsetName); + this(source.newInputStream(), charsetName); } /** diff --git a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java index c07acfdbc61..06c2439abda 100644 --- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java +++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java @@ -26,22 +26,15 @@ package sun.management; import java.lang.management.*; -import java.util.logging.LogManager; -import javax.management.DynamicMBean; import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.MBeanInfo; -import javax.management.NotificationEmitter; import javax.management.ObjectName; -import javax.management.ObjectInstance; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.MBeanRegistrationException; import javax.management.NotCompliantMBeanException; import javax.management.RuntimeOperationsException; -import javax.management.StandardEmitterMBean; -import javax.management.StandardMBean; +import java.nio.BufferPoolMXBean; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; @@ -49,11 +42,6 @@ import sun.security.action.LoadLibraryAction; import java.util.ArrayList; 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.HotSpotDiagnosticMXBean; @@ -68,7 +56,6 @@ public class ManagementFactoryHelper { private static VMManagement jvm; - private static boolean mbeansCreated = false; private static ClassLoadingImpl classMBean = null; private static MemoryImpl memoryMBean = null; private static ThreadImpl threadMBean = null; @@ -148,6 +135,58 @@ public class ManagementFactoryHelper { return result; } + public static List getBufferPoolMXBeans() { + List pools = new ArrayList(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 HotspotRuntime hsRuntimeMBean = null; private static HotspotClassLoading hsClassMBean = null; @@ -162,8 +201,6 @@ public class ManagementFactoryHelper { return hsDiagMBean; } - /** - /** * This method is for testing only. */ diff --git a/jdk/src/share/classes/sun/misc/JavaNioAccess.java b/jdk/src/share/classes/sun/misc/JavaNioAccess.java index 4781cb7b443..d72686aa572 100644 --- a/jdk/src/share/classes/sun/misc/JavaNioAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaNioAccess.java @@ -25,8 +25,15 @@ package sun.misc; -import java.nio.BufferPoolMXBean; - public interface JavaNioAccess { - BufferPoolMXBean getDirectBufferPoolMXBean(); + /** + * Provides access to information on buffer usage. + */ + interface BufferPool { + String getName(); + long getCount(); + long getTotalCapacity(); + long getMemoryUsed(); + } + BufferPool getDirectBufferPool(); } diff --git a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java index d0461b30b9a..612a739bba9 100644 --- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java @@ -29,13 +29,10 @@ import java.io.FileDescriptor; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; -import java.nio.BufferPoolMXBean; import java.nio.channels.*; import java.util.ArrayList; import java.util.List; import java.security.AccessController; -import javax.management.ObjectName; -import javax.management.MalformedObjectNameException; import sun.misc.Cleaner; import sun.security.action.GetPropertyAction; @@ -805,47 +802,28 @@ public class FileChannelImpl } /** - * Returns the management interface for mapped buffers + * Invoked by sun.management.ManagementFactoryHelper to create the management + * interface for mapped buffers. */ - public static BufferPoolMXBean getMappedBufferPoolMXBean() { - return LazyInitialization.mappedBufferPoolMXBean; - } - - // Lazy initialization of management interface - 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); + public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() { + return new sun.misc.JavaNioAccess.BufferPool() { + @Override + public String getName() { + return "mapped"; } - return new BufferPoolMXBean() { - @Override - public ObjectName getObjectName() { - return obj; - } - @Override - public String getName() { - return pool; - } - @Override - public long getCount() { - return Unmapper.count; - } - @Override - public long getTotalCapacity() { - return Unmapper.totalCapacity; - } - @Override - public long getMemoryUsed() { - return Unmapper.totalSize; - } - }; - } + @Override + public long getCount() { + return Unmapper.count; + } + @Override + public long getTotalCapacity() { + return Unmapper.totalCapacity; + } + @Override + public long getMemoryUsed() { + return Unmapper.totalSize; + } + }; } // -- Locks -- diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java index 053e3dcfbb0..d7794f9a2bc 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java @@ -26,15 +26,15 @@ package sun.nio.fs; import java.nio.file.attribute.*; -import java.io.IOException; import java.util.*; +import java.io.IOException; /** * Base implementation of AclFileAttributeView */ abstract class AbstractAclFileAttributeView - implements AclFileAttributeView + implements AclFileAttributeView, DynamicFileAttributeView { private static final String OWNER_NAME = "owner"; private static final String ACL_NAME = "acl"; @@ -66,38 +66,29 @@ abstract class AbstractAclFileAttributeView setAcl((List)value); return; } - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("'" + name() + ":" + + attribute + "' not supported"); } @Override - public final Map readAttributes(String first, String[] rest) + public final Map readAttributes(String[] attributes) throws IOException { boolean acl = false; boolean owner = false; - - if (first.equals(ACL_NAME)) acl = true; - else if (first.equals(OWNER_NAME)) owner = true; - else if (first.equals("*")) { - owner = true; - acl = true; - } - - if (!acl || !owner) { - for (String attribute: rest) { - if (attribute.equals("*")) { - owner = true; - acl = true; - break; - } - if (attribute.equals(ACL_NAME)) { - acl = true; - continue; - } - if (attribute.equals(OWNER_NAME)) { - owner = true; - continue; - } + for (String attribute: attributes) { + if (attribute.equals("*")) { + owner = true; + acl = true; + continue; + } + if (attribute.equals(ACL_NAME)) { + acl = true; + continue; + } + if (attribute.equals(OWNER_NAME)) { + owner = true; + continue; } } Map result = new HashMap(2); diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java index 18cf00d501c..306e4cb5910 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java @@ -26,24 +26,21 @@ package sun.nio.fs; import java.nio.file.attribute.*; -import java.io.IOException; import java.util.*; -import java.util.concurrent.TimeUnit; +import java.io.IOException; /** * Base implementation of BasicFileAttributeView */ abstract class AbstractBasicFileAttributeView - implements BasicFileAttributeView + implements BasicFileAttributeView, DynamicFileAttributeView { private static final String SIZE_NAME = "size"; private static final String CREATION_TIME_NAME = "creationTime"; private static final String LAST_ACCESS_TIME_NAME = "lastAccessTime"; 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 LINK_COUNT_NAME = "linkCount"; private static final String IS_DIRECTORY_NAME = "isDirectory"; private static final String IS_REGULAR_FILE_NAME = "isRegularFile"; private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink"; @@ -67,12 +64,8 @@ abstract class AbstractBasicFileAttributeView return attrs.lastAccessTime(); if (attribute.equals(LAST_MODIFIED_TIME_NAME)) return attrs.lastModifiedTime(); - if (attribute.equals(RESOLUTION_NAME)) - return attrs.resolution(); if (attribute.equals(FILE_KEY_NAME)) return attrs.fileKey(); - if (attribute.equals(LINK_COUNT_NAME)) - return attrs.linkCount(); if (attribute.equals(IS_DIRECTORY_NAME)) return attrs.isDirectory(); if (attribute.equals(IS_REGULAR_FILE_NAME)) @@ -84,29 +77,20 @@ abstract class AbstractBasicFileAttributeView 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 public void setAttribute(String attribute, Object value) throws IOException { if (attribute.equals(LAST_MODIFIED_TIME_NAME)) { - setTimes(toTimeValue(value), null, null, TimeUnit.MILLISECONDS); + setTimes((FileTime)value, null, null); return; } if (attribute.equals(LAST_ACCESS_TIME_NAME)) { - setTimes(null, toTimeValue(value), null, TimeUnit.MILLISECONDS); + setTimes(null, (FileTime)value, null); return; } if (attribute.equals(CREATION_TIME_NAME)) { - setTimes(null, null, toTimeValue(value), TimeUnit.MILLISECONDS); + setTimes(null, null, (FileTime)value); return; } throw new UnsupportedOperationException("'" + attribute + @@ -114,24 +98,18 @@ abstract class AbstractBasicFileAttributeView } /** - * + * Used to build a map of attribute name/values. */ static class AttributesBuilder { private Set set = new HashSet(); private Map map = new HashMap(); private boolean copyAll; - private AttributesBuilder(String first, String[] rest) { - if (first.equals("*")) { - copyAll = true; - } else { - set.add(first); - // copy names into the given Set bailing out if "*" is found - for (String attribute: rest) { - if (attribute.equals("*")) { - copyAll = true; - break; - } + private AttributesBuilder(String[] attributes) { + for (String attribute: attributes) { + if (attribute.equals("*")) { + copyAll = true; + } else { set.add(attribute); } } @@ -140,8 +118,8 @@ abstract class AbstractBasicFileAttributeView /** * Creates builder to build up a map of the matching attributes */ - static AttributesBuilder create(String first, String[] rest) { - return new AttributesBuilder(first, rest); + static AttributesBuilder create(String[] attributes) { + return new AttributesBuilder(attributes); } /** @@ -181,12 +159,8 @@ abstract class AbstractBasicFileAttributeView builder.add(LAST_ACCESS_TIME_NAME, attrs.lastAccessTime()); if (builder.match(LAST_MODIFIED_TIME_NAME)) 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)) 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)) builder.add(IS_DIRECTORY_NAME, attrs.isDirectory()); if (builder.match(IS_REGULAR_FILE_NAME)) @@ -198,10 +172,8 @@ abstract class AbstractBasicFileAttributeView } @Override - public Map readAttributes(String first, String[] rest) - throws IOException - { - AttributesBuilder builder = AttributesBuilder.create(first, rest); + public Map readAttributes(String[] attributes) throws IOException { + AttributesBuilder builder = AttributesBuilder.create(attributes); addBasicAttributesToBuilder(readAttributes(), builder); return builder.unmodifiableMap(); } diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java deleted file mode 100644 index 73c8c2a0db1..00000000000 --- a/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package sun.nio.fs; - -import java.nio.file.attribute.*; -import java.io.IOException; -import java.util.*; - -/** - * Base implementation of FileStoreSpaceAttributeView - */ - -abstract class AbstractFileStoreSpaceAttributeView - implements FileStoreSpaceAttributeView -{ - private static final String TOTAL_SPACE_NAME = "totalSpace"; - private static final String USABLE_SPACE_NAME = "usableSpace"; - private static final String UNALLOCATED_SPACE_NAME = "unallocatedSpace"; - - @Override - public final String name() { - return "space"; - } - - @Override - public final Object getAttribute(String attribute) throws IOException { - FileStoreSpaceAttributes attrs = readAttributes(); - if (attribute.equals(TOTAL_SPACE_NAME)) - return attrs.totalSpace(); - if (attribute.equals(USABLE_SPACE_NAME)) - return attrs.usableSpace(); - if (attribute.equals(UNALLOCATED_SPACE_NAME)) - return attrs.unallocatedSpace(); - return null; - } - - @Override - public final void setAttribute(String attribute, Object value) - throws IOException - { - if (attribute == null || value == null) - throw new NullPointerException(); - throw new UnsupportedOperationException(); - } - - @Override - public final Map 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 result = new HashMap(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); - } -} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java index d8a391b8081..d421ad96c6f 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java @@ -27,8 +27,8 @@ package sun.nio.fs; import java.nio.file.FileRef; import java.nio.file.spi.FileTypeDetector; +import java.util.Locale; import java.io.IOException; -import sun.nio.fs.MimeType; /** * Base implementation of FileTypeDetector @@ -42,23 +42,15 @@ public abstract class AbstractFileTypeDetector } /** - * Invokes the implProbeContentType method to guess the file's content type, - * and this validates that the content type's syntax is valid. + * Invokes the appropriate probe method to guess a file's content type, + * and checks that the content type's syntax is valid. */ @Override public final String probeContentType(FileRef file) throws IOException { if (file == null) throw new NullPointerException("'file' is null"); String result = implProbeContentType(file); - if (result != null) { - // check the content type - try { - MimeType.parse(result); - } catch (IllegalArgumentException ignore) { - result = null; - } - } - return result; + return (result == null) ? null : parse(result); } /** @@ -66,4 +58,54 @@ public abstract class AbstractFileTypeDetector */ protected abstract String implProbeContentType(FileRef file) 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; + } } diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractPath.java b/jdk/src/share/classes/sun/nio/fs/AbstractPath.java new file mode 100644 index 00000000000..71204bd0a2e --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractPath.java @@ -0,0 +1,404 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.nio.file.attribute.*; +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.io.*; +import java.util.*; + +/** + * Base implementation class for a {@code Path}. + */ + +abstract class AbstractPath extends Path { + protected AbstractPath() { } + + @Override + public final Path createFile(FileAttribute... attrs) + throws IOException + { + EnumSet options = EnumSet.of(CREATE_NEW, WRITE); + SeekableByteChannel sbc = newByteChannel(options, attrs); + try { + sbc.close(); + } catch (IOException x) { + // ignore + } + return this; + } + + /** + * Deletes a file. The {@code failIfNotExists} parameters determines if an + * {@code IOException} is thrown when the file does not exist. + */ + abstract void implDelete(boolean failIfNotExists) throws IOException; + + @Override + public final void delete() throws IOException { + implDelete(true); + } + + @Override + public final void deleteIfExists() throws IOException { + implDelete(false); + } + + @Override + public final InputStream newInputStream(OpenOption... options) + throws IOException + { + if (options.length > 0) { + for (OpenOption opt: options) { + if (opt != READ) + throw new UnsupportedOperationException("'" + opt + "' not allowed"); + } + } + return Channels.newInputStream(newByteChannel()); + } + + @Override + public final OutputStream newOutputStream(OpenOption... options) + throws IOException + { + int len = options.length; + Set opts = new HashSet(len + 3); + if (len == 0) { + opts.add(CREATE); + opts.add(TRUNCATE_EXISTING); + } else { + for (OpenOption opt: options) { + if (opt == READ) + throw new IllegalArgumentException("READ not allowed"); + opts.add(opt); + } + } + opts.add(WRITE); + return Channels.newOutputStream(newByteChannel(opts)); + } + + @Override + public final SeekableByteChannel newByteChannel(OpenOption... options) + throws IOException + { + Set set = new HashSet(options.length); + Collections.addAll(set, options); + return newByteChannel(set); + } + + private static final DirectoryStream.Filter acceptAllFilter = + new DirectoryStream.Filter() { + @Override public boolean accept(Path entry) { return true; } + }; + + @Override + public final DirectoryStream newDirectoryStream() throws IOException { + return newDirectoryStream(acceptAllFilter); + } + + @Override + public final DirectoryStream newDirectoryStream(String glob) + throws IOException + { + // avoid creating a matcher if all entries are required. + if (glob.equals("*")) + return newDirectoryStream(); + + // create a matcher and return a filter that uses it. + final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); + DirectoryStream.Filter filter = new DirectoryStream.Filter() { + @Override + public boolean accept(Path entry) { + return matcher.matches(entry.getName()); + } + }; + return newDirectoryStream(filter); + } + + @Override + public final boolean exists() { + try { + checkAccess(); + return true; + } catch (IOException x) { + // unable to determine if file exists + } + return false; + } + + @Override + public final boolean notExists() { + try { + checkAccess(); + return false; + } catch (NoSuchFileException x) { + // file confirmed not to exist + return true; + } catch (IOException x) { + return false; + } + } + + private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0]; + + @Override + public final WatchKey register(WatchService watcher, + WatchEvent.Kind... events) + throws IOException + { + return register(watcher, events, NO_MODIFIERS); + } + + abstract void implCopyTo(Path target, CopyOption... options) + throws IOException; + + @Override + public final Path copyTo(Path target, CopyOption... options) + throws IOException + { + if ((getFileSystem().provider() == target.getFileSystem().provider())) { + implCopyTo(target, options); + } else { + copyToForeignTarget(target, options); + } + return target; + } + + abstract void implMoveTo(Path target, CopyOption... options) + throws IOException; + + @Override + public final Path moveTo(Path target, CopyOption... options) + throws IOException + { + if ((getFileSystem().provider() == target.getFileSystem().provider())) { + implMoveTo(target, options); + } else { + // different providers so copy + delete + copyToForeignTarget(target, convertMoveToCopyOptions(options)); + delete(); + } + return target; + } + + /** + * Converts the given array of options for moving a file to options suitable + * for copying the file when a move is implemented as copy + delete. + */ + private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) + throws AtomicMoveNotSupportedException + { + int len = options.length; + CopyOption[] newOptions = new CopyOption[len+2]; + for (int i=0; i 0; + buf.flip(); + while (buf.hasRemaining()) { + sbc.write(buf); + } + buf.rewind(); + } + + } finally { + sbc.close(); + } + } finally { + rbc.close(); + } + } + + /** + * Splits the given attribute name into the name of an attribute view and + * the attribute. If the attribute view is not identified then it assumed + * to be "basic". + */ + private static String[] split(String attribute) { + String[] s = new String[2]; + int pos = attribute.indexOf(':'); + if (pos == -1) { + s[0] = "basic"; + s[1] = attribute; + } else { + s[0] = attribute.substring(0, pos++); + s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos); + } + return s; + } + + /** + * Gets a DynamicFileAttributeView by name. Returns {@code null} if the + * view is not available. + */ + abstract DynamicFileAttributeView getFileAttributeView(String name, + LinkOption... options); + + @Override + public final void setAttribute(String attribute, + Object value, + LinkOption... options) + throws IOException + { + String[] s = split(attribute); + DynamicFileAttributeView view = getFileAttributeView(s[0], options); + if (view == null) + throw new UnsupportedOperationException("View '" + s[0] + "' not available"); + view.setAttribute(s[1], value); + } + + @Override + public final Object getAttribute(String attribute, LinkOption... options) + throws IOException + { + String[] s = split(attribute); + DynamicFileAttributeView view = getFileAttributeView(s[0], options); + return (view == null) ? null : view.getAttribute(s[1]); + } + + @Override + public final Map readAttributes(String attributes, LinkOption... options) + throws IOException + { + String[] s = split(attributes); + DynamicFileAttributeView view = getFileAttributeView(s[0], options); + if (view == null) + return Collections.emptyMap(); + return view.readAttributes(s[1].split(",")); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java index 3ac9b507fc0..4a37cfcc8e5 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java @@ -31,11 +31,11 @@ import java.io.IOException; import java.util.*; /** - * Base implementation of NamedAttributeView + * Base implementation of UserDefinedAttributeView */ abstract class AbstractUserDefinedFileAttributeView - implements UserDefinedFileAttributeView + implements UserDefinedFileAttributeView, DynamicFileAttributeView { protected AbstractUserDefinedFileAttributeView() { } @@ -56,7 +56,7 @@ abstract class AbstractUserDefinedFileAttributeView @Override public final String name() { - return "xattr"; + return "user"; } @Override @@ -70,6 +70,7 @@ abstract class AbstractUserDefinedFileAttributeView throw e; return null; } + byte[] buf = new byte[size]; int n = read(attribute, ByteBuffer.wrap(buf)); return (n == size) ? buf : Arrays.copyOf(buf, n); @@ -89,27 +90,20 @@ abstract class AbstractUserDefinedFileAttributeView } @Override - public final Map readAttributes(String first, String... rest) + public final Map readAttributes(String[] attributes) throws IOException { // names of attributes to return List names = new ArrayList(); - boolean readAll = false; - if (first.equals("*")) { - readAll = true; - } else { - names.add(first); - } - for (String name: rest) { + for (String name: attributes) { if (name.equals("*")) { - readAll = true; + names = list(); + break; } else { names.add(name); } } - if (readAll) - names = list(); // read each value and return in map Map result = new HashMap(); diff --git a/jdk/src/share/classes/java/nio/file/FileAction.java b/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java similarity index 52% rename from jdk/src/share/classes/java/nio/file/FileAction.java rename to jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java index 58088c2f814..6ba481f47e2 100644 --- a/jdk/src/share/classes/java/nio/file/FileAction.java +++ b/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,42 +23,29 @@ * have any questions. */ -package java.nio.file; +package sun.nio.fs; +import java.util.Map; import java.io.IOException; /** - * An interface that is implemented by objects that operate on a file. An - * implementation of this interface is provided to the {@link Files#withDirectory - * 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. - * - *

Usage Example: - * Suppose we require to perform a task on all class files in a directory: - *

- *     Path dir = ...
- *     Files.withDirectory(dir, "*.class", new FileAction<Path>() {
- *         public void invoke(Path entry) {
- *             :
- *         }
- *     });
- * 
- * - * @param the type of file reference - * - * @since 1.7 + * Implemented by FileAttributeView implementations to support access to + * attributes by names. */ -public interface FileAction { +interface DynamicFileAttributeView { /** - * Invoked for a file. - * - * @param file - * the file - * - * @throws IOException - * if the block terminates due an uncaught I/O exception + * Reads the value of an attribute. */ - void invoke(T file) throws IOException; + Object getAttribute(String attribute) throws IOException; + + /** + * Sets/updates the value of an attribute. + */ + void setAttribute(String attribute, Object value) throws IOException; + + /** + * Reads a set of file attributes as a bulk operation. + */ + Map readAttributes(String[] attributes) throws IOException; } diff --git a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java index f40c2a79740..c172b3de86c 100644 --- a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java +++ b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java @@ -34,7 +34,9 @@ import java.io.IOException; * PosixFileAttributeView or AclFileAttributeView object. */ -final class FileOwnerAttributeViewImpl implements FileOwnerAttributeView { +final class FileOwnerAttributeViewImpl + implements FileOwnerAttributeView, DynamicFileAttributeView +{ private static final String OWNER_NAME = "owner"; private final FileAttributeView view; @@ -70,20 +72,16 @@ final class FileOwnerAttributeViewImpl implements FileOwnerAttributeView { setOwner((UserPrincipal)value); return; } - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("'" + name() + ":" + + attribute + "' not supported"); } @Override - public Map readAttributes(String first, String[] rest) throws IOException { + public Map readAttributes(String[] attributes) throws IOException { Map result = new HashMap(); - if (first.equals("*") || first.equals(OWNER_NAME)) { - result.put(OWNER_NAME, getOwner()); - } else { - for (String attribute: rest) { - if (attribute.equals("*") || attribute.equals(OWNER_NAME)) { - result.put(OWNER_NAME, getOwner()); - break; - } + for (String attribute: attributes) { + if (attribute.equals("*") || attribute.equals(OWNER_NAME)) { + result.put(OWNER_NAME, getOwner()); } } return result; diff --git a/jdk/src/share/classes/sun/nio/fs/MimeType.java b/jdk/src/share/classes/sun/nio/fs/MimeType.java deleted file mode 100644 index 053ea44c205..00000000000 --- a/jdk/src/share/classes/sun/nio/fs/MimeType.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package sun.nio.fs; - -/** - * Represents a MIME type for the purposes of validation and matching. For - * now this class is implemented using the javax.activation.MimeType class but - * this dependency can easily be eliminated when required. - */ - -public class MimeType { - private final javax.activation.MimeType type; - - private MimeType(javax.activation.MimeType type) { - this.type = type; - } - - /** - * Parses the given string as a MIME type. - * - * @throws IllegalArgumentException - * If the string is not a valid MIME type - */ - public static MimeType parse(String type) { - try { - return new MimeType(new javax.activation.MimeType(type)); - } catch (javax.activation.MimeTypeParseException x) { - throw new IllegalArgumentException(x); - } - } - - /** - * Returns {@code true} if this MIME type has parameters. - */ - public boolean hasParameters() { - return !type.getParameters().isEmpty(); - } - - /** - * Matches this MIME type against a given MIME type. This method returns - * true if the given string is a MIME type and it matches this type. - */ - public boolean match(String other) { - try { - return type.match(other); - } catch (javax.activation.MimeTypeParseException x) { - return false; - } - } -} diff --git a/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java index 73a89c27136..beda225a206 100644 --- a/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java +++ b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java @@ -265,7 +265,7 @@ class PollingWatchService // don't follow links long lastModified = Attributes .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS) - .lastModifiedTime(); + .lastModifiedTime().toMillis(); entries.put(entry.getName(), new CacheEntry(lastModified, tickCount)); } @@ -357,7 +357,7 @@ class PollingWatchService try { lastModified = Attributes .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS) - .lastModifiedTime(); + .lastModifiedTime().toMillis(); } catch (IOException x) { // unable to get attributes of entry. If file has just // been deleted then we'll report it as deleted on the diff --git a/jdk/src/share/classes/sun/nio/fs/Util.java b/jdk/src/share/classes/sun/nio/fs/Util.java new file mode 100644 index 00000000000..1a323441589 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/Util.java @@ -0,0 +1,59 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Utility methods + */ + +class Util { + private Util() { } + + /** + * Splits a string around the given character. The array returned by this + * method contains each substring that is terminated by the character. Use + * for simple string spilting cases when needing to avoid loading regex. + */ + static String[] split(String s, char c) { + int count = 0; + for (int i=0; i readAttributes(String first, String[] rest) + public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(first, rest); + AttributesBuilder builder = AttributesBuilder.create(attributes); DosFileAttributes attrs = readAttributes(); addBasicAttributesToBuilder(attrs, builder); if (builder.match(READONLY_NAME)) @@ -132,22 +131,18 @@ class LinuxDosFileAttributeView return new DosFileAttributes() { @Override - public long lastModifiedTime() { + public FileTime lastModifiedTime() { return attrs.lastModifiedTime(); } @Override - public long lastAccessTime() { + public FileTime lastAccessTime() { return attrs.lastAccessTime(); } @Override - public long creationTime() { + public FileTime creationTime() { return attrs.creationTime(); } @Override - public TimeUnit resolution() { - return attrs.resolution(); - } - @Override public boolean isRegularFile() { return attrs.isRegularFile(); } @@ -168,10 +163,6 @@ class LinuxDosFileAttributeView return attrs.size(); } @Override - public int linkCount() { - return attrs.linkCount(); - } - @Override public Object fileKey() { return attrs.fileKey(); } diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java index 8c07ce5f66a..7eb45bde481 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java @@ -53,7 +53,7 @@ class LinuxFileStore */ @Override UnixMountEntry findMountEntry() throws IOException { - UnixFileSystem fs = file().getFileSystem(); + LinuxFileSystem fs = (LinuxFileSystem)file().getFileSystem(); // step 1: get realpath UnixPath path = null; @@ -79,14 +79,15 @@ class LinuxFileStore 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(); - for (UnixMountEntry entry: fs.getMountEntries()) { + for (UnixMountEntry entry: fs.getMountEntries("/proc/mounts")) { if (Arrays.equals(dir, entry.dir())) 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 @@ -113,9 +114,9 @@ class LinuxFileStore @Override public boolean supportsFileAttributeView(String name) { - // support DosFileAttributeView and NamedAttributeView if extended + // support DosFileAttributeView and UserDefinedAttributeView if extended // attributes enabled - if (name.equals("dos") || name.equals("xattr")) { + if (name.equals("dos") || name.equals("user")) { // lookup fstypes.properties FeatureStatus status = checkIfFeaturePresent("user_xattr"); if (status == FeatureStatus.PRESENT) diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java index d574c9dff09..b9846ce792e 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java @@ -39,7 +39,6 @@ import static sun.nio.fs.LinuxNativeDispatcher.*; class LinuxFileSystem extends UnixFileSystem { private final boolean hasInotify; - private final boolean hasAtSysCalls; LinuxFileSystem(UnixFileSystemProvider provider, String dir) { super(provider, dir); @@ -47,14 +46,14 @@ class LinuxFileSystem extends UnixFileSystem { // assume X.Y[-Z] format String osversion = AccessController .doPrivileged(new GetPropertyAction("os.version")); - String[] vers = osversion.split("\\.", 0); + String[] vers = Util.split(osversion, '.'); assert vers.length >= 2; int majorVersion = Integer.parseInt(vers[0]); int minorVersion = Integer.parseInt(vers[1]); int microVersion = 0; if (vers.length > 2) { - String[] microVers = vers[2].split("-", 0); + String[] microVers = Util.split(vers[2], '-'); microVersion = (microVers.length > 0) ? Integer.parseInt(microVers[0]) : 0; } @@ -63,11 +62,6 @@ class LinuxFileSystem extends UnixFileSystem { this.hasInotify = ((majorVersion > 2) || (majorVersion == 2 && minorVersion > 6) || ((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 @@ -97,13 +91,13 @@ class LinuxFileSystem extends UnixFileSystem { @Override @SuppressWarnings("unchecked") - public FileAttributeView newFileAttributeView(String name, - UnixPath file, - LinkOption... options) + public DynamicFileAttributeView newFileAttributeView(String name, + UnixPath file, + LinkOption... options) { if (name.equals("dos")) return new LinuxDosFileAttributeView(file, followLinks(options)); - if (name.equals("xattr")) + if (name.equals("user")) return new LinuxUserDefinedFileAttributeView(file, followLinks(options)); return super.newFileAttributeView(name, file, options); } @@ -117,7 +111,7 @@ class LinuxFileSystem extends UnixFileSystem { result.addAll(UnixFileSystem.standardFileAttributeViews()); // additional Linux-specific views result.add("dos"); - result.add("xattr"); + result.add("user"); return Collections.unmodifiableSet(result); } } @@ -132,19 +126,13 @@ class LinuxFileSystem extends UnixFileSystem { 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 getMountEntries() { + Iterable getMountEntries(String fstab) { ArrayList entries = new ArrayList(); try { - long fp = setmntent("/etc/mtab".getBytes(), "r".getBytes()); + long fp = setmntent(fstab.getBytes(), "r".getBytes()); try { for (;;) { UnixMountEntry entry = new UnixMountEntry(); @@ -163,6 +151,14 @@ class LinuxFileSystem extends UnixFileSystem { return entries; } + /** + * Returns object to iterate over the mount entries in /etc/mtab + */ + @Override + Iterable getMountEntries() { + return getMountEntries("/etc/mtab"); + } + @Override FileStore getFileStore(UnixPath path) throws IOException { return new LinuxFileStore(path); diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java index e96361e20ba..c576f968197 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java @@ -98,7 +98,7 @@ class SolarisAclFileAttributeView // map UserPrincipal to uid and flags UserPrincipal who = ace.principal(); - if (!(who instanceof UnixUserPrincipals)) + if (!(who instanceof UnixUserPrincipals.User)) throw new ProviderMismatchException(); UnixUserPrincipals.User user = (UnixUserPrincipals.User)who; int uid; diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java index bdf71a5593c..aaa737137d3 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java @@ -83,7 +83,7 @@ class SolarisFileStore // AclFileAttributeView available on ZFS return (type().equals("zfs")); } - if (name.equals("xattr")) { + if (name.equals("user")) { // lookup fstypes.properties FeatureStatus status = checkIfFeaturePresent("xattr"); if (status == FeatureStatus.PRESENT) diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java index fa7f34f53b0..6e5d1c7d96e 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java @@ -46,7 +46,7 @@ class SolarisFileSystem extends UnixFileSystem { // check os.version String osversion = AccessController .doPrivileged(new GetPropertyAction("os.version")); - String[] vers = osversion.split("\\.", 0); + String[] vers = Util.split(osversion, '.'); assert vers.length >= 2; int majorVersion = Integer.parseInt(vers[0]); int minorVersion = Integer.parseInt(vers[1]); @@ -85,13 +85,13 @@ class SolarisFileSystem extends UnixFileSystem { } @Override - protected FileAttributeView newFileAttributeView(String name, - UnixPath file, - LinkOption... options) + protected DynamicFileAttributeView newFileAttributeView(String name, + UnixPath file, + LinkOption... options) { if (name.equals("acl")) return new SolarisAclFileAttributeView(file, followLinks(options)); - if (name.equals("xattr")) + if (name.equals("user")) return new SolarisUserDefinedFileAttributeView(file, followLinks(options)); return super.newFileAttributeView(name, file, options); } @@ -105,7 +105,7 @@ class SolarisFileSystem extends UnixFileSystem { result.addAll(UnixFileSystem.standardFileAttributeViews()); // additional Solaris-specific views result.add("acl"); - result.add("xattr"); + result.add("user"); return Collections.unmodifiableSet(result); } } @@ -121,11 +121,6 @@ class SolarisFileSystem extends UnixFileSystem { // TDB: copy ACL from source to target } - @Override - boolean supportsSecureDirectoryStreams() { - return true; - } - /** * Returns object to iterate over entries in /etc/mnttab */ diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java index a8265dca7f6..ac625a6b0bd 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java @@ -49,13 +49,13 @@ class UnixChannelFactory { private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); - private UnixChannelFactory() { + protected UnixChannelFactory() { } /** * Represents the flags from a user-supplied set of open options. */ - private static class Flags { + protected static class Flags { boolean read; boolean write; boolean append; @@ -179,11 +179,11 @@ class UnixChannelFactory { * Opens file based on parameters and options, returning a FileDescriptor * encapsulating the handle to the open file. */ - static FileDescriptor open(int dfd, - UnixPath path, - String pathForPermissionCheck, - Flags flags, - int mode) + protected static FileDescriptor open(int dfd, + UnixPath path, + String pathForPermissionCheck, + Flags flags, + int mode) throws UnixException { // map to oflags diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java index 808cc1e34dc..0b16813240d 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import com.sun.nio.file.ExtendedCopyOption; import static sun.nio.fs.UnixNativeDispatcher.*; @@ -189,11 +190,13 @@ class UnixCopyFile { if (flags.copyBasicAttributes) { try { if (dfd >= 0) { - futimes(dfd, attrs.lastAccessTime(), - attrs.lastModifiedTime()); + futimes(dfd, + attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), + attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); } else { - utimes(target, attrs.lastAccessTime(), - attrs.lastModifiedTime()); + utimes(target, + attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), + attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); } } catch (UnixException x) { // unable to set times @@ -266,7 +269,9 @@ class UnixCopyFile { // copy time attributes if (flags.copyBasicAttributes) { try { - futimes(fo, attrs.lastAccessTime(), attrs.lastModifiedTime()); + futimes(fo, + attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), + attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); } catch (UnixException x) { if (flags.failIfUnableToCopyBasic) x.rethrowAsIOException(target); @@ -341,7 +346,9 @@ class UnixCopyFile { } if (flags.copyBasicAttributes) { try { - utimes(target, attrs.lastAccessTime(), attrs.lastModifiedTime()); + utimes(target, + attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), + attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); } catch (UnixException x) { if (flags.failIfUnableToCopyBasic) x.rethrowAsIOException(target); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java index a723d71adb2..591f49051c2 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java @@ -194,8 +194,11 @@ class UnixDirectoryStream Path entry = dir.resolve(nameAsBytes); // return entry if no filter or filter accepts it - if (filter.accept(entry)) { - return entry; + try { + if (filter == null || filter.accept(entry)) + return entry; + } catch (IOException ioe) { + throwAsConcurrentModificationException(ioe); } } } @@ -248,7 +251,7 @@ class UnixDirectoryStream ((UnixSecureDirectoryStream)stream) .implDelete(entry.getName(), false, 0); } else { - entry.delete(true); + entry.delete(); } } catch (IOException ioe) { throwAsConcurrentModificationException(ioe); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java index 7bbf925b734..27fe847a842 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -56,11 +56,11 @@ class UnixFileAttributeViews { return null; // keep compiler happy } } + @Override - public void setTimes(Long lastModifiedTime, - Long lastAccessTime, - Long createTime, - TimeUnit unit) throws IOException + public void setTimes(FileTime lastModifiedTime, + FileTime lastAccessTime, + FileTime createTime) throws IOException { // null => don't change if (lastModifiedTime == null && lastAccessTime == null) { @@ -68,53 +68,49 @@ class UnixFileAttributeViews { return; } + // permission check file.checkWrite(); int fd = file.openForAttributeAccess(followLinks); try { - UnixFileAttributes attrs = null; - // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - attrs = UnixFileAttributes.get(fd); + UnixFileAttributes attrs = UnixFileAttributes.get(fd); + if (lastModifiedTime == null) + lastModifiedTime = attrs.lastModifiedTime(); + if (lastAccessTime == null) + lastAccessTime = attrs.lastAccessTime(); } catch (UnixException x) { x.rethrowAsIOException(file); } } - // modified time = existing, now, or new value - long modTime; - if (lastModifiedTime == null) { - modTime = attrs.lastModifiedTime(); - } else { - if (lastModifiedTime >= 0L) { - modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); - } else { - if (lastModifiedTime != -1L) - throw new IllegalArgumentException(); - modTime = System.currentTimeMillis(); - } - } - - // access time = existing, now, or new value - long accTime; - if (lastAccessTime == null) { - accTime = attrs.lastAccessTime(); - } else { - if (lastAccessTime >= 0L) { - accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); - } else { - if (lastAccessTime != -1L) - throw new IllegalArgumentException(); - accTime = System.currentTimeMillis(); - } - } + // uptime times + long modValue = lastModifiedTime.to(TimeUnit.MICROSECONDS); + long accessValue= lastAccessTime.to(TimeUnit.MICROSECONDS); + boolean retry = false; try { - futimes(fd, accTime, modTime); + futimes(fd, accessValue, modValue); } catch (UnixException x) { - x.rethrowAsIOException(file); + // if futimes fails with EINVAL and one/both of the times is + // negative then we adjust the value to the epoch and retry. + if (x.errno() == UnixConstants.EINVAL && + (modValue < 0L || accessValue < 0L)) { + retry = true; + } else { + x.rethrowAsIOException(file); + } + } + if (retry) { + if (modValue < 0L) modValue = 0L; + if (accessValue < 0L) accessValue= 0L; + try { + futimes(fd, accessValue, modValue); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } } } finally { close(fd); @@ -199,10 +195,10 @@ class UnixFileAttributeViews { } @Override - public Map readAttributes(String first, String[] rest) + public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(first, rest); + AttributesBuilder builder = AttributesBuilder.create(attributes); PosixFileAttributes attrs = readAttributes(); addBasicAttributesToBuilder(attrs, builder); addPosixAttributesToBuilder(attrs, builder); @@ -297,6 +293,7 @@ class UnixFileAttributeViews { private static final String INO_NAME = "ino"; private static final String DEV_NAME = "dev"; private static final String RDEV_NAME = "rdev"; + private static final String NLINK_NAME = "nlink"; private static final String UID_NAME = "uid"; private static final String GID_NAME = "gid"; private static final String CTIME_NAME = "ctime"; @@ -320,6 +317,8 @@ class UnixFileAttributeViews { return readAttributes().dev(); if (attribute.equals(RDEV_NAME)) return readAttributes().rdev(); + if (attribute.equals(NLINK_NAME)) + return readAttributes().nlink(); if (attribute.equals(UID_NAME)) return readAttributes().uid(); if (attribute.equals(GID_NAME)) @@ -349,10 +348,10 @@ class UnixFileAttributeViews { } @Override - public Map readAttributes(String first, String[] rest) + public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(first, rest); + AttributesBuilder builder = AttributesBuilder.create(attributes); UnixFileAttributes attrs = readAttributes(); addBasicAttributesToBuilder(attrs, builder); addPosixAttributesToBuilder(attrs, builder); @@ -364,6 +363,8 @@ class UnixFileAttributeViews { builder.add(DEV_NAME, attrs.dev()); if (builder.match(RDEV_NAME)) builder.add(RDEV_NAME, attrs.rdev()); + if (builder.match(NLINK_NAME)) + builder.add(NLINK_NAME, attrs.nlink()); if (builder.match(UID_NAME)) builder.add(UID_NAME, attrs.uid()); if (builder.match(GID_NAME)) @@ -374,19 +375,19 @@ class UnixFileAttributeViews { } } - static BasicFileAttributeView createBasicView(UnixPath file, boolean followLinks) { + static Basic createBasicView(UnixPath file, boolean followLinks) { return new Basic(file, followLinks); } - static PosixFileAttributeView createPosixView(UnixPath file, boolean followLinks) { + static Posix createPosixView(UnixPath file, boolean followLinks) { return new Posix(file, followLinks); } - static PosixFileAttributeView createUnixView(UnixPath file, boolean followLinks) { + static Unix createUnixView(UnixPath file, boolean followLinks) { return new Unix(file, followLinks); } - static FileOwnerAttributeView createOwnerView(UnixPath file, boolean followLinks) { + static FileOwnerAttributeViewImpl createOwnerView(UnixPath file, boolean followLinks) { return new FileOwnerAttributeViewImpl(createPosixView(file, followLinks)); } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java index c1882d7536b..b26d49a3e5a 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java @@ -97,9 +97,13 @@ class UnixFileAttributes long ino() { return st_ino; } long dev() { return st_dev; } long rdev() { return st_rdev; } + int nlink() { return st_nlink; } int uid() { return st_uid; } int gid() { return st_gid; } - long ctime() { return st_ctime; } + + FileTime ctime() { + return FileTime.from(st_ctime, TimeUnit.SECONDS); + } boolean isDevice() { int type = st_mode & UnixConstants.S_IFMT; @@ -109,23 +113,18 @@ class UnixFileAttributes } @Override - public long lastModifiedTime() { - return st_mtime; + public FileTime lastModifiedTime() { + return FileTime.from(st_mtime, TimeUnit.SECONDS); } @Override - public long lastAccessTime() { - return st_atime; + public FileTime lastAccessTime() { + return FileTime.from(st_atime, TimeUnit.SECONDS); } @Override - public long creationTime() { - return -1L; - } - - @Override - public TimeUnit resolution() { - return TimeUnit.MILLISECONDS; + public FileTime creationTime() { + return null; } @Override @@ -156,11 +155,6 @@ class UnixFileAttributes return st_size; } - @Override - public int linkCount() { - return st_nlink; - } - @Override public UnixFileKey fileKey() { if (key == null) { @@ -260,22 +254,18 @@ class UnixFileAttributes } @Override - public long lastModifiedTime() { + public FileTime lastModifiedTime() { return attrs.lastModifiedTime(); } @Override - public long lastAccessTime() { + public FileTime lastAccessTime() { return attrs.lastAccessTime(); } @Override - public long creationTime() { + public FileTime creationTime() { return attrs.creationTime(); } @Override - public TimeUnit resolution() { - return attrs.resolution(); - } - @Override public boolean isRegularFile() { return attrs.isRegularFile(); } @@ -296,10 +286,6 @@ class UnixFileAttributes return attrs.size(); } @Override - public int linkCount() { - return attrs.linkCount(); - } - @Override public Object fileKey() { return attrs.fileKey(); } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java index 4ab3aec6c30..44a3b69ecd8 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java @@ -53,4 +53,15 @@ class UnixFileKey { UnixFileKey other = (UnixFileKey)obj; return (this.st_dev == other.st_dev) && (this.st_ino == other.st_ino); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("(dev=") + .append(Long.toHexString(st_dev)) + .append(",ino=") + .append(st_ino) + .append(')'); + return sb.toString(); + } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java index 67ea59e943d..f19b6f7ff50 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java @@ -42,10 +42,7 @@ class UnixFileModeAttribute { static final int TEMPFILE_PERMISSIONS = UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR; - private Set perms; - - UnixFileModeAttribute() { - perms = Collections.emptySet(); + private UnixFileModeAttribute() { } static int toUnixMode(Set perms) { diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java index 483a4ea4825..02397648eae 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java @@ -78,7 +78,7 @@ abstract class UnixFileStore /** * Returns true if this file store represents a loopback file system that - * will have the same device ID as undelrying file system. + * will have the same device ID as underlying file system. */ abstract boolean isLoopback(); @@ -111,22 +111,33 @@ abstract class UnixFileStore @Override @SuppressWarnings("unchecked") - public V getFileStoreAttributeView(Class viewType) + public V getFileStoreAttributeView(Class view) { - if (viewType == FileStoreSpaceAttributeView.class) + if (view == null) + throw new NullPointerException(); + if (view == FileStoreSpaceAttributeView.class) return (V) new UnixFileStoreSpaceAttributeView(this); return (V) null; } @Override - public FileStoreAttributeView getFileStoreAttributeView(String name) { - if (name.equals("space")) - return new UnixFileStoreSpaceAttributeView(this); - return null; + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals("space:totalSpace")) + return new UnixFileStoreSpaceAttributeView(this) + .readAttributes().totalSpace(); + if (attribute.equals("space:usableSpace")) + return new UnixFileStoreSpaceAttributeView(this) + .readAttributes().usableSpace(); + if (attribute.equals("space:unallocatedSpace")) + return new UnixFileStoreSpaceAttributeView(this) + .readAttributes().unallocatedSpace(); + throw new UnsupportedOperationException("'" + attribute + "' not recognized"); } @Override public boolean supportsFileAttributeView(Class type) { + if (type == null) + throw new NullPointerException(); if (type == BasicFileAttributeView.class) return true; if (type == PosixFileAttributeView.class || @@ -187,7 +198,7 @@ abstract class UnixFileStore } private static class UnixFileStoreSpaceAttributeView - extends AbstractFileStoreSpaceAttributeView + implements FileStoreSpaceAttributeView { private final UnixFileStore fs; @@ -195,6 +206,11 @@ abstract class UnixFileStore this.fs = fs; } + @Override + public String name() { + return "space"; + } + @Override public FileStoreSpaceAttributes readAttributes() throws IOException @@ -275,7 +291,7 @@ abstract class UnixFileStore private static Properties loadProperties() { Properties result = new Properties(); String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties"; - FileRef file = Paths.get(fstypes); + Path file = Paths.get(fstypes); try { ReadableByteChannel rbc = file.newByteChannel(); try { diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java index 6e46b2647d9..953850c3e35 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java @@ -137,13 +137,9 @@ abstract class UnixFileSystem * @param tfd * Open file descriptor to target file */ - abstract void copyNonPosixAttributes(int sfd, int tfd); - - /** - * Tells if directory relative system calls (openat, etc.) are available - * on this operating system. - */ - abstract boolean supportsSecureDirectoryStreams(); + void copyNonPosixAttributes(int sfd, int tfd) { + // no-op by default + } /** * Unix systems only have a single root directory (/) @@ -340,9 +336,9 @@ abstract class UnixFileSystem return Arrays.asList("basic", "posix", "unix", "owner"); } - protected FileAttributeView newFileAttributeView(String name, - UnixPath file, - LinkOption... options) + protected DynamicFileAttributeView newFileAttributeView(String name, + UnixPath file, + LinkOption... options) { boolean followLinks = followLinks(options); if (name.equals("basic")) diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java index 878fe25c5e4..5dd610b7a83 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -93,7 +93,7 @@ public abstract class UnixFileSystemProvider return UnixUriUtils.fromUri(theFileSystem, uri); } - private UnixPath checkPath(Path obj) { + protected UnixPath checkPath(Path obj) { if (obj == null) throw new NullPointerException(); if (!(obj instanceof UnixPath)) @@ -102,9 +102,9 @@ public abstract class UnixFileSystemProvider } @Override - public final FileChannel newFileChannel(Path obj, - Set options, - FileAttribute... attrs) + public FileChannel newFileChannel(Path obj, + Set options, + FileAttribute... attrs) throws IOException { UnixPath file = checkPath(obj); @@ -119,10 +119,10 @@ public abstract class UnixFileSystemProvider } @Override - public final AsynchronousFileChannel newAsynchronousFileChannel(Path obj, - Set options, - ExecutorService executor, - FileAttribute... attrs) throws IOException + public AsynchronousFileChannel newAsynchronousFileChannel(Path obj, + Set options, + ExecutorService executor, + FileAttribute... attrs) throws IOException { UnixPath file = checkPath(obj); int mode = UnixFileModeAttribute diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java b/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java index c4769e7a7d8..92c1ca8b0fd 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java @@ -66,7 +66,7 @@ class UnixMountEntry { boolean hasOption(String requested) { if (optionsAsString == null) optionsAsString = new String(opts); - for (String opt: optionsAsString.split("\\,", 0)) { + for (String opt: Util.split(optionsAsString, ',')) { if (opt.equals(requested)) return true; } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java index 29140e3ec31..1b9e1898b33 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -542,8 +542,17 @@ class UnixNativeDispatcher { */ static native byte[] strerror(int errnum); - // initialize field IDs - private static native void initIDs(); + // indicates if openat, unlinkat, etc. is supported + private static final boolean hasAtSysCalls; + static boolean supportsAtSysCalls() { + return hasAtSysCalls; + } + + // initialize syscalls and fieldIDs + private static native int init(); + + // flags returned by init to indicate capabilities + private static final int HAS_AT_SYSCALLS = 0x1; static { AccessController.doPrivileged(new PrivilegedAction() { @@ -551,6 +560,8 @@ class UnixNativeDispatcher { System.loadLibrary("nio"); return null; }}); - initIDs(); + int flags = init(); + + hasAtSysCalls = (flags & HAS_AT_SYSCALLS) > 0; } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java index c1330f005ce..9d5db356255 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -28,7 +28,6 @@ package sun.nio.fs; import java.nio.*; import java.nio.file.*; import java.nio.file.attribute.*; -import java.nio.file.spi.AbstractPath; import java.nio.charset.*; import java.nio.channels.*; import java.security.AccessController; @@ -88,10 +87,9 @@ class UnixPath char prevChar = 0; for (int i=0; i < n; i++) { char c = input.charAt(i); - if (c == '\u0000') - throw new InvalidPathException(input, "Nul character not allowed"); if ((c == '/') && (prevChar == '/')) return normalize(input, n, i - 1); + checkNotNul(input, c); prevChar = c; } if (prevChar == '/') @@ -99,6 +97,11 @@ class UnixPath return input; } + private static void checkNotNul(String input, char c) { + if (c == '\u0000') + throw new InvalidPathException(input, "Nul character not allowed"); + } + private static String normalize(String input, int len, int off) { if (len == 0) return input; @@ -114,6 +117,7 @@ class UnixPath char c = input.charAt(i); if ((c == '/') && (prevChar == '/')) continue; + checkNotNul(input, c); sb.append(c); prevChar = c; } @@ -862,7 +866,7 @@ class UnixPath } @Override - public void delete(boolean failIfNotExists) throws IOException { + void implDelete(boolean failIfNotExists) throws IOException { checkDelete(); // need file attributes to know if file is directory @@ -896,13 +900,14 @@ class UnixPath throw new NullPointerException(); checkRead(); - // can't return SecureDirectoryStream on older kernels. - if (!getFileSystem().supportsSecureDirectoryStreams()) { + // can't return SecureDirectoryStream on kernels that don't support + // openat, etc. + if (!supportsAtSysCalls()) { try { long ptr = opendir(this); return new UnixDirectoryStream(this, ptr, filter); } catch (UnixException x) { - if (x.errno() == UnixConstants.ENOTDIR) + if (x.errno() == ENOTDIR) throw new NotDirectoryException(getPathForExecptionMessage()); x.rethrowAsIOException(this); } @@ -959,7 +964,9 @@ class UnixPath } @Override - public FileAttributeView getFileAttributeView(String name, LinkOption... options) { + public DynamicFileAttributeView getFileAttributeView(String name, + LinkOption... options) + { return getFileSystem().newFileAttributeView(name, this, options); } @@ -979,21 +986,9 @@ class UnixPath return this; } - @Override - public InputStream newInputStream()throws IOException { - try { - Set options = Collections.emptySet(); - FileChannel fc = UnixChannelFactory.newFileChannel(this, options, 0); - return Channels.newInputStream(fc); - } catch (UnixException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - @Override public SeekableByteChannel newByteChannel(Set options, - FileAttribute... attrs) + FileAttribute... attrs) throws IOException { int mode = UnixFileModeAttribute @@ -1007,29 +1002,7 @@ class UnixPath } @Override - public OutputStream newOutputStream(Set options, - FileAttribute... attrs) - throws IOException - { - // need to copy options to add WRITE - Set opts = new HashSet(options); - if (opts.contains(StandardOpenOption.READ)) - throw new IllegalArgumentException("READ not allowed"); - opts.add(StandardOpenOption.WRITE); - - int mode = UnixFileModeAttribute - .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); - try { - FileChannel fc = UnixChannelFactory.newFileChannel(this, opts, mode); - return Channels.newOutputStream(fc); - } catch (UnixException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - - @Override - public boolean isSameFile(FileRef obj) throws IOException { + public boolean isSameFile(Path obj) throws IOException { if (this.equals(obj)) return true; if (!(obj instanceof UnixPath)) // includes null check @@ -1188,13 +1161,6 @@ class UnixPath } result = result.resolve(element); } - - // finally check that file exists - try { - UnixFileAttributes.get(result, true); - } catch (UnixException x) { - x.rethrowAsIOException(result); - } return result; } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java b/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java index e5894878709..34fa167bdc8 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java @@ -40,7 +40,7 @@ import static sun.nio.fs.UnixConstants.*; */ class UnixSecureDirectoryStream - extends SecureDirectoryStream + extends SecureDirectoryStream { private final UnixDirectoryStream ds; private final int dfd; @@ -85,13 +85,13 @@ class UnixSecureDirectoryStream * Opens sub-directory in this directory */ @Override - public SecureDirectoryStream newDirectoryStream(Path obj, - boolean followLinks, - DirectoryStream.Filter filter) + public SecureDirectoryStream newDirectoryStream(Path obj, + LinkOption... options) throws IOException { UnixPath file = getName(obj); UnixPath child = ds.directory().resolve(file); + boolean followLinks = file.getFileSystem().followLinks(options); // permission check using name resolved against original path of directory SecurityManager sm = System.getSecurityManager(); @@ -124,7 +124,7 @@ class UnixSecureDirectoryStream throw new NotDirectoryException(file.toString()); x.rethrowAsIOException(file); } - return new UnixSecureDirectoryStream(child, ptr, newdfd2, filter); + return new UnixSecureDirectoryStream(child, ptr, newdfd2, null); } finally { ds.readLock().unlock(); } @@ -225,7 +225,7 @@ class UnixSecureDirectoryStream * Rename/move file in this directory to another (open) directory */ @Override - public void move(Path fromObj, SecureDirectoryStream dir, Path toObj) + public void move(Path fromObj, SecureDirectoryStream dir, Path toObj) throws IOException { UnixPath from = getName(fromObj); @@ -310,14 +310,11 @@ class UnixSecureDirectoryStream * A BasicFileAttributeView implementation that using a dfd/name pair. */ private class BasicFileAttributeViewImpl - extends AbstractBasicFileAttributeView + implements BasicFileAttributeView { final UnixPath file; final boolean followLinks; - // set to true when binding to another object - volatile boolean forwarding; - BasicFileAttributeViewImpl(UnixPath file, boolean followLinks) { this.file = file; @@ -380,17 +377,11 @@ class UnixSecureDirectoryStream } @Override - public void setTimes(Long lastModifiedTime, - Long lastAccessTime, - Long createTime, // ignore - TimeUnit unit) + public void setTimes(FileTime lastModifiedTime, + FileTime lastAccessTime, + FileTime createTime) // ignore throws IOException { - // no effect - if (lastModifiedTime == null && lastAccessTime == null) { - return; - } - checkWriteAccess(); ds.readLock().lock(); @@ -400,47 +391,23 @@ class UnixSecureDirectoryStream int fd = (file == null) ? dfd : open(); try { - UnixFileAttributes attrs = null; - // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - attrs = UnixFileAttributes.get(fd); + UnixFileAttributes attrs = UnixFileAttributes.get(fd); + if (lastModifiedTime == null) + lastModifiedTime = attrs.lastModifiedTime(); + if (lastAccessTime == null) + lastAccessTime = attrs.lastAccessTime(); } catch (UnixException x) { x.rethrowAsIOException(file); } } - - // modified time = existing, now, or new value - long modTime; - if (lastModifiedTime == null) { - modTime = attrs.lastModifiedTime(); - } else { - if (lastModifiedTime >= 0L) { - modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); - } else { - if (lastModifiedTime != -1L) - throw new IllegalArgumentException(); - modTime = System.currentTimeMillis(); - } - } - - // access time = existing, now, or new value - long accTime; - if (lastAccessTime == null) { - accTime = attrs.lastAccessTime(); - } else { - if (lastAccessTime >= 0L) { - accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); - } else { - if (lastAccessTime != -1L) - throw new IllegalArgumentException(); - accTime = System.currentTimeMillis(); - } - } - + // update times try { - futimes(fd, accTime, modTime); + futimes(fd, + lastAccessTime.to(TimeUnit.MICROSECONDS), + lastModifiedTime.to(TimeUnit.MICROSECONDS)); } catch (UnixException x) { x.rethrowAsIOException(file); } @@ -460,10 +427,6 @@ class UnixSecureDirectoryStream private class PosixFileAttributeViewImpl extends BasicFileAttributeViewImpl implements PosixFileAttributeView { - private static final String PERMISSIONS_NAME = "permissions"; - private static final String OWNER_NAME = "owner"; - private static final String GROUP_NAME = "group"; - PosixFileAttributeViewImpl(UnixPath file, boolean followLinks) { super(file, followLinks); } @@ -481,59 +444,6 @@ class UnixSecureDirectoryStream return "posix"; } - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(PERMISSIONS_NAME)) - return readAttributes().permissions(); - if (attribute.equals(OWNER_NAME)) - return readAttributes().owner(); - if (attribute.equals(GROUP_NAME)) - return readAttributes().group(); - return super.getAttribute(attribute); - } - - @Override - @SuppressWarnings("unchecked") - public void setAttribute(String attribute, Object value) - throws IOException - { - if (attribute.equals(PERMISSIONS_NAME)) { - setPermissions((Set)value); - return; - } - if (attribute.equals(OWNER_NAME)) { - setOwner((UserPrincipal)value); - return; - } - if (attribute.equals(GROUP_NAME)) { - setGroup((GroupPrincipal)value); - return; - } - super.setAttribute(attribute, value); - } - - final void addPosixAttributesToBuilder(PosixFileAttributes attrs, - AttributesBuilder builder) - { - if (builder.match(PERMISSIONS_NAME)) - builder.add(PERMISSIONS_NAME, attrs.permissions()); - if (builder.match(OWNER_NAME)) - builder.add(OWNER_NAME, attrs.owner()); - if (builder.match(GROUP_NAME)) - builder.add(GROUP_NAME, attrs.group()); - } - - @Override - public Map readAttributes(String first, String[] rest) - throws IOException - { - AttributesBuilder builder = AttributesBuilder.create(first, rest); - PosixFileAttributes attrs = readAttributes(); - addBasicAttributesToBuilder(attrs, builder); - addPosixAttributesToBuilder(attrs, builder); - return builder.unmodifiableMap(); - } - @Override public PosixFileAttributes readAttributes() throws IOException { SecurityManager sm = System.getSecurityManager(); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java b/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java index 88dfe9c4d90..8e56e512b1d 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java @@ -147,8 +147,14 @@ class UnixUserPrincipals { } catch (UnixException x) { throw new IOException(name + ": " + x.errorString()); } - if (id == -1) - throw new UserPrincipalNotFoundException(name); + if (id == -1) { + // lookup failed, allow input to be uid or gid + try { + id = Integer.parseInt(name); + } catch (NumberFormatException ignore) { + throw new UserPrincipalNotFoundException(name); + } + } return id; } diff --git a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c index 13a1a3a215f..6f55bbed069 100644 --- a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c +++ b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c @@ -92,14 +92,12 @@ typedef int fstatat64_func(int, const char *, struct stat64 *, int); typedef int unlinkat_func(int, const char*, int); typedef int renameat_func(int, const char*, int, const char*); typedef int futimesat_func(int, const char *, const struct timeval *); -typedef DIR* fdopendir_func(int); static openat64_func* my_openat64_func = NULL; static fstatat64_func* my_fstatat64_func = NULL; static unlinkat_func* my_unlinkat_func = NULL; static renameat_func* my_renameat_func = NULL; static futimesat_func* my_futimesat_func = NULL; -static fdopendir_func* my_fdopendir_func = NULL; /** * fstatat missing from glibc on Linux. Temporary workaround @@ -142,16 +140,17 @@ static void throwUnixException(JNIEnv* env, int errnum) { } /** - * Initialize jfieldIDs + * Initialization */ -JNIEXPORT void JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this) +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) { + jint flags = 0; jclass clazz; clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileAttributes"); if (clazz == NULL) { - return; + return 0; } attrs_st_mode = (*env)->GetFieldID(env, clazz, "st_mode", "I"); attrs_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J"); @@ -167,7 +166,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this) clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes"); if (clazz == NULL) { - return; + return 0; } attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J"); attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J"); @@ -176,7 +175,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this) clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); if (clazz == NULL) { - return; + return 0; } entry_name = (*env)->GetFieldID(env, clazz, "name", "[B"); entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B"); @@ -197,13 +196,21 @@ Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this) my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat"); my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat"); my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat"); - my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir"); #if defined(FSTATAT64_SYSCALL_AVAILABLE) /* fstatat64 missing from glibc */ if (my_fstatat64_func == NULL) my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper; #endif + + if (my_openat64_func != NULL && my_fstatat64_func != NULL && + my_unlinkat_func != NULL && my_renameat_func != NULL && + my_futimesat_func != NULL) + { + flags |= sun_nio_fs_UnixNativeDispatcher_HAS_AT_SYSCALLS; + } + + return flags; } JNIEXPORT jbyteArray JNICALL @@ -364,9 +371,9 @@ static void prepAttributes(JNIEnv* env, struct stat64* buf, jobject attrs) { (*env)->SetIntField(env, attrs, attrs_st_uid, (jint)buf->st_uid); (*env)->SetIntField(env, attrs, attrs_st_gid, (jint)buf->st_gid); (*env)->SetLongField(env, attrs, attrs_st_size, (jlong)buf->st_size); - (*env)->SetLongField(env, attrs, attrs_st_atime, (jlong)buf->st_atime * 1000); - (*env)->SetLongField(env, attrs, attrs_st_mtime, (jlong)buf->st_mtime * 1000); - (*env)->SetLongField(env, attrs, attrs_st_ctime, (jlong)buf->st_ctime * 1000); + (*env)->SetLongField(env, attrs, attrs_st_atime, (jlong)buf->st_atime); + (*env)->SetLongField(env, attrs, attrs_st_mtime, (jlong)buf->st_mtime); + (*env)->SetLongField(env, attrs, attrs_st_ctime, (jlong)buf->st_ctime); } JNIEXPORT void JNICALL @@ -506,11 +513,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this, struct timeval times[2]; const char* path = (const char*)jlong_to_ptr(pathAddress); - times[0].tv_sec = accessTime / 1000; - times[0].tv_usec = (accessTime % 1000) * 1000; + times[0].tv_sec = accessTime / 1000000; + times[0].tv_usec = accessTime % 1000000; - times[1].tv_sec = modificationTime / 1000; - times[1].tv_usec = (modificationTime % 1000) * 1000; + times[1].tv_sec = modificationTime / 1000000; + times[1].tv_usec = modificationTime % 1000000; RESTARTABLE(utimes(path, ×[0]), err); if (err == -1) { @@ -525,11 +532,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint file struct timeval times[2]; int err = 0; - times[0].tv_sec = accessTime / 1000; - times[0].tv_usec = (accessTime % 1000) * 1000; + times[0].tv_sec = accessTime / 1000000; + times[0].tv_usec = accessTime % 1000000; - times[1].tv_sec = modificationTime / 1000; - times[1].tv_usec = (modificationTime % 1000) * 1000; + times[1].tv_sec = modificationTime / 1000000; + times[1].tv_usec = modificationTime % 1000000; if (my_futimesat_func != NULL) { RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err); @@ -558,13 +565,8 @@ JNIEXPORT jlong JNICALL Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) { DIR* dir; - if (my_fdopendir_func == NULL) { - JNU_ThrowInternalError(env, "should not reach here"); - return (jlong)-1; - } - /* EINTR not listed as a possible error */ - dir = (*my_fdopendir_func)((int)dfd); + dir = fdopendir((int)dfd); if (dir == NULL) { throwUnixException(env, errno); } diff --git a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c index c01f641a690..ed82102fd5e 100644 --- a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c +++ b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c @@ -66,16 +66,6 @@ int main(int argc, const char* argv[]) { DEFX(O_DSYNC); DEFX(O_NOFOLLOW); - // flags used with openat/unlinkat/etc. -#ifdef __solaris__ - DEFX(AT_SYMLINK_NOFOLLOW); - DEFX(AT_REMOVEDIR); -#endif -#ifdef __linux__ - emitX("AT_SYMLINK_NOFOLLOW", 0x100); // since 2.6.16 - emitX("AT_REMOVEDIR", 0x200); -#endif - // mode masks emitX("S_IAMB", (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH)); @@ -119,6 +109,16 @@ int main(int argc, const char* argv[]) { DEF(ENODATA); DEF(ERANGE); + // flags used with openat/unlinkat/etc. +#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR) + DEFX(AT_SYMLINK_NOFOLLOW) + DEFX(AT_REMOVEDIR); +#else + // not supported (dummy values will not be used at runtime). + emitX("AT_SYMLINK_NOFOLLOW", 0x0); + emitX("AT_REMOVEDIR", 0x0); +#endif + out("} "); return 0; diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java index f2619ac8060..077a4893b2f 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java @@ -93,6 +93,7 @@ class WindowsConstants { public static final int ERROR_NOT_SAME_DEVICE = 17; public static final int ERROR_NOT_READY = 21; public static final int ERROR_FILE_EXISTS = 80; + public static final int ERROR_INVALID_PARAMATER = 87; public static final int ERROR_DISK_FULL = 112; public static final int ERROR_INSUFFICIENT_BUFFER = 122; public static final int ERROR_INVALID_LEVEL = 124; diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java b/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java index fa0b148346c..df773489152 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java @@ -152,11 +152,13 @@ class WindowsDirectoryStream } Path entry = WindowsPath .createFromNormalizedPath(dir.getFileSystem(), s, attrs); - if (filter.accept(entry)) { - return entry; - } else { - return null; + try { + if (filter.accept(entry)) + return entry; + } catch (IOException ioe) { + throwAsConcurrentModificationException(ioe); } + return null; } // reads next directory entry @@ -244,7 +246,7 @@ class WindowsDirectoryStream prevEntry = null; } try { - entry.delete(true); + entry.delete(); } catch (IOException ioe) { throwAsConcurrentModificationException(ioe); } catch (SecurityException se) { diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java index 39c34a10ea9..5af9876f33c 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java @@ -28,7 +28,6 @@ package sun.nio.fs; import java.nio.file.attribute.*; import java.util.*; -import java.util.concurrent.TimeUnit; import java.io.IOException; import static sun.nio.fs.WindowsNativeDispatcher.*; @@ -55,10 +54,25 @@ class WindowsFileAttributeViews { } } + /** + * Adjusts a Windows time for the FAT epoch. + */ + private long adjustForFatEpoch(long time) { + // 1/1/1980 in Windows Time + final long FAT_EPOCH = 119600064000000000L; + if (time != -1L && time < FAT_EPOCH) { + return FAT_EPOCH; + } else { + return time; + } + } + /** * Parameter values in Windows times. */ - void setFileTimes(long createTime, long lastAccessTime, long lastWriteTime) + void setFileTimes(long createTime, + long lastAccessTime, + long lastWriteTime) throws IOException { long handle = -1L; @@ -76,24 +90,43 @@ class WindowsFileAttributeViews { x.rethrowAsIOException(file); } - // update attributes + // update times try { - SetFileTime(handle, createTime, lastAccessTime, lastWriteTime); + SetFileTime(handle, + createTime, + lastAccessTime, + lastWriteTime); } catch (WindowsException x) { - x.rethrowAsIOException(file); + // If ERROR_INVALID_PARAMATER is returned and the volume is + // FAT then adjust to the FAT epoch and retry. + if (followLinks && x.lastError() == ERROR_INVALID_PARAMATER) { + try { + if (WindowsFileStore.create(file).type().equals("FAT")) { + SetFileTime(handle, + adjustForFatEpoch(createTime), + adjustForFatEpoch(lastAccessTime), + adjustForFatEpoch(lastWriteTime)); + // retry succeeded + x = null; + } + } catch (SecurityException ignore) { + } catch (WindowsException ignore) { + } catch (IOException ignore) { + // ignore exceptions to let original exception be thrown + } + } + if (x != null) + x.rethrowAsIOException(file); } finally { CloseHandle(handle); } } @Override - public void setTimes(Long lastModifiedTime, - Long lastAccessTime, - Long createTime, - TimeUnit unit) throws IOException + public void setTimes(FileTime lastModifiedTime, + FileTime lastAccessTime, + FileTime createTime) throws IOException { - file.checkWrite(); - // if all null then do nothing if (lastModifiedTime == null && lastAccessTime == null && createTime == null) @@ -102,42 +135,17 @@ class WindowsFileAttributeViews { return; } - // null => no change - // -1 => change to current time - long now = System.currentTimeMillis(); - long modTime = 0L, accTime = 0L, crTime = 0L; - if (lastModifiedTime != null) { - if (lastModifiedTime < 0L) { - if (lastModifiedTime != -1L) - throw new IllegalArgumentException(); - modTime = now; - } else { - modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); - } - modTime = WindowsFileAttributes.toWindowsTime(modTime); - } - if (lastAccessTime != null) { - if (lastAccessTime < 0L) { - if (lastAccessTime != -1L) - throw new IllegalArgumentException(); - accTime = now; - } else { - accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); - } - accTime = WindowsFileAttributes.toWindowsTime(accTime); - } - if (createTime != null) { - if (createTime < 0L) { - if (createTime != -1L) - throw new IllegalArgumentException(); - crTime = now; - } else { - crTime = TimeUnit.MILLISECONDS.convert(createTime, unit); - } - crTime = WindowsFileAttributes.toWindowsTime(crTime); - } + // permission check + file.checkWrite(); - setFileTimes(crTime, accTime, modTime); + // update times + long t1 = (createTime == null) ? -1L : + WindowsFileAttributes.toWindowsTime(createTime); + long t2 = (lastAccessTime == null) ? -1L : + WindowsFileAttributes.toWindowsTime(lastAccessTime); + long t3 = (lastModifiedTime == null) ? -1L : + WindowsFileAttributes.toWindowsTime(lastModifiedTime); + setFileTimes(t1, t2, t3); } } @@ -197,10 +205,10 @@ class WindowsFileAttributeViews { } @Override - public Map readAttributes(String first, String[] rest) + public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(first, rest); + AttributesBuilder builder = AttributesBuilder.create(attributes); WindowsFileAttributes attrs = readAttributes(); addBasicAttributesToBuilder(attrs, builder); if (builder.match(READONLY_NAME)) @@ -286,11 +294,11 @@ class WindowsFileAttributeViews { } } - static BasicFileAttributeView createBasicView(WindowsPath file, boolean followLinks) { + static Basic createBasicView(WindowsPath file, boolean followLinks) { return new Basic(file, followLinks); } - static WindowsFileAttributeViews.Dos createDosView(WindowsPath file, boolean followLinks) { + static Dos createDosView(WindowsPath file, boolean followLinks) { return new Dos(file, followLinks); } } diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java index ce053cf901f..f930eab98d3 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -65,7 +65,6 @@ class WindowsFileAttributes private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM = 28; private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH = 32; private static final short OFFSETOF_FILE_INFORMATION_SIZELOW = 36; - private static final short OFFSETOF_FILE_INFORMATION_NUMLINKS = 40; private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH = 44; private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW = 48; @@ -110,6 +109,9 @@ class WindowsFileAttributes private static final short OFFSETOF_FIND_DATA_SIZELOW = 32; private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36; + // used to adjust values between Windows and java epoch + private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; + // indicates if accurate metadata is required (interesting on NTFS only) private static final boolean ensureAccurateMetadata; static { @@ -128,29 +130,33 @@ class WindowsFileAttributes private final int reparseTag; // additional attributes when using GetFileInformationByHandle - private final int linkCount; private final int volSerialNumber; private final int fileIndexHigh; private final int fileIndexLow; /** * Convert 64-bit value representing the number of 100-nanosecond intervals - * since January 1, 1601 to java time. + * since January 1, 1601 to a FileTime. */ - private static long toJavaTime(long time) { - time /= 10000L; - time -= 11644473600000L; - return time; + static FileTime toFileTime(long time) { + // 100ns -> us + time /= 10L; + // adjust to java epoch + time += WINDOWS_EPOCH_IN_MICROSECONDS; + return FileTime.from(time, TimeUnit.MICROSECONDS); } /** - * Convert java time to 64-bit value representing the number of 100-nanosecond + * Convert FileTime to 64-bit value representing the number of 100-nanosecond * intervals since January 1, 1601. */ - static long toWindowsTime(long time) { - time += 11644473600000L; - time *= 10000L; - return time; + static long toWindowsTime(FileTime time) { + long value = time.to(TimeUnit.MICROSECONDS); + // adjust to Windows epoch+= 11644473600000000L; + value -= WINDOWS_EPOCH_IN_MICROSECONDS; + // us -> 100ns + value *= 10L; + return value; } /** @@ -162,7 +168,6 @@ class WindowsFileAttributes long lastWriteTime, long size, int reparseTag, - int linkCount, int volSerialNumber, int fileIndexHigh, int fileIndexLow) @@ -173,7 +178,6 @@ class WindowsFileAttributes this.lastWriteTime = lastWriteTime; this.size = size; this.reparseTag = reparseTag; - this.linkCount = linkCount; this.volSerialNumber = volSerialNumber; this.fileIndexHigh = fileIndexHigh; this.fileIndexLow = fileIndexLow; @@ -184,15 +188,11 @@ class WindowsFileAttributes */ private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) { int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES); - long creationTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME)); - long lastAccessTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME)); - long lastWriteTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME)); + long creationTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME); + long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME); + long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME); long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32) + (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL); - int linkCount = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_NUMLINKS); int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM); int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH); int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW); @@ -202,7 +202,6 @@ class WindowsFileAttributes lastWriteTime, size, reparseTag, - linkCount, volSerialNumber, fileIndexHigh, fileIndexLow); @@ -213,12 +212,9 @@ class WindowsFileAttributes */ private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) { int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES); - long creationTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME)); - long lastAccessTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME)); - long lastWriteTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME)); + long creationTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME); + long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME); + long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME); long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32) + (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL); return new WindowsFileAttributes(fileAttrs, @@ -227,7 +223,6 @@ class WindowsFileAttributes lastWriteTime, size, reparseTag, - 1, // linkCount 0, // volSerialNumber 0, // fileIndexHigh 0); // fileIndexLow @@ -246,12 +241,9 @@ class WindowsFileAttributes */ static WindowsFileAttributes fromFindData(long address) { int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES); - long creationTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME)); - long lastAccessTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME)); - long lastWriteTime = - toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME)); + long creationTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME); + long lastAccessTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME); + long lastWriteTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME); long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32) + (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL); int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ? @@ -262,7 +254,6 @@ class WindowsFileAttributes lastWriteTime, size, reparseTag, - 1, // linkCount 0, // volSerialNumber 0, // fileIndexHigh 0); // fileIndexLow @@ -375,28 +366,18 @@ class WindowsFileAttributes } @Override - public long lastModifiedTime() { - return (lastWriteTime >= 0L) ? lastWriteTime : 0L; + public FileTime lastModifiedTime() { + return toFileTime(lastWriteTime); } @Override - public long lastAccessTime() { - return (lastAccessTime >= 0L) ? lastAccessTime : 0L; + public FileTime lastAccessTime() { + return toFileTime(lastAccessTime); } @Override - public long creationTime() { - return (creationTime >= 0L) ? creationTime : 0L; - } - - @Override - public TimeUnit resolution() { - return TimeUnit.MILLISECONDS; - } - - @Override - public int linkCount() { - return linkCount; + public FileTime creationTime() { + return toFileTime(creationTime); } @Override diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java index 5d3a0af2533..a906b54e0de 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java @@ -27,7 +27,6 @@ package sun.nio.fs; import java.nio.file.*; import java.nio.file.attribute.*; -import java.util.*; import java.io.IOException; import static sun.nio.fs.WindowsConstants.*; @@ -120,23 +119,40 @@ class WindowsFileStore @Override @SuppressWarnings("unchecked") - public V getFileStoreAttributeView(Class view) { - if (view == FileStoreSpaceAttributeView.class) + public V getFileStoreAttributeView(Class type) { + if (type == null) + throw new NullPointerException(); + if (type == FileStoreSpaceAttributeView.class) return (V) new WindowsFileStoreAttributeView(this); return (V) null; } @Override - public FileStoreAttributeView getFileStoreAttributeView(String name) { - if (name.equals("space")) - return new WindowsFileStoreAttributeView(this); - if (name.equals("volume")) - return new VolumeFileStoreAttributeView(this); - return null; + public Object getAttribute(String attribute) throws IOException { + // standard + if (attribute.equals("space:totalSpace")) + return new WindowsFileStoreAttributeView(this) + .readAttributes().totalSpace(); + if (attribute.equals("space:usableSpace")) + return new WindowsFileStoreAttributeView(this) + .readAttributes().usableSpace(); + if (attribute.equals("space:unallocatedSpace")) + return new WindowsFileStoreAttributeView(this) + .readAttributes().unallocatedSpace(); + // windows specific for testing purposes + if (attribute.equals("volume:vsn")) + return volInfo.volumeSerialNumber(); + if (attribute.equals("volume:isRemovable")) + return volType == DRIVE_REMOVABLE; + if (attribute.equals("volume:isCdrom")) + return volType == DRIVE_CDROM; + throw new UnsupportedOperationException("'" + attribute + "' not recognized"); } @Override public boolean supportsFileAttributeView(Class type) { + if (type == null) + throw new NullPointerException(); if (type == BasicFileAttributeView.class) return true; if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class) @@ -154,7 +170,7 @@ class WindowsFileStore return supportsFileAttributeView(AclFileAttributeView.class); if (name.equals("owner")) return supportsFileAttributeView(FileOwnerAttributeView.class); - if (name.equals("xattr")) + if (name.equals("user")) return supportsFileAttributeView(UserDefinedFileAttributeView.class); return false; } @@ -188,7 +204,7 @@ class WindowsFileStore } static class WindowsFileStoreAttributeView - extends AbstractFileStoreSpaceAttributeView + implements FileStoreSpaceAttributeView { private final WindowsFileStore fs; @@ -196,6 +212,11 @@ class WindowsFileStore this.fs = fs; } + @Override + public String name() { + return "space"; + } + @Override public FileStoreSpaceAttributes readAttributes() throws IOException @@ -225,113 +246,4 @@ class WindowsFileStore }; } } - - /** - * Windows-specific attribute view to allow access to volume information. - */ - static class VolumeFileStoreAttributeView - implements FileStoreAttributeView - { - private static final String VSN_NAME = "vsn"; - private static final String COMPRESSED_NAME = "compressed"; - private static final String REMOVABLE_NAME = "removable"; - private static final String CDROM_NAME = "cdrom"; - - private final WindowsFileStore fs; - - VolumeFileStoreAttributeView(WindowsFileStore fs) { - this.fs = fs; - } - - @Override - public String name() { - return "volume"; - } - - private int vsn() { - return fs.volumeInformation().volumeSerialNumber(); - } - - private boolean isCompressed() { - return (fs.volumeInformation().flags() & - FILE_VOLUME_IS_COMPRESSED) > 0; - } - - private boolean isRemovable() { - return fs.volumeType() == DRIVE_REMOVABLE; - } - - private boolean isCdrom() { - return fs.volumeType() == DRIVE_CDROM; - } - - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(VSN_NAME)) - return vsn(); - if (attribute.equals(COMPRESSED_NAME)) - return isCompressed(); - if (attribute.equals(REMOVABLE_NAME)) - return isRemovable(); - if (attribute.equals(CDROM_NAME)) - return isCdrom(); - return null; - } - - @Override - public void setAttribute(String attribute, Object value) - throws IOException - { - throw new UnsupportedOperationException(); - } - - @Override - public Map readAttributes(String first, String... rest) - throws IOException - { - boolean all = false; - boolean vsn = false; - boolean compressed = false; - boolean removable = false; - boolean cdrom = false; - - if (first.equals(VSN_NAME)) vsn = true; - else if (first.equals(COMPRESSED_NAME)) compressed = true; - else if (first.equals(REMOVABLE_NAME)) removable = true; - else if (first.equals(CDROM_NAME)) cdrom = true; - else if (first.equals("*")) all = true; - - if (!all) { - for (String attribute: rest) { - if (attribute.equals("*")) { - all = true; - break; - } - if (attribute.equals(VSN_NAME)) { - vsn = true; - continue; - } - if (attribute.equals(COMPRESSED_NAME)) { - compressed = true; - continue; - } - if (attribute.equals(REMOVABLE_NAME)) { - removable = true; - continue; - } - } - } - - Map result = new HashMap(); - if (all || vsn) - result.put(VSN_NAME, vsn()); - if (all || compressed) - result.put(COMPRESSED_NAME, isCompressed()); - if (all || removable) - result.put(REMOVABLE_NAME, isRemovable()); - if (all || cdrom) - result.put(CDROM_NAME, isCdrom()); - return result; - } - } -} + } diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java index e80c829f311..54712098b67 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java @@ -63,7 +63,7 @@ class WindowsFileSystem PrivilegedAction pa = new GetPropertyAction("os.version"); String osversion = AccessController.doPrivileged(pa); - String[] vers = osversion.split("\\.", 0); + String[] vers = Util.split(osversion, '.'); int major = Integer.parseInt(vers[0]); int minor = Integer.parseInt(vers[1]); @@ -227,7 +227,7 @@ class WindowsFileSystem // supported views private static final Set supportedFileAttributeViews = Collections - .unmodifiableSet(new HashSet(Arrays.asList("basic", "dos", "acl", "owner", "xattr"))); + .unmodifiableSet(new HashSet(Arrays.asList("basic", "dos", "acl", "owner", "user"))); @Override public Set supportedFileAttributeViews() { diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java index 516275dfe55..9ad84818927 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java @@ -76,7 +76,7 @@ class WindowsLinkSupport { if (!followLinks || !fs.supportsLinks()) return input.getPathForWin32Calls(); - // if file is a sym link then don't need final path + // if file is not a sym link then don't need final path if (!WindowsFileAttributes.get(input, false).isSymbolicLink()) { return input.getPathForWin32Calls(); } diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java index fafee20a4cd..a116bf81190 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java @@ -379,8 +379,11 @@ class WindowsNativeDispatcher { * CONST FILETIME *lpLastWriteTime * ) */ - static native void SetFileTime(long handle, long createTime, - long lastAccessTime, long lastWriteTime) throws WindowsException; + static native void SetFileTime(long handle, + long createTime, + long lastAccessTime, + long lastWriteTime) + throws WindowsException; /** * SetEndOfFile( diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java index 2fda59d2bfb..029431faa0f 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java @@ -27,7 +27,6 @@ package sun.nio.fs; import java.nio.file.*; import java.nio.file.attribute.*; -import java.nio.file.spi.AbstractPath; import java.nio.channels.*; import java.io.*; import java.net.URI; @@ -166,6 +165,8 @@ class WindowsPath extends AbstractPath { public void invalidate() { ref.clear(); } + + // no need to override equals/hashCode. } // use this message when throwing exceptions @@ -948,7 +949,7 @@ class WindowsPath extends AbstractPath { } @Override - public void delete(boolean failIfNotExists) throws IOException { + void implDelete(boolean failIfNotExists) throws IOException { checkDelete(); WindowsFileAttributes attrs = null; @@ -1040,7 +1041,7 @@ class WindowsPath extends AbstractPath { } @Override - public FileAttributeView getFileAttributeView(String name, LinkOption... options) { + public DynamicFileAttributeView getFileAttributeView(String name, LinkOption... options) { boolean followLinks = followLinks(options); if (name.equals("basic")) return WindowsFileAttributeViews.createBasicView(this, followLinks); @@ -1051,7 +1052,7 @@ class WindowsPath extends AbstractPath { if (name.equals("owner")) return new FileOwnerAttributeViewImpl( new WindowsAclFileAttributeView(this, followLinks)); - if (name.equals("xattr")) + if (name.equals("user")) return new WindowsUserDefinedFileAttributeView(this, followLinks); return null; } @@ -1072,22 +1073,6 @@ class WindowsPath extends AbstractPath { return this; } - @Override - public InputStream newInputStream()throws IOException { - try { - Set options = Collections.emptySet(); - FileChannel fc = WindowsChannelFactory - .newFileChannel(getPathForWin32Calls(), - getPathForPermissionCheck(), - options, - 0L); - return Channels.newInputStream(fc); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - @Override public SeekableByteChannel newByteChannel(Set options, FileAttribute... attrs) @@ -1110,36 +1095,7 @@ class WindowsPath extends AbstractPath { } @Override - public OutputStream newOutputStream(Set options, - FileAttribute... attrs) - throws IOException - { - // need to copy options to add WRITE - Set opts = new HashSet(options); - if (opts.contains(StandardOpenOption.READ)) - throw new IllegalArgumentException("READ not allowed"); - opts.add(StandardOpenOption.WRITE); - - WindowsSecurityDescriptor sd = - WindowsSecurityDescriptor.fromAttribute(attrs); - FileChannel fc; - try { - fc = WindowsChannelFactory - .newFileChannel(getPathForWin32Calls(), - getPathForPermissionCheck(), - opts, - sd.address()); - return Channels.newOutputStream(fc); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } finally { - sd.release(); - } - } - - @Override - public boolean isSameFile(FileRef obj) throws IOException { + public boolean isSameFile(Path obj) throws IOException { if (this.equals(obj)) return true; if (!(obj instanceof WindowsPath)) // includes null check @@ -1216,7 +1172,7 @@ class WindowsPath extends AbstractPath { * creates a link with the resolved target for this case. */ if (target.type == WindowsPathType.DRIVE_RELATIVE) { - throw new IOException("Cannot create symbolic link to drive-relative target"); + throw new IOException("Cannot create symbolic link to working directory relative target"); } /* diff --git a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c index 45a3646275c..d5195c4f7b3 100644 --- a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c +++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c @@ -560,9 +560,9 @@ Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this, HANDLE h = (HANDLE)jlong_to_ptr(handle); if (SetFileTime(h, - (createTime == (jlong)0) ? NULL : (CONST FILETIME *)&createTime, - (lastAccessTime == (jlong)0) ? NULL : (CONST FILETIME *)&lastAccessTime, - (lastWriteTime == (jlong)0) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0) + (createTime == (jlong)-1) ? NULL : (CONST FILETIME *)&createTime, + (lastAccessTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastAccessTime, + (lastWriteTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0) { throwWindowsException(env, GetLastError()); } diff --git a/jdk/test/java/nio/file/DirectoryStream/Basic.java b/jdk/test/java/nio/file/DirectoryStream/Basic.java index b92447d70f6..4b5a5dff6be 100644 --- a/jdk/test/java/nio/file/DirectoryStream/Basic.java +++ b/jdk/test/java/nio/file/DirectoryStream/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.DirectoryStream * @library .. */ @@ -38,20 +38,23 @@ public class Basic { DirectoryStream stream; // test that directory is empty - Files.withDirectory(dir, new FileAction() { - public void invoke(FileRef entry) { + stream = dir.newDirectoryStream(); + try { + if (stream.iterator().hasNext()) throw new RuntimeException("directory not empty"); - } - }); + } finally { + stream.close(); + } // create file in directory final Path foo = Paths.get("foo"); dir.resolve(foo).createFile(); // iterate over directory and check there is one entry + stream = dir.newDirectoryStream(); found = false; - Files.withDirectory(dir, new FileAction() { - public void invoke(Path entry) { + try { + for (Path entry: stream) { if (entry.getName().equals(foo)) { if (found) throw new RuntimeException("entry already found"); @@ -61,7 +64,9 @@ public class Basic { " not expected"); } } - }); + } finally { + stream.close(); + } if (!found) throw new RuntimeException("entry not found"); @@ -73,12 +78,15 @@ public class Basic { return matcher.matches(file); } }; - Files.withDirectory(dir, filter, new FileAction() { - public void invoke(Path entry) { + stream = dir.newDirectoryStream(filter); + try { + for (Path entry: stream) { if (!entry.getName().equals(foo)) throw new RuntimeException("entry not expected"); } - }); + } finally { + stream.close(); + } // check filtering: z* should not match any files filter = new DirectoryStream.Filter() { @@ -88,11 +96,31 @@ public class Basic { return matcher.matches(file); } }; - Files.withDirectory(dir, filter, new FileAction() { - public void invoke(FileRef entry) { + stream = dir.newDirectoryStream(filter); + try { + if (stream.iterator().hasNext()) throw new RuntimeException("no matching entries expected"); + } finally { + stream.close(); + } + + // check that IOExceptions throws by filters are propagated + filter = new DirectoryStream.Filter() { + public boolean accept(Path file) throws IOException { + throw new IOException(); } - }); + }; + stream = dir.newDirectoryStream(filter); + try { + stream.iterator().hasNext(); + throw new RuntimeException("ConcurrentModificationException expected"); + } catch (ConcurrentModificationException x) { + Throwable t = x.getCause(); + if (!(t instanceof IOException)) + throw new RuntimeException("Cause is not IOException as expected"); + } finally { + stream.close(); + } // check that exception or error thrown by filter is not thrown // by newDirectoryStream or iterator method. diff --git a/jdk/test/java/nio/file/DirectoryStream/Filters.java b/jdk/test/java/nio/file/DirectoryStream/Filters.java deleted file mode 100644 index ea539c95df3..00000000000 --- a/jdk/test/java/nio/file/DirectoryStream/Filters.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -/* @test - * @bug 4313887 - * @summary Unit test for java.nio.file.DirectoryStreamFilters - * @library .. - */ - -import java.nio.file.*; -import static java.nio.file.DirectoryStreamFilters.*; -import java.nio.file.attribute.Attributes; -import java.io.*; -import java.util.*; - -public class Filters { - static final Random rand = new Random(); - - // returns a filter that only accepts files that are larger than a given size - static DirectoryStream.Filter newMinimumSizeFilter(final long min) { - return new DirectoryStream.Filter() { - public boolean accept(FileRef file) { - try { - long size = Attributes.readBasicFileAttributes(file).size(); - return size >= min; - } catch (IOException e) { - throw new IOError(e); - } - } - }; - } - - // returns a filter that only accepts files that are matched by a given glob - static DirectoryStream.Filter newGlobFilter(final String glob) { - return new DirectoryStream.Filter() { - PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:"+ glob); - public boolean accept(Path file) { - return matcher.matches(file.getName()); - } - }; - } - - static final int BIG_FILE_THRESHOLD = 8192; - - static int totalCount; - static int htmlCount; - static int bigAndHtmlCount; - static int bigOrHtmlCount; - - // generates random files in the test directory and initializes the counts - static void setup(Path dir) throws IOException { - // create 10-26 files. - totalCount = 10 + rand.nextInt(17); - char firstChar = 'A'; - for (int i=0; i 0) - out.write(new byte[size]); - } finally { - out.close(); - } - System.out.format("Created %s, size %d byte(s)\n", name, size); - } - } - - static boolean isHtml(Path file) { - return file.toString().endsWith(".html"); - } - - static boolean isBig(Path file) throws IOException { - long size = Attributes.readBasicFileAttributes(file).size(); - return size >= BIG_FILE_THRESHOLD; - } - - static void checkCount(int expected, int actual) { - if (actual != expected) - throw new RuntimeException("'" + expected + - "' entries expected, actual: " + actual); - } - - static void doTests(Path dir) throws IOException { - final List> emptyList = Collections.emptyList(); - - // list containing two filters - List> filters = - new ArrayList>(); - filters.add(newMinimumSizeFilter(BIG_FILE_THRESHOLD)); - filters.add(newGlobFilter("*.html")); - - int accepted; - DirectoryStream stream; - - System.out.println("Test: newContentTypeFilter"); - accepted = 0; - stream = dir.newDirectoryStream(newContentTypeFilter("text/html")); - try { - for (Path entry: stream) { - if (!isHtml(entry)) - throw new RuntimeException("html file expected"); - accepted++; - } - } finally { - stream.close(); - } - checkCount(htmlCount, accepted); - - System.out.println("Test: allOf with list of filters"); - accepted = 0; - stream = dir.newDirectoryStream(allOf(filters)); - try { - for (Path entry: stream) { - if (!isHtml(entry)) - throw new RuntimeException("html file expected"); - if (!isBig(entry)) - throw new RuntimeException("big file expected"); - accepted++; - } - } finally { - stream.close(); - } - checkCount(bigAndHtmlCount, accepted); - - System.out.println("Test: allOf with empty list"); - accepted = 0; - stream = dir.newDirectoryStream(allOf(emptyList)); - try { - for (Path entry: stream) { - accepted++; - } - } finally { - stream.close(); - } - checkCount(totalCount, accepted); - - System.out.println("Test: anyOf with list of filters"); - accepted = 0; - stream = dir.newDirectoryStream(anyOf(filters)); - try { - for (Path entry: stream) { - if (!isHtml(entry) && !isBig(entry)) - throw new RuntimeException("html or big file expected"); - accepted++; - } - } finally { - stream.close(); - } - checkCount(bigOrHtmlCount, accepted); - - System.out.println("Test: anyOf with empty list"); - accepted = 0; - stream = dir.newDirectoryStream(anyOf(emptyList)); - try { - for (Path entry: stream) { - accepted++; - } - } finally { - stream.close(); - } - checkCount(0, accepted); - - System.out.println("Test: complementOf"); - accepted = 0; - stream = dir.newDirectoryStream(complementOf(newGlobFilter("*.html"))); - try { - for (Path entry: stream) { - accepted++; - } - } finally { - stream.close(); - } - checkCount(totalCount-htmlCount, accepted); - - System.out.println("Test: nulls"); - try { - newContentTypeFilter(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - try { - allOf(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - try { - anyOf(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - try { - complementOf(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - } - - public static void main(String[] args) throws IOException { - Path dir = TestUtil.createTemporaryDirectory(); - try { - setup(dir); - doTests(dir); - } finally { - TestUtil.removeAll(dir); - } - } -} diff --git a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java index 98367d8958c..3c7799e5646 100644 --- a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java +++ b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.SecureDirectoryStream * @library .. */ @@ -41,7 +41,7 @@ public class SecureDS { public static void main(String[] args) throws IOException { Path dir = TestUtil.createTemporaryDirectory(); try { - DirectoryStream stream = dir.newDirectoryStream(); + DirectoryStream stream = dir.newDirectoryStream(); stream.close(); if (!(stream instanceof SecureDirectoryStream)) { System.out.println("SecureDirectoryStream not supported."); @@ -81,8 +81,8 @@ public class SecureDS { // open directory and then move it so that it is no longer accessible // via its original path. - SecureDirectoryStream stream = - (SecureDirectoryStream)dir1.newDirectoryStream(); + SecureDirectoryStream stream = + (SecureDirectoryStream)dir1.newDirectoryStream(); dir1.moveTo(dir2); // Test: iterate over all entries @@ -96,18 +96,6 @@ public class SecureDS { .readAttributes() .isDirectory()); - // Test: dynamic access to directory's attributes - BasicFileAttributeView view = stream. - getFileAttributeView(BasicFileAttributeView.class); - Map attrs = view.readAttributes("*"); - assertTrue((Boolean)attrs.get("isDirectory")); - attrs = view.readAttributes("isRegularFile", "size"); - assertTrue(!(Boolean)attrs.get("isRegularFile")); - assertTrue((Long)attrs.get("size") >= 0); - int linkCount = (Integer)view.getAttribute("linkCount"); - assertTrue(linkCount > 0); - view.setAttribute("lastModifiedTime", 0L); - // Test: getFileAttributeView to access attributes of entries assertTrue(stream .getFileAttributeView(fileEntry, BasicFileAttributeView.class) @@ -144,17 +132,6 @@ public class SecureDS { .isSymbolicLink()); } - // Test: dynamic access to entry attributes - view = stream - .getFileAttributeView(fileEntry, PosixFileAttributeView.class, NOFOLLOW_LINKS); - if (view != null) { - attrs = view.readAttributes("owner", "size"); - UserPrincipal owner = (UserPrincipal)attrs.get("owner"); - assertTrue(owner != null); - assertTrue((Long)attrs.get("size") >= 0L); - view.setAttribute("lastAccessTime", 0L); - } - // Test: newByteChannel Set opts = Collections.emptySet(); stream.newByteChannel(fileEntry, opts).close(); @@ -170,12 +147,13 @@ public class SecureDS { } // Test: newDirectoryStream - stream.newDirectoryStream(dirEntry, true, null).close(); - stream.newDirectoryStream(dirEntry, false, null).close(); + stream.newDirectoryStream(dirEntry).close(); + stream.newDirectoryStream(dirEntry, LinkOption.NOFOLLOW_LINKS).close(); if (supportsLinks) { - stream.newDirectoryStream(link2Entry, true, null).close(); + stream.newDirectoryStream(link2Entry).close(); try { - stream.newDirectoryStream(link2Entry, false, null).close(); + stream.newDirectoryStream(link2Entry, LinkOption.NOFOLLOW_LINKS) + .close(); shouldNotGetHere(); } catch (IOException x) { } } @@ -193,7 +171,7 @@ public class SecureDS { stream.close(); dir2.moveTo(dir1); dir1.resolve(fileEntry).createFile(); - stream = (SecureDirectoryStream)dir1.newDirectoryStream(); + stream = (SecureDirectoryStream)dir1.newDirectoryStream(); dir1.moveTo(dir2); Iterator iter = stream.iterator(); int removed = 0; @@ -227,10 +205,10 @@ public class SecureDS { Path target = Paths.get("newfile"); // open stream to both directories - SecureDirectoryStream stream1 = - (SecureDirectoryStream)dir1.newDirectoryStream(); - SecureDirectoryStream stream2 = - (SecureDirectoryStream)dir2.newDirectoryStream(); + SecureDirectoryStream stream1 = + (SecureDirectoryStream)dir1.newDirectoryStream(); + SecureDirectoryStream stream2 = + (SecureDirectoryStream)dir2.newDirectoryStream(); // Test: move dir1/myfile -> dir2/newfile stream1.move(fileEntry, stream2, target); @@ -259,8 +237,8 @@ public class SecureDS { if (testDirAsString != null) { Path testDir = Paths.get(testDirAsString); if (!dir1.getFileStore().equals(testDir.getFileStore())) { - SecureDirectoryStream ts = - (SecureDirectoryStream)testDir.newDirectoryStream(); + SecureDirectoryStream ts = + (SecureDirectoryStream)testDir.newDirectoryStream(); dir1.resolve(fileEntry).createFile(); try { stream1.move(fileEntry, ts, target); @@ -281,8 +259,8 @@ public class SecureDS { Path file = Paths.get("file"); dir.resolve(file).createFile(); - SecureDirectoryStream stream = - (SecureDirectoryStream)dir.newDirectoryStream(); + SecureDirectoryStream stream = + (SecureDirectoryStream)dir.newDirectoryStream(); // NullPointerException try { @@ -322,7 +300,7 @@ public class SecureDS { shouldNotGetHere(); } catch (NullPointerException x) { } try { - stream.newDirectoryStream(null, true, null); + stream.newDirectoryStream(null); shouldNotGetHere(); } catch (NullPointerException x) { } try { @@ -340,7 +318,7 @@ public class SecureDS { // ClosedDirectoryStreamException try { - stream.newDirectoryStream(file, true, null); + stream.newDirectoryStream(file); shouldNotGetHere(); } catch (ClosedDirectoryStreamException x) { } try { diff --git a/jdk/test/java/nio/file/FileSystem/Basic.java b/jdk/test/java/nio/file/FileSystem/Basic.java index 8df7c1e8de6..4caf79fc5ea 100644 --- a/jdk/test/java/nio/file/FileSystem/Basic.java +++ b/jdk/test/java/nio/file/FileSystem/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.FileSystem * @library .. */ @@ -73,10 +73,10 @@ public class Basic { checkSupported(fs, "basic"); String os = System.getProperty("os.name"); if (os.equals("SunOS")) - checkSupported(fs, "posix", "unix", "owner", "acl", "xattr"); + checkSupported(fs, "posix", "unix", "owner", "acl", "user"); if (os.equals("Linux")) - checkSupported(fs, "posix", "unix", "owner", "dos", "xattr"); + checkSupported(fs, "posix", "unix", "owner", "dos", "user"); if (os.equals("Windows")) - checkSupported(fs, "owner", "dos", "acl", "xattr"); + checkSupported(fs, "owner", "dos", "acl", "user"); } } diff --git a/jdk/test/java/nio/file/Files/ContentType.java b/jdk/test/java/nio/file/Files/ContentType.java index a0a5afc22b7..8a2267ebd4e 100644 --- a/jdk/test/java/nio/file/Files/ContentType.java +++ b/jdk/test/java/nio/file/Files/ContentType.java @@ -21,6 +21,13 @@ * have any questions. */ +/* @test + * @bug 4313887 + * @summary Unit test for probeContentType method + * @library .. + * @build ContentType SimpleFileTypeDetector + */ + import java.nio.file.*; import java.io.*; @@ -30,7 +37,7 @@ import java.io.*; public class ContentType { - static FileRef createHtmlFile() throws IOException { + static Path createHtmlFile() throws IOException { Path file = File.createTempFile("foo", ".html").toPath(); OutputStream out = file.newOutputStream(); try { @@ -42,18 +49,14 @@ public class ContentType { return file; } - static FileRef createUnknownFile() throws IOException { - return File.createTempFile("unknown", "unknown-file-type-789").toPath(); - } - - static FileRef createGrapeFile() throws IOException { + static Path createGrapeFile() throws IOException { return File.createTempFile("red", ".grape").toPath(); } public static void main(String[] args) throws IOException { // exercise default file type detector - FileRef file = createHtmlFile(); + Path file = createHtmlFile(); try { String type = Files.probeContentType(file); if (type == null) { @@ -63,16 +66,7 @@ public class ContentType { throw new RuntimeException("Unexpected type: " + type); } } finally { - TestUtil.deleteUnchecked(file); - } - file = createUnknownFile(); - try { - String type = Files.probeContentType(file); - if (type != null) - throw new RuntimeException(file + " should not be recognized as:" + - type); - } finally { - TestUtil.deleteUnchecked(file); + file.delete(); } // exercise custom file type detector @@ -84,7 +78,7 @@ public class ContentType { if (!type.equals("grape/unknown")) throw new RuntimeException("Unexpected type: " + type); } finally { - TestUtil.deleteUnchecked(file); + file.delete(); } } diff --git a/jdk/test/java/nio/file/Files/Misc.java b/jdk/test/java/nio/file/Files/Misc.java index dde74a4b546..cd7e17a4bb8 100644 --- a/jdk/test/java/nio/file/Files/Misc.java +++ b/jdk/test/java/nio/file/Files/Misc.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.Files for miscellenous cases not * covered by other tests * @library .. @@ -39,74 +39,66 @@ public class Misc { } public static void main(String[] args) throws IOException { + + // -- Files.createDirectories -- + + Path dir = TestUtil.createTemporaryDirectory(); + try { + // no-op + Files.createDirectories(dir); + + // create one directory + Path subdir = dir.resolve("a"); + Files.createDirectories(subdir); + if (!subdir.exists()) + throw new RuntimeException("directory not created"); + + // create parents + subdir = subdir.resolve("b/c/d"); + Files.createDirectories(subdir); + if (!subdir.exists()) + throw new RuntimeException("directory not created"); + + // existing file is not a directory + Path file = dir.resolve("x").createFile(); + try { + Files.createDirectories(file); + throw new RuntimeException("failure expected"); + } catch (FileAlreadyExistsException x) { } + try { + Files.createDirectories(file.resolve("y")); + throw new RuntimeException("failure expected"); + } catch (IOException x) { } + + } finally { + TestUtil.removeAll(dir); + } + + // --- NullPointerException -- + try { Files.probeContentType(null); npeExpected(); } catch (NullPointerException e) { } - - try { - Files.withDirectory(null, "*", new FileAction() { - public void invoke(Path entry) { - } - }); - npeExpected(); - } catch (NullPointerException e) { - } - - try { - Files.withDirectory(Paths.get("."), (String)null, new FileAction() { - public void invoke(Path entry) { - } - }); - npeExpected(); - } catch (NullPointerException e) { - } - - try { - Files.withDirectory(Paths.get("."), "*", null); - npeExpected(); - } catch (NullPointerException e) { - } - - // test propogation of IOException - Path tmpdir = TestUtil.createTemporaryDirectory(); - try { - tmpdir.resolve("foo").createFile(); - try { - Files.withDirectory(tmpdir, new FileAction() { - public void invoke(Path entry) throws IOException { - throw new IOException(); - } - }); - throw new RuntimeException("IOException expected"); - } catch (IOException e) { - } - } finally { - TestUtil.removeAll(tmpdir); - } - try { Files.walkFileTree(null, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, new SimpleFileVisitor(){}); npeExpected(); } catch (NullPointerException e) { } - try { Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE, new SimpleFileVisitor(){}); npeExpected(); } catch (NullPointerException e) { } - try { Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), -1, new SimpleFileVisitor(){}); throw new RuntimeException("IllegalArgumentExpected expected"); } catch (IllegalArgumentException e) { } - try { Set opts = new HashSet(1); opts.add(null); @@ -115,7 +107,6 @@ public class Misc { npeExpected(); } catch (NullPointerException e) { } - try { Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, null); diff --git a/jdk/test/java/nio/file/Files/content_type.sh b/jdk/test/java/nio/file/Files/content_type.sh deleted file mode 100644 index 46f4626c72a..00000000000 --- a/jdk/test/java/nio/file/Files/content_type.sh +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# - -# @test -# @bug 4313887 -# @summary Unit test for probeContentType method -# @library .. -# @build ContentType SimpleFileTypeDetector -# @run shell content_type.sh - -# if TESTJAVA isn't set then we assume an interactive run. - -if [ -z "$TESTJAVA" ]; then - TESTSRC=. - TESTCLASSES=. - JAVA=java -else - JAVA="${TESTJAVA}/bin/java" -fi - -OS=`uname -s` -case "$OS" in - Windows_* ) - CLASSPATH="${TESTCLASSES};${TESTSRC}" - ;; - * ) - CLASSPATH=${TESTCLASSES}:${TESTSRC} - ;; -esac -export CLASSPATH - -failures=0 - -go() { - echo '' - $JAVA $1 $2 $3 2>&1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - -# Run the test - -go ContentType - -# -# Results -# -echo '' -if [ $failures -gt 0 ]; - then echo "$failures test(s) failed"; - else echo "All test(s) passed"; fi -exit $failures diff --git a/jdk/test/java/nio/file/Path/CopyAndMove.java b/jdk/test/java/nio/file/Path/CopyAndMove.java index 4e4c75fd2aa..39ac66871f5 100644 --- a/jdk/test/java/nio/file/Path/CopyAndMove.java +++ b/jdk/test/java/nio/file/Path/CopyAndMove.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.Path copyTo/moveTo methods * @library .. */ @@ -69,9 +69,9 @@ public class CopyAndMove { assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink()); assertTrue(attrs1.isOther() == attrs2.isOther()); - // check last modified time (assume millisecond precision) - long time1 = attrs1.resolution().toMillis(attrs1.lastModifiedTime()); - long time2 = attrs1.resolution().toMillis(attrs2.lastModifiedTime()); + // check last modified time + long time1 = attrs1.lastModifiedTime().toMillis(); + long time2 = attrs2.lastModifiedTime().toMillis(); assertTrue(time1 == time2); // check size diff --git a/jdk/test/java/nio/file/attribute/Attributes/Basic.java b/jdk/test/java/nio/file/Path/FileAttributes.java similarity index 56% rename from jdk/test/java/nio/file/attribute/Attributes/Basic.java rename to jdk/test/java/nio/file/Path/FileAttributes.java index 8dfde80d9a5..d6a09ad1656 100644 --- a/jdk/test/java/nio/file/attribute/Attributes/Basic.java +++ b/jdk/test/java/nio/file/Path/FileAttributes.java @@ -22,9 +22,9 @@ */ /* @test - * @bug 4313887 - * @summary Unit test for java.nio.file.attribute.Attributes - * @library ../.. + * @bug 4313887 6838333 + * @summary Unit test for java.nio.file.Path + * @library .. */ import java.nio.file.*; @@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit; * Exercises getAttribute/setAttribute/readAttributes methods. */ -public class Basic { +public class FileAttributes { static void assertTrue(boolean okay) { if (!okay) @@ -52,56 +52,54 @@ public class Basic { } } + // checks that two time values are within 1s of each other + static void checkNearEqual(FileTime t1, FileTime t2) { + long diff = Math.abs(t1.toMillis() - t2.toMillis()); + assertTrue(diff <= 1000); + } + // Exercise getAttribute/setAttribute/readAttributes on basic attributes static void checkBasicAttributes(FileRef file, BasicFileAttributes attrs) throws IOException { // getAttribute - checkEqual(attrs.size(), Attributes.getAttribute(file, "size")); - checkEqual(attrs.lastModifiedTime(), - Attributes.getAttribute(file, "basic:lastModifiedTime")); - checkEqual(attrs.lastAccessTime(), - Attributes.getAttribute(file, "lastAccessTime")); - checkEqual(attrs.creationTime(), - Attributes.getAttribute(file, "basic:creationTime")); - assertTrue((Boolean)Attributes.getAttribute(file, "isRegularFile")); - assertTrue(!(Boolean)Attributes.getAttribute(file, "basic:isDirectory")); - assertTrue(!(Boolean)Attributes.getAttribute(file, "isSymbolicLink")); - assertTrue(!(Boolean)Attributes.getAttribute(file, "basic:isOther")); - checkEqual(attrs.linkCount(), - (Integer)Attributes.getAttribute(file, "linkCount")); - checkEqual(attrs.fileKey(), Attributes.getAttribute(file, "basic:fileKey")); + checkEqual(attrs.size(), file.getAttribute("size")); + checkEqual(attrs.lastModifiedTime(), file.getAttribute("basic:lastModifiedTime")); + checkEqual(attrs.lastAccessTime(), file.getAttribute("lastAccessTime")); + checkEqual(attrs.creationTime(), file.getAttribute("basic:creationTime")); + assertTrue((Boolean)file.getAttribute("isRegularFile")); + assertTrue(!(Boolean)file.getAttribute("basic:isDirectory")); + assertTrue(!(Boolean)file.getAttribute("isSymbolicLink")); + assertTrue(!(Boolean)file.getAttribute("basic:isOther")); + checkEqual(attrs.fileKey(), file.getAttribute("basic:fileKey")); // setAttribute - if (attrs.resolution() == TimeUnit.MILLISECONDS) { - long modTime = attrs.lastModifiedTime(); - Attributes.setAttribute(file, "basic:lastModifiedTime", 0L); - assertTrue(Attributes.readBasicFileAttributes(file).lastModifiedTime() == 0L); - Attributes.setAttribute(file, "lastModifiedTime", modTime); - assertTrue(Attributes.readBasicFileAttributes(file).lastModifiedTime() == modTime); - } + FileTime modTime = attrs.lastModifiedTime(); + file.setAttribute("basic:lastModifiedTime", FileTime.fromMillis(0L)); + checkEqual(Attributes.readBasicFileAttributes(file).lastModifiedTime(), + FileTime.fromMillis(0L)); + file.setAttribute("lastModifiedTime", modTime); + checkEqual(Attributes.readBasicFileAttributes(file).lastModifiedTime(), modTime); - // readAttributes Map map; - map = Attributes.readAttributes(file, "*"); - assertTrue(map.size() >= 11); + map = file.readAttributes("*"); + assertTrue(map.size() >= 9); checkEqual(attrs.isRegularFile(), map.get("isRegularFile")); // check one - map = Attributes.readAttributes(file, "basic:*"); - assertTrue(map.size() >= 11); + map = file.readAttributes("basic:*"); + assertTrue(map.size() >= 9); checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); // check one - map = Attributes.readAttributes(file, "size,lastModifiedTime"); + map = file.readAttributes("size,lastModifiedTime"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); - map = Attributes.readAttributes(file, - "basic:lastModifiedTime,lastAccessTime,linkCount,ShouldNotExist"); - assertTrue(map.size() == 3); + map = file.readAttributes( + "basic:lastModifiedTime,lastAccessTime,ShouldNotExist"); + assertTrue(map.size() == 2); checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); - checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); } // Exercise getAttribute/setAttribute/readAttributes on posix attributes @@ -111,12 +109,9 @@ public class Basic { checkBasicAttributes(file, attrs); // getAttribute - checkEqual(attrs.permissions(), - Attributes.getAttribute(file, "posix:permissions")); - checkEqual(attrs.owner(), - Attributes.getAttribute(file, "posix:owner")); - checkEqual(attrs.group(), - Attributes.getAttribute(file, "posix:group")); + checkEqual(attrs.permissions(), file.getAttribute("posix:permissions")); + checkEqual(attrs.owner(), file.getAttribute("posix:owner")); + checkEqual(attrs.group(), file.getAttribute("posix:group")); // setAttribute Set orig = attrs.permissions(); @@ -124,102 +119,115 @@ public class Basic { newPerms.remove(PosixFilePermission.OTHERS_READ); newPerms.remove(PosixFilePermission.OTHERS_WRITE); newPerms.remove(PosixFilePermission.OTHERS_EXECUTE); - Attributes.setAttribute(file, "posix:permissions", newPerms); + file.setAttribute("posix:permissions", newPerms); checkEqual(Attributes.readPosixFileAttributes(file).permissions(), newPerms); - Attributes.setAttribute(file, "posix:permissions", orig); + file.setAttribute("posix:permissions", orig); checkEqual(Attributes.readPosixFileAttributes(file).permissions(), orig); - Attributes.setAttribute(file, "posix:owner", attrs.owner()); - Attributes.setAttribute(file, "posix:group", attrs.group()); + file.setAttribute("posix:owner", attrs.owner()); + file.setAttribute("posix:group", attrs.group()); // readAttributes Map map; - map = Attributes.readAttributes(file, "posix:*"); - assertTrue(map.size() >= 14); + map = file.readAttributes("posix:*"); + assertTrue(map.size() >= 12); checkEqual(attrs.permissions(), map.get("permissions")); // check one - map = Attributes.readAttributes(file, "posix:size,owner,ShouldNotExist"); + map = file.readAttributes("posix:size,owner,ShouldNotExist"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.owner(), map.get("owner")); } - // Exercise getAttribute/setAttribute/readAttributes on unix attributes + // Exercise getAttribute/readAttributes on unix attributes static void checkUnixAttributes(FileRef file) throws IOException { // getAttribute - int mode = (Integer)Attributes.getAttribute(file, "unix:mode"); - long ino = (Long)Attributes.getAttribute(file, "unix:ino"); - long dev = (Long)Attributes.getAttribute(file, "unix:dev"); - long rdev = (Long)Attributes.getAttribute(file, "unix:rdev"); - int uid = (Integer)Attributes.getAttribute(file, "unix:uid"); - int gid = (Integer)Attributes.getAttribute(file, "unix:gid"); - long ctime = (Long)Attributes.getAttribute(file, "unix:ctime"); + int mode = (Integer)file.getAttribute("unix:mode"); + long ino = (Long)file.getAttribute("unix:ino"); + long dev = (Long)file.getAttribute("unix:dev"); + long rdev = (Long)file.getAttribute("unix:rdev"); + int nlink = (Integer)file.getAttribute("unix:nlink"); + int uid = (Integer)file.getAttribute("unix:uid"); + int gid = (Integer)file.getAttribute("unix:gid"); + FileTime ctime = (FileTime)file.getAttribute("unix:ctime"); // readAttributes Map map; - map = Attributes.readAttributes(file, "unix:*"); - assertTrue(map.size() >= 21); + map = file.readAttributes("unix:*"); + assertTrue(map.size() >= 20); - map = Attributes.readAttributes(file, "unix:size,uid,gid,ShouldNotExist"); + map = file.readAttributes("unix:size,uid,gid,ShouldNotExist"); assertTrue(map.size() == 3); checkEqual(map.get("size"), Attributes.readBasicFileAttributes(file).size()); } - // Exercise getAttribute/setAttribute/readAttributes on dos attributes + // Exercise getAttribute/setAttribute on dos attributes static void checkDosAttributes(FileRef file, DosFileAttributes attrs) throws IOException { checkBasicAttributes(file, attrs); // getAttribute - checkEqual(attrs.isReadOnly(), - Attributes.getAttribute(file, "dos:readonly")); - checkEqual(attrs.isHidden(), - Attributes.getAttribute(file, "dos:hidden")); - checkEqual(attrs.isSystem(), - Attributes.getAttribute(file, "dos:system")); - checkEqual(attrs.isArchive(), - Attributes.getAttribute(file, "dos:archive")); + checkEqual(attrs.isReadOnly(), file.getAttribute("dos:readonly")); + checkEqual(attrs.isHidden(), file.getAttribute("dos:hidden")); + checkEqual(attrs.isSystem(), file.getAttribute("dos:system")); + checkEqual(attrs.isArchive(), file.getAttribute("dos:archive")); // setAttribute boolean value; value = attrs.isReadOnly(); - Attributes.setAttribute(file, "dos:readonly", !value); + file.setAttribute("dos:readonly", !value); checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), !value); - Attributes.setAttribute(file, "dos:readonly", value); + file.setAttribute("dos:readonly", value); checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), value); value = attrs.isHidden(); - Attributes.setAttribute(file, "dos:hidden", !value); + file.setAttribute("dos:hidden", !value); checkEqual(Attributes.readDosFileAttributes(file).isHidden(), !value); - Attributes.setAttribute(file, "dos:hidden", value); + file.setAttribute("dos:hidden", value); checkEqual(Attributes.readDosFileAttributes(file).isHidden(), value); value = attrs.isSystem(); - Attributes.setAttribute(file, "dos:system", !value); + file.setAttribute("dos:system", !value); checkEqual(Attributes.readDosFileAttributes(file).isSystem(), !value); - Attributes.setAttribute(file, "dos:system", value); + file.setAttribute("dos:system", value); checkEqual(Attributes.readDosFileAttributes(file).isSystem(), value); value = attrs.isArchive(); - Attributes.setAttribute(file, "dos:archive", !value); + file.setAttribute("dos:archive", !value); checkEqual(Attributes.readDosFileAttributes(file).isArchive(), !value); - Attributes.setAttribute(file, "dos:archive", value); + file.setAttribute("dos:archive", value); checkEqual(Attributes.readDosFileAttributes(file).isArchive(), value); // readAttributes Map map; - map = Attributes.readAttributes(file, "dos:*"); - assertTrue(map.size() >= 15); + map = file.readAttributes("dos:*"); + assertTrue(map.size() >= 13); checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one - map = Attributes.readAttributes(file, "dos:size,hidden,ShouldNotExist"); + map = file.readAttributes("dos:size,hidden,ShouldNotExist"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.isHidden(), map.get("hidden")); } + static void miscTests(Path file) throws IOException { + // NPE tests + try { + file.getAttribute(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + try { + file.getAttribute("isRegularFile", (LinkOption[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + try { + file.setAttribute(null, 0L); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + } + static void doTests(Path dir) throws IOException { Path file = dir.resolve("foo").createFile(); FileStore store = file.getFileStore(); @@ -237,6 +245,8 @@ public class Basic { if (store.supportsFileAttributeView("dos")) checkDosAttributes(file, Attributes.readDosFileAttributes(file)); + + miscTests(file); } finally { file.delete(); } diff --git a/jdk/test/java/nio/file/Path/Links.java b/jdk/test/java/nio/file/Path/Links.java index 3b0d6daeaa8..a6f85beb7cd 100644 --- a/jdk/test/java/nio/file/Path/Links.java +++ b/jdk/test/java/nio/file/Path/Links.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.Path createSymbolicLink, * readSymbolicLink, and createLink methods * @library .. @@ -99,16 +99,6 @@ public class Links { Object key2 = Attributes .readBasicFileAttributes(bar).fileKey(); assertTrue((key1 == null) || (key1.equals(key2))); - -// Testing of linkCount disabled until linkCount method removed frmo -// BasicFileAttributes -/* - assertTrue(Attributes - .readBasicFileAttributes(foo).linkCount() >= 2); - assertTrue(Attributes - .readBasicFileAttributes(bar).linkCount() >= 2); -*/ - } finally { bar.delete(); } diff --git a/jdk/test/java/nio/file/Path/Misc.java b/jdk/test/java/nio/file/Path/Misc.java index ba6640f7f34..066cf6bedf9 100644 --- a/jdk/test/java/nio/file/Path/Misc.java +++ b/jdk/test/java/nio/file/Path/Misc.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.Path for miscellenous methods not * covered by other tests * @library .. @@ -212,12 +212,7 @@ public class Misc { instanceof BasicFileAttributeView); assertTrue(dir.getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) instanceof BasicFileAttributeView); - assertTrue(dir.getFileAttributeView("basic") - instanceof BasicFileAttributeView); - assertTrue(dir.getFileAttributeView("basic", NOFOLLOW_LINKS) - instanceof BasicFileAttributeView); assertTrue(dir.getFileAttributeView(BogusFileAttributeView.class) == null); - assertTrue(dir.getFileAttributeView("bogus") == null); try { dir.getFileAttributeView((Class)null); } catch (NullPointerException ignore) { } @@ -227,15 +222,6 @@ public class Misc { try { dir.getFileAttributeView(BasicFileAttributeView.class, (LinkOption)null); } catch (NullPointerException ignore) { } - try { - dir.getFileAttributeView((String)null); - } catch (NullPointerException ignore) { } - try { - dir.getFileAttributeView("basic", (LinkOption[])null); - } catch (NullPointerException ignore) { } - try { - dir.getFileAttributeView("basic", (LinkOption)null); - } catch (NullPointerException ignore) { } } interface BogusFileAttributeView extends FileAttributeView { } @@ -271,6 +257,16 @@ public class Misc { link.delete(); } + /** + * Test: toRealPath(false) with broken link + */ + if (supportsLinks) { + Path broken = dir.resolve("doesNotExist"); + link.createSymbolicLink(broken); + assertTrue(link.toRealPath(false).getName().equals(link.getName())); + link.delete(); + } + /** * Test: toRealPath should eliminate "." */ @@ -358,7 +354,7 @@ public class Misc { } } } finally { - thisFile.delete(false); + thisFile.delete(); } } @@ -372,7 +368,7 @@ public class Misc { if (isWindows) { file.createFile(); try { - Attributes.setAttribute(file, "dos:hidden", true); + file.setAttribute("dos:hidden", true); assertTrue(file.isHidden()); } finally { file.delete(); diff --git a/jdk/test/java/nio/file/Path/PathOps.java b/jdk/test/java/nio/file/Path/PathOps.java index 231123c7d9a..6482d5e88b2 100644 --- a/jdk/test/java/nio/file/Path/PathOps.java +++ b/jdk/test/java/nio/file/Path/PathOps.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.Path path operations */ @@ -687,7 +687,17 @@ public class PathOps { .normalize("/foo"); // invalid - test("foo\u0000\bar") + test("foo\u0000bar") + .invalid(); + test("\u0000foo") + .invalid(); + test("bar\u0000") + .invalid(); + test("//foo\u0000bar") + .invalid(); + test("//\u0000foo") + .invalid(); + test("//bar\u0000") .invalid(); // normalization diff --git a/jdk/test/java/nio/file/Path/TemporaryFiles.java b/jdk/test/java/nio/file/Path/TemporaryFiles.java index 6a9d28d9782..59ac4ec8c76 100644 --- a/jdk/test/java/nio/file/Path/TemporaryFiles.java +++ b/jdk/test/java/nio/file/Path/TemporaryFiles.java @@ -21,21 +21,30 @@ * have any questions. */ +/* @test + * @bug 4313887 6838333 + * @summary Unit test for File.createTemporaryXXX (to be be moved to test/java/io/File) + * @library .. + */ + import java.nio.file.*; import static java.nio.file.StandardOpenOption.*; import java.nio.file.attribute.*; import java.io.File; import java.io.IOException; -import java.io.OutputStream; import java.util.Set; public class TemporaryFiles { - static void checkFile(Path file) throws IOException { - // check file is in temporary directory + static void checkInTempDirectory(Path file) { Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); if (!file.getParent().equals(tmpdir)) throw new RuntimeException("Not in temporary directory"); + } + + static void checkFile(Path file) throws IOException { + // check file is in temporary directory + checkInTempDirectory(file); // check that file can be opened for reading and writing file.newByteChannel(READ).close(); @@ -53,24 +62,37 @@ public class TemporaryFiles { } } + static void checkDirectory(Path dir) throws IOException { + // check directory is in temporary directory + checkInTempDirectory(dir); + + // check directory is empty + DirectoryStream stream = dir.newDirectoryStream(); + try { + if (stream.iterator().hasNext()) + throw new RuntimeException("Tempory directory not empty"); + } finally { + stream.close(); + } + + // check file permissions are 0700 or more secure + if (dir.getFileStore().supportsFileAttributeView("posix")) { + Set perms = Attributes + .readPosixFileAttributes(dir).permissions(); + perms.remove(PosixFilePermission.OWNER_READ); + perms.remove(PosixFilePermission.OWNER_WRITE); + perms.remove(PosixFilePermission.OWNER_EXECUTE); + if (!perms.isEmpty()) + throw new RuntimeException("Temporary directory is not secure"); + } + } + public static void main(String[] args) throws IOException { - Path file = File.createTempFile("blah", null, false).toPath(); + Path file = File.createTemporaryFile("blah", null).toPath(); try { checkFile(file); } finally { TestUtil.deleteUnchecked(file); } - - // temporary file with deleteOnExit - file = File.createTempFile("blah", "tmp", true).toPath(); - checkFile(file); - // write path to temporary file to file so that calling script can - // check that it is deleted - OutputStream out = Paths.get(args[0]).newOutputStream(); - try { - out.write(file.toString().getBytes()); - } finally { - out.close(); - } } } diff --git a/jdk/test/java/nio/file/Path/temporary_files.sh b/jdk/test/java/nio/file/Path/temporary_files.sh deleted file mode 100644 index 552dcfdab46..00000000000 --- a/jdk/test/java/nio/file/Path/temporary_files.sh +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# - -# @test -# @bug 4313887 -# @summary Unit test for File.createTempFile (to be be moved to test/java/io/File) -# @library .. -# @build TemporaryFiles -# @run shell temporary_files.sh - -# if TESTJAVA isn't set then we assume an interactive run. - -if [ -z "$TESTJAVA" ]; then - TESTSRC=. - TESTCLASSES=. - JAVA=java -else - JAVA="${TESTJAVA}/bin/java" -fi - -OS=`uname -s` -case "$OS" in - Windows_* ) - CLASSPATH="${TESTCLASSES};${TESTSRC}" - ;; - * ) - CLASSPATH=${TESTCLASSES}:${TESTSRC} - ;; -esac -export CLASSPATH - -TMPFILENAME="$$.tmp" -$JAVA TemporaryFiles $TMPFILENAME 2>&1 -if [ $? != 0 ]; then exit 1; fi -if [ ! -f $TMPFILENAME ]; then - echo "$TMPFILENAME not found" - exit 1 -fi -TMPFILE=`cat $TMPFILENAME` -if [ -f $TMPFILE ]; then - echo "$TMPFILE not deleted" - exit 1 -fi - -exit 0 diff --git a/jdk/test/java/nio/file/TestUtil.java b/jdk/test/java/nio/file/TestUtil.java index c19e28fbdc4..2436a45992c 100644 --- a/jdk/test/java/nio/file/TestUtil.java +++ b/jdk/test/java/nio/file/TestUtil.java @@ -55,7 +55,7 @@ public class TestUtil { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { try { - file.delete(false); + file.delete(); } catch (IOException x) { System.err.format("Unable to delete %s: %s\n", file, x); } @@ -64,7 +64,7 @@ public class TestUtil { @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { try { - dir.delete(false); + dir.delete(); } catch (IOException x) { System.err.format("Unable to delete %s: %s\n", dir, x); } @@ -78,7 +78,7 @@ public class TestUtil { }); } - static void deleteUnchecked(FileRef file) { + static void deleteUnchecked(Path file) { try { file.delete(); } catch (IOException exc) { @@ -114,7 +114,7 @@ public class TestUtil { Path target = dir.resolve("testtarget"); try { link.createSymbolicLink(target); - target.delete(false); + link.delete(); return true; } catch (UnsupportedOperationException x) { return false; diff --git a/jdk/test/java/nio/file/WatchService/Basic.java b/jdk/test/java/nio/file/WatchService/Basic.java index 60c18d74b9b..f6a501b8923 100644 --- a/jdk/test/java/nio/file/WatchService/Basic.java +++ b/jdk/test/java/nio/file/WatchService/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.WatchService * @library .. * @run main/timeout=120 Basic @@ -114,7 +114,7 @@ public class Basic { throw new RuntimeException("register did not return existing key"); System.out.format("delete %s\n", file); - file.delete(false); + file.delete(); takeExpectedKey(watcher, myKey); checkExpectedEvent(myKey.pollEvents(), StandardWatchEventKind.ENTRY_DELETE, name); @@ -137,7 +137,7 @@ public class Basic { throw new RuntimeException("register did not return existing key"); System.out.format("update: %s\n", file); - OutputStream out = file.newOutputStream(EnumSet.of(StandardOpenOption.APPEND)); + OutputStream out = file.newOutputStream(StandardOpenOption.APPEND); try { out.write("I am a small file".getBytes("UTF-8")); } finally { @@ -151,7 +151,7 @@ public class Basic { System.out.println("OKAY"); // done - file.delete(false); + file.delete(); } finally { watcher.close(); @@ -190,7 +190,7 @@ public class Basic { } // done - file.delete(false); + file.delete(); System.out.println("OKAY"); @@ -216,7 +216,7 @@ public class Basic { new WatchEvent.Kind[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY }); System.out.format("delete: %s\n", subdir); - subdir.delete(false); + subdir.delete(); takeExpectedKey(watcher, myKey); System.out.println("reset key"); @@ -439,7 +439,7 @@ public class Basic { throw new RuntimeException("key not expected"); // delete gus1 - file1.delete(false); + file1.delete(); // check that key2 got ENTRY_DELETE takeExpectedKey(watcher2, key2); diff --git a/jdk/test/java/nio/file/WatchService/FileTreeModifier.java b/jdk/test/java/nio/file/WatchService/FileTreeModifier.java index 741c86df094..c47cc344dec 100644 --- a/jdk/test/java/nio/file/WatchService/FileTreeModifier.java +++ b/jdk/test/java/nio/file/WatchService/FileTreeModifier.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Sanity test for Sun-specific FILE_TREE watch event modifier * @library .. */ @@ -85,7 +85,7 @@ public class FileTreeModifier { throw new RuntimeException("Existing key not returned"); // delete a/b/c/foo and check we get delete event - file.delete(false); + file.delete(); checkExpectedEvent(watcher, ENTRY_DELETE, top.relativize(file)); key.reset(); diff --git a/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java index 3a9960702f9..14563202bd8 100644 --- a/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.attribute.AclFileAttribueView * @library ../.. */ @@ -147,7 +147,10 @@ public class Basic { } public static void main(String[] args) throws IOException { - Path dir = TestUtil.createTemporaryDirectory(); + // use work directory rather than system temporary directory to + // improve chances that ACLs are supported + Path dir = Paths.get("./work" + new Random().nextInt()) + .createDirectory(); try { if (!dir.getFileStore().supportsFileAttributeView("acl")) { System.out.println("ACLs not supported - test skipped!"); diff --git a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java index 1cc192f2a45..120cda38207 100644 --- a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.attribute.BasicFileAttributeView * @library ../.. */ @@ -48,14 +48,11 @@ public class Basic { check(!attrs.isRegularFile(), "is not a regular file"); check(!attrs.isSymbolicLink(), "is not a link"); check(!attrs.isOther(), "is not other"); - check(attrs.linkCount() >= 1, "should be at least 1"); // last-modified-time should match java.io.File - if (attrs.resolution() == TimeUnit.MILLISECONDS) { - File f = new File(dir.toString()); - check(f.lastModified() == attrs.lastModifiedTime(), - "last-modified time should be the same"); - } + File f = new File(dir.toString()); + check(f.lastModified() == attrs.lastModifiedTime().toMillis(), + "last-modified time should be the same"); } static void checkAttributesOfFile(Path dir, Path file) @@ -66,30 +63,27 @@ public class Basic { check(!attrs.isDirectory(), "is not a directory"); check(!attrs.isSymbolicLink(), "is not a link"); check(!attrs.isOther(), "is not other"); - check(attrs.linkCount() >= 1, "should be at least 1"); // size and last-modified-time should match java.io.File File f = new File(file.toString()); check(f.length() == attrs.size(), "size should be the same"); - if (attrs.resolution() == TimeUnit.MILLISECONDS) { - check(f.lastModified() == attrs.lastModifiedTime(), - "last-modified time should be the same"); - } + check(f.lastModified() == attrs.lastModifiedTime().toMillis(), + "last-modified time should be the same"); // copy last-modified time and file create time from directory to file, // re-read attribtues, and check they match BasicFileAttributeView view = file.getFileAttributeView(BasicFileAttributeView.class); BasicFileAttributes dirAttrs = Attributes.readBasicFileAttributes(dir); - view.setTimes(dirAttrs.lastModifiedTime(), null, null, dirAttrs.resolution()); - if (dirAttrs.creationTime() != -1L) { - view.setTimes(null, null, dirAttrs.creationTime(), dirAttrs.resolution()); + view.setTimes(dirAttrs.lastModifiedTime(), null, null); + if (dirAttrs.creationTime() != null) { + view.setTimes(null, null, dirAttrs.creationTime()); } attrs = view.readAttributes(); - check(attrs.lastModifiedTime() == dirAttrs.lastModifiedTime(), + check(attrs.lastModifiedTime().equals(dirAttrs.lastModifiedTime()), "last-modified time should be equal"); - if (dirAttrs.creationTime() != -1L) { - check(attrs.creationTime() == dirAttrs.creationTime(), + if (dirAttrs.creationTime() != null) { + check(attrs.creationTime().equals(dirAttrs.creationTime()), "create time should be the same"); } @@ -107,7 +101,6 @@ public class Basic { check(!attrs.isDirectory(), "is a directory"); check(!attrs.isRegularFile(), "is not a regular file"); check(!attrs.isOther(), "is not other"); - check(attrs.linkCount() >= 1, "should be at least 1"); } static void attributeReadWriteTests(Path dir) diff --git a/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java index 3c8a296188b..28d12c7bd39 100644 --- a/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.attribute.DosFileAttributeView * @library ../.. */ @@ -75,7 +75,7 @@ public class Basic { // create "foo" and test that we can read/write each FAT attribute Path file = dir.resolve("foo"); - file.newOutputStream().close(); + file.createFile(); try { testAttributes(file .getFileAttributeView(DosFileAttributeView.class)); diff --git a/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java index 993e8c1ddec..13fed78501d 100644 --- a/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.attribute.FileStoreAttributeView * @library ../.. */ @@ -106,43 +106,10 @@ public class Basic { checkWithin1GB(free, attrs.unallocatedSpace()); checkWithin1GB(usable, attrs.usableSpace()); - // get values by name (and in bulk) - FileStoreAttributeView view = fs.getFileStoreAttributeView("space"); - checkWithin1GB(total, (Long)view.getAttribute("totalSpace")); - checkWithin1GB(free, (Long)view.getAttribute("unallocatedSpace")); - checkWithin1GB(usable, (Long)view.getAttribute("usableSpace")); - Map map = view.readAttributes("*"); - checkWithin1GB(total, (Long)map.get("totalSpace")); - checkWithin1GB(free, (Long)map.get("unallocatedSpace")); - checkWithin1GB(usable, (Long)map.get("usableSpace")); - map = view.readAttributes("totalSpace", "unallocatedSpace", "usableSpace"); - checkWithin1GB(total, (Long)map.get("totalSpace")); - checkWithin1GB(free, (Long)map.get("unallocatedSpace")); - checkWithin1GB(usable, (Long)map.get("usableSpace")); - } - - /** - * Check (Windows-specific) volume attributes - */ - static void checkVolumeAttributes() throws IOException { - System.out.println(" -- volumes -- "); - for (FileStore store: FileSystems.getDefault().getFileStores()) { - FileStoreAttributeView view = store.getFileStoreAttributeView("volume"); - if (view == null) - continue; - Map attrs = view.readAttributes("*"); - int vsn = (Integer)attrs.get("vsn"); - boolean compressed = (Boolean)attrs.get("compressed"); - boolean removable = (Boolean)attrs.get("removable"); - boolean cdrom = (Boolean)attrs.get("cdrom"); - String type; - if (removable) type = "removable"; - else if (cdrom) type = "cdrom"; - else type = "unknown"; - System.out.format("%s (%s) vsn:%x compressed:%b%n", store.name(), - type, vsn, compressed); - } - + // get values by name + checkWithin1GB(total, (Long)fs.getAttribute("space:totalSpace")); + checkWithin1GB(free, (Long)fs.getAttribute("space:unallocatedSpace")); + checkWithin1GB(usable, (Long)fs.getAttribute("space:usableSpace")); } public static void main(String[] args) throws IOException { @@ -161,9 +128,6 @@ public class Basic { Path file = dir.resolve("foo").createFile(); checkSpace(file); - // volume attributes (Windows specific) - checkVolumeAttributes(); - } finally { TestUtil.removeAll(dir); } diff --git a/jdk/test/java/nio/file/attribute/FileTime/Basic.java b/jdk/test/java/nio/file/attribute/FileTime/Basic.java new file mode 100644 index 00000000000..13bebf32678 --- /dev/null +++ b/jdk/test/java/nio/file/attribute/FileTime/Basic.java @@ -0,0 +1,122 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6844313 + * @summary Unit test for java.nio.file.FileTime + */ + +import java.nio.file.attribute.FileTime; +import java.util.concurrent.TimeUnit; +import static java.util.concurrent.TimeUnit.*; +import java.io.IOException; + +public class Basic { + + public static void main(String[] args) throws IOException { + long now = System.currentTimeMillis(); + long tomorrowInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) + 1; + + // equals + eq(now, MILLISECONDS, now, MILLISECONDS); + eq(now, MILLISECONDS, now*1000L, MICROSECONDS); + neq(now, MILLISECONDS, 0, MILLISECONDS); + neq(now, MILLISECONDS, 0, MICROSECONDS); + + // compareTo + cmp(now, MILLISECONDS, now, MILLISECONDS, 0); + cmp(now, MILLISECONDS, now*1000L, MICROSECONDS, 0); + cmp(now, MILLISECONDS, now-1234, MILLISECONDS, 1); + cmp(now, MILLISECONDS, now+1234, MILLISECONDS, -1); + cmp(tomorrowInDays, DAYS, now, MILLISECONDS, 1); + cmp(now, MILLISECONDS, tomorrowInDays, DAYS, -1); + + // toString + ts(1L, DAYS, "1970-01-02T00:00:00Z"); + ts(1L, HOURS, "1970-01-01T01:00:00Z"); + ts(1L, MINUTES, "1970-01-01T00:01:00Z"); + ts(1L, SECONDS, "1970-01-01T00:00:01Z"); + ts(1L, MILLISECONDS, "1970-01-01T00:00:00.001Z"); + ts(1L, MICROSECONDS, "1970-01-01T00:00:00.000001Z"); + ts(1L, NANOSECONDS, "1970-01-01T00:00:00.000000001Z"); + + ts(-1L, DAYS, "1969-12-31T00:00:00Z"); + ts(-1L, HOURS, "1969-12-31T23:00:00Z"); + ts(-1L, MINUTES, "1969-12-31T23:59:00Z"); + ts(-1L, SECONDS, "1969-12-31T23:59:59Z"); + ts(-1L, MILLISECONDS, "1969-12-31T23:59:59.999Z"); + ts(-1L, MICROSECONDS, "1969-12-31T23:59:59.999999Z"); + ts(-1L, NANOSECONDS, "1969-12-31T23:59:59.999999999Z"); + + ts(-62135596799999L, MILLISECONDS, "0001-01-01T00:00:00.001Z"); + ts(-62135596800000L, MILLISECONDS, "0001-01-01T00:00:00Z"); + ts(-62135596800001L, MILLISECONDS, "-0001-12-31T23:59:59.999Z"); + + ts(253402300799999L, MILLISECONDS, "9999-12-31T23:59:59.999Z"); + ts(-377642044800001L, MILLISECONDS, "-9999-12-31T23:59:59.999Z"); + + // NTFS epoch in usec. + ts(-11644473600000000L, MICROSECONDS, "1601-01-01T00:00:00Z"); + + // nulls + try { + FileTime.from(0L, null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + FileTime time = FileTime.fromMillis(now); + if (time.equals(null)) + throw new RuntimeException("should not be equal to null"); + try { + time.compareTo(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + } + + static void cmp(long v1, TimeUnit u1, long v2, TimeUnit u2, int expected) { + int result = FileTime.from(v1, u1).compareTo(FileTime.from(v2, u2)); + if (result != expected) + throw new RuntimeException("unexpected order"); + } + + static void eq(long v1, TimeUnit u1, long v2, TimeUnit u2) { + FileTime t1 = FileTime.from(v1, u1); + FileTime t2 = FileTime.from(v2, u2); + if (!t1.equals(t2)) + throw new RuntimeException("not equal"); + if (t1.hashCode() != t2.hashCode()) + throw new RuntimeException("hashCodes should be equal"); + } + + static void neq(long v1, TimeUnit u1, long v2, TimeUnit u2) { + FileTime t1 = FileTime.from(v1, u1); + FileTime t2 = FileTime.from(v2, u2); + if (t1.equals(t2)) + throw new RuntimeException("should not be equal"); + } + + static void ts(long v, TimeUnit y, String expected) { + String s = FileTime.from(v, y).toString(); + if (!s.equals(expected)) + throw new RuntimeException("unexpected format"); + } +} diff --git a/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java index 2ee059bb95d..2b518bdc3d7 100644 --- a/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.attribute.PosixFileAttributeView * @library ../.. */ @@ -44,15 +44,14 @@ public class Basic { * Use view to update permission to the given mode and check that the * permissions have been updated. */ - static void testPermissions(PosixFileAttributeView view, String mode) - throws IOException - { + static void testPermissions(Path file, String mode) throws IOException { System.out.format("change mode: %s\n", mode); Set perms = PosixFilePermissions.fromString(mode); // change permissions and re-read them. - view.setPermissions(perms); - Set current = view.readAttributes().permissions(); + Attributes.setPosixFilePermissions(file, perms); + Set current = Attributes + .readPosixFileAttributes(file).permissions(); if (!current.equals(perms)) { throw new RuntimeException("Actual permissions: " + PosixFilePermissions.toString(current) + ", expected: " + @@ -60,8 +59,8 @@ public class Basic { } // repeat test using setAttribute/getAttribute - view.setAttribute("permissions", perms); - current = (Set)view.getAttribute("permissions"); + file.setAttribute("posix:permissions", perms); + current = (Set)file.getAttribute("posix:permissions"); if (!current.equals(perms)) { throw new RuntimeException("Actual permissions: " + PosixFilePermissions.toString(current) + ", expected: " + @@ -98,17 +97,14 @@ public class Basic { FileAttribute> attr = PosixFilePermissions.asFileAttribute(requested); System.out.format("create file with mode: %s\n", mode); - - EnumSet options = EnumSet.of(StandardOpenOption.CREATE_NEW, - StandardOpenOption.WRITE); - file.newOutputStream(options, attr).close(); + file.createFile(attr); try { checkSecure(requested, file .getFileAttributeView(PosixFileAttributeView.class) .readAttributes() .permissions()); } finally { - file.delete(false); + file.delete(); } System.out.format("create directory with mode: %s\n", mode); @@ -119,7 +115,7 @@ public class Basic { .readAttributes() .permissions()); } finally { - file.delete(false); + file.delete(); } } @@ -134,7 +130,7 @@ public class Basic { // create file and test updating and reading its permissions Path file = dir.resolve("foo"); System.out.format("create %s\n", file); - file.newOutputStream().close(); + file.createFile(); try { // get initial permissions so that we can restore them later PosixFileAttributeView view = file @@ -144,32 +140,32 @@ public class Basic { // test various modes try { - testPermissions(view, "---------"); - testPermissions(view, "r--------"); - testPermissions(view, "-w-------"); - testPermissions(view, "--x------"); - testPermissions(view, "rwx------"); - testPermissions(view, "---r-----"); - testPermissions(view, "----w----"); - testPermissions(view, "-----x---"); - testPermissions(view, "---rwx---"); - testPermissions(view, "------r--"); - testPermissions(view, "-------w-"); - testPermissions(view, "--------x"); - testPermissions(view, "------rwx"); - testPermissions(view, "r--r-----"); - testPermissions(view, "r--r--r--"); - testPermissions(view, "rw-rw----"); - testPermissions(view, "rwxrwx---"); - testPermissions(view, "rw-rw-r--"); - testPermissions(view, "r-xr-x---"); - testPermissions(view, "r-xr-xr-x"); - testPermissions(view, "rwxrwxrwx"); + testPermissions(file, "---------"); + testPermissions(file, "r--------"); + testPermissions(file, "-w-------"); + testPermissions(file, "--x------"); + testPermissions(file, "rwx------"); + testPermissions(file, "---r-----"); + testPermissions(file, "----w----"); + testPermissions(file, "-----x---"); + testPermissions(file, "---rwx---"); + testPermissions(file, "------r--"); + testPermissions(file, "-------w-"); + testPermissions(file, "--------x"); + testPermissions(file, "------rwx"); + testPermissions(file, "r--r-----"); + testPermissions(file, "r--r--r--"); + testPermissions(file, "rw-rw----"); + testPermissions(file, "rwxrwx---"); + testPermissions(file, "rw-rw-r--"); + testPermissions(file, "r-xr-x---"); + testPermissions(file, "r-xr-xr-x"); + testPermissions(file, "rwxrwxrwx"); } finally { view.setPermissions(save); } } finally { - file.delete(false); + file.delete(); } // create link (to file that doesn't exist) and test reading of @@ -185,7 +181,7 @@ public class Basic { throw new RuntimeException("not a link"); } } finally { - link.delete(false); + link.delete(); } } @@ -239,7 +235,7 @@ public class Basic { Path file = dir.resolve("gus"); System.out.format("create %s\n", file); - file.newOutputStream().close(); + file.createFile(); try { // read attributes of directory to get owner/group @@ -251,13 +247,14 @@ public class Basic { view.setOwner(attrs.owner()); view.setGroup(attrs.group()); - // repeat test using setAttribute - Map map = view.readAttributes("owner","group"); - view.setAttribute("owner", map.get("owner")); - view.setAttribute("group", map.get("group")); + // repeat test using set/getAttribute + UserPrincipal owner = (UserPrincipal)file.getAttribute("posix:owner"); + file.setAttribute("posix:owner", owner); + UserPrincipal group = (UserPrincipal)file.getAttribute("posix:group"); + file.setAttribute("posix:group", group); } finally { - file.delete(false); + file.delete(); } System.out.println("OKAY"); diff --git a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java index ffdb5b86e89..b540e22521b 100644 --- a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.attribute.UserDefinedFileAttributeView * @library ../.. */ @@ -129,23 +129,24 @@ public class Basic { throw new RuntimeException("Attribute name in list"); // Test: dynamic access + String name = "user:" + ATTR_NAME; byte[] valueAsBytes = ATTR_VALUE.getBytes(); - view.setAttribute(ATTR_NAME, valueAsBytes); - byte[] actualAsBytes = (byte[])view.getAttribute(ATTR_NAME); + file.setAttribute(name, valueAsBytes); + byte[] actualAsBytes = (byte[])file.getAttribute(name); if (!Arrays.equals(valueAsBytes, actualAsBytes)) throw new RuntimeException("Unexpected attribute value"); - Map map = view.readAttributes(ATTR_NAME); + Map map = file.readAttributes(name); if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) throw new RuntimeException("Unexpected attribute value"); - map = view.readAttributes(ATTR_NAME, "*"); + map = file.readAttributes("user:*"); if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) throw new RuntimeException("Unexpected attribute value"); - map = view.readAttributes("DoesNotExist"); + map = file.readAttributes("user:DoesNotExist"); if (!map.isEmpty()) throw new RuntimeException("Map expected to be empty"); } - static void miscTests(Path file) throws IOException { + static void miscTests(final Path file) throws IOException { final UserDefinedFileAttributeView view = file .getFileAttributeView(UserDefinedFileAttributeView.class); view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes())); @@ -179,27 +180,31 @@ public class Basic { }}); expectNullPointerException(new Task() { public void run() throws IOException { - view.getAttribute(null); + file.getAttribute(null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - view.setAttribute(ATTR_NAME, null); + file.getAttribute("user:" + ATTR_NAME, (LinkOption[])null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - view.setAttribute(null, new byte[0]); - }}); - expectNullPointerException(new Task() { - public void run() throws IOException { - view.readAttributes(null); + file.setAttribute("user:" + ATTR_NAME, null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - view.readAttributes("*", (String[])null); + file.setAttribute(null, new byte[0]); }}); expectNullPointerException(new Task() { public void run() throws IOException { - view.readAttributes("*", ATTR_NAME, null); + file.setAttribute("user: " + ATTR_NAME, new byte[0], (LinkOption[])null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + file.readAttributes((String)null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + file.readAttributes("*", (LinkOption[])null); }}); // Read-only buffer @@ -224,7 +229,7 @@ public class Basic { // create temporary directory to run tests Path dir = TestUtil.createTemporaryDirectory(); try { - if (!dir.getFileStore().supportsFileAttributeView("xattr")) { + if (!dir.getFileStore().supportsFileAttributeView("user")) { System.out.println("UserDefinedFileAttributeView not supported - skip test"); return; }