OpenJDK / amber / amber
changeset 3069:d83a89ff2c3b
Merge
author | tbell |
---|---|
date | Sun, 28 Jun 2009 23:16:18 -0700 |
parents | 1f377edfe18f f024ac2a48d1 |
children | 72ecb77419d1 |
files | jdk/src/share/classes/java/nio/file/DirectoryStreamFilters.java jdk/src/share/classes/java/nio/file/FileAction.java jdk/src/share/classes/java/nio/file/spi/AbstractPath.java jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java jdk/src/share/classes/sun/nio/fs/MimeType.java jdk/test/java/nio/file/DirectoryStream/Filters.java jdk/test/java/nio/file/Files/content_type.sh jdk/test/java/nio/file/Path/temporary_files.sh jdk/test/java/nio/file/attribute/Attributes/Basic.java |
diffstat | 120 files changed, 3104 insertions(+), 4185 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/make/java/java/FILES_java.gmk Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/make/java/java/FILES_java.gmk Sun Jun 28 23:16:18 2009 -0700 @@ -412,6 +412,7 @@ 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 \
--- a/jdk/make/java/nio/FILES_java.gmk Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/make/java/nio/FILES_java.gmk Sun Jun 28 23:16:18 2009 -0700 @@ -86,8 +86,6 @@ 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 @@ 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 @@ 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 @@ \ 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 @@ 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 \
--- a/jdk/make/java/nio/mapfile-linux Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/make/java/nio/mapfile-linux Sun Jun 28 23:16:18 2009 -0700 @@ -142,7 +142,7 @@ 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;
--- a/jdk/make/java/nio/mapfile-solaris Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/make/java/nio/mapfile-solaris Sun Jun 28 23:16:18 2009 -0700 @@ -120,7 +120,7 @@ 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;
--- a/jdk/src/share/classes/java/io/File.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/io/File.java Sun Jun 28 23:16:18 2009 -0700 @@ -30,15 +30,15 @@ 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 @@ * java.lang.SecurityManager#checkRead(java.lang.String)}</code> * 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 @@ * java.lang.SecurityManager#checkRead(java.lang.String)}</code> * 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 @@ * java.lang.SecurityManager#checkRead(java.lang.String)}</code> * 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 @@ * java.lang.SecurityManager#checkRead(java.lang.String)}</code> * 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 @@ * Sets the owner's or everybody's write permission for this abstract * pathname. * - * <p> 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. + * <p> The {@link java.nio.file.attribute.Attributes Attributes} class + * defines methods that operate on file attributes including file + * permissions. This may be used when finer manipulation of file permissions + * is required. * * @param writable * If <code>true</code>, sets the access permission to allow write @@ -1436,9 +1437,10 @@ * Sets the owner's or everybody's read permission for this abstract * pathname. * - * <p> 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. + * <p> The {@link java.nio.file.attribute.Attributes Attributes} class + * defines methods that operate on file attributes including file + * permissions. This may be used when finer manipulation of file permissions + * is required. * * @param readable * If <code>true</code>, sets the access permission to allow read @@ -1509,9 +1511,10 @@ * Sets the owner's or everybody's execute permission for this abstract * pathname. * - * <p> 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. + * <p> The {@link java.nio.file.attribute.Attributes Attributes} class + * defines methods that operate on file attributes including file + * permissions. This may be used when finer manipulation of file permissions + * is required. * * @param executable * If <code>true</code>, sets the access permission to allow execute @@ -1748,16 +1751,17 @@ 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 @@ } return new File(dir, prefix + Long.toString(n) + suffix); } - - // default file permissions - static final FileAttribute<Set<PosixFilePermission>> defaultPosixFilePermissions = - PosixFilePermissions.asFileAttribute(EnumSet - .of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)); - static final boolean isPosix = isPosix(); - static boolean isPosix() { - return AccessController.doPrivileged( - new PrivilegedAction<Boolean>() { - public Boolean run() { - try { - return FileSystems.getDefault().getPath(valueAsString) - .getFileStore().supportsFileAttributeView("posix"); - } catch (IOException e) { - throw new IOError(e); - } - } - }); - } } /** @@ -1869,12 +1854,11 @@ 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 @@ /** * Creates an empty file in the default temporary-file directory, using - * the given prefix and suffix to generate its name. Invoking this method + * the given prefix and suffix to generate its name. Invoking this method * is equivalent to invoking <code>{@link #createTempFile(java.lang.String, * java.lang.String, java.io.File) * createTempFile(prefix, suffix, null)}</code>. * + * <p> The {@link #createTemporaryFile(String,String,FileAttribute[])} method + * provides an alternative method to create an empty file in the + * temporary-file directory. Files created by that method may have more + * restrictive access permissions to files created by this method and so + * may be more suited to security-sensitive applications. + * * @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 @@ /** * 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. - * - * <p> When the value of the {@code deleteOnExit} method is {@code true} - * then the resulting file is requested to be deleted when the Java virtual - * machine terminates as if by invoking the {@link #deleteOnExit deleteOnExit} - * method. + * the given prefix and suffix to generate its name. * * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute * attributes} to set atomically when creating the file. Each attribute is @@ -1944,6 +1924,12 @@ * of the same name is included in the array then all but the last occurrence * is ignored. * + * <p> Where the {@code attrs} parameter does not specify <i>access + * permissions</i> to set atomically when creating the file, then the + * resulting file may have more restrictive access permissions than files + * created by the {@link #createTempFile(java.lang.String, java.lang.String)} + * method. + * * @param prefix * The prefix string to be used in generating the file's * name; must be at least three characters long @@ -1951,9 +1937,6 @@ * 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 @@ * @return An abstract pathname denoting a newly-created empty file * * @throws IllegalArgumentException - * If the <code>prefix</code> 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 @@ * @throws SecurityException * If a security manager exists and its <code>{@link * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> - * method does not allow a file to be created. 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<attrs.length; i++) { - if (attrs[i].name().equals("posix:permissions")) { - hasPermissions = true; - break; - } - } - if (!hasPermissions) { - FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length+1]; - System.arraycopy(attrs, 0, copy, 0, attrs.length); - attrs = copy; - attrs[attrs.length-1] = - TemporaryDirectory.defaultPosixFilePermissions; - } - } - } - - // use Path#createFile to create file - SecurityManager sm = System.getSecurityManager(); - for (;;) { - File f = TemporaryDirectory - .generateFile(prefix, suffix, TemporaryDirectory.valueAsFile); - if (sm != null && deleteOnExit) - sm.checkDelete(f.getPath()); - try { - f.toPath().createFile(attrs); - if (deleteOnExit) - DeleteOnExitHook.add(f.getPath()); - return f; - } catch (InvalidPathException e) { - // don't reveal temporary directory location - if (sm != null) - throw new IllegalArgumentException("Invalid prefix or suffix"); - throw e; - } catch (SecurityException e) { - // don't reveal temporary directory location - if (sm != null) - throw new SecurityException("Unable to create temporary file"); - throw e; - } catch (FileAlreadyExistsException e) { - // ignore - } - } + return TempFileHelper.createFile(prefix, suffix, attrs); } /* -- Basic infrastructure -- */ @@ -2153,40 +2081,45 @@ /** * 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}. + * + * <p> The first invocation of this method works as if invoking it were + * equivalent to evaluating the expression: * <blockquote><pre> - * {@link FileSystems#getDefault FileSystems.getDefault}().{@link FileSystem#getPath getPath}(this.{@link #getPath getPath}()); + * {@link java.nio.file.FileSystems#getDefault FileSystems.getDefault}().{@link + * java.nio.file.FileSystem#getPath getPath}(this.{@link #getPath getPath}()); * </pre></blockquote> * Subsequent invocations of this method return the same {@code Path}. * * <p> If this abstract pathname is the empty abstract pathname then this - * method returns a {@code Path} that may be used to access to the current + * method returns a {@code Path} that may be used to access the current * user directory. * - * @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; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/io/TempFileHelper.java Sun Jun 28 23:16:18 2009 -0700 @@ -0,0 +1,139 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.io; + +import java.nio.file.FileSystems; +import java.nio.file.InvalidPathException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import static java.nio.file.attribute.PosixFilePermission.*; +import java.util.Set; +import java.util.EnumSet; + +/** + * Helper class to support creation of temporary files and directory with + * initial attributes. + */ + +class TempFileHelper { + private TempFileHelper() { } + + // default file and directory permissions (lazily initialized) + private static class PermissionsHolder { + static final boolean hasPosixPermissions = FileSystems.getDefault() + .supportedFileAttributeViews().contains("posix"); + static final FileAttribute<Set<PosixFilePermission>> filePermissions = + PosixFilePermissions.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE)); + static final FileAttribute<Set<PosixFilePermission>> directoryPermissions = + PosixFilePermissions.asFileAttribute(EnumSet + .of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)); + } + + /** + * Creates a file or directory in the temporary directory. + */ + private static File create(String prefix, + String suffix, + FileAttribute[] attrs, + boolean isDirectory) + throws IOException + { + // in POSIX environments use default file and directory permissions + // if initial permissions not given by caller. + if (PermissionsHolder.hasPosixPermissions) { + if (attrs.length == 0) { + // no attributes so use default permissions + attrs = new FileAttribute<?>[1]; + attrs[0] = (isDirectory) ? PermissionsHolder.directoryPermissions : + PermissionsHolder.filePermissions; + } else { + // check if posix permissions given; if not use default + boolean hasPermissions = false; + for (int i=0; i<attrs.length; i++) { + if (attrs[i].name().equals("posix:permissions")) { + hasPermissions = true; + break; + } + } + if (!hasPermissions) { + FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length+1]; + System.arraycopy(attrs, 0, copy, 0, attrs.length); + attrs = copy; + attrs[attrs.length-1] = (isDirectory) ? + PermissionsHolder.directoryPermissions : + PermissionsHolder.filePermissions; + } + } + } + + // loop generating random names until file or directory can be created + SecurityManager sm = System.getSecurityManager(); + for (;;) { + File tmpdir = File.TempDirectory.location(); + File f = File.TempDirectory.generateFile(prefix, suffix, tmpdir); + try { + if (isDirectory) { + f.toPath().createDirectory(attrs); + } else { + f.toPath().createFile(attrs); + } + return f; + } catch (InvalidPathException e) { + // don't reveal temporary directory location + if (sm != null) + throw new IllegalArgumentException("Invalid prefix or suffix"); + throw e; + } catch (SecurityException e) { + // don't reveal temporary directory location + if (sm != null) + throw new SecurityException("Unable to create temporary file"); + throw e; + } catch (FileAlreadyExistsException e) { + // ignore + } + } + } + + /** + * Creates a file in the temporary directory. + */ + static File createFile(String prefix, String suffix, FileAttribute[] attrs) + throws IOException + { + return create(prefix, suffix, attrs, false); + } + + /** + * Creates a directory in the temporary directory. + */ + static File createDirectory(String prefix, FileAttribute[] attrs) + throws IOException + { + return create(prefix, "", attrs, true); + } +}
--- a/jdk/src/share/classes/java/lang/management/PlatformComponent.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/lang/management/PlatformComponent.java Sun Jun 28 23:16:18 2009 -0700 @@ -34,7 +34,6 @@ 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 @@ "java.nio", "BufferPool", keyProperties("name"), new MXBeanFetcher<BufferPoolMXBean>() { public List<BufferPoolMXBean> getMXBeans() { - List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2); - pools.add( sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPoolMXBean() ); - pools.add( sun.nio.ch.FileChannelImpl.getMappedBufferPoolMXBean() ); - return pools; + return ManagementFactoryHelper.getBufferPoolMXBeans(); } }),
--- a/jdk/src/share/classes/java/nio/Bits.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/Bits.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ } } - // -- 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 --
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java Sun Jun 28 23:16:18 2009 -0700 @@ -30,7 +30,6 @@ import sun.misc.Cleaner; import sun.misc.Unsafe; import sun.nio.ch.DirectBuffer; -import sun.nio.ch.FileChannelImpl; class Direct$Type$Buffer$RW$$BO$
--- a/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java Sun Jun 28 23:16:18 2009 -0700 @@ -47,7 +47,7 @@ * 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
--- a/jdk/src/share/classes/java/nio/file/AccessMode.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/AccessMode.java Sun Jun 28 23:16:18 2009 -0700 @@ -30,7 +30,7 @@ * * @since 1.7 * - * @see FileRef#checkAccess + * @see Path#checkAccess */ public enum AccessMode {
--- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java Sun Jun 28 23:16:18 2009 -0700 @@ -27,6 +27,7 @@ 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 @@ * * <p> 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}. * * <p> A directory stream is not required to be <i>asynchronously closeable</i>. * If a thread is blocked on the directory stream's iterator reading from the @@ -79,7 +77,7 @@ * * <p> 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 @@ * newDirectoryStream} method when opening a directory to iterate over the * entries in the directory. * - * <p> The {@link DirectoryStreamFilters} class defines factory methods to - * create filters for a number of common usages and also methods to combine - * filters. - * * @param <T> the type of the directory entry * * @since 1.7 @@ -120,8 +114,11 @@ * 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; } /**
--- a/jdk/src/share/classes/java/nio/file/DirectoryStreamFilters.java Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/* - * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.nio.file; - -import java.io.IOException; -import java.io.IOError; -import sun.nio.fs.MimeType; - -/** - * This class consists exclusively of static methods that construct or combine - * filters. - * - * @since 1.7 - */ - -public final class DirectoryStreamFilters { - private DirectoryStreamFilters() { } - - /** - * Constructs a directory stream filter that filters directory entries by - * their <a href="http://www.ietf.org/rfc/rfc2045.txt">MIME</a> content - * type. The directory stream filter's {@link - * java.nio.file.DirectoryStream.Filter#accept accept} method returns {@code - * true} if the content type of the directory entry can be determined by - * invoking the {@link Files#probeContentType probeContentType} method, and - * the content type matches the given content type. - * - * <p> The {@code type} parameter is the value of a Multipurpose Internet - * Mail Extension (MIME) content type as defined by <a - * href="http://www.ietf.org/rfc/rfc2045.txt"><i>RFC 2045: Multipurpose - * Internet Mail Extensions (MIME) Part One: Format of Internet Message - * Bodies</i></a>. It is parsable according to the grammar in the RFC. Any - * space characters (<code>'\u0020'</code>) surrounding its components are - * ignored. The {@code type} parameter is parsed into its primary and subtype - * components which are used to match the primary and subtype components of - * each directory entry's content type. Parameters are not allowed. The - * primary type matches if it has value {@code '*'} or is equal to the - * primary type of the directory entry's content type without regard to - * case. The subtype matches if has the value {@code '*'} or is equal to the - * subtype of the directory entry's content type without regard to case. If - * both the primary and subtype match then the filter's {@code accept} method - * returns {@code true}. If the content type of a directory entry cannot be - * determined then the entry is filtered. - * - * <p> The {@code accept} method of the resulting directory stream filter - * throws {@link IOError} if the probing of the content type fails by - * throwing an {@link IOException}. Security exceptions are also propogated - * to the caller of the {@code accept} method. - * - * <p> <b>Usage Example:</b> - * Suppose we require to list only the HTML files in a directory. - * <pre> - * DirectoryStream.Filter<FileRef> filter = - * DirectoryStreamFilters.newContentTypeFilter("text/html"); - * </pre> - * - * @param type - * the content type - * - * @return a new directory stream filter - * - * @throws IllegalArgumentException - * if the {@code type} parameter cannot be parsed as a MIME type - * or it has parameters - */ - public static <T extends FileRef> DirectoryStream.Filter<T> - newContentTypeFilter(String type) - { - final MimeType matchType = MimeType.parse(type); - if (matchType.hasParameters()) - throw new IllegalArgumentException("Parameters not allowed"); - return new DirectoryStream.Filter<T>() { - @Override - public boolean accept(T entry) { - String fileType; - try { - fileType = Files.probeContentType(entry); - } catch (IOException x) { - throw new IOError(x); - } - if (fileType != null) { - return matchType.match(fileType); - } - return false; - } - }; - } - - /** - * Returns a directory stream filter that {@link DirectoryStream.Filter#accept - * accepts} a directory entry if the entry is accepted by all of the given - * filters. - * - * <p> This method returns a filter that invokes, in iterator order, the - * {@code accept} method of each of the filters. If {@code false} is returned - * by any of the filters then the directory entry is filtered. If the - * directory entry is not filtered then the resulting filter accepts the - * entry. If the iterator returns zero elements then the resulting filter - * accepts all directory entries. - * - * <p> <b>Usage Example:</b> - * <pre> - * List<DirectoryStream.Filter<? super Path>> filters = ... - * DirectoryStream.Filter<Path> filter = DirectoryStreamFilters.allOf(filters); - * </pre> - * - * @param filters - * the sequence of filters - * - * @return the resulting filter - */ - public static <T> DirectoryStream.Filter<T> - allOf(final Iterable<? extends DirectoryStream.Filter<? super T>> filters) - { - if (filters == null) - throw new NullPointerException("'filters' is null"); - return new DirectoryStream.Filter<T>() { - @Override - public boolean accept(T entry) { - for (DirectoryStream.Filter<? super T> filter: filters) { - if (!filter.accept(entry)) - return false; - } - return true; - } - }; - } - - /** - * Returns a directory stream filter that {@link DirectoryStream.Filter#accept - * accepts} a directory entry if the entry is accepted by one or more of - * the given filters. - * - * <p> This method returns a filter that invokes, in iteration order, the - * {@code accept} method of each of filter. If {@code true} is returned by - * any of the filters then the directory entry is accepted. If none of the - * filters accepts the directory entry then it is filtered. If the iterator - * returns zero elements then the resulting filter filters all directory - * entries. - * - * @param filters - * the sequence of filters - * - * @return the resulting filter - */ - public static <T> DirectoryStream.Filter<T> - anyOf(final Iterable<? extends DirectoryStream.Filter<? super T>> filters) - { - if (filters == null) - throw new NullPointerException("'filters' is null"); - return new DirectoryStream.Filter<T>() { - @Override - public boolean accept(T entry) { - for (DirectoryStream.Filter<? super T> filter: filters) { - if (filter.accept(entry)) - return true; - } - return false; - } - }; - } - - /** - * Returns a directory stream filter that is the <em>complement</em> of the - * given filter. The resulting filter {@link - * java.nio.file.DirectoryStream.Filter#accept accepts} a directory entry - * if filtered by the given filter, and filters any entries that are accepted - * by the given filter. - * - * @param filter - * the given filter - * - * @return the resulting filter that is the complement of the given filter - */ - public static <T> DirectoryStream.Filter<T> - complementOf(final DirectoryStream.Filter<T> filter) - { - if (filter == null) - throw new NullPointerException("'filter' is null"); - return new DirectoryStream.Filter<T>() { - @Override - public boolean accept(T entry) { - return !filter.accept(entry); - } - }; - } -}
--- a/jdk/src/share/classes/java/nio/file/FileAction.java Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +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; - -/** - * 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. - * - * <p> <b>Usage Example:</b> - * Suppose we require to perform a task on all class files in a directory: - * <pre> - * Path dir = ... - * Files.withDirectory(dir, "*.class", new FileAction<Path>() { - * public void invoke(Path entry) { - * : - * } - * }); - * </pre> - * - * @param <T> the type of file reference - * - * @since 1.7 - */ - -public interface FileAction<T extends FileRef> { - /** - * Invoked for a file. - * - * @param file - * the file - * - * @throws IOException - * if the block terminates due an uncaught I/O exception - */ - void invoke(T file) throws IOException; -}
--- a/jdk/src/share/classes/java/nio/file/FileRef.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/FileRef.java Sun Jun 28 23:16:18 2009 -0700 @@ -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. * * <p> A {@code FileRef} is an object that locates a file and defines methods to - * access the file. The means by which the file is located depends on the - * 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. - * - * <p> This interface defines the following operations: - * <ul> - * <li><p> The {@link #newByteChannel newByteChannel} method - * may be used to open a file and obtain a byte channel for reading or - * writing. </p></li> - * <li><p> The {@link #delete delete} method may be used to delete a file. - * </p></li> - * <li><p> The {@link #checkAccess checkAccess} method may be used to check - * the existence or accessibility of a file. </p></li> - * <li><p> The {@link #isSameFile isSameFile} method may be used to test if - * two file references locate the same file. </p></li> - * <li><p> The {@link #getFileStore getFileStore} method may be used to - * obtain the {@link FileStore} representing the storage where a file is - * located. </p></li> - * </ul> - * - * <p> Access to associated metadata or file attributes requires an appropriate - * {@link FileAttributeView FileAttributeView}. The {@link - * #getFileAttributeView(Class,LinkOption[]) getFileAttributeView(Class,LinkOption[])} - * method may be used to obtain a file attribute view that defines type-safe - * methods to read or update file attributes. The {@link - * #getFileAttributeView(String,LinkOption[]) getFileAttributeView(String,LinkOption[])} - * method may be used to obtain a file attribute view where dynamic access to - * file attributes where required. - * - * <p> A {@code FileRef} is immutable and safe for use by multiple concurrent - * threads. + * 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. * * <p> 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. - * - * <p> In the addition to {@code READ} and {@code WRITE}, the following - * options may be present: + * 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. * - * <table border=1 cellpadding=5 summary=""> - * <tr> <th>Option</th> <th>Description</th> </tr> - * <tr> - * <td> {@link StandardOpenOption#APPEND APPEND} </td> - * <td> If this option is present then the file is opened for writing and - * each invocation of the channel's {@code write} method first advances - * the position to the end of the file and then writes the requested - * data. Whether the advancement of the position and the writing of the - * data are done in a single atomic operation is system-dependent and - * therefore unspecified. This option may not be used in conjunction - * with the {@code READ} or {@code TRUNCATE_EXISTING} options. </td> - * </tr> - * <tr> - * <td> {@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} </td> - * <td> If this option is present then the existing file is truncated to - * a size of 0 bytes. This option is ignored when the file is opened only - * for reading. </td> - * </tr> - * <tr> - * <td> {@link StandardOpenOption#SYNC SYNC} </td> - * <td> Requires that every update to the file's content or metadata be - * written synchronously to the underlying storage device. (see <a - * href="package-summary.html#integrity"> Synchronized I/O file - * integrity</a>). </td> - * </tr> - * <tr> - * <td> {@link StandardOpenOption#DSYNC DSYNC} </td> - * <td> Requires that every update to the file's content be written - * synchronously to the underlying storage device. (see <a - * href="package-summary.html#integrity"> Synchronized I/O file - * integrity</a>). </td> - * </tr> - * </table> - * - * <p> An implementation of this interface may support additional options - * defined by the {@link StandardOpenOption} enumeration type or other - * implementation specific options. - * - * <p> The {@link java.nio.channels.Channels} utility classes defines methods - * to construct input and output streams where inter-operation with the - * {@link java.io} package is required. - * - * @param options - * Options specifying how the file is opened - * - * @return a new seekable byte channel + * @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; - - /** - * Returns the {@link FileStore} representing the file store where the file - * referenced by this object is stored. - * - * <p> Once a reference to the {@code FileStore} is obtained it is - * implementation specific if operations on the returned {@code FileStore}, - * or {@link FileStoreAttributeView} objects obtained from it, continue - * to depend on the existence of the file. In particular the behavior is not - * defined for the case that the file is deleted or moved to a different - * file store. - * - * @return The file store where the file is stored - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the file, and in - * addition it checks {@link RuntimePermission}<tt> - * ("getFileStoreAttributes")</tt> - */ - FileStore getFileStore() throws IOException; + InputStream newInputStream(OpenOption... options) throws IOException; /** - * Checks the existence and optionally the accessibility of the file - * referenced by this object. - * - * <p> This method checks the existence of a file and that this Java virtual - * 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: + * Opens or creates the file located by this object for writing, returning + * an output stream to write bytes to the file. * - * <table border=1 cellpadding=5 summary=""> - * <tr> <th>Value</th> <th>Description</th> </tr> - * <tr> - * <td> {@link AccessMode#READ READ} </td> - * <td> Checks that the file exists and that the Java virtual machine has - * permission to read the file. </td> - * </tr> - * <tr> - * <td> {@link AccessMode#WRITE WRITE} </td> - * <td> Checks that the file exists and that the Java virtual machine has - * permission to write to the file, </td> - * </tr> - * <tr> - * <td> {@link AccessMode#EXECUTE EXECUTE} </td> - * <td> Checks that the file exists and that the Java virtual machine has - * permission to {@link Runtime#exec execute} the file. The semantics - * may differ when checking access to a directory. For example, on UNIX - * systems, checking for {@code EXECUTE} access checks that the Java - * virtual machine has permission to search the directory in order to - * access file or subdirectories. </td> - * </tr> - * </table> + * <p> The {@code options} parameter determines how the file is opened. + * If no options are present then this method creates a new file for writing + * or truncates an existing file. In addition to the {@link StandardOpenOption + * standard} options, an implementation may also support additional + * implementation specific options. + * + * <p> The resulting stream will not be buffered. The stream will be safe + * for access by multiple concurrent threads. * - * <p> If the {@code modes} parameter is of length zero, then the existence - * of the file is checked. + * @param options + * options specifying how the file is opened * - * <p> This method follows symbolic links if the file referenced by this - * object is a symbolic link. Depending on the implementation, this method - * may require to read file permissions, access control lists, or other - * file attributes in order to check the effective access to the file. To - * determine the effective access to a file may require access to several - * attributes and so in some implementations this method may not be atomic - * with respect to other file system operations. Furthermore, as the result - * of this method is immediately outdated, there is no guarantee that a - * subsequence access will succeed (or even that it will access the same - * file). Care should be taken when using this method in security sensitive - * applications. + * @return a new output stream * - * @param modes - * The access modes to check; may have zero elements - * + * @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 <i>(optional specific exception)</i> - * @throws AccessDeniedException - * The requested access would be denied or the access cannot be - * determined because the Java virtual machine has insufficient - * privileges or other reasons. <i>(optional specific exception)</i> + * 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 @@ * 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 @@ * * @see Attributes#readBasicFileAttributes */ - <V extends FileAttributeView> V getFileAttributeView(Class<V> type, LinkOption... options); + <V extends FileAttributeView> V getFileAttributeView(Class<V> type, + LinkOption... options); + + /** + * Sets the value of a file attribute. + * + * <p> The {@code attribute} parameter identifies the attribute to be set + * and takes the form: + * <blockquote> + * [<i>view-name</i><b>:</b>]<i>attribute-name</i> + * </blockquote> + * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + * <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link + * FileAttributeView} that identifies a set of file attributes. If not + * specified then it defaults to {@code "basic"}, the name of the file + * attribute view that identifies the basic set of file attributes common to + * many file systems. <i>attribute-name</i> is the name of the attribute + * within the set. + * + * <p> <b>Usage Example:</b> + * Suppose we want to set the DOS "hidden" attribute: + * <pre> + * file.setAttribute("dos:hidden", true); + * </pre> + * + * @param attribute + * the attribute to set + * @param value + * the attribute value + * @param options + * options indicating how symbolic links are handled + * + * @throws UnsupportedOperationException + * if the attribute view is not available or it does not support + * updating the attribute + * @throws IllegalArgumentException + * if the attribute value is of the correct type but has an + * inappropriate value + * @throws ClassCastException + * If the attribute value is not of the expected type or is a + * collection containing elements that are not of the expected + * type + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the file. If this method is invoked + * to set security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + void setAttribute(String attribute, Object value, LinkOption... options) + throws IOException; /** - * Returns a file attribute view of the given name. + * Reads the value of a file attribute. * - * <p> A file attribute view provides a read-only or updatable view of a - * set of file attributes. This method is intended to be used where - * <em>dynamic access</em> 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. + * <p> The {@code attribute} parameter identifies the attribute to be read + * and takes the form: + * <blockquote> + * [<i>view-name</i><b>:</b>]<i>attribute-name</i> + * </blockquote> + * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + * <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link + * FileAttributeView} that identifies a set of file attributes. If not + * specified then it defaults to {@code "basic"}, the name of the file + * attribute view that identifies the basic set of file attributes common to + * many file systems. <i>attribute-name</i> is the name of the attribute. * * <p> The {@code options} array may be used to indicate how symbolic links - * are handled 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. + * + * <p> <b>Usage Example:</b> + * Suppose we require the user ID of the file owner on a system that + * supports a "{@code unix}" view: + * <pre> + * int uid = (Integer)file.getAttribute("unix:uid"); + * </pre> + * + * @param attribute + * the attribute to read + * @param options + * options indicating how symbolic links are handled + * @return the attribute value or {@code null} if the attribute view + * is not available or it does not support reading the attribute + * + * reading the attribute + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. If this method is invoked + * to read security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + Object getAttribute(String attribute, LinkOption... options) throws IOException; + + /** + * Reads a set of file attributes as a bulk operation. + * + * <p> The {@code attributes} parameter identifies the attributes to be read + * and takes the form: + * <blockquote> + * [<i>view-name</i><b>:</b>]<i>attribute-list</i> + * </blockquote> + * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. * - * @param name - * The name of the file attribute view + * <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link + * FileAttributeView} that identifies a set of file attributes. If not + * specified then it defaults to {@code "basic"}, the name of the file + * attribute view that identifies the basic set of file attributes common to + * many file systems. + * + * <p> The <i>attribute-list</i> component is a comma separated list of + * zero or more names of attributes to read. If the list contains the value + * {@code "*"} then all attributes are read. Attributes that are not supported + * are ignored and will not be present in the returned map. It is + * implementation specific if all attributes are read as an atomic operation + * with respect to other file system operations. + * + * <p> The following examples demonstrate possible values for the {@code + * attributes} parameter: + * + * <blockquote> + * <table border="0"> + * <tr> + * <td> {@code "*"} </td> + * <td> Read all {@link BasicFileAttributes basic-file-attributes}. </td> + * </tr> + * <tr> + * <td> {@code "size,lastModifiedTime,lastAccessTime"} </td> + * <td> Reads the file size, last modified time, and last access time + * attributes. </td> + * </tr> + * <tr> + * <td> {@code "posix:*"} </td> + * <td> Read all {@link PosixFileAttributes POSIX-file-attributes}.. </td> + * </tr> + * <tr> + * <td> {@code "posix:permissions,owner,size"} </td> + * <td> Reads the POSX file permissions, owner, and file size. </td> + * </tr> + * </table> + * </blockquote> + * + * <p> The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed and so + * the method returns the file attribute of the symbolic link. + * + * @param attributes + * The attributes to read * @param options * Options indicating how symbolic links are handled * - * @return A 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. - * - * <p> If this {@code FileRef} and the given {@code FileRef} are {@link - * #equals(Object) equal} then this method returns {@code true} without checking - * if the file exists. If the {@code FileRef} and the given {@code FileRef} - * are associated with different providers, or the given {@code FileRef} is - * {@code null} then this method returns {@code false}. Otherwise, this method - * checks if both {@code FileRefs} locate the same file, and depending on the - * implementation, may require to open or access both files. - * - * <p> If the file system and files remain static, then this method implements - * an equivalence relation for non-null {@code FileRefs}. - * <ul> - * <li>It is <i>reflexive</i>: for a non-null {@code FileRef} {@code f}, - * {@code f.isSameFile(f)} should return {@code true}. - * <li>It is <i>symmetric</i>: for two non-null {@code FileRefs} - * {@code f} and {@code g}, {@code f.isSameFile(g)} will equal - * {@code g.isSameFile(f)}. - * <li>It is <i>transitive</i>: for three {@code FileRefs} - * {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns - * {@code true} and {@code g.isSameFile(h)} returns {@code true}, then - * {@code f.isSameFile(h)} will return return {@code true}. - * </ul> - * - * @param other - * The other file reference - * - * @return {@code true} if, and only if, this object and the given object - * locate the same file + * @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. - * - * <p> An implementation may require to examine the file to determine if the - * file is a directory. Consequently this method may not be atomic with respect - * to other file system operations. If the file is a symbolic-link then the - * link is deleted and not the final target of the link. - * - * <p> If the file is a directory then the directory must be empty. In some - * implementations a directory has entries for special files or links that - * are created when the directory is created. In such implementations a - * directory is considered empty when only the special entries exist. - * - * <p> On some operating systems it may not be possible to remove a file when - * it is open and in use by this Java virtual machine or other programs. - * - * @throws NoSuchFileException - * If the file does not exist <i>(optional specific exception)</i> - * @throws DirectoryNotEmptyException - * If the file is a directory and could not otherwise be deleted - * because the directory is not empty <i>(optional specific - * exception)</i> - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkDelete(String)} method - * is invoked to check delete access to the file - */ - void delete() throws IOException; - - /** - * Tests this object for equality with another object. - * - * <p> If the given object is not a {@code FileRef} then this method - * immediately returns {@code false}. - * - * <p> For two file references to be considered equal requires that they - * are both the same type of {@code FileRef} and encapsulate components - * to locate the same file. This method does not access the file system and - * the file may not exist. - * - * <p> This method satisfies the general contract of the {@link - * java.lang.Object#equals(Object) Object.equals} method. </p> - * - * @param ob The object to which this object is to be compared - * - * @return {@code true} if, and only if, the given object is a {@code FileRef} - * that is identical to this {@code FileRef} - * - * @see #isSameFile - */ - boolean equals(Object ob); - - /** - * Returns the hash-code value for this object. - * - * <p> This method satisfies the general contract of the - * {@link java.lang.Object#hashCode() Object.hashCode} method. - */ - int hashCode(); + Map<String,?> readAttributes(String attributes, LinkOption... options) + throws IOException; }
--- a/jdk/src/share/classes/java/nio/file/FileStore.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/FileStore.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ getFileStoreAttributeView(Class<V> type); /** - * Returns a {@code FileStoreAttributeView} of the given name. + * Reads the value of a file store attribute. * - * <p> This method is intended to be used where <em>dynamic access</em> to - * 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. + * <p> The {@code attribute} parameter identifies the attribute to be read + * and takes the form: + * <blockquote> + * <i>view-name</i><b>:</b><i>attribute-name</i> + * </blockquote> + * where the character {@code ':'} stands for itself. + * + * <p> <i>view-name</i> is the {@link FileStoreAttributeView#name name} of + * a {@link FileStore AttributeView} that identifies a set of file attributes. + * <i>attribute-name</i> is the name of the attribute. * * <p> For {@code FileStore} objects created by the default provider, then * 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. + * + * <p> <b>Usage Example:</b> + * Suppose we want to know if ZFS compression is enabled (assuming the "zfs" + * view is supported): + * <pre> + * boolean compression = (Boolean)fs.getAttribute("zfs:compression"); + * </pre> * - * @param name - * the name of the attribute view + * @param attribute + * the attribute to read + + * @return the attribute value; {@code null} may be a valid valid for some + * attributes * - * @return a file store attribute view of the given name, or {@code null} - * if the attribute view is not available + * @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; }
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java Sun Jun 28 23:16:18 2009 -0700 @@ -50,8 +50,6 @@ 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 @@ } 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() {
--- a/jdk/src/share/classes/java/nio/file/FileVisitor.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/FileVisitor.java Sun Jun 28 23:16:18 2009 -0700 @@ -42,9 +42,9 @@ * @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 @@ * 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 @@ * } 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 @@ * 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 @@ * @since 1.7 */ -public interface FileVisitor<T extends FileRef> { +public interface FileVisitor<T> { /** * Invoked for a directory before entries in the directory are visited.
--- a/jdk/src/share/classes/java/nio/file/Files.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/Files.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ * @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 @@ -128,158 +128,6 @@ } /** - * Invokes a {@link FileAction} for each entry in a directory accepted - * by a given {@link java.nio.file.DirectoryStream.Filter filter}. - * - * <p> This method opens the given directory and invokes the file action's - * {@link FileAction#invoke invoke} method for each entry accepted by the - * filter. When iteration is completed then the directory is closed. If the - * {@link DirectoryStream#close close} method throws an {@code IOException} - * then it is silently ignored. - * - * <p> If the {@code FileAction}'s {@code invoke} method terminates due - * to an uncaught {@link IOException}, {@code Error} or {@code RuntimeException} - * then the exception is propagated by this method after closing the - * directory. - * - * @param dir - * The directory - * @param filter - * The filter - * @param action - * The {@code FileAction} to invoke for each accepted entry - * - * @throws NotDirectoryException - * If the {@code dir} parameter is not a directory <i>(optional - * specific exception)</i> - * @throws IOException - * If an I/O error occurs or the {@code invoke} method terminates - * due to an uncaught {@code IOException} - * @throws SecurityException - * In the case of the default provider, the {@link - * SecurityManager#checkRead(String) checkRead} method is invoked - * to check read access to the directory. - */ - public static void withDirectory(Path dir, - DirectoryStream.Filter<? super Path> filter, - FileAction<? super Path> action) - throws IOException - { - // explicit null check required in case directory is empty - if (action == null) - throw new NullPointerException(); - - DirectoryStream<Path> stream = dir.newDirectoryStream(filter); - try { - // set to true when invoking the action so as to distinguish a - // CME thrown by the iteration from a CME thrown by the invoke - boolean inAction = false; - try { - for (Path entry: stream) { - inAction = true; - action.invoke(entry); - inAction = false; - } - } catch (ConcurrentModificationException cme) { - if (!inAction) { - Throwable cause = cme.getCause(); - if (cause instanceof IOException) - throw (IOException)cause; - } - throw cme; - } - } finally { - try { - stream.close(); - } catch (IOException x) { } - } - } - - /** - * Invokes a {@link FileAction} for each entry in a directory with a - * file name that matches a given pattern. - * - * <p> This method opens the given directory and invokes the file action's - * {@link FileAction#invoke invoke} method for each entry that matches the - * given pattern. When iteration is completed then the directory is closed. - * If the {@link DirectoryStream#close close} method throws an {@code - * IOException} then it is silently ignored. - * - * <p> If the {@code FileAction}'s {@code invoke} method terminates due - * to an uncaught {@link IOException}, {@code Error} or {@code RuntimeException} - * then the exception is propagated by this method after closing the - * directory. - * - * <p> The globbing pattern language supported by this method is as - * specified by the {@link FileSystem#getPathMatcher getPathMatcher} method. - * - * @param dir - * The directory - * @param glob - * The globbing pattern - * @param action - * The {@code FileAction} to invoke for each entry - * - * @throws NotDirectoryException - * If the {@code dir} parameter is not a directory <i>(optional - * specific exception)</i> - * @throws IOException - * If an I/O error occurs or the {@code invoke} method terminates - * due to an uncaught {@code IOException} - * @throws SecurityException - * In the case of the default provider, the {@link - * SecurityManager#checkRead(String) checkRead} method is invoked - * to check read access to the directory. - */ - public static void withDirectory(Path dir, - String glob, - FileAction<? super Path> action) - throws IOException - { - if (glob == null) - throw new NullPointerException("'glob' is null"); - final PathMatcher matcher = dir.getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { - @Override - public boolean accept(Path entry) { - return matcher.matches(entry.getName()); - } - }; - withDirectory(dir, filter, action); - } - - /** - * Invokes a {@link FileAction} for all entries in a directory. - * - * <p> This method works as if invoking it were equivalent to evaluating the - * expression: - * <blockquote><pre> - * withDirectory(dir, "*", action) - * </pre></blockquote> - * - * @param dir - * The directory - * @param action - * The {@code FileAction} to invoke for each entry - * - * @throws NotDirectoryException - * If the {@code dir} parameter is not a directory <i>(optional - * specific exception)</i> - * @throws IOException - * If an I/O error occurs or the {@code invoke} method terminates - * due to an uncaught {@code IOException} - * @throws SecurityException - * In the case of the default provider, the {@link - * SecurityManager#checkRead(String) checkRead} method is invoked - * to check read access to the directory. - */ - public static void withDirectory(Path dir, FileAction<? super Path> action) - throws IOException - { - withDirectory(dir, "*", action); - } - - /** * Walks a file tree. * * <p> This method walks a file tree rooted at a given starting file. The @@ -328,7 +176,7 @@ * 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 @@ Integer.MAX_VALUE, visitor); } + + /** + * Creates a directory by creating all nonexistent parent directories first. + * + * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute + * file-attributes} to set atomically when creating the nonexistent + * directories. Each file attribute is identified by its {@link + * FileAttribute#name name}. If more than one attribute of the same name is + * included in the array then all but the last occurrence is ignored. + * + * <p> If this method fails, then it may do so after creating some, but not + * all, of the parent directories. + * + * @param dir + * the directory to create + * + * @param attrs + * an optional list of file attributes to set atomically when + * creating the directory + * + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws FileAlreadyExistsException + * if {@code dir} exists but is not a directory <i>(optional specific + * exception)</i> + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * in the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked prior to attempting to create a directory and + * its {@link SecurityManager#checkRead(String) checkRead} is + * invoked for each parent directory that is checked. If {@code + * dir} is not an absolute path then its {@link Path#toAbsolutePath + * toAbsolutePath} may need to be invoked to get its absolute path. + * This may invoke the security manager's {@link + * SecurityManager#checkPropertyAccess(String) checkPropertyAccess} + * method to check access to the system property {@code user.dir} + * + */ + public static void createDirectories(Path dir, FileAttribute<?>... attrs) + throws IOException + { + // attempt to create the directory + try { + createAndCheckIsDirectory(dir, attrs); + return; + } catch (FileAlreadyExistsException x) { + // file exists and is not a directory + throw x; + } catch (IOException x) { + // parent may not exist or other reason + } + + // find existing parent (may require absolute path) + SecurityException se = null; + try { + dir = dir.toAbsolutePath(); + } catch (SecurityException x) { + // don't have permission to get absolute path + se = x; + } + Path parent = dir.getParent(); + while (parent != null) { + try { + parent.checkAccess(); + break; + } catch (NoSuchFileException x) { + // does not exist + } + parent = parent.getParent(); + } + if (parent == null) { + // unable to find existing parent + if (se != null) + throw se; + throw new IOException("Root directory does not exist"); + } + + // create directories + Path child = parent; + for (Path name: parent.relativize(dir)) { + child = child.resolve(name); + createAndCheckIsDirectory(child, attrs); + } + } + + /** + * Attempts to create a directory. Does nothing if the directory already + * exists. + */ + private static void createAndCheckIsDirectory(Path dir, FileAttribute<?>... attrs) + throws IOException + { + try { + dir.createDirectory(attrs); + } catch (FileAlreadyExistsException x) { + boolean isDirectory = Attributes + .readBasicFileAttributes(dir, LinkOption.NOFOLLOW_LINKS).isDirectory(); + if (!isDirectory) + throw x; + } + } }
--- a/jdk/src/share/classes/java/nio/file/LinkPermission.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/LinkPermission.java Sun Jun 28 23:16:18 2009 -0700 @@ -95,7 +95,7 @@ * {@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);
--- a/jdk/src/share/classes/java/nio/file/OpenOption.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/OpenOption.java Sun Jun 28 23:16:18 2009 -0700 @@ -30,7 +30,7 @@ * * <p> 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.
--- a/jdk/src/share/classes/java/nio/file/Path.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/Path.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ * this class defines the following operations: * * <ul> + * <li><p> The {@link #newByteChannel newByteChannel} method + * may be used to open a file and obtain a byte channel for reading or + * writing. </p></li> * <li><p> Files may be {@link #createFile(FileAttribute[]) created}, or * directories may be {@link #createDirectory(FileAttribute[]) created}. * </p></li> + * <li><p> The {@link #delete delete} method may be used to delete a file. + * </p></li> + * <li><p> The {@link #checkAccess checkAccess} method may be used to check + * the existence or accessibility of a file. </p></li> + * <li><p> The {@link #isSameFile isSameFile} method may be used to test if + * two file references locate the same file. </p></li> + * <li><p> The {@link #getFileStore getFileStore} method may be used to + * obtain the {@link FileStore} representing the storage where a file is + * located. </p></li> * <li><p> Directories can be {@link #newDirectoryStream opened} so as to * iterate over the entries in the directory. </p></li> * <li><p> Files can be {@link #copyTo(Path,CopyOption[]) copied} or * {@link #moveTo(Path,CopyOption[]) moved}. </p></li> * <li><p> Symbolic-links may be {@link #createSymbolicLink created}, or the * target of a link may be {@link #readSymbolicLink read}. </p></li> - * <li><p> {@link #newInputStream InputStream} or {@link #newOutputStream - * OutputStream} streams can be created to allow for interoperation with the - * <a href="../../../java/io/package-summary.html">{@code java.io}</a> package - * where required. </li></p> * <li><p> The {@link #toRealPath real} path of an existing file may be * obtained. </li></p> * </ul> @@ -93,13 +103,14 @@ * * <h4>File attributes</h4> * - * The <a href="attribute/package-summary.html">{@code java.nio.file.attribute}</a> - * package provides access to file attributes or <em>meta-data</em> 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 <em>basic</em> 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 <a href="attribute/package-summary.html">{@code + * java.nio.file.attribute}</a> package provides type-safe and efficient access + * to file attributes or <em>meta-data</em> 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 + * <em>basic</em> meta-data are obtained, in bulk, by invoking the {@link + * Attributes#readBasicFileAttributes Attributes.readBasicFileAttributes} method: * <pre> * Path file = ... * BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file); @@ -417,12 +428,38 @@ /** * Deletes the file located by this path. * - * <p> 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. + * <p> An implementation may require to examine the file to determine if the + * file is a directory. Consequently this method may not be atomic with respect + * to other file system operations. If the file is a symbolic-link then the + * link is deleted and not the final target of the link. + * + * <p> If the file is a directory then the directory must be empty. In some + * implementations a directory has entries for special files or links that + * are created when the directory is created. In such implementations a + * directory is considered empty when only the special entries exist. + * + * <p> On some operating systems it may not be possible to remove a file when + * it is open and in use by this Java virtual machine or other programs. * - * <p> As with the {@link FileRef#delete delete()} method, an implementation + * @throws NoSuchFileException + * if the file does not exist <i>(optional specific exception)</i> + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty <i>(optional specific + * exception)</i> + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkDelete(String)} method + * is invoked to check delete access to the file + */ + public abstract void delete() throws IOException; + + /** + * Deletes the file located by this path, if it exists. + * + * <p> As with the {@link #delete delete()} method, an implementation * may require to examine the file to determine if the file is a directory. * 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 @@ * <p> On some operating systems it may not be possible to remove a file when * it is open and in use by this Java virtual machine or other programs. * - * @param failIfNotExists - * {@code true} if the method should fail when the file does not - * exist - * - * @throws NoSuchFileException - * if the value of the {@code failIfNotExists} is {@code true} and - * the file does not exist <i>(optional specific exception)</i> * @throws DirectoryNotEmptyException * if the file is a directory and could not otherwise be deleted * because the directory is not empty <i>(optional specific @@ -454,7 +484,7 @@ * 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 <i>(optional operation)</i>. @@ -536,8 +566,6 @@ * 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 @@ * * @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 @@ * @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 @@ * 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. </td> + * copied to the target file if supported by both the source and target + * file store. Copying of file timestamps may result in precision + * loss. </td> * </tr> * <tr> * <td> {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} </td> @@ -867,10 +898,7 @@ * * <p> The directory stream's {@code close} method should be invoked after * iteration is completed so as to free any resources held for the open - * 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. * * <p> 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 @@ * * @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 <i>(optional specific exception)</i> @@ -950,19 +976,18 @@ * 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}. * * <p> The directory stream's {@code close} method should be invoked after * iteration is completed so as to free any resources held for the open - * 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. * * <p> 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. * * <p> 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 @@ * larger than 8K. * <pre> * 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 @@ * 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 @@ * FileAttribute file-attributes} to set atomically when a new file is created. * * <p> In the case of the default provider, the returned seekable byte channel - * is a {@link FileChannel}. + * is a {@link java.nio.channels.FileChannel}. * * <p> <b>Usage Examples:</b> * <pre> @@ -1212,12 +1234,9 @@ * Opens or creates a file, returning a seekable byte channel to access the * file. * - * <p> 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}. + * <p> 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 @@ * if a file of that name already exists and the {@link * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified * <i>(optional specific exception)</i> - * @throws IOException {@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. * * <p> 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. - * - * <p> The resulting stream will not be buffered. The stream will be safe - * for access by multiple concurrent threads. - * - * <p> <b>Usage Example:</b> - * Suppose we wish to open a log file for writing so that we append to the - * file if it already exists, or create it when it doesn't exist. - * <pre> - * Path logfile = ... - * OutputStream out = new BufferedOutputStream(logfile.newOutputStream(CREATE, APPEND)); - * </pre> + * 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. - * - * <p> This method opens or creates a file in exactly the manner specified - * by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel} - * method except that {@code options} parameter may not contain the {@link - * StandardOpenOption#READ READ} option. If no open options are present - * then this method creates a new file for writing or truncates an existing - * file. - * - * <p> The resulting stream will not be buffered. The stream will be safe - * for access by multiple concurrent threads. - * - * @param options - * options specifying how the file is opened - * @param attrs - * an optional list of file attributes to set atomically when - * creating the file - * * @return a new output stream * - * @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<? extends OpenOption> options, - FileAttribute<?>... attrs) + @Override + public abstract OutputStream newOutputStream(OpenOption... options) throws IOException; /** @@ -1359,6 +1310,80 @@ public abstract boolean isHidden() throws IOException; /** + * Checks the existence and optionally the accessibility of the file + * located by this path. + * + * <p> This method checks the existence of a file and that this Java virtual + * machine has appropriate privileges that would allow it access the file + * according to all of access modes specified in the {@code modes} parameter + * as follows: + * + * <table border=1 cellpadding=5 summary=""> + * <tr> <th>Value</th> <th>Description</th> </tr> + * <tr> + * <td> {@link AccessMode#READ READ} </td> + * <td> Checks that the file exists and that the Java virtual machine has + * permission to read the file. </td> + * </tr> + * <tr> + * <td> {@link AccessMode#WRITE WRITE} </td> + * <td> Checks that the file exists and that the Java virtual machine has + * permission to write to the file, </td> + * </tr> + * <tr> + * <td> {@link AccessMode#EXECUTE EXECUTE} </td> + * <td> Checks that the file exists and that the Java virtual machine has + * permission to {@link Runtime#exec execute} the file. The semantics + * may differ when checking access to a directory. For example, on UNIX + * systems, checking for {@code EXECUTE} access checks that the Java + * virtual machine has permission to search the directory in order to + * access file or subdirectories. </td> + * </tr> + * </table> + * + * <p> If the {@code modes} parameter is of length zero, then the existence + * of the file is checked. + * + * <p> This method follows symbolic links if the file referenced by this + * object is a symbolic link. Depending on the implementation, this method + * may require to read file permissions, access control lists, or other + * file attributes in order to check the effective access to the file. To + * determine the effective access to a file may require access to several + * attributes and so in some implementations this method may not be atomic + * with respect to other file system operations. Furthermore, as the result + * of this method is immediately outdated, there is no guarantee that a + * subsequence access will succeed (or even that it will access the same + * file). Care should be taken when using this method in security sensitive + * applications. + * + * @param modes + * The access modes to check; may have zero elements + * + * @throws UnsupportedOperationException + * an implementation is required to support checking for + * {@code READ}, {@code WRITE}, and {@code EXECUTE} access. This + * exception is specified to allow for the {@code Access} enum to + * be extended in future releases. + * @throws NoSuchFileException + * if a file does not exist <i>(optional specific exception)</i> + * @throws AccessDeniedException + * the requested access would be denied or the access cannot be + * determined because the Java virtual machine has insufficient + * privileges or other reasons. <i>(optional specific exception)</i> + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * is invoked when checking read access to the file or only the + * existence of the file, the {@link SecurityManager#checkWrite(String) + * checkWrite} is invoked when checking write access to the file, + * and {@link SecurityManager#checkExec(String) checkExec} is invoked + * when checking execute access. + */ + public abstract void checkAccess(AccessMode... modes) throws IOException; + + /** * Tests whether the file located by this path exists. * * <p> This convenience method is intended for cases where it is required to @@ -1414,6 +1439,30 @@ */ public abstract boolean notExists(); + /** + * Returns the {@link FileStore} representing the file store where an + * existing file, located by this path, is stored. + * + * <p> Once a reference to the {@code FileStore} is obtained it is + * implementation specific if operations on the returned {@code FileStore}, + * or {@link FileStoreAttributeView} objects obtained from it, continue + * to depend on the existence of the file. In particular the behavior is not + * defined for the case that the file is deleted or moved to a different + * file store. + * + * @return the file store where the file is stored + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file, and in + * addition it checks {@link RuntimePermission}<tt> + * ("getFileStoreAttributes")</tt> + */ + public abstract FileStore getFileStore() throws IOException; + // -- watchable -- /** @@ -1562,6 +1611,49 @@ public abstract int compareTo(Path other); /** + * Tests if the file referenced by this object is the same file referenced + * by another object. + * + * <p> If this {@code FileRef} and the given {@code FileRef} are {@link + * #equals(Object) equal} then this method returns {@code true} without checking + * if the file exists. If the {@code FileRef} and the given {@code FileRef} + * are associated with different providers, or the given {@code FileRef} is + * {@code null} then this method returns {@code false}. Otherwise, this method + * checks if both {@code FileRefs} locate the same file, and depending on the + * implementation, may require to open or access both files. + * + * <p> If the file system and files remain static, then this method implements + * an equivalence relation for non-null {@code FileRefs}. + * <ul> + * <li>It is <i>reflexive</i>: for a non-null {@code FileRef} {@code f}, + * {@code f.isSameFile(f)} should return {@code true}. + * <li>It is <i>symmetric</i>: for two non-null {@code FileRefs} + * {@code f} and {@code g}, {@code f.isSameFile(g)} will equal + * {@code g.isSameFile(f)}. + * <li>It is <i>transitive</i>: for three {@code FileRefs} + * {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns + * {@code true} and {@code g.isSameFile(h)} returns {@code true}, then + * {@code f.isSameFile(h)} will return return {@code true}. + * </ul> + * + * @param other + * the other file reference + * + * @return {@code true} if, and only if, this object and the given object + * locate the same file + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to both files. + * + * @see java.nio.file.attribute.BasicFileAttributes#fileKey + */ + public abstract boolean isSameFile(Path other) throws IOException; + + /** * Tests this path for equality with the given object. * * <p> If the given object is not a Path, or is a Path associated with a
--- a/jdk/src/share/classes/java/nio/file/Paths.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/Paths.java Sun Jun 28 23:16:18 2009 -0700 @@ -35,7 +35,7 @@ * @since 1.7 */ -public class Paths { +public final class Paths { private Paths() { } /** @@ -106,8 +106,9 @@ * 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
--- a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java Sun Jun 28 23:16:18 2009 -0700 @@ -36,7 +36,7 @@ * 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 <em>working directory</em>. @@ -65,8 +65,8 @@ * @since 1.7 */ -public abstract class SecureDirectoryStream - implements DirectoryStream<Path> +public abstract class SecureDirectoryStream<T> + implements DirectoryStream<T> { /** * Initialize a new instance of this class. @@ -78,13 +78,12 @@ * SecureDirectoryStream} to iterate over the entries in the directory. * * <p> This method works in exactly the manner specified by the {@link - * Path#newDirectoryStream newDirectoryStream} method for the case that + * 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. * * <p> 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 @@ * * @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 @@ * 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<? super Path> filter) + public abstract SecureDirectoryStream<T> newDirectoryStream(T path, + LinkOption... options) throws IOException; /** @@ -162,7 +158,7 @@ * 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<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException; @@ -170,7 +166,7 @@ /** * Deletes a file. * - * <p> Unlike the {@link FileRef#delete delete()} method, this method + * <p> Unlike the {@link Path#delete delete()} method, this method * does not first examine the file to determine if the file is a directory. * 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 @@ * 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. * - * <p> Unlike the {@link FileRef#delete delete()} method, this method + * <p> Unlike the {@link Path#delete delete()} method, this method * does not first examine the file to determine if the file is a directory. * 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 @@ * 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 @@ * 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<T> targetdir, T targetpath) throws IOException; /** @@ -318,7 +314,7 @@ * type is not available * */ - public abstract <V extends FileAttributeView> V getFileAttributeView(Path path, + public abstract <V extends FileAttributeView> V getFileAttributeView(T path, Class<V> type, LinkOption... options); }
--- a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java Sun Jun 28 23:16:18 2009 -0700 @@ -40,7 +40,7 @@ * @since 1.7 */ -public class SimpleFileVisitor<T extends FileRef> implements FileVisitor<T> { +public class SimpleFileVisitor<T> implements FileVisitor<T> { /** * Initializes a new instance of this class. */
--- a/jdk/src/share/classes/java/nio/file/StandardWatchEventKind.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/StandardWatchEventKind.java Sun Jun 28 23:16:18 2009 -0700 @@ -31,7 +31,7 @@ * @since 1.7 */ -public class StandardWatchEventKind { +public final class StandardWatchEventKind { private StandardWatchEventKind() { } /**
--- a/jdk/src/share/classes/java/nio/file/WatchKey.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/WatchKey.java Sun Jun 28 23:16:18 2009 -0700 @@ -103,7 +103,7 @@ * * <p> Note that this method does not wait if there are no events pending. * - * @return the list of the events retrieved + * @return the list of the events retrieved; may be empty */ public abstract List<WatchEvent<?>> pollEvents(); @@ -128,7 +128,7 @@ * 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. * * <p> If this watch key has already been cancelled then invoking this
--- a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -110,13 +110,13 @@ * </table> * </blockquote> * - * <p> 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. + * <p> 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. * - * <p> 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. + * <p> 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. * * <h4> Setting the ACL when creating a file </h4> *
--- a/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 <em>view</em> 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 <em>dynamic access</em> where the {@link #readAttributes - * readAttributes}, {@link #getAttribute getAttribute} and {@link #setAttribute - * setAttributs} methods are used to access the attributes by names defined - * by the attribute view. Implementations must ensure that the attribute names - * do not contain the colon (':') or comma (',') characters. + * type-safe methods to read or update the attributes that it supports. * * @since 1.7 */ @@ -48,71 +40,4 @@ * 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. - * - * <p> The {@code first} and {@code rest} parameters are the names of the - * attributes to read. If any of the parameters has the value {@code "*"} - * then all attributes are read. Attributes that are not supported are - * ignored and will not be present in the returned map. It is implementation - * specific if all attributes are read as an atomic operation with respect - * to other file system operations. - * - * @param first - * the name of an attribute to read (case sensitive) - * @param rest - * the names of other attributes to read (case sensitive) - * - * @return an unmodifiable map of the attributes; may be empty. Its keys are - * the attribute names, its values are the attribute values - * - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * if a security manager is set and it denies access - */ - Map<String,?> readAttributes(String first, String... rest) throws IOException; }
--- a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/Attributes.java Sun Jun 28 23:16:18 2009 -0700 @@ -28,7 +28,6 @@ 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 @@ */ 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. - * - * <p> The {@code attribute} parameter identifies the attribute to be set - * and takes the form: - * <blockquote> - * [<i>view-name</i><b>:</b>]<i>attribute-name</i> - * </blockquote> - * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - * <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link - * FileAttributeView} that identifies a set of file attributes. If not - * specified then it defaults to {@code "basic"}, the name of the file - * attribute view that identifies the basic set of file attributes common to - * many file systems. <i>attribute-name</i> is the name of the attribute - * within the set. - * - * <p> <b>Usage Example:</b> - * Suppose we want to set the DOS "hidden" attribute: - * <pre> - * Attributes.setAttribute(file, "dos:hidden", true); - * </pre> - * - * @param file - * A file reference that locates the file - * @param attribute - * The attribute to set - * @param value - * The attribute value - * - * @throws UnsupportedOperationException - * If the attribute view is not available or it does not - * support updating the attribute - * @throws IllegalArgumentException - * If the attribute value is of the correct type but has an - * inappropriate value - * @throws ClassCastException - * If the attribute value is not of the expected type or is a - * collection containing elements that are not of the expected - * type - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to the file. If this method is invoked - * to set security sensitive attributes then the security manager - * may be invoked to check for additional permissions. - */ - public static void setAttribute(FileRef file, String attribute, Object value) - throws IOException - { - String[] s = split(attribute); - FileAttributeView view = file.getFileAttributeView(s[0]); - if (view == null) - throw new UnsupportedOperationException("View '" + s[0] + "' not available"); - view.setAttribute(s[1], value); - } - - /** - * Reads the value of a file attribute. - * - * <p> The {@code attribute} parameter identifies the attribute to be read - * and takes the form: - * <blockquote> - * [<i>view-name</i><b>:</b>]<i>attribute-name</i> - * </blockquote> - * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - * <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link - * FileAttributeView} that identifies a set of file attributes. If not - * specified then it defaults to {@code "basic"}, the name of the file - * attribute view that identifies the basic set of file attributes common to - * many file systems. <i>attribute-name</i> is the name of the attribute. - * - * <p> The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attribute of the final target - * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attribute of the symbolic link. - * - * <p> <b>Usage Example:</b> - * Suppose we require the user ID of the file owner on a system that - * supports a "{@code unix}" view: - * <pre> - * int uid = (Integer)Attributes.getAttribute(file, "unix:uid"); - * </pre> - * - * @param file - * A file reference that locates the file - * @param attribute - * The attribute to read - * @param options - * Options indicating how symbolic links are handled - * - * @return The attribute value, or {@code null} if the attribute view - * is not available or it does not support reading the attribute - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, its {@link SecurityManager#checkRead(String) checkRead} - * method denies read access to the file. If this method is invoked - * to read security sensitive attributes then the security manager - * may be invoked to check for additional permissions. - */ - public static Object getAttribute(FileRef file, - String attribute, - LinkOption... options) - throws IOException - { - String[] s = split(attribute); - FileAttributeView view = file.getFileAttributeView(s[0], options); - if (view != null) - return view.getAttribute(s[1]); - // view not available - return null; - } - - /** - * Reads a set of file attributes as a bulk operation. - * - * <p> The {@code attributes} parameter identifies the attributes to be read - * and takes the form: - * <blockquote> - * [<i>view-name</i><b>:</b>]<i>attribute-list</i> - * </blockquote> - * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - * <p> <i>view-name</i> is the {@link FileAttributeView#name name} of a {@link - * FileAttributeView} that identifies a set of file attributes. If not - * specified then it defaults to {@code "basic"}, the name of the file - * attribute view that identifies the basic set of file attributes common to - * many file systems. - * - * <p> The <i>attribute-list</i> component is a comma separated list of - * zero or more names of attributes to read. If the list contains the value - * {@code "*"} then all attributes are read. Attributes that are not supported - * are ignored and will not be present in the returned map. It is - * implementation specific if all attributes are read as an atomic operation - * with respect to other file system operations. - * - * <p> The following examples demonstrate possible values for the {@code - * attributes} parameter: - * - * <blockquote> - * <table border="0"> - * <tr> - * <td> {@code "*"} </td> - * <td> Read all {@link BasicFileAttributes basic-file-attributes}. </td> - * </tr> - * <tr> - * <td> {@code "size,lastModifiedTime,lastAccessTime"} </td> - * <td> Reads the file size, last modified time, and last access time - * attributes. </td> - * </tr> - * <tr> - * <td> {@code "posix:*"} </td> - * <td> Read all {@link PosixFileAttributes POSIX-file-attributes}.. </td> - * </tr> - * <tr> - * <td> {@code "posix:permissions,owner,size"} </td> - * <td> Reads the POSX file permissions, owner, and file size. </td> - * </tr> - * </table> - * </blockquote> - * - * <p> The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attributes of the final target - * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link. - * - * @param file - * A file reference that locates the file - * @param attributes - * The attributes to read - * @param options - * Options indicating how symbolic links are handled - * - * @return A map of the attributes returned; may be empty. The map's keys - * are the attribute names, its values are the attribute values - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, its {@link SecurityManager#checkRead(String) checkRead} - * method denies read access to the file. If this method is invoked - * to read security sensitive attributes then the security manager - * may be invoke to check for additional permissions. - */ - public static Map<String,?> readAttributes(FileRef file, - String attributes, - LinkOption... options) - throws IOException - { - String[] s = split(attributes); - FileAttributeView view = file.getFileAttributeView(s[0], options); - if (view != null) { - // further split attributes into the first and rest. - String[] names = s[1].split(","); - int rem = names.length-1; - String first = names[0]; - String[] rest = new String[rem]; - if (rem > 0) System.arraycopy(names, 1, rest, 0, rem); - - return view.readAttributes(first, rest); - } - // view not available - return Collections.emptyMap(); - } + private Attributes() { } /** * Reads the basic file attributes of a file. @@ -551,29 +312,28 @@ } /** - * Updates the value of a file's last modified time attribute. + * Updates a file's last modified time attribute. The file time is converted + * to the epoch and precision supported by the file system. Converting from + * finer to coarser granularities result in precision loss. The behavior of + * this method when attempting to set a timestamp to a value that is outside + * the range supported by the underlying file store is not defined. It may + * or not fail by throwing an {@code IOException}. * - * <p> The time value is measured since the epoch - * (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. + * <p> If the file system does not support a last modified time attribute + * then this method has no effect. * - * <p> If the file system does not support a last modified time attribute then - * this method has no effect. + * <p> <b>Usage Example:</b> + * Suppose we want to set the last modified time to the current time: + * <pre> + * FileTime now = FileTime.fromMillis(System.currentTimeMillis()); + * Attributes.setLastModifiedTime(file, now); + * </pre> * * @param file * A file reference that locates the file + * @param lastModifiedTime + * The new last modified time * - * @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 - * - * @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 @@ * @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. - * - * <p> 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}. * * <p> If the file system does not support a last access time attribute then * this method has no effect. * + * @param file + * A file reference that locates the file * @param lastAccessTime - * The new last access time, 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 @@ * @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); } /**
--- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -25,7 +25,6 @@ package java.nio.file.attribute; -import java.util.concurrent.TimeUnit; import java.io.IOException; /** @@ -49,19 +48,15 @@ * </tr> * <tr> * <td> "lastModifiedTime" </td> - * <td> {@link Long} </td> + * <td> {@link FileTime} </td> * </tr> * <tr> * <td> "lastAccessTime" </td> - * <td> {@link Long} </td> + * <td> {@link FileTime} </td> * </tr> * <tr> * <td> "creationTime" </td> - * <td> {@link Long} </td> - * </tr> - * <tr> - * <td> "resolution" </td> - * <td> {@link java.util.concurrent.TimeUnit} </td> + * <td> {@link FileTime} </td> * </tr> * <tr> * <td> "size" </td> @@ -84,26 +79,19 @@ * <td> {@link Boolean} </td> * </tr> * <tr> - * <td> "linkCount" </td> - * <td> {@link Integer} </td> - * </tr> - * <tr> * <td> "fileKey" </td> * <td> {@link Object} </td> * </tr> * </table> * </blockquote> * - * <p> 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 + * <p> 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. * - * <p> 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. + * <p> 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 @@ * and create time attributes. * * <p> This method updates the file's timestamp attributes. The values are - * measured since the epoch (00:00:00 GMT, January 1, 1970) and converted to - * 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}. * * <p> If any of the {@code lastModifiedTime}, {@code lastAccessTime}, * or {@code createTime} parameters has the value {@code null} then the @@ -153,25 +141,19 @@ * 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 @@ * 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; }
--- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ /** * Returns the time of last modification. * - * <p> The {@link #resolution() resolution} method returns the {@link TimeUnit} - * to interpret the return value of this method. - * - * @return a <code>long</code> value representing the time the file was - * last modified since the epoch (00:00:00 GMT, January 1, 1970), - * or {@code -1L} if the attribute is not supported. + * @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. * - * <p> The {@link #resolution() resolution} method returns the {@link TimeUnit} - * to interpret the return value of this method. - * - * @return a <code>long</code> value representing the time of last access - * since the epoch (00:00:00 GMT, January 1, 1970), or {@code -1L} - * if the attribute is not supported. + * @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. * - * <p> The {@link #resolution() resolution} method returns the {@link TimeUnit} - * to interpret the return value of this method. - * - * @return a <code>long</code> value representing the time the file was - * created since the epoch (00:00:00 GMT, January 1, 1970), or - * {@code -1L} if the attribute is not supported. + * @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. @@ -125,18 +103,6 @@ long size(); /** - * Returns the number of <em>links</em> to this file. - * - * <p> On file systems where the same file may be in several directories then - * the link count is the number of directory entries for the file. The return - * value is {@code 1} on file systems that only allow a file to have a - * single name in a single directory. - * - * @see java.nio.file.Path#createLink - */ - int linkCount(); - - /** * Returns an object that uniquely identifies the given file, or {@code * null} if a file key is not available. On some platforms or file systems * it is possible to use an identifier, or a combination of identifiers to @@ -154,7 +120,7 @@ * * <p> File keys returned by this method can be compared for equality and are * suitable for use in collections. If the file system and files remain static, - * and two files are the {@link java.nio.file.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
--- a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -65,17 +65,17 @@ * </table> * </blockquote> * - * <p> 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. + * <p> 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. * - * <p> 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. + * <p> 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 */
--- a/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -34,7 +34,6 @@ * @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
--- a/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -37,11 +37,11 @@ * <p> The {@link #getOwner getOwner} or {@link #setOwner setOwner} methods may * be used to read or update the owner of the file. * - * <p> 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. + * <p> 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 */
--- a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -52,10 +52,8 @@ * </tr> * </table> * </blockquote> - * <p> 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. + * <p> The {@link java.nio.file.FileStore#getAttribute getAttribute} method may + * be used to read any of these attributes. * * @since 1.7 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java Sun Jun 28 23:16:18 2009 -0700 @@ -0,0 +1,305 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.file.attribute; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Date; +import java.util.Formatter; +import java.util.Locale; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; + +/** + * Represents the value of a file's time stamp attribute. For example, it may + * represent the time that the file was last modified, accessed, or created. + * + * <p> Instances of this class are immutable. + * + * @since 1.7 + * @see BasicFileAttributes + * @see Attributes#setLastModifiedTime + */ + +public final class FileTime implements Comparable<FileTime> { + private final long value; + private final TimeUnit unit; + private String valueAsString; // created lazily + + private FileTime(long value, TimeUnit unit) { + if (unit == null) + throw new NullPointerException(); + this.value = value; + this.unit = unit; + } + + /** + * Returns a {@code FileTime} representing a value at the given unit of + * granularity. + * + * @param value + * the value since the epoch (1970-01-01T00:00:00Z); can be + * negative + * @param unit + * the unit of granularity to interpret the value + * + * @return a {@code FileTime} representing the given value + */ + public static FileTime from(long value, TimeUnit unit) { + return new FileTime(value, unit); + } + + /** + * Returns a {@code FileTime} representing the given value in milliseconds. + * + * @param value + * the value, in milliseconds, since the epoch + * (1970-01-01T00:00:00Z); can be negative + * + * @return a {@code FileTime} representing the given value + */ + public static FileTime fromMillis(long value) { + return new FileTime(value, TimeUnit.MILLISECONDS); + } + + /** + * Returns the value at the given unit of granularity. + * + * <p> Conversion from a coarser granularity that would numerically overflow + * saturate to {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE} + * if positive. + * + * @param unit + * the unit of granularity for the return value + * + * @return value in the given unit of granularity, since the epoch + * since the epoch (1970-01-01T00:00:00Z); can be negative + */ + public long to(TimeUnit unit) { + return unit.convert(this.value, this.unit); + } + + /** + * Returns the value in milliseconds. + * + * <p> Conversion from a coarser granularity that would numerically overflow + * saturate to {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE} + * if positive. + * + * @return the value in milliseconds, since the epoch (1970-01-01T00:00:00Z) + */ + public long toMillis() { + return unit.toMillis(value); + } + + /** + * Tests this {@code FileTime} for equality with the given object. + * + * <p> The result is {@code true} if and only if the argument is not {@code + * null} and is a {@code FileTime} that represents the same time. This + * method satisfies the general contract of the {@code Object.equals} method. + * + * @param obj + * the object to compare with + * + * @return {@code true} if, and only if, the given object is a {@code + * FileTime} that represents the same time + */ + @Override + public boolean equals(Object obj) { + return (obj instanceof FileTime) ? compareTo((FileTime)obj) == 0 : false; + } + + /** + * Computes a hash code for this file time. + * + * <p> The hash code is based upon the value represented, and satisfies the + * general contract of the {@link Object#hashCode} method. + * + * @return the hash-code value + */ + @Override + public int hashCode() { + // hash value for fixed granularity to satisfy contract with equals + long ms = toMillis(); + return (int)(ms ^ (ms >>> 32)); + } + + /** + * Compares the value of two {@code FileTime} objects for order. + * + * @param other + * the other {@code FileTime} to be compared + * + * @return {@code 0} if this {@code FileTime} is equal to {@code other}, a + * value less than 0 if this {@code FileTime} represents a time + * that is before {@code other}, and a value greater than 0 if this + * {@code FileTime} represents a time that is after {@code other} + */ + @Override + public int compareTo(FileTime other) { + // same granularity + if (unit == other.unit) + return (value < other.value) ? -1 : (value == other.value ? 0 : 1); + + // compare in days + long thisValueInDays = unit.toDays(value); + long otherValueInDays = other.unit.toDays(other.value); + if (thisValueInDays != otherValueInDays) + return (thisValueInDays < otherValueInDays) ? -1 : 1; + + // compare remainder in nanoseconds + long thisRemainder = remainderInNanos(thisValueInDays); + long otherRemainder = other.remainderInNanos(otherValueInDays); + return (thisRemainder < otherRemainder) ? -1 : + (thisRemainder == otherRemainder) ? 0 : 1; + } + + private long remainderInNanos(long days) { + // constants for conversion + final long C0 = 1L; + final long C1 = C0 * 24L; + final long C2 = C1 * 60L; + final long C3 = C2 * 60L; + final long C4 = C3 * 1000L; + final long C5 = C4 * 1000L; + final long C6 = C5 * 1000L; + + long scale; + switch (unit) { + case DAYS : scale = C0; break; + case HOURS : scale = C1; break; + case MINUTES : scale = C2; break; + case SECONDS : scale = C3; break; + case MILLISECONDS : scale = C4; break; + case MICROSECONDS : scale = C5; break; + case NANOSECONDS : scale = C6; break; + default: + throw new AssertionError("Unit not handled"); + } + long rem = value - (days * scale); + return unit.toNanos(rem); + } + + /** + * Returns the string representation of this {@code FileTime}. The string + * is returned in the <a + * href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a> format: + * <pre> + * YYYY-MM-DDThh:mm:ss[.s+]Z + * </pre> + * where "{@code [.s+]}" represents a dot followed by one of more digits + * for the decimal fraction of a second. It is only present when the decimal + * fraction of a second is not zero. For example, {@code + * FileTime.fromMillis(1234567890000L).toString()} yields {@code + * "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()} + * yields {@code "2009-02-13T23:31:30.123Z"}. + * + * <p> A {@code FileTime} is primarly intended to represent the value of a + * file's time stamp. Where used to represent <i>extreme values</i>, where + * the year is less than "{@code 0001}" or greater than "{@code 9999}" then + * the year may be expanded to more than four digits and may be + * negative-signed. If more than four digits then leading zeros are not + * present. The year before "{@code 0001}" is "{@code -0001}". + * + * @return the string representation of this file time + */ + @Override + public String toString() { + String v = valueAsString; + if (v == null) { + // overflow saturates to Long.MIN_VALUE or Long.MAX_VALUE so this + // limits the range: + // [-292275056-05-16T16:47:04.192Z,292278994-08-17T07:12:55.807Z] + long ms = toMillis(); + + // nothing to do when seconds/minutes/hours/days + String fractionAsString = ""; + if (unit.compareTo(TimeUnit.SECONDS) < 0) { + // constants for conversion + final long C0 = 1L; + final long C1 = C0 * 1000L; + final long C2 = C1 * 1000L; + final long C3 = C2 * 1000L; + + long scale; + int width; + switch (unit) { + case MILLISECONDS : scale = C1; width = 3; break; + case MICROSECONDS : scale = C2; width = 6; break; + case NANOSECONDS : scale = C3; width = 9; break; + default: + throw new AssertionError("Unit not handled"); + } + long fraction = value % scale; + if (fraction != 0L) { + // fraction must be positive + if (fraction < 0L) { + fraction += scale; + if (ms != Long.MIN_VALUE) ms--; + } + + // convert to String, adding leading zeros as required and + // stripping any trailing zeros + String s = Long.toString(fraction); + int len = s.length(); + width -= len; + StringBuilder sb = new StringBuilder("."); + while (width-- > 0) { + sb.append('0'); + } + if (s.charAt(len-1) == '0') { + // drop trailing zeros + len--; + while (s.charAt(len-1) == '0') + len--; + sb.append(s.substring(0, len)); + } else { + sb.append(s); + } + fractionAsString = sb.toString(); + } + } + + // create calendar to use with formatter. + GregorianCalendar cal = + new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT); + if (value < 0L) + cal.setGregorianChange(new Date(Long.MIN_VALUE)); + cal.setTimeInMillis(ms); + + // years are negative before common era + String sign = (cal.get(Calendar.ERA) == GregorianCalendar.BC) ? "-" : ""; + + // [-]YYYY-MM-DDThh:mm:ss[.s]Z + v = new Formatter(Locale.ROOT) + .format("%s%tFT%tR:%tS%sZ", sign, cal, cal, cal, fractionAsString) + .toString(); + valueAsString = v; + } + return v; + } +}
--- a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -90,14 +90,13 @@ * </table> * </blockquote> * - * <p> 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 + * <p> 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. * - * <p> The {@link #setAttribute setAttribute} method may be used to update the - * file's last modified time, last access time or create time attributes as + * <p> 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
--- a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java Sun Jun 28 23:16:18 2009 -0700 @@ -35,7 +35,7 @@ * @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 @@ } /** - * Returns the {@code String} representation of a set of permissions. + * Returns the {@code String} representation of a set of permissions. It + * is guaranteed that the returned {@code String} can be parsed by the + * {@link #fromString} method. * * <p> If the set contains {@code null} or elements that are not of type * {@code PosixFilePermission} then these elements are ignored. @@ -67,8 +69,6 @@ * the set of permissions * * @return the string representation of the permission set - * - * @see #fromString */ public static String toString(Set<PosixFilePermission> perms) { StringBuilder sb = new StringBuilder(9);
--- a/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -59,12 +59,11 @@ * attributes. * * <p> 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 @@ { /** * 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();
--- a/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java Sun Jun 28 23:16:18 2009 -0700 @@ -89,7 +89,7 @@ * @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
--- a/jdk/src/share/classes/java/nio/file/spi/AbstractPath.java Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,568 +0,0 @@ -/* - * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.nio.file.spi; - -import java.nio.file.*; -import static java.nio.file.StandardOpenOption.*; -import java.nio.file.attribute.*; -import java.nio.channels.*; -import java.nio.ByteBuffer; -import java.io.*; -import java.util.*; - -/** - * Base implementation class for a {@code Path}. - * - * <p> This class is intended to be extended by provider implementors. It - * implements, or provides default implementations for several of the methods - * defined by the {@code Path} class. It implements the {@link #copyTo copyTo} - * and {@link #moveTo moveTo} methods for the case that the source and target - * are not associated with the same provider. - * - * @since 1.7 - */ - -public abstract class AbstractPath extends Path { - - /** - * Initializes a new instance of this class. - */ - protected AbstractPath() { } - - /** - * Deletes the file referenced by this object. - * - * <p> This method invokes the {@link #delete(boolean) delete(boolean)} - * method with a parameter of {@code true}. It may be overridden where - * required. - * - * @throws NoSuchFileException {@inheritDoc} - * @throws DirectoryNotEmptyException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public void delete() throws IOException { - delete(true); - } - - /** - * Creates a new and empty file, failing if the file already exists. - * - * <p> This method invokes the {@link #newByteChannel(Set,FileAttribute[]) - * newByteChannel(Set,FileAttribute...)} method to create the file. It may be - * overridden where required. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public Path createFile(FileAttribute<?>... attrs) - throws IOException - { - EnumSet<StandardOpenOption> options = EnumSet.of(CREATE_NEW, WRITE); - SeekableByteChannel sbc = newByteChannel(options, attrs); - try { - sbc.close(); - } catch (IOException x) { - // ignore - } - return this; - } - - /** - * Opens or creates a file, returning a seekable byte channel to access the - * file. - * - * <p> This method invokes the {@link #newByteChannel(Set,FileAttribute[]) - * newByteChannel(Set,FileAttribute...)} method to open or create the file. - * It may be overridden where required. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException - { - Set<OpenOption> set = new HashSet<OpenOption>(options.length); - Collections.addAll(set, options); - return newByteChannel(set); - } - - /** - * Opens the file located by this path for reading, returning an input - * stream to read bytes from the file. - * - * <p> This method returns an {@code InputStream} that is constructed by - * invoking the {@link java.nio.channels.Channels#newInputStream - * Channels.newInputStream} method. It may be overridden where a more - * efficient implementation is available. - * - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public InputStream newInputStream() throws IOException { - return Channels.newInputStream(newByteChannel()); - } - - // opts must be modifiable - private OutputStream implNewOutputStream(Set<OpenOption> opts, - FileAttribute<?>... attrs) - throws IOException - { - if (opts.isEmpty()) { - opts.add(CREATE); - opts.add(TRUNCATE_EXISTING); - } else { - if (opts.contains(READ)) - throw new IllegalArgumentException("READ not allowed"); - } - opts.add(WRITE); - return Channels.newOutputStream(newByteChannel(opts, attrs)); - } - - /** - * Opens or creates the file located by this path for writing, returning an - * output stream to write bytes to the file. - * - * <p> This method returns an {@code OutputStream} that is constructed by - * invoking the {@link java.nio.channels.Channels#newOutputStream - * Channels.newOutputStream} method. It may be overridden where a more - * efficient implementation is available. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public OutputStream newOutputStream(OpenOption... options) throws IOException { - int len = options.length; - Set<OpenOption> opts = new HashSet<OpenOption>(len + 3); - if (len > 0) { - for (OpenOption opt: options) { - opts.add(opt); - } - } - return implNewOutputStream(opts); - } - - /** - * Opens or creates the file located by this path for writing, returning an - * output stream to write bytes to the file. - * - * <p> This method returns an {@code OutputStream} that is constructed by - * invoking the {@link java.nio.channels.Channels#newOutputStream - * Channels.newOutputStream} method. It may be overridden where a more - * efficient implementation is available. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public OutputStream newOutputStream(Set<? extends OpenOption> options, - FileAttribute<?>... attrs) - throws IOException - { - Set<OpenOption> opts = new HashSet<OpenOption>(options); - return implNewOutputStream(opts, attrs); - } - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over all entries in the directory. - * - * <p> This method invokes the {@link - * #newDirectoryStream(java.nio.file.DirectoryStream.Filter) - * newDirectoryStream(Filter)} method with a filter that accept all entries. - * It may be overridden where required. - * - * @throws NotDirectoryException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public DirectoryStream<Path> newDirectoryStream() throws IOException { - return newDirectoryStream(acceptAllFilter); - } - private static final DirectoryStream.Filter<Path> acceptAllFilter = - new DirectoryStream.Filter<Path>() { - @Override public boolean accept(Path entry) { return true; } - }; - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over the entries in the directory. The - * entries are filtered by matching the {@code String} representation of - * their file names against a given pattern. - * - * <p> This method constructs a {@link PathMatcher} by invoking the - * file system's {@link java.nio.file.FileSystem#getPathMatcher - * getPathMatcher} method. This method may be overridden where a more - * efficient implementation is available. - * - * @throws java.util.regex.PatternSyntaxException {@inheritDoc} - * @throws UnsupportedOperationException {@inheritDoc} - * @throws NotDirectoryException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public DirectoryStream<Path> newDirectoryStream(String glob) - throws IOException - { - // avoid creating a matcher if all entries are required. - if (glob.equals("*")) - return newDirectoryStream(); - - // create a matcher and return a filter that uses it. - final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { - @Override - public boolean accept(Path entry) { - return matcher.matches(entry.getName()); - } - }; - return newDirectoryStream(filter); - } - - /** - * Tests whether the file located by this path exists. - * - * <p> This method invokes the {@link #checkAccess checkAccess} method to - * check if the file exists. It may be overridden where a more efficient - * implementation is available. - */ - @Override - public boolean exists() { - try { - checkAccess(); - return true; - } catch (IOException x) { - // unable to determine if file exists - } - return false; - } - - /** - * Tests whether the file located by this path does not exist. - * - * <p> This method invokes the {@link #checkAccess checkAccess} method to - * check if the file exists. It may be overridden where a more efficient - * implementation is available. - */ - @Override - public boolean notExists() { - try { - checkAccess(); - return false; - } catch (NoSuchFileException x) { - // file confirmed not to exist - return true; - } catch (IOException x) { - return false; - } - } - - /** - * Registers the file located by this path with a watch service. - * - * <p> This method invokes the {@link #register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier[]) - * register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier...)} - * method to register the file. It may be overridden where required. - */ - @Override - public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) - throws IOException - { - return register(watcher, events, NO_MODIFIERS); - } - private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0]; - - /** - * Copy the file located by this path to a target location. - * - * <p> This method is invoked by the {@link #copyTo copyTo} method for - * the case that this {@code Path} and the target {@code Path} are - * associated with the same provider. - * - * @param target - * The target location - * @param options - * Options specifying how the copy should be done - * - * @throws IllegalArgumentException - * If an invalid option is specified - * @throws FileAlreadyExistsException - * The target file exists and cannot be replaced because the - * {@code REPLACE_EXISTING} option is not specified, or the target - * file is a non-empty directory <i>(optional specific exception)</i> - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the source file, the - * {@link SecurityManager#checkWrite(String) checkWrite} is invoked - * to check write access to the target file. If a symbolic link is - * copied the security manager is invoked to check {@link - * LinkPermission}{@code ("symbolic")}. - */ - protected abstract void implCopyTo(Path target, CopyOption... options) - throws IOException; - - /** - * Move the file located by this path to a target location. - * - * <p> This method is invoked by the {@link #moveTo moveTo} method for - * the case that this {@code Path} and the target {@code Path} are - * associated with the same provider. - * - * @param target - * The target location - * @param options - * Options specifying how the move should be done - * - * @throws IllegalArgumentException - * If an invalid option is specified - * @throws FileAlreadyExistsException - * The target file exists and cannot be replaced because the - * {@code REPLACE_EXISTING} option is not specified, or the target - * file is a non-empty directory - * @throws AtomicMoveNotSupportedException - * The options array contains the {@code ATOMIC_MOVE} option but - * the file cannot be moved as an atomic file system operation. - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to both the source and - * target file. - */ - protected abstract void implMoveTo(Path target, CopyOption... options) - throws IOException; - - /** - * Copy the file located by this path to a target location. - * - * <p> If this path is associated with the same {@link FileSystemProvider - * provider} as the {@code target} then the {@link #implCopyTo implCopyTo} - * method is invoked to copy the file. Otherwise, this method attempts to - * copy the file to the target location in a manner that may be less - * efficient than would be the case that target is associated with the same - * provider as this path. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public final Path copyTo(Path target, CopyOption... options) - throws IOException - { - if ((getFileSystem().provider() == target.getFileSystem().provider())) { - implCopyTo(target, options); - } else { - xProviderCopyTo(target, options); - } - return target; - } - - /** - * Move or rename the file located by this path to a target location. - * - * <p> If this path is associated with the same {@link FileSystemProvider - * provider} as the {@code target} then the {@link #implCopyTo implMoveTo} - * method is invoked to move the file. Otherwise, this method attempts to - * copy the file to the target location and delete the source file. This - * implementation may be less efficient than would be the case that - * target is associated with the same provider as this path. - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws FileAlreadyExistsException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public final Path moveTo(Path target, CopyOption... options) - throws IOException - { - if ((getFileSystem().provider() == target.getFileSystem().provider())) { - implMoveTo(target, options); - } else { - // different providers so copy + delete - xProviderCopyTo(target, convertMoveToCopyOptions(options)); - delete(false); - } - return target; - } - - /** - * Converts the given array of options for moving a file to options suitable - * for copying the file when a move is implemented as copy + delete. - */ - private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) - throws AtomicMoveNotSupportedException - { - int len = options.length; - CopyOption[] newOptions = new CopyOption[len+2]; - for (int i=0; i<len; i++) { - CopyOption option = options[i]; - if (option == StandardCopyOption.ATOMIC_MOVE) { - throw new AtomicMoveNotSupportedException(null, null, - "Atomic move between providers is not supported"); - } - newOptions[i] = option; - } - newOptions[len] = LinkOption.NOFOLLOW_LINKS; - newOptions[len+1] = StandardCopyOption.COPY_ATTRIBUTES; - return newOptions; - } - - /** - * Parses the arguments for a file copy operation. - */ - private static class CopyOptions { - boolean replaceExisting = false; - boolean copyAttributes = false; - boolean followLinks = true; - - private CopyOptions() { } - - static CopyOptions parse(CopyOption... options) { - CopyOptions result = new CopyOptions(); - for (CopyOption option: options) { - if (option == StandardCopyOption.REPLACE_EXISTING) { - result.replaceExisting = true; - continue; - } - if (option == LinkOption.NOFOLLOW_LINKS) { - result.followLinks = false; - continue; - } - if (option == StandardCopyOption.COPY_ATTRIBUTES) { - result.copyAttributes = true; - continue; - } - if (option == null) - throw new NullPointerException(); - throw new IllegalArgumentException("'" + option + - "' is not a valid copy option"); - } - return result; - } - } - - /** - * Simple cross-provider copy where the target is a Path. - */ - private void xProviderCopyTo(Path target, CopyOption... options) - throws IOException - { - CopyOptions opts = CopyOptions.parse(options); - LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] : - new LinkOption[] { LinkOption.NOFOLLOW_LINKS }; - - // attributes of source file - BasicFileAttributes attrs = Attributes - .readBasicFileAttributes(this, linkOptions); - if (attrs.isSymbolicLink()) - throw new IOException("Copying of symbolic links not supported"); - - // delete target file - if (opts.replaceExisting) - target.delete(false); - - // create directory or file - if (attrs.isDirectory()) { - target.createDirectory(); - } else { - xProviderCopyRegularFileTo(target); - } - - // copy basic attributes to target - if (opts.copyAttributes) { - BasicFileAttributeView view = target - .getFileAttributeView(BasicFileAttributeView.class, linkOptions); - try { - view.setTimes(attrs.lastModifiedTime(), - attrs.lastAccessTime(), - attrs.creationTime(), - attrs.resolution()); - } catch (IOException x) { - // rollback - try { - target.delete(false); - } catch (IOException ignore) { } - throw x; - } - } - } - - - /** - * Simple copy of regular file to a target file that exists. - */ - private void xProviderCopyRegularFileTo(FileRef target) - throws IOException - { - ReadableByteChannel rbc = newByteChannel(); - try { - // open target file for writing - SeekableByteChannel sbc = target.newByteChannel(CREATE, WRITE); - - // simple copy loop - try { - ByteBuffer buf = ByteBuffer.wrap(new byte[8192]); - int n = 0; - for (;;) { - n = rbc.read(buf); - if (n < 0) - break; - assert n > 0; - buf.flip(); - while (buf.hasRemaining()) { - sbc.write(buf); - } - buf.rewind(); - } - - } finally { - sbc.close(); - } - } finally { - rbc.close(); - } - } -}
--- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java Sun Jun 28 23:16:18 2009 -0700 @@ -270,7 +270,9 @@ public abstract FileSystem getFileSystem(URI uri); /** - * Return a {@code Path} object by converting the given {@link URI}. + * Return a {@code Path} object by converting the given {@link URI}. The + * resulting {@code Path} is associated with a {@link FileSystem} that + * already exists or is constructed automatically. * * <p> The exact form of the URI is file system provider dependent. In the * case of the default provider, the URI scheme is {@code "file"} and the @@ -290,7 +292,8 @@ * 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.
--- a/jdk/src/share/classes/java/util/Scanner.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/java/util/Scanner.java Sun Jun 28 23:16:18 2009 -0700 @@ -690,7 +690,7 @@ public Scanner(FileRef source) throws IOException { - this(source.newByteChannel()); + this(source.newInputStream()); } /** @@ -713,7 +713,7 @@ public Scanner(FileRef source, String charsetName) throws IOException { - this(source.newByteChannel(), charsetName); + this(source.newInputStream(), charsetName); } /**
--- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 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 @@ 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 @@ return result; } + public static List<BufferPoolMXBean> getBufferPoolMXBeans() { + List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2); + pools.add(createBufferPoolMXBean(sun.misc.SharedSecrets.getJavaNioAccess() + .getDirectBufferPool())); + pools.add(createBufferPoolMXBean(sun.nio.ch.FileChannelImpl + .getMappedBufferPool())); + return pools; + } + + private final static String BUFFER_POOL_MXBEAN_NAME = "java.nio:type=BufferPool"; + + /** + * Creates management interface for the given buffer pool. + */ + private static BufferPoolMXBean + createBufferPoolMXBean(final sun.misc.JavaNioAccess.BufferPool pool) + { + return new BufferPoolMXBean() { + private volatile ObjectName objname; // created lazily + @Override + public ObjectName getObjectName() { + ObjectName result = objname; + if (result == null) { + synchronized (this) { + if (objname == null) { + result = ObjectName.valueOf(BUFFER_POOL_MXBEAN_NAME + + ",name=" + pool.getName()); + objname = result; + } + } + } + return result; + } + @Override + public String getName() { + return pool.getName(); + } + @Override + public long getCount() { + return pool.getCount(); + } + @Override + public long getTotalCapacity() { + return pool.getTotalCapacity(); + } + @Override + public long getMemoryUsed() { + return pool.getMemoryUsed(); + } + }; + } + private static HotSpotDiagnostic hsDiagMBean = null; private static HotspotRuntime hsRuntimeMBean = null; private static HotspotClassLoading hsClassMBean = null; @@ -163,8 +202,6 @@ } /** - - /** * This method is for testing only. */ public static synchronized HotspotRuntimeMBean getHotspotRuntimeMBean() {
--- a/jdk/src/share/classes/sun/misc/JavaNioAccess.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/misc/JavaNioAccess.java Sun Jun 28 23:16:18 2009 -0700 @@ -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(); }
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Sun Jun 28 23:16:18 2009 -0700 @@ -29,13 +29,10 @@ 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 @@ } /** - * 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 --
--- a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -26,15 +26,15 @@ package sun.nio.fs; import java.nio.file.attribute.*; +import java.util.*; import java.io.IOException; -import java.util.*; /** * 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 @@ setAcl((List<AclEntry>)value); return; } - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("'" + name() + ":" + + attribute + "' not supported"); } @Override - public final Map<String,?> readAttributes(String first, String[] rest) + public final Map<String,?> 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<String,Object> result = new HashMap<String,Object>(2);
--- a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -26,24 +26,21 @@ package sun.nio.fs; import java.nio.file.attribute.*; +import java.util.*; import java.io.IOException; -import java.util.*; -import java.util.concurrent.TimeUnit; /** * 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 @@ 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 @@ 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 @@ } /** - * + * Used to build a map of attribute name/values. */ static class AttributesBuilder { private Set<String> set = new HashSet<String>(); private Map<String,Object> map = new HashMap<String,Object>(); private 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 @@ /** * 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 @@ 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 @@ } @Override - public Map<String,?> readAttributes(String first, String[] rest) - throws IOException - { - AttributesBuilder builder = AttributesBuilder.create(first, rest); + public Map<String,?> readAttributes(String[] attributes) throws IOException { + AttributesBuilder builder = AttributesBuilder.create(attributes); addBasicAttributesToBuilder(readAttributes(), builder); return builder.unmodifiableMap(); }
--- a/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package sun.nio.fs; - -import java.nio.file.attribute.*; -import java.io.IOException; -import java.util.*; - -/** - * Base implementation of FileStoreSpaceAttributeView - */ - -abstract class AbstractFileStoreSpaceAttributeView - implements FileStoreSpaceAttributeView -{ - private static final String TOTAL_SPACE_NAME = "totalSpace"; - private static final String USABLE_SPACE_NAME = "usableSpace"; - private static final String UNALLOCATED_SPACE_NAME = "unallocatedSpace"; - - @Override - public final String name() { - return "space"; - } - - @Override - public final Object getAttribute(String attribute) throws IOException { - FileStoreSpaceAttributes attrs = readAttributes(); - if (attribute.equals(TOTAL_SPACE_NAME)) - return attrs.totalSpace(); - if (attribute.equals(USABLE_SPACE_NAME)) - return attrs.usableSpace(); - if (attribute.equals(UNALLOCATED_SPACE_NAME)) - return attrs.unallocatedSpace(); - return null; - } - - @Override - public final void setAttribute(String attribute, Object value) - throws IOException - { - if (attribute == null || value == null) - throw new NullPointerException(); - throw new UnsupportedOperationException(); - } - - @Override - public final Map<String,?> readAttributes(String first, String[] rest) - throws IOException - { - boolean total = false; - boolean usable = false; - boolean unallocated = false; - - if (first.equals(TOTAL_SPACE_NAME)) total = true; - else if (first.equals(USABLE_SPACE_NAME)) usable = true; - else if (first.equals(UNALLOCATED_SPACE_NAME)) unallocated = true; - else if (first.equals("*")) { - total = true; - usable = true; - unallocated = true; - } - - if (!total || !usable || !unallocated) { - for (String attribute: rest) { - if (attribute.equals("*")) { - total = true; - usable = true; - unallocated = true; - break; - } - if (attribute.equals(TOTAL_SPACE_NAME)) { - total = true; - continue; - } - if (attribute.equals(USABLE_SPACE_NAME)) { - usable = true; - continue; - } - if (attribute.equals(UNALLOCATED_SPACE_NAME)) { - unallocated = true; - continue; - } - } - } - - FileStoreSpaceAttributes attrs = readAttributes(); - Map<String,Object> result = new HashMap<String,Object>(2); - if (total) - result.put(TOTAL_SPACE_NAME, attrs.totalSpace()); - if (usable) - result.put(USABLE_SPACE_NAME, attrs.usableSpace()); - if (unallocated) - result.put(UNALLOCATED_SPACE_NAME, attrs.unallocatedSpace()); - return Collections.unmodifiableMap(result); - } -}
--- a/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java Sun Jun 28 23:16:18 2009 -0700 @@ -27,8 +27,8 @@ 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 @@ } /** - * 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 @@ */ 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; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/nio/fs/AbstractPath.java Sun Jun 28 23:16:18 2009 -0700 @@ -0,0 +1,404 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.nio.file.attribute.*; +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.io.*; +import java.util.*; + +/** + * Base implementation class for a {@code Path}. + */ + +abstract class AbstractPath extends Path { + protected AbstractPath() { } + + @Override + public final Path createFile(FileAttribute<?>... attrs) + throws IOException + { + EnumSet<StandardOpenOption> options = EnumSet.of(CREATE_NEW, WRITE); + SeekableByteChannel sbc = newByteChannel(options, attrs); + try { + sbc.close(); + } catch (IOException x) { + // ignore + } + return this; + } + + /** + * Deletes a file. The {@code failIfNotExists} parameters determines if an + * {@code IOException} is thrown when the file does not exist. + */ + abstract void implDelete(boolean failIfNotExists) throws IOException; + + @Override + public final void delete() throws IOException { + implDelete(true); + } + + @Override + public final void deleteIfExists() throws IOException { + implDelete(false); + } + + @Override + public final InputStream newInputStream(OpenOption... options) + throws IOException + { + if (options.length > 0) { + for (OpenOption opt: options) { + if (opt != READ) + throw new UnsupportedOperationException("'" + opt + "' not allowed"); + } + } + return Channels.newInputStream(newByteChannel()); + } + + @Override + public final OutputStream newOutputStream(OpenOption... options) + throws IOException + { + int len = options.length; + Set<OpenOption> opts = new HashSet<OpenOption>(len + 3); + if (len == 0) { + opts.add(CREATE); + opts.add(TRUNCATE_EXISTING); + } else { + for (OpenOption opt: options) { + if (opt == READ) + throw new IllegalArgumentException("READ not allowed"); + opts.add(opt); + } + } + opts.add(WRITE); + return Channels.newOutputStream(newByteChannel(opts)); + } + + @Override + public final SeekableByteChannel newByteChannel(OpenOption... options) + throws IOException + { + Set<OpenOption> set = new HashSet<OpenOption>(options.length); + Collections.addAll(set, options); + return newByteChannel(set); + } + + private static final DirectoryStream.Filter<Path> acceptAllFilter = + new DirectoryStream.Filter<Path>() { + @Override public boolean accept(Path entry) { return true; } + }; + + @Override + public final DirectoryStream<Path> newDirectoryStream() throws IOException { + return newDirectoryStream(acceptAllFilter); + } + + @Override + public final DirectoryStream<Path> newDirectoryStream(String glob) + throws IOException + { + // avoid creating a matcher if all entries are required. + if (glob.equals("*")) + return newDirectoryStream(); + + // create a matcher and return a filter that uses it. + final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); + DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { + @Override + public boolean accept(Path entry) { + return matcher.matches(entry.getName()); + } + }; + return newDirectoryStream(filter); + } + + @Override + public final boolean exists() { + try { + checkAccess(); + return true; + } catch (IOException x) { + // unable to determine if file exists + } + return false; + } + + @Override + public final boolean notExists() { + try { + checkAccess(); + return false; + } catch (NoSuchFileException x) { + // file confirmed not to exist + return true; + } catch (IOException x) { + return false; + } + } + + private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0]; + + @Override + public final WatchKey register(WatchService watcher, + WatchEvent.Kind<?>... events) + throws IOException + { + return register(watcher, events, NO_MODIFIERS); + } + + abstract void implCopyTo(Path target, CopyOption... options) + throws IOException; + + @Override + public final Path copyTo(Path target, CopyOption... options) + throws IOException + { + if ((getFileSystem().provider() == target.getFileSystem().provider())) { + implCopyTo(target, options); + } else { + copyToForeignTarget(target, options); + } + return target; + } + + abstract void implMoveTo(Path target, CopyOption... options) + throws IOException; + + @Override + public final Path moveTo(Path target, CopyOption... options) + throws IOException + { + if ((getFileSystem().provider() == target.getFileSystem().provider())) { + implMoveTo(target, options); + } else { + // different providers so copy + delete + copyToForeignTarget(target, convertMoveToCopyOptions(options)); + delete(); + } + return target; + } + + /** + * Converts the given array of options for moving a file to options suitable + * for copying the file when a move is implemented as copy + delete. + */ + private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) + throws AtomicMoveNotSupportedException + { + int len = options.length; + CopyOption[] newOptions = new CopyOption[len+2]; + for (int i=0; i<len; i++) { + CopyOption option = options[i]; + if (option == StandardCopyOption.ATOMIC_MOVE) { + throw new AtomicMoveNotSupportedException(null, null, + "Atomic move between providers is not supported"); + } + newOptions[i] = option; + } + newOptions[len] = LinkOption.NOFOLLOW_LINKS; + newOptions[len+1] = StandardCopyOption.COPY_ATTRIBUTES; + return newOptions; + } + + /** + * Parses the arguments for a file copy operation. + */ + private static class CopyOptions { + boolean replaceExisting = false; + boolean copyAttributes = false; + boolean followLinks = true; + + private CopyOptions() { } + + static CopyOptions parse(CopyOption... options) { + CopyOptions result = new CopyOptions(); + for (CopyOption option: options) { + if (option == StandardCopyOption.REPLACE_EXISTING) { + result.replaceExisting = true; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + result.followLinks = false; + continue; + } + if (option == StandardCopyOption.COPY_ATTRIBUTES) { + result.copyAttributes = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new IllegalArgumentException("'" + option + + "' is not a valid copy option"); + } + return result; + } + } + + /** + * Simple cross-provider copy where the target is a Path. + */ + private void copyToForeignTarget(Path target, CopyOption... options) + throws IOException + { + CopyOptions opts = CopyOptions.parse(options); + LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] : + new LinkOption[] { LinkOption.NOFOLLOW_LINKS }; + + // attributes of source file + BasicFileAttributes attrs = Attributes + .readBasicFileAttributes(this, linkOptions); + if (attrs.isSymbolicLink()) + throw new IOException("Copying of symbolic links not supported"); + + // delete target file + if (opts.replaceExisting) + target.deleteIfExists(); + + // create directory or file + if (attrs.isDirectory()) { + target.createDirectory(); + } else { + copyRegularFileToForeignTarget(target); + } + + // copy basic attributes to target + if (opts.copyAttributes) { + BasicFileAttributeView view = target + .getFileAttributeView(BasicFileAttributeView.class, linkOptions); + try { + view.setTimes(attrs.lastModifiedTime(), + attrs.lastAccessTime(), + attrs.creationTime()); + } catch (IOException x) { + // rollback + try { + target.delete(); + } catch (IOException ignore) { } + throw x; + } + } + } + + + /** + * Simple copy of regular file to a target file that exists. + */ + private void copyRegularFileToForeignTarget(Path target) + throws IOException + { + ReadableByteChannel rbc = newByteChannel(); + try { + // open target file for writing + SeekableByteChannel sbc = target.newByteChannel(CREATE, WRITE); + + // simple copy loop + try { + ByteBuffer buf = ByteBuffer.wrap(new byte[8192]); + int n = 0; + for (;;) { + n = rbc.read(buf); + if (n < 0) + break; + assert n > 0; + buf.flip(); + while (buf.hasRemaining()) { + sbc.write(buf); + } + buf.rewind(); + } + + } finally { + sbc.close(); + } + } finally { + rbc.close(); + } + } + + /** + * Splits the given attribute name into the name of an attribute view and + * the attribute. If the attribute view is not identified then it assumed + * to be "basic". + */ + private static String[] split(String attribute) { + String[] s = new String[2]; + int pos = attribute.indexOf(':'); + if (pos == -1) { + s[0] = "basic"; + s[1] = attribute; + } else { + s[0] = attribute.substring(0, pos++); + s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos); + } + return s; + } + + /** + * Gets a DynamicFileAttributeView by name. Returns {@code null} if the + * view is not available. + */ + abstract DynamicFileAttributeView getFileAttributeView(String name, + LinkOption... options); + + @Override + public final void setAttribute(String attribute, + Object value, + LinkOption... options) + throws IOException + { + String[] s = split(attribute); + DynamicFileAttributeView view = getFileAttributeView(s[0], options); + if (view == null) + throw new UnsupportedOperationException("View '" + s[0] + "' not available"); + view.setAttribute(s[1], value); + } + + @Override + public final Object getAttribute(String attribute, LinkOption... options) + throws IOException + { + String[] s = split(attribute); + DynamicFileAttributeView view = getFileAttributeView(s[0], options); + return (view == null) ? null : view.getAttribute(s[1]); + } + + @Override + public final Map<String,?> readAttributes(String attributes, LinkOption... options) + throws IOException + { + String[] s = split(attributes); + DynamicFileAttributeView view = getFileAttributeView(s[0], options); + if (view == null) + return Collections.emptyMap(); + return view.readAttributes(s[1].split(",")); + } +}
--- a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -31,11 +31,11 @@ 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 @@ @Override public final String name() { - return "xattr"; + return "user"; } @Override @@ -70,6 +70,7 @@ 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 @@ } @Override - public final Map<String,?> readAttributes(String first, String... rest) + public final Map<String,?> readAttributes(String[] attributes) throws IOException { // names of attributes to return List<String> names = new ArrayList<String>(); - 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<String,Object> result = new HashMap<String,Object>();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -0,0 +1,51 @@ +/* + * 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.util.Map; +import java.io.IOException; + +/** + * Implemented by FileAttributeView implementations to support access to + * attributes by names. + */ + +interface DynamicFileAttributeView { + /** + * Reads the value of an attribute. + */ + Object getAttribute(String attribute) throws IOException; + + /** + * Sets/updates the value of an attribute. + */ + void setAttribute(String attribute, Object value) throws IOException; + + /** + * Reads a set of file attributes as a bulk operation. + */ + Map<String,?> readAttributes(String[] attributes) throws IOException; +}
--- a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java Sun Jun 28 23:16:18 2009 -0700 @@ -34,7 +34,9 @@ * 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 @@ setOwner((UserPrincipal)value); return; } - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("'" + name() + ":" + + attribute + "' not supported"); } @Override - public Map<String,?> readAttributes(String first, String[] rest) throws IOException { + public Map<String,?> readAttributes(String[] attributes) throws IOException { Map<String,Object> result = new HashMap<String,Object>(); - 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;
--- a/jdk/src/share/classes/sun/nio/fs/MimeType.java Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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; - } - } -}
--- a/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java Sun Jun 28 23:16:18 2009 -0700 @@ -265,7 +265,7 @@ // 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 @@ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/nio/fs/Util.java Sun Jun 28 23:16:18 2009 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Utility methods + */ + +class Util { + private Util() { } + + /** + * Splits a string around the given character. The array returned by this + * method contains each substring that is terminated by the character. Use + * for simple string spilting cases when needing to avoid loading regex. + */ + static String[] split(String s, char c) { + int count = 0; + for (int i=0; i<s.length(); i++) { + if (s.charAt(i) == c) + count++; + } + String[] result = new String[count+1]; + int n = 0; + int last = 0; + for (int i=0; i<s.length(); i++) { + if (s.charAt(i) == c) { + result[n++] = s.substring(last, i); + last = i + 1; + } + } + result[n] = s.substring(last, s.length()); + return result; + + } +}
--- a/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c Sun Jun 28 23:16:18 2009 -0700 @@ -2227,7 +2227,8 @@ CrwCpoolIndex this_class; CrwCpoolIndex super_class; unsigned magic; - unsigned classfileVersion; + unsigned classfileMajorVersion; + unsigned classfileMinorVersion; unsigned interface_count; CRW_ASSERT_CI(ci); @@ -2258,10 +2259,12 @@ } /* minor version number not used */ - (void)copyU2(ci); + classfileMinorVersion = copyU2(ci); /* major version number not used */ - classfileVersion = copyU2(ci); - CRW_ASSERT(ci, classfileVersion <= 50); /* Mustang class files or less */ + classfileMajorVersion = copyU2(ci); + CRW_ASSERT(ci, (classfileMajorVersion <= JVM_CLASSFILE_MAJOR_VERSION) || + ((classfileMajorVersion == JVM_CLASSFILE_MAJOR_VERSION) && + (classfileMinorVersion <= JVM_CLASSFILE_MINOR_VERSION))); cpool_setup(ci);
--- a/jdk/src/share/javavm/export/classfile_constants.h Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/javavm/export/classfile_constants.h Sun Jun 28 23:16:18 2009 -0700 @@ -30,6 +30,10 @@ extern "C" { #endif +/* Classfile version number for this information */ +#define JVM_CLASSFILE_MAJOR_VERSION 51 +#define JVM_CLASSFILE_MINOR_VERSION 0 + /* Flags */ enum {
--- a/jdk/src/share/sample/nio/file/Copy.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/sample/nio/file/Copy.java Sun Jun 28 23:16:18 2009 -0700 @@ -127,8 +127,7 @@ Path newdir = target.resolve(source.relativize(dir)); try { BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir); - Attributes.setLastModifiedTime(newdir, - attrs.lastModifiedTime(), attrs.resolution()); + Attributes.setLastModifiedTime(newdir, attrs.lastModifiedTime()); } catch (IOException x) { System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x); }
--- a/jdk/src/share/sample/nio/file/Xdd.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/share/sample/nio/file/Xdd.java Sun Jun 28 23:16:18 2009 -0700 @@ -59,7 +59,7 @@ // check that user defined attributes are supported by the file system FileStore store = file.getFileStore(); - if (!store.supportsFileAttributeView("xattr")) { + if (!store.supportsFileAttributeView("user")) { System.err.format("UserDefinedFileAttributeView not supported on %s\n", store); System.exit(-1);
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -26,8 +26,7 @@ package sun.nio.fs; import java.nio.file.attribute.*; -import java.util.*; -import java.util.concurrent.TimeUnit; +import java.util.Map; import java.io.IOException; import sun.misc.Unsafe; @@ -104,10 +103,10 @@ } @Override - public Map<String,?> readAttributes(String first, String[] rest) + public Map<String,?> 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 @@ 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 @@ return attrs.size(); } @Override - public int linkCount() { - return attrs.linkCount(); - } - @Override public Object fileKey() { return attrs.fileKey(); }
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java Sun Jun 28 23:16:18 2009 -0700 @@ -53,7 +53,7 @@ */ @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 @@ 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 @@ @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)
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java Sun Jun 28 23:16:18 2009 -0700 @@ -39,7 +39,6 @@ class LinuxFileSystem extends UnixFileSystem { private final boolean hasInotify; - private final boolean hasAtSysCalls; LinuxFileSystem(UnixFileSystemProvider provider, String dir) { super(provider, dir); @@ -47,14 +46,14 @@ // 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 @@ 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 @@ @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 @@ 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 @@ LinuxUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd); } - @Override - boolean supportsSecureDirectoryStreams() { - return hasAtSysCalls; - } - /** - * Returns object to iterate over entries in /etc/mtab + * Returns object to iterate over the mount entries in the given fstab file. */ - @Override - Iterable<UnixMountEntry> getMountEntries() { + Iterable<UnixMountEntry> getMountEntries(String fstab) { ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>(); 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 @@ return entries; } + /** + * Returns object to iterate over the mount entries in /etc/mtab + */ + @Override + Iterable<UnixMountEntry> getMountEntries() { + return getMountEntries("/etc/mtab"); + } + @Override FileStore getFileStore(UnixPath path) throws IOException { return new LinuxFileStore(path);
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java Sun Jun 28 23:16:18 2009 -0700 @@ -98,7 +98,7 @@ // 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;
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java Sun Jun 28 23:16:18 2009 -0700 @@ -83,7 +83,7 @@ // 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)
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java Sun Jun 28 23:16:18 2009 -0700 @@ -46,7 +46,7 @@ // 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 @@ } @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 @@ 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 @@ // TDB: copy ACL from source to target } - @Override - boolean supportsSecureDirectoryStreams() { - return true; - } - /** * Returns object to iterate over entries in /etc/mnttab */
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java Sun Jun 28 23:16:18 2009 -0700 @@ -49,13 +49,13 @@ 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 @@ * 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
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java Sun Jun 28 23:16:18 2009 -0700 @@ -30,6 +30,7 @@ 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 @@ 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 @@ // 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 @@ } 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);
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Sun Jun 28 23:16:18 2009 -0700 @@ -194,8 +194,11 @@ 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 @@ ((UnixSecureDirectoryStream)stream) .implDelete(entry.getName(), false, 0); } else { - entry.delete(true); + entry.delete(); } } catch (IOException ioe) { throwAsConcurrentModificationException(ioe);
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java Sun Jun 28 23:16:18 2009 -0700 @@ -56,11 +56,11 @@ 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,54 +68,50 @@ 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); + // uptime times + long modValue = lastModifiedTime.to(TimeUnit.MICROSECONDS); + long accessValue= lastAccessTime.to(TimeUnit.MICROSECONDS); + + boolean retry = false; + try { + futimes(fd, accessValue, modValue); + } catch (UnixException x) { + // 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 { - if (lastModifiedTime != -1L) - throw new IllegalArgumentException(); - modTime = System.currentTimeMillis(); + x.rethrowAsIOException(file); } } - - // 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(); + if (retry) { + if (modValue < 0L) modValue = 0L; + if (accessValue < 0L) accessValue= 0L; + try { + futimes(fd, accessValue, modValue); + } catch (UnixException x) { + x.rethrowAsIOException(file); } } - - try { - futimes(fd, accTime, modTime); - } catch (UnixException x) { - x.rethrowAsIOException(file); - } } finally { close(fd); } @@ -199,10 +195,10 @@ } @Override - public Map<String,?> readAttributes(String first, String[] rest) + public Map<String,?> 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 @@ 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 @@ 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 @@ } @Override - public Map<String,?> readAttributes(String first, String[] rest) + public Map<String,?> 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 @@ 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 @@ } } - 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)); } }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java Sun Jun 28 23:16:18 2009 -0700 @@ -97,9 +97,13 @@ 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 @@ } @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 @@ -157,11 +156,6 @@ } @Override - public int linkCount() { - return st_nlink; - } - - @Override public UnixFileKey fileKey() { if (key == null) { synchronized (this) { @@ -260,22 +254,18 @@ } @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 @@ return attrs.size(); } @Override - public int linkCount() { - return attrs.linkCount(); - } - @Override public Object fileKey() { return attrs.fileKey(); }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java Sun Jun 28 23:16:18 2009 -0700 @@ -53,4 +53,15 @@ 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(); + } }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java Sun Jun 28 23:16:18 2009 -0700 @@ -42,10 +42,7 @@ static final int TEMPFILE_PERMISSIONS = UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR; - private Set<PosixFilePermission> perms; - - UnixFileModeAttribute() { - perms = Collections.emptySet(); + private UnixFileModeAttribute() { } static int toUnixMode(Set<PosixFilePermission> perms) {
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java Sun Jun 28 23:16:18 2009 -0700 @@ -78,7 +78,7 @@ /** * 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 @@ @Override @SuppressWarnings("unchecked") - public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> viewType) + public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view) { - if (viewType == FileStoreSpaceAttributeView.class) + if (view == null) + throw new NullPointerException(); + if (view == FileStoreSpaceAttributeView.class) return (V) new UnixFileStoreSpaceAttributeView(this); return (V) 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<? extends FileAttributeView> type) { + if (type == null) + throw new NullPointerException(); if (type == BasicFileAttributeView.class) return true; if (type == PosixFileAttributeView.class || @@ -187,7 +198,7 @@ } private static class UnixFileStoreSpaceAttributeView - extends AbstractFileStoreSpaceAttributeView + implements FileStoreSpaceAttributeView { private final UnixFileStore fs; @@ -196,6 +207,11 @@ } @Override + public String name() { + return "space"; + } + + @Override public FileStoreSpaceAttributes readAttributes() throws IOException { @@ -275,7 +291,7 @@ 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 {
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Sun Jun 28 23:16:18 2009 -0700 @@ -137,13 +137,9 @@ * @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 @@ 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"))
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java Sun Jun 28 23:16:18 2009 -0700 @@ -93,7 +93,7 @@ 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 @@ } @Override - public final FileChannel newFileChannel(Path obj, - Set<? extends OpenOption> options, - FileAttribute<?>... attrs) + public FileChannel newFileChannel(Path obj, + Set<? extends OpenOption> options, + FileAttribute<?>... attrs) throws IOException { UnixPath file = checkPath(obj); @@ -119,10 +119,10 @@ } @Override - public final AsynchronousFileChannel newAsynchronousFileChannel(Path obj, - Set<? extends OpenOption> options, - ExecutorService executor, - FileAttribute<?>... attrs) throws IOException + public AsynchronousFileChannel newAsynchronousFileChannel(Path obj, + Set<? extends OpenOption> options, + ExecutorService executor, + FileAttribute<?>... attrs) throws IOException { UnixPath file = checkPath(obj); int mode = UnixFileModeAttribute
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java Sun Jun 28 23:16:18 2009 -0700 @@ -66,7 +66,7 @@ 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; }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java Sun Jun 28 23:16:18 2009 -0700 @@ -542,8 +542,17 @@ */ 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<Void>() { @@ -551,6 +560,8 @@ System.loadLibrary("nio"); return null; }}); - initIDs(); + int flags = init(); + + hasAtSysCalls = (flags & HAS_AT_SYSCALLS) > 0; } }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java Sun Jun 28 23:16:18 2009 -0700 @@ -28,7 +28,6 @@ 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 @@ 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 @@ 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 @@ char c = input.charAt(i); if ((c == '/') && (prevChar == '/')) continue; + checkNotNul(input, c); sb.append(c); prevChar = c; } @@ -862,7 +866,7 @@ } @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 @@ 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 @@ } @Override - public FileAttributeView getFileAttributeView(String name, LinkOption... options) { + public DynamicFileAttributeView getFileAttributeView(String name, + LinkOption... options) + { return getFileSystem().newFileAttributeView(name, this, options); } @@ -980,20 +987,8 @@ } @Override - public InputStream newInputStream()throws IOException { - try { - Set<OpenOption> options = Collections.emptySet(); - FileChannel fc = UnixChannelFactory.newFileChannel(this, options, 0); - return Channels.newInputStream(fc); - } catch (UnixException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - - @Override public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options, - FileAttribute<?>... attrs) + FileAttribute<?>... attrs) throws IOException { int mode = UnixFileModeAttribute @@ -1007,29 +1002,7 @@ } @Override - public OutputStream newOutputStream(Set<? extends OpenOption> options, - FileAttribute<?>... attrs) - throws IOException - { - // need to copy options to add WRITE - Set<OpenOption> opts = new HashSet<OpenOption>(options); - if (opts.contains(StandardOpenOption.READ)) - throw new IllegalArgumentException("READ not allowed"); - opts.add(StandardOpenOption.WRITE); - - int mode = UnixFileModeAttribute - .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); - try { - FileChannel fc = UnixChannelFactory.newFileChannel(this, opts, mode); - return Channels.newOutputStream(fc); - } catch (UnixException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - - @Override - public boolean isSameFile(FileRef obj) throws IOException { + public boolean isSameFile(Path obj) throws IOException { if (this.equals(obj)) return true; if (!(obj instanceof UnixPath)) // includes null check @@ -1188,13 +1161,6 @@ } result = result.resolve(element); } - - // finally check that file exists - try { - UnixFileAttributes.get(result, true); - } catch (UnixException x) { - x.rethrowAsIOException(result); - } return result; }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java Sun Jun 28 23:16:18 2009 -0700 @@ -40,7 +40,7 @@ */ class UnixSecureDirectoryStream - extends SecureDirectoryStream + extends SecureDirectoryStream<Path> { private final UnixDirectoryStream ds; private final int dfd; @@ -85,13 +85,13 @@ * Opens sub-directory in this directory */ @Override - public SecureDirectoryStream newDirectoryStream(Path obj, - boolean followLinks, - DirectoryStream.Filter<? super Path> filter) + public SecureDirectoryStream<Path> 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 @@ 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 @@ * 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<Path> dir, Path toObj) throws IOException { UnixPath from = getName(fromObj); @@ -310,14 +310,11 @@ * 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 @@ } @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 @@ 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 @@ 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); } @@ -482,59 +445,6 @@ } @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(PERMISSIONS_NAME)) - return readAttributes().permissions(); - if (attribute.equals(OWNER_NAME)) - return readAttributes().owner(); - if (attribute.equals(GROUP_NAME)) - return readAttributes().group(); - return super.getAttribute(attribute); - } - - @Override - @SuppressWarnings("unchecked") - public void setAttribute(String attribute, Object value) - throws IOException - { - if (attribute.equals(PERMISSIONS_NAME)) { - setPermissions((Set<PosixFilePermission>)value); - return; - } - if (attribute.equals(OWNER_NAME)) { - setOwner((UserPrincipal)value); - return; - } - if (attribute.equals(GROUP_NAME)) { - setGroup((GroupPrincipal)value); - return; - } - super.setAttribute(attribute, value); - } - - final void addPosixAttributesToBuilder(PosixFileAttributes attrs, - AttributesBuilder builder) - { - if (builder.match(PERMISSIONS_NAME)) - builder.add(PERMISSIONS_NAME, attrs.permissions()); - if (builder.match(OWNER_NAME)) - builder.add(OWNER_NAME, attrs.owner()); - if (builder.match(GROUP_NAME)) - builder.add(GROUP_NAME, attrs.group()); - } - - @Override - public Map<String,?> readAttributes(String first, String[] rest) - throws IOException - { - AttributesBuilder builder = AttributesBuilder.create(first, rest); - PosixFileAttributes attrs = readAttributes(); - addBasicAttributesToBuilder(attrs, builder); - addPosixAttributesToBuilder(attrs, builder); - return builder.unmodifiableMap(); - } - - @Override public PosixFileAttributes readAttributes() throws IOException { SecurityManager sm = System.getSecurityManager(); if (sm != null) {
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java Sun Jun 28 23:16:18 2009 -0700 @@ -147,8 +147,14 @@ } 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; }
--- a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c Sun Jun 28 23:16:18 2009 -0700 @@ -92,14 +92,12 @@ 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 @@ } /** - * 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 @@ 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 @@ 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 @@ 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 @@ (*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 @@ 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 @@ 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 @@ 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); }
--- a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c Sun Jun 28 23:16:18 2009 -0700 @@ -66,16 +66,6 @@ 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 @@ 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;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Sun Jun 28 23:16:18 2009 -0700 @@ -93,6 +93,7 @@ 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;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java Sun Jun 28 23:16:18 2009 -0700 @@ -152,11 +152,13 @@ } 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 @@ prevEntry = null; } try { - entry.delete(true); + entry.delete(); } catch (IOException ioe) { throwAsConcurrentModificationException(ioe); } catch (SecurityException se) {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Sun Jun 28 23:16:18 2009 -0700 @@ -28,7 +28,6 @@ import java.nio.file.attribute.*; import java.util.*; -import java.util.concurrent.TimeUnit; import java.io.IOException; import static sun.nio.fs.WindowsNativeDispatcher.*; @@ -56,9 +55,24 @@ } /** + * 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 @@ 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 @@ 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 @@ } @Override - public Map<String,?> readAttributes(String first, String[] rest) + public Map<String,?> 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 @@ } } - 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); } }
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java Sun Jun 28 23:16:18 2009 -0700 @@ -65,7 +65,6 @@ 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 @@ 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 @@ 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 @@ long lastWriteTime, long size, int reparseTag, - int linkCount, int volSerialNumber, int fileIndexHigh, int fileIndexLow) @@ -173,7 +178,6 @@ 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 @@ */ 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 @@ lastWriteTime, size, reparseTag, - linkCount, volSerialNumber, fileIndexHigh, fileIndexLow); @@ -213,12 +212,9 @@ */ 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 @@ lastWriteTime, size, reparseTag, - 1, // linkCount 0, // volSerialNumber 0, // fileIndexHigh 0); // fileIndexLow @@ -246,12 +241,9 @@ */ 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 @@ lastWriteTime, size, reparseTag, - 1, // linkCount 0, // volSerialNumber 0, // fileIndexHigh 0); // fileIndexLow @@ -375,28 +366,18 @@ } @Override - public long lastModifiedTime() { - return (lastWriteTime >= 0L) ? lastWriteTime : 0L; - } - - @Override - public long lastAccessTime() { - return (lastAccessTime >= 0L) ? lastAccessTime : 0L; + public FileTime lastModifiedTime() { + return toFileTime(lastWriteTime); } @Override - public long creationTime() { - return (creationTime >= 0L) ? creationTime : 0L; + public FileTime lastAccessTime() { + return toFileTime(lastAccessTime); } @Override - public TimeUnit resolution() { - return TimeUnit.MILLISECONDS; - } - - @Override - public int linkCount() { - return linkCount; + public FileTime creationTime() { + return toFileTime(creationTime); } @Override
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java Sun Jun 28 23:16:18 2009 -0700 @@ -27,7 +27,6 @@ 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 @@ @Override @SuppressWarnings("unchecked") - public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view) { - if (view == FileStoreSpaceAttributeView.class) + public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> 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<? extends FileAttributeView> type) { + if (type == null) + throw new NullPointerException(); if (type == BasicFileAttributeView.class) return true; if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class) @@ -154,7 +170,7 @@ 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 @@ } static class WindowsFileStoreAttributeView - extends AbstractFileStoreSpaceAttributeView + implements FileStoreSpaceAttributeView { private final WindowsFileStore fs; @@ -197,6 +213,11 @@ } @Override + public String name() { + return "space"; + } + + @Override public FileStoreSpaceAttributes readAttributes() throws IOException { @@ -225,113 +246,4 @@ }; } } - - /** - * Windows-specific attribute view to allow access to volume information. - */ - static class VolumeFileStoreAttributeView - implements FileStoreAttributeView - { - private static final String VSN_NAME = "vsn"; - private static final String COMPRESSED_NAME = "compressed"; - private static final String REMOVABLE_NAME = "removable"; - private static final String CDROM_NAME = "cdrom"; - - private final WindowsFileStore fs; - - VolumeFileStoreAttributeView(WindowsFileStore fs) { - this.fs = fs; - } - - @Override - public String name() { - return "volume"; - } - - private int vsn() { - return fs.volumeInformation().volumeSerialNumber(); - } - - private boolean isCompressed() { - return (fs.volumeInformation().flags() & - FILE_VOLUME_IS_COMPRESSED) > 0; - } - - private boolean isRemovable() { - return fs.volumeType() == DRIVE_REMOVABLE; - } - - private boolean isCdrom() { - return fs.volumeType() == DRIVE_CDROM; - } - - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(VSN_NAME)) - return vsn(); - if (attribute.equals(COMPRESSED_NAME)) - return isCompressed(); - if (attribute.equals(REMOVABLE_NAME)) - return isRemovable(); - if (attribute.equals(CDROM_NAME)) - return isCdrom(); - return null; - } - - @Override - public void setAttribute(String attribute, Object value) - throws IOException - { - throw new UnsupportedOperationException(); - } - - @Override - public Map<String,?> readAttributes(String first, String... rest) - throws IOException - { - boolean all = false; - boolean vsn = false; - boolean compressed = false; - boolean removable = false; - boolean cdrom = false; - - if (first.equals(VSN_NAME)) vsn = true; - else if (first.equals(COMPRESSED_NAME)) compressed = true; - else if (first.equals(REMOVABLE_NAME)) removable = true; - else if (first.equals(CDROM_NAME)) cdrom = true; - else if (first.equals("*")) all = true; - - if (!all) { - for (String attribute: rest) { - if (attribute.equals("*")) { - all = true; - break; - } - if (attribute.equals(VSN_NAME)) { - vsn = true; - continue; - } - if (attribute.equals(COMPRESSED_NAME)) { - compressed = true; - continue; - } - if (attribute.equals(REMOVABLE_NAME)) { - removable = true; - continue; - } - } - } - - Map<String,Object> result = new HashMap<String,Object>(); - if (all || vsn) - result.put(VSN_NAME, vsn()); - if (all || compressed) - result.put(COMPRESSED_NAME, isCompressed()); - if (all || removable) - result.put(REMOVABLE_NAME, isRemovable()); - if (all || cdrom) - result.put(CDROM_NAME, isCdrom()); - return result; - } - } -} + }
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java Sun Jun 28 23:16:18 2009 -0700 @@ -63,7 +63,7 @@ PrivilegedAction<String> 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 @@ // supported views private static final Set<String> supportedFileAttributeViews = Collections - .unmodifiableSet(new HashSet<String>(Arrays.asList("basic", "dos", "acl", "owner", "xattr"))); + .unmodifiableSet(new HashSet<String>(Arrays.asList("basic", "dos", "acl", "owner", "user"))); @Override public Set<String> supportedFileAttributeViews() {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Sun Jun 28 23:16:18 2009 -0700 @@ -76,7 +76,7 @@ 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(); }
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Sun Jun 28 23:16:18 2009 -0700 @@ -379,8 +379,11 @@ * 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(
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Sun Jun 28 23:16:18 2009 -0700 @@ -27,7 +27,6 @@ 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 @@ public void invalidate() { ref.clear(); } + + // no need to override equals/hashCode. } // use this message when throwing exceptions @@ -948,7 +949,7 @@ } @Override - public void delete(boolean failIfNotExists) throws IOException { + void implDelete(boolean failIfNotExists) throws IOException { checkDelete(); WindowsFileAttributes attrs = null; @@ -1040,7 +1041,7 @@ } @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 @@ 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; } @@ -1073,22 +1074,6 @@ } @Override - public InputStream newInputStream()throws IOException { - try { - Set<OpenOption> options = Collections.emptySet(); - FileChannel fc = WindowsChannelFactory - .newFileChannel(getPathForWin32Calls(), - getPathForPermissionCheck(), - options, - 0L); - return Channels.newInputStream(fc); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - - @Override public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException @@ -1110,36 +1095,7 @@ } @Override - public OutputStream newOutputStream(Set<? extends OpenOption> options, - FileAttribute<?>... attrs) - throws IOException - { - // need to copy options to add WRITE - Set<OpenOption> opts = new HashSet<OpenOption>(options); - if (opts.contains(StandardOpenOption.READ)) - throw new IllegalArgumentException("READ not allowed"); - opts.add(StandardOpenOption.WRITE); - - WindowsSecurityDescriptor sd = - WindowsSecurityDescriptor.fromAttribute(attrs); - FileChannel fc; - try { - fc = WindowsChannelFactory - .newFileChannel(getPathForWin32Calls(), - getPathForPermissionCheck(), - opts, - sd.address()); - return Channels.newOutputStream(fc); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } finally { - sd.release(); - } - } - - @Override - public boolean isSameFile(FileRef obj) throws IOException { + public boolean isSameFile(Path obj) throws IOException { if (this.equals(obj)) return true; if (!(obj instanceof WindowsPath)) // includes null check @@ -1216,7 +1172,7 @@ * 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"); } /*
--- a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Sun Jun 28 23:16:18 2009 -0700 @@ -560,9 +560,9 @@ 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()); }
--- a/jdk/test/java/nio/file/DirectoryStream/Basic.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/DirectoryStream/Basic.java Sun Jun 28 23:16:18 2009 -0700 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.DirectoryStream * @library .. */ @@ -38,20 +38,23 @@ DirectoryStream<Path> stream; // test that directory is empty - Files.withDirectory(dir, new FileAction<FileRef>() { - 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<Path>() { - 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 @@ " not expected"); } } - }); + } finally { + stream.close(); + } if (!found) throw new RuntimeException("entry not found"); @@ -73,12 +78,15 @@ return matcher.matches(file); } }; - Files.withDirectory(dir, filter, new FileAction<Path>() { - 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<Path>() { @@ -88,11 +96,31 @@ return matcher.matches(file); } }; - Files.withDirectory(dir, filter, new FileAction<FileRef>() { - 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<Path>() { + public boolean accept(Path file) throws IOException { + throw new IOException(); } - }); + }; + stream = dir.newDirectoryStream(filter); + try { + stream.iterator().hasNext(); + throw new RuntimeException("ConcurrentModificationException expected"); + } catch (ConcurrentModificationException x) { + Throwable t = x.getCause(); + if (!(t instanceof IOException)) + throw new RuntimeException("Cause is not IOException as expected"); + } finally { + stream.close(); + } // check that exception or error thrown by filter is not thrown // by newDirectoryStream or iterator method.
--- a/jdk/test/java/nio/file/DirectoryStream/Filters.java Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -/* @test - * @bug 4313887 - * @summary Unit test for java.nio.file.DirectoryStreamFilters - * @library .. - */ - -import java.nio.file.*; -import static java.nio.file.DirectoryStreamFilters.*; -import java.nio.file.attribute.Attributes; -import java.io.*; -import java.util.*; - -public class Filters { - static final Random rand = new Random(); - - // returns a filter that only accepts files that are larger than a given size - static DirectoryStream.Filter<FileRef> newMinimumSizeFilter(final long min) { - return new DirectoryStream.Filter<FileRef>() { - public boolean accept(FileRef file) { - try { - long size = Attributes.readBasicFileAttributes(file).size(); - return size >= min; - } catch (IOException e) { - throw new IOError(e); - } - } - }; - } - - // returns a filter that only accepts files that are matched by a given glob - static DirectoryStream.Filter<Path> newGlobFilter(final String glob) { - return new DirectoryStream.Filter<Path>() { - PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:"+ glob); - public boolean accept(Path file) { - return matcher.matches(file.getName()); - } - }; - } - - static final int BIG_FILE_THRESHOLD = 8192; - - static int totalCount; - static int htmlCount; - static int bigAndHtmlCount; - static int bigOrHtmlCount; - - // generates random files in the test directory and initializes the counts - static void setup(Path dir) throws IOException { - // create 10-26 files. - totalCount = 10 + rand.nextInt(17); - char firstChar = 'A'; - for (int i=0; i<totalCount; i++) { - boolean isHtml = rand.nextBoolean(); - boolean isBig = rand.nextBoolean(); - if (isHtml) { - htmlCount++; - if (isBig) bigAndHtmlCount++; - } - if (isHtml || isBig) - bigOrHtmlCount++; - String name; - if (isHtml) { - name = firstChar + ".html"; - } else { - name = firstChar + ".tmp"; - } - firstChar++; - int size = rand.nextInt(BIG_FILE_THRESHOLD); - if (isBig) - size += BIG_FILE_THRESHOLD; - Path file = dir.resolve(name); - OutputStream out = file.newOutputStream(); - try { - if (size > 0) - out.write(new byte[size]); - } finally { - out.close(); - } - System.out.format("Created %s, size %d byte(s)\n", name, size); - } - } - - static boolean isHtml(Path file) { - return file.toString().endsWith(".html"); - } - - static boolean isBig(Path file) throws IOException { - long size = Attributes.readBasicFileAttributes(file).size(); - return size >= BIG_FILE_THRESHOLD; - } - - static void checkCount(int expected, int actual) { - if (actual != expected) - throw new RuntimeException("'" + expected + - "' entries expected, actual: " + actual); - } - - static void doTests(Path dir) throws IOException { - final List<DirectoryStream.Filter<Path>> emptyList = Collections.emptyList(); - - // list containing two filters - List<DirectoryStream.Filter<? super Path>> filters = - new ArrayList<DirectoryStream.Filter<? super Path>>(); - filters.add(newMinimumSizeFilter(BIG_FILE_THRESHOLD)); - filters.add(newGlobFilter("*.html")); - - int accepted; - DirectoryStream<Path> stream; - - System.out.println("Test: newContentTypeFilter"); - accepted = 0; - stream = dir.newDirectoryStream(newContentTypeFilter("text/html")); - try { - for (Path entry: stream) { - if (!isHtml(entry)) - throw new RuntimeException("html file expected"); - accepted++; - } - } finally { - stream.close(); - } - checkCount(htmlCount, accepted); - - System.out.println("Test: allOf with list of filters"); - accepted = 0; - stream = dir.newDirectoryStream(allOf(filters)); - try { - for (Path entry: stream) { - if (!isHtml(entry)) - throw new RuntimeException("html file expected"); - if (!isBig(entry)) - throw new RuntimeException("big file expected"); - accepted++; - } - } finally { - stream.close(); - } - checkCount(bigAndHtmlCount, accepted); - - System.out.println("Test: allOf with empty list"); - accepted = 0; - stream = dir.newDirectoryStream(allOf(emptyList)); - try { - for (Path entry: stream) { - accepted++; - } - } finally { - stream.close(); - } - checkCount(totalCount, accepted); - - System.out.println("Test: anyOf with list of filters"); - accepted = 0; - stream = dir.newDirectoryStream(anyOf(filters)); - try { - for (Path entry: stream) { - if (!isHtml(entry) && !isBig(entry)) - throw new RuntimeException("html or big file expected"); - accepted++; - } - } finally { - stream.close(); - } - checkCount(bigOrHtmlCount, accepted); - - System.out.println("Test: anyOf with empty list"); - accepted = 0; - stream = dir.newDirectoryStream(anyOf(emptyList)); - try { - for (Path entry: stream) { - accepted++; - } - } finally { - stream.close(); - } - checkCount(0, accepted); - - System.out.println("Test: complementOf"); - accepted = 0; - stream = dir.newDirectoryStream(complementOf(newGlobFilter("*.html"))); - try { - for (Path entry: stream) { - accepted++; - } - } finally { - stream.close(); - } - checkCount(totalCount-htmlCount, accepted); - - System.out.println("Test: nulls"); - try { - newContentTypeFilter(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - try { - allOf(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - try { - anyOf(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - try { - complementOf(null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException npe) { } - } - - public static void main(String[] args) throws IOException { - Path dir = TestUtil.createTemporaryDirectory(); - try { - setup(dir); - doTests(dir); - } finally { - TestUtil.removeAll(dir); - } - } -}
--- a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java Sun Jun 28 23:16:18 2009 -0700 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.SecureDirectoryStream * @library .. */ @@ -41,7 +41,7 @@ public static void main(String[] args) throws IOException { Path dir = TestUtil.createTemporaryDirectory(); try { - DirectoryStream stream = dir.newDirectoryStream(); + DirectoryStream<Path> stream = dir.newDirectoryStream(); stream.close(); if (!(stream instanceof SecureDirectoryStream)) { System.out.println("SecureDirectoryStream not supported."); @@ -81,8 +81,8 @@ // open directory and then move it so that it is no longer accessible // via its original path. - SecureDirectoryStream stream = - (SecureDirectoryStream)dir1.newDirectoryStream(); + SecureDirectoryStream<Path> stream = + (SecureDirectoryStream<Path>)dir1.newDirectoryStream(); dir1.moveTo(dir2); // Test: iterate over all entries @@ -96,18 +96,6 @@ .readAttributes() .isDirectory()); - // Test: dynamic access to directory's attributes - BasicFileAttributeView view = stream. - getFileAttributeView(BasicFileAttributeView.class); - Map<String,?> attrs = view.readAttributes("*"); - assertTrue((Boolean)attrs.get("isDirectory")); - attrs = view.readAttributes("isRegularFile", "size"); - assertTrue(!(Boolean)attrs.get("isRegularFile")); - assertTrue((Long)attrs.get("size") >= 0); - int linkCount = (Integer)view.getAttribute("linkCount"); - assertTrue(linkCount > 0); - view.setAttribute("lastModifiedTime", 0L); - // Test: getFileAttributeView to access attributes of entries assertTrue(stream .getFileAttributeView(fileEntry, BasicFileAttributeView.class) @@ -144,17 +132,6 @@ .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<StandardOpenOption> opts = Collections.emptySet(); stream.newByteChannel(fileEntry, opts).close(); @@ -170,12 +147,13 @@ } // 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 @@ stream.close(); dir2.moveTo(dir1); dir1.resolve(fileEntry).createFile(); - stream = (SecureDirectoryStream)dir1.newDirectoryStream(); + stream = (SecureDirectoryStream<Path>)dir1.newDirectoryStream(); dir1.moveTo(dir2); Iterator<Path> iter = stream.iterator(); int removed = 0; @@ -227,10 +205,10 @@ Path target = Paths.get("newfile"); // open stream to both directories - SecureDirectoryStream stream1 = - (SecureDirectoryStream)dir1.newDirectoryStream(); - SecureDirectoryStream stream2 = - (SecureDirectoryStream)dir2.newDirectoryStream(); + SecureDirectoryStream<Path> stream1 = + (SecureDirectoryStream<Path>)dir1.newDirectoryStream(); + SecureDirectoryStream<Path> stream2 = + (SecureDirectoryStream<Path>)dir2.newDirectoryStream(); // Test: move dir1/myfile -> dir2/newfile stream1.move(fileEntry, stream2, target); @@ -259,8 +237,8 @@ if (testDirAsString != null) { Path testDir = Paths.get(testDirAsString); if (!dir1.getFileStore().equals(testDir.getFileStore())) { - SecureDirectoryStream ts = - (SecureDirectoryStream)testDir.newDirectoryStream(); + SecureDirectoryStream<Path> ts = + (SecureDirectoryStream<Path>)testDir.newDirectoryStream(); dir1.resolve(fileEntry).createFile(); try { stream1.move(fileEntry, ts, target); @@ -281,8 +259,8 @@ Path file = Paths.get("file"); dir.resolve(file).createFile(); - SecureDirectoryStream stream = - (SecureDirectoryStream)dir.newDirectoryStream(); + SecureDirectoryStream<Path> stream = + (SecureDirectoryStream<Path>)dir.newDirectoryStream(); // NullPointerException try { @@ -322,7 +300,7 @@ shouldNotGetHere(); } catch (NullPointerException x) { } try { - stream.newDirectoryStream(null, true, null); + stream.newDirectoryStream(null); shouldNotGetHere(); } catch (NullPointerException x) { } try { @@ -340,7 +318,7 @@ // ClosedDirectoryStreamException try { - stream.newDirectoryStream(file, true, null); + stream.newDirectoryStream(file); shouldNotGetHere(); } catch (ClosedDirectoryStreamException x) { } try {
--- a/jdk/test/java/nio/file/FileSystem/Basic.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/FileSystem/Basic.java Sun Jun 28 23:16:18 2009 -0700 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.FileSystem * @library .. */ @@ -73,10 +73,10 @@ 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"); } }
--- a/jdk/test/java/nio/file/Files/ContentType.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Files/ContentType.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ 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 @@ 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 @@ 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 @@ if (!type.equals("grape/unknown")) throw new RuntimeException("Unexpected type: " + type); } finally { - TestUtil.deleteUnchecked(file); + file.delete(); } }
--- a/jdk/test/java/nio/file/Files/Misc.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Files/Misc.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 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<Path>() { - public void invoke(Path entry) { - } - }); - npeExpected(); - } catch (NullPointerException e) { - } - - try { - Files.withDirectory(Paths.get("."), (String)null, new FileAction<Path>() { - public void invoke(Path entry) { - } - }); - npeExpected(); - } catch (NullPointerException e) { - } - - try { - Files.withDirectory(Paths.get("."), "*", null); - npeExpected(); - } catch (NullPointerException e) { - } - - // test propogation of IOException - Path tmpdir = TestUtil.createTemporaryDirectory(); - try { - tmpdir.resolve("foo").createFile(); - try { - Files.withDirectory(tmpdir, new FileAction<Path>() { - public void invoke(Path entry) throws IOException { - throw new IOException(); - } - }); - throw new RuntimeException("IOException expected"); - } catch (IOException e) { - } - } finally { - TestUtil.removeAll(tmpdir); - } - try { Files.walkFileTree(null, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, new SimpleFileVisitor<Path>(){}); npeExpected(); } catch (NullPointerException e) { } - try { Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE, new SimpleFileVisitor<Path>(){}); npeExpected(); } catch (NullPointerException e) { } - try { Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), -1, new SimpleFileVisitor<Path>(){}); throw new RuntimeException("IllegalArgumentExpected expected"); } catch (IllegalArgumentException e) { } - try { Set<FileVisitOption> opts = new HashSet<FileVisitOption>(1); opts.add(null); @@ -115,7 +107,6 @@ npeExpected(); } catch (NullPointerException e) { } - try { Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, null);
--- a/jdk/test/java/nio/file/Files/content_type.sh Sun Jun 28 00:00:25 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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
--- a/jdk/test/java/nio/file/Path/CopyAndMove.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Path/CopyAndMove.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/nio/file/Path/FileAttributes.java Sun Jun 28 23:16:18 2009 -0700 @@ -0,0 +1,264 @@ +/* + * 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 6838333 + * @summary Unit test for java.nio.file.Path + * @library .. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Exercises getAttribute/setAttribute/readAttributes methods. + */ + +public class FileAttributes { + + static void assertTrue(boolean okay) { + if (!okay) + throw new RuntimeException("Assertion Failed"); + } + + static void checkEqual(Object o1, Object o2) { + if (o1 == null) { + assertTrue(o2 == null); + } else { + assertTrue (o1.equals(o2)); + } + } + + // 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(), 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 + 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); + + Map<String,?> map; + map = file.readAttributes("*"); + assertTrue(map.size() >= 9); + checkEqual(attrs.isRegularFile(), map.get("isRegularFile")); // check one + + map = file.readAttributes("basic:*"); + assertTrue(map.size() >= 9); + checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); // check one + + map = file.readAttributes("size,lastModifiedTime"); + assertTrue(map.size() == 2); + checkEqual(attrs.size(), map.get("size")); + checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); + + map = file.readAttributes( + "basic:lastModifiedTime,lastAccessTime,ShouldNotExist"); + assertTrue(map.size() == 2); + checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); + checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); + } + + // Exercise getAttribute/setAttribute/readAttributes on posix attributes + static void checkPosixAttributes(FileRef file, PosixFileAttributes attrs) + throws IOException + { + checkBasicAttributes(file, attrs); + + // getAttribute + checkEqual(attrs.permissions(), file.getAttribute("posix:permissions")); + checkEqual(attrs.owner(), file.getAttribute("posix:owner")); + checkEqual(attrs.group(), file.getAttribute("posix:group")); + + // setAttribute + Set<PosixFilePermission> orig = attrs.permissions(); + Set<PosixFilePermission> newPerms = new HashSet<PosixFilePermission>(orig); + newPerms.remove(PosixFilePermission.OTHERS_READ); + newPerms.remove(PosixFilePermission.OTHERS_WRITE); + newPerms.remove(PosixFilePermission.OTHERS_EXECUTE); + file.setAttribute("posix:permissions", newPerms); + checkEqual(Attributes.readPosixFileAttributes(file).permissions(), newPerms); + file.setAttribute("posix:permissions", orig); + checkEqual(Attributes.readPosixFileAttributes(file).permissions(), orig); + file.setAttribute("posix:owner", attrs.owner()); + file.setAttribute("posix:group", attrs.group()); + + // readAttributes + Map<String,?> map; + map = file.readAttributes("posix:*"); + assertTrue(map.size() >= 12); + checkEqual(attrs.permissions(), map.get("permissions")); // check one + + 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/readAttributes on unix attributes + static void checkUnixAttributes(FileRef file) throws IOException { + // getAttribute + 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<String,?> map; + map = file.readAttributes("unix:*"); + assertTrue(map.size() >= 20); + + map = file.readAttributes("unix:size,uid,gid,ShouldNotExist"); + assertTrue(map.size() == 3); + checkEqual(map.get("size"), + Attributes.readBasicFileAttributes(file).size()); + } + + // Exercise getAttribute/setAttribute on dos attributes + static void checkDosAttributes(FileRef file, DosFileAttributes attrs) + throws IOException + { + checkBasicAttributes(file, attrs); + + // getAttribute + 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(); + file.setAttribute("dos:readonly", !value); + checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), !value); + file.setAttribute("dos:readonly", value); + checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), value); + + value = attrs.isHidden(); + file.setAttribute("dos:hidden", !value); + checkEqual(Attributes.readDosFileAttributes(file).isHidden(), !value); + file.setAttribute("dos:hidden", value); + checkEqual(Attributes.readDosFileAttributes(file).isHidden(), value); + + value = attrs.isSystem(); + file.setAttribute("dos:system", !value); + checkEqual(Attributes.readDosFileAttributes(file).isSystem(), !value); + file.setAttribute("dos:system", value); + checkEqual(Attributes.readDosFileAttributes(file).isSystem(), value); + + value = attrs.isArchive(); + file.setAttribute("dos:archive", !value); + checkEqual(Attributes.readDosFileAttributes(file).isArchive(), !value); + file.setAttribute("dos:archive", value); + checkEqual(Attributes.readDosFileAttributes(file).isArchive(), value); + + // readAttributes + Map<String,?> map; + map = file.readAttributes("dos:*"); + assertTrue(map.size() >= 13); + checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one + + 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(); + try { + checkBasicAttributes(file, + Attributes.readBasicFileAttributes(file)); + + if (store.supportsFileAttributeView("posix")) + checkPosixAttributes(file, + Attributes.readPosixFileAttributes(file)); + + if (store.supportsFileAttributeView("unix")) + checkUnixAttributes(file); + + if (store.supportsFileAttributeView("dos")) + checkDosAttributes(file, + Attributes.readDosFileAttributes(file)); + + miscTests(file); + } finally { + file.delete(); + } + } + + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + doTests(dir); + } finally { + TestUtil.removeAll(dir); + } + } +}
--- a/jdk/test/java/nio/file/Path/Links.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Path/Links.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ 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(); }
--- a/jdk/test/java/nio/file/Path/Misc.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Path/Misc.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ 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<FileAttributeView>)null); } catch (NullPointerException ignore) { } @@ -227,15 +222,6 @@ 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 { } @@ -272,6 +258,16 @@ } /** + * 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 "." */ assertTrue(dir.resolve(".").toRealPath(true).equals(dir.toRealPath(true))); @@ -358,7 +354,7 @@ } } } finally { - thisFile.delete(false); + thisFile.delete(); } } @@ -372,7 +368,7 @@ if (isWindows) { file.createFile(); try { - Attributes.setAttribute(file, "dos:hidden", true); + file.setAttribute("dos:hidden", true); assertTrue(file.isHidden()); } finally { file.delete();
--- a/jdk/test/java/nio/file/Path/PathOps.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Path/PathOps.java Sun Jun 28 23:16:18 2009 -0700 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 6838333 * @summary Unit test for java.nio.file.Path path operations */ @@ -687,7 +687,17 @@ .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
--- a/jdk/test/java/nio/file/Path/TemporaryFiles.java Sun Jun 28 00:00:25 2009 -0700 +++ b/jdk/test/java/nio/file/Path/TemporaryFiles.java Sun Jun 28 23:16:18 2009 -0700 @@ -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 @@ } } + static void checkDirectory(Path dir) throws IOException { + // check directory is in temporary directory + checkInTempDirectory(dir); + +