changeset 1330:424420bf5917

Merge
author michaelm
date Mon, 29 Jun 2009 15:08:52 +0100
parents 89b14d3740dc (current diff) a44009aba19f (diff)
children d926534a1c17 1cc9eb0c952e b22f9e823be7
files src/share/classes/java/nio/file/DirectoryStreamFilters.java src/share/classes/java/nio/file/FileAction.java src/share/classes/java/nio/file/spi/AbstractPath.java src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java src/share/classes/sun/nio/fs/MimeType.java test/java/nio/file/DirectoryStream/Filters.java test/java/nio/file/Files/content_type.sh test/java/nio/file/Path/temporary_files.sh test/java/nio/file/attribute/Attributes/Basic.java
diffstat 136 files changed, 3900 insertions(+), 4295 deletions(-) [+]
line wrap: on
line diff
--- a/make/com/sun/nio/sctp/mapfile-vers	Mon Jun 29 15:05:15 2009 +0100
+++ b/make/com/sun/nio/sctp/mapfile-vers	Mon Jun 29 15:08:52 2009 +0100
@@ -27,6 +27,7 @@
 	global:
 		Java_sun_nio_ch_SctpNet_socket0;
 		Java_sun_nio_ch_SctpNet_bindx;
+		Java_sun_nio_ch_SctpNet_branch0;
 		Java_sun_nio_ch_SctpNet_getLocalAddresses0;
 		Java_sun_nio_ch_SctpNet_getRemoteAddresses0;
 		Java_sun_nio_ch_SctpNet_getPrimAddrOption0;
--- a/make/java/java/FILES_java.gmk	Mon Jun 29 15:05:15 2009 +0100
+++ b/make/java/java/FILES_java.gmk	Mon Jun 29 15:08:52 2009 +0100
@@ -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/make/java/nio/FILES_java.gmk	Mon Jun 29 15:05:15 2009 +0100
+++ b/make/java/nio/FILES_java.gmk	Mon Jun 29 15:08:52 2009 +0100
@@ -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/make/java/nio/mapfile-linux	Mon Jun 29 15:05:15 2009 +0100
+++ b/make/java/nio/mapfile-linux	Mon Jun 29 15:08:52 2009 +0100
@@ -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/make/java/nio/mapfile-solaris	Mon Jun 29 15:05:15 2009 +0100
+++ b/make/java/nio/mapfile-solaris	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/io/File.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/io/File.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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,&nbsp;suffix,&nbsp;null)}</code>.
      *
+     * <p> The {@link #createTemporaryFile(String,String,FileAttribute[])} method
+     * provides an alternative method to create an empty file in the
+     * temporary-file directory. Files created by that method may have more
+     * restrictive access permissions to files created by this method and so
+     * may be more suited to security-sensitive applications.
+     *
      * @param  prefix     The prefix string to be used in generating the file's
      *                    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,&nbsp;suffix)} method with the addition that the
-     * resulting pathname may be requested to be deleted when the Java virtual
-     * machine terminates, and the initial file attributes to set atomically
-     * when creating the file may be specified.
-     *
-     * <p> When the value of the {@code deleteOnExit} method is {@code true}
-     * then the resulting file is requested to be deleted when the Java virtual
-     * machine terminates as if by invoking the {@link #deleteOnExit deleteOnExit}
-     * method.
+     * 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/src/share/classes/java/io/TempFileHelper.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/lang/annotation/ElementType.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/lang/annotation/ElementType.java	Mon Jun 29 15:08:52 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
@@ -40,6 +40,12 @@
     /** Class, interface (including annotation type), or enum declaration */
     TYPE,
 
+    /** Uses of a type */
+    TYPE_USE,
+
+    /** type parameters */
+    TYPE_PARAMETER,
+
     /** Field declaration (includes enum constants) */
     FIELD,
 
--- a/src/share/classes/java/lang/management/PlatformComponent.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/lang/management/PlatformComponent.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/Bits.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/Bits.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/Direct-X-Buffer.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/Direct-X-Buffer.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/channels/SeekableByteChannel.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/channels/SeekableByteChannel.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/AccessMode.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/AccessMode.java	Mon Jun 29 15:08:52 2009 +0100
@@ -30,7 +30,7 @@
  *
  * @since 1.7
  *
- * @see FileRef#checkAccess
+ * @see Path#checkAccess
  */
 
 public enum AccessMode {
--- a/src/share/classes/java/nio/file/DirectoryStream.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/DirectoryStream.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/DirectoryStreamFilters.java	Mon Jun 29 15:05:15 2009 +0100
+++ /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&nbsp;2045: Multipurpose
-     * Internet Mail Extensions (MIME) Part One: Format of Internet Message
-     * Bodies</i></a>. It is parsable according to the grammar in the RFC. Any
-     * space characters (<code>'&#92;u0020'</code>) surrounding its components are
-     * ignored. The {@code type} parameter is parsed into its primary and subtype
-     * components which are used to match the primary and subtype components of
-     * each directory entry's content type. Parameters are not allowed. The
-     * primary type matches if it has value {@code '*'} or is equal to the
-     * primary type of the directory entry's content type without regard to
-     * case. The subtype matches if has the value {@code '*'} or is equal to the
-     * subtype of the directory entry's content type without regard to case. If
-     * both the primary and subtype match then the filter's {@code accept} method
-     * returns {@code true}. If the content type of a directory entry cannot be
-     * determined then the entry is filtered.
-     *
-     * <p> The {@code accept} method of the resulting directory stream filter
-     * throws {@link IOError} if the probing of the content type fails by
-     * throwing an {@link IOException}. Security exceptions are also propogated
-     * to the caller of the {@code accept} method.
-     *
-     * <p> <b>Usage Example:</b>
-     * Suppose we require to list only the HTML files in a directory.
-     * <pre>
-     *     DirectoryStream.Filter&lt;FileRef&gt; filter =
-     *         DirectoryStreamFilters.newContentTypeFilter("text/html");
-     * </pre>
-     *
-     * @param   type
-     *          the content type
-     *
-     * @return  a new directory stream filter
-     *
-     * @throws  IllegalArgumentException
-     *          if the {@code type} parameter cannot be parsed as a MIME type
-     *          or it has parameters
-     */
-    public static <T extends FileRef> DirectoryStream.Filter<T>
-        newContentTypeFilter(String type)
-    {
-        final MimeType matchType = MimeType.parse(type);
-        if (matchType.hasParameters())
-            throw new IllegalArgumentException("Parameters not allowed");
-        return new DirectoryStream.Filter<T>() {
-            @Override
-            public boolean accept(T entry) {
-                String fileType;
-                try {
-                    fileType = Files.probeContentType(entry);
-                } catch (IOException x) {
-                    throw new IOError(x);
-                }
-                if (fileType != null) {
-                    return matchType.match(fileType);
-                }
-                return false;
-            }
-        };
-    }
-
-    /**
-     * Returns a directory stream filter that {@link DirectoryStream.Filter#accept
-     * accepts} a directory entry if the entry is accepted by all of the given
-     * filters.
-     *
-     * <p> This method returns a filter that invokes, in iterator order, the
-     * {@code accept} method of each of the filters. If {@code false} is returned
-     * by any of the filters then the directory entry is filtered. If the
-     * directory entry is not filtered then the resulting filter accepts the
-     * entry. If the iterator returns zero elements then the resulting filter
-     * accepts all directory entries.
-     *
-     * <p> <b>Usage Example:</b>
-     * <pre>
-     *     List&lt;DirectoryStream.Filter&lt;? super Path&gt;&gt; filters = ...
-     *     DirectoryStream.Filter&lt;Path&gt; filter = DirectoryStreamFilters.allOf(filters);
-     * </pre>
-     *
-     * @param   filters
-     *          the sequence of filters
-     *
-     * @return  the resulting filter
-     */
-    public static <T> DirectoryStream.Filter<T>
-        allOf(final Iterable<? extends DirectoryStream.Filter<? super T>> filters)
-    {
-        if (filters == null)
-            throw new NullPointerException("'filters' is null");
-        return new DirectoryStream.Filter<T>() {
-            @Override
-            public boolean accept(T entry) {
-                for (DirectoryStream.Filter<? super T> filter: filters) {
-                    if (!filter.accept(entry))
-                        return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    /**
-     * Returns a directory stream filter that {@link DirectoryStream.Filter#accept
-     * accepts} a directory entry if the entry is accepted by one or more of
-     * the given filters.
-     *
-     * <p> This method returns a filter that invokes, in iteration order, the
-     * {@code accept} method of each of filter. If {@code true} is returned by
-     * any of the filters then the directory entry is accepted. If none of the
-     * filters accepts the directory entry then it is filtered. If the iterator
-     * returns zero elements then the resulting filter filters all directory
-     * entries.
-     *
-     * @param   filters
-     *          the sequence of filters
-     *
-     * @return  the resulting filter
-     */
-    public static <T> DirectoryStream.Filter<T>
-        anyOf(final Iterable<? extends DirectoryStream.Filter<? super T>> filters)
-    {
-        if (filters == null)
-            throw new NullPointerException("'filters' is null");
-        return new DirectoryStream.Filter<T>() {
-            @Override
-            public boolean accept(T entry) {
-                for (DirectoryStream.Filter<? super T> filter: filters) {
-                    if (filter.accept(entry))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    /**
-     * Returns a directory stream filter that is the <em>complement</em> of the
-     * given filter. The resulting filter {@link
-     * java.nio.file.DirectoryStream.Filter#accept accepts} a directory entry
-     * if filtered by the given filter, and filters any entries that are accepted
-     * by the given filter.
-     *
-     * @param   filter
-     *          the given filter
-     *
-     * @return  the resulting filter that is the complement of the given filter
-     */
-    public static <T> DirectoryStream.Filter<T>
-        complementOf(final DirectoryStream.Filter<T> filter)
-    {
-        if (filter == null)
-            throw new NullPointerException("'filter' is null");
-        return new DirectoryStream.Filter<T>() {
-            @Override
-            public boolean accept(T entry) {
-                return !filter.accept(entry);
-            }
-        };
-    }
-}
--- a/src/share/classes/java/nio/file/FileAction.java	Mon Jun 29 15:05:15 2009 +0100
+++ /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&lt;Path&gt;() {
- *         public void invoke(Path entry) {
- *             :
- *         }
- *     });
- * </pre>
- *
- * @param   <T>     the type of file reference
- *
- * @since 1.7
- */
-
-public interface FileAction<T extends FileRef> {
-    /**
-     * 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/src/share/classes/java/nio/file/FileRef.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/FileRef.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/FileStore.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/FileStore.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/FileTreeWalker.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/FileTreeWalker.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/FileVisitor.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/FileVisitor.java	Mon Jun 29 15:08:52 2009 +0100
@@ -42,9 +42,9 @@
  *         &#64;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/src/share/classes/java/nio/file/Files.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/Files.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/LinkPermission.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/LinkPermission.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/OpenOption.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/OpenOption.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/Path.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/Path.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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&lt;Path&gt; filter = new DirectoryStream.Filter&lt;Path&gt;() {
-     *         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/src/share/classes/java/nio/file/Paths.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/Paths.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/SecureDirectoryStream.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/SecureDirectoryStream.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/SimpleFileVisitor.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/SimpleFileVisitor.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/StandardWatchEventKind.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/StandardWatchEventKind.java	Mon Jun 29 15:08:52 2009 +0100
@@ -31,7 +31,7 @@
  * @since 1.7
  */
 
-public class StandardWatchEventKind {
+public final class StandardWatchEventKind {
     private StandardWatchEventKind() { }
 
     /**
--- a/src/share/classes/java/nio/file/WatchKey.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/WatchKey.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/AttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/AttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/Attributes.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/Attributes.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/FileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/FileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/FileTime.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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&nbsp;8601</a> format:
+     * <pre>
+     *     YYYY-MM-DDThh:mm:ss[.s+]Z
+     * </pre>
+     * where "{@code [.s+]}" represents a dot followed by one of more digits
+     * for the decimal fraction of a second. It is only present when the decimal
+     * fraction of a second is not zero. For example, {@code
+     * FileTime.fromMillis(1234567890000L).toString()} yields {@code
+     * "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()}
+     * yields {@code "2009-02-13T23:31:30.123Z"}.
+     *
+     * <p> A {@code FileTime} is primarly intended to represent the value of a
+     * file's time stamp. Where used to represent <i>extreme values</i>, where
+     * the year is less than "{@code 0001}" or greater than "{@code 9999}" then
+     * the year may be expanded to more than four digits and may be
+     * negative-signed. If more than four digits then leading zeros are not
+     * present. The year before "{@code 0001}" is "{@code -0001}".
+     *
+     * @return  the string representation of this file time
+     */
+    @Override
+    public String toString() {
+        String v = valueAsString;
+        if (v == null) {
+            // overflow saturates to Long.MIN_VALUE or Long.MAX_VALUE so this
+            // limits the range:
+            // [-292275056-05-16T16:47:04.192Z,292278994-08-17T07:12:55.807Z]
+            long ms = toMillis();
+
+            // nothing to do when seconds/minutes/hours/days
+            String fractionAsString = "";
+            if (unit.compareTo(TimeUnit.SECONDS) < 0) {
+                // constants for conversion
+                final long C0 = 1L;
+                final long C1 = C0 * 1000L;
+                final long C2 = C1 * 1000L;
+                final long C3 = C2 * 1000L;
+
+                long scale;
+                int width;
+                switch (unit) {
+                    case MILLISECONDS : scale = C1; width = 3; break;
+                    case MICROSECONDS : scale = C2; width = 6; break;
+                    case NANOSECONDS  : scale = C3; width = 9; break;
+                    default:
+                        throw new AssertionError("Unit not handled");
+                }
+                long fraction = value % scale;
+                if (fraction != 0L) {
+                    // fraction must be positive
+                    if (fraction < 0L) {
+                        fraction += scale;
+                        if (ms != Long.MIN_VALUE) ms--;
+                    }
+
+                    // convert to String, adding leading zeros as required and
+                    // stripping any trailing zeros
+                    String s = Long.toString(fraction);
+                    int len = s.length();
+                    width -= len;
+                    StringBuilder sb = new StringBuilder(".");
+                    while (width-- > 0) {
+                        sb.append('0');
+                    }
+                    if (s.charAt(len-1) == '0') {
+                        // drop trailing zeros
+                        len--;
+                        while (s.charAt(len-1) == '0')
+                            len--;
+                        sb.append(s.substring(0, len));
+                    } else {
+                        sb.append(s);
+                    }
+                    fractionAsString = sb.toString();
+                }
+            }
+
+            // create calendar to use with formatter.
+            GregorianCalendar cal =
+                new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT);
+            if (value < 0L)
+                cal.setGregorianChange(new Date(Long.MIN_VALUE));
+            cal.setTimeInMillis(ms);
+
+            // years are negative before common era
+            String sign = (cal.get(Calendar.ERA) == GregorianCalendar.BC) ? "-" : "";
+
+            // [-]YYYY-MM-DDThh:mm:ss[.s]Z
+            v = new Formatter(Locale.ROOT)
+                .format("%s%tFT%tR:%tS%sZ", sign, cal, cal, cal, fractionAsString)
+                .toString();
+            valueAsString = v;
+        }
+        return v;
+    }
+}
--- a/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/nio/file/spi/AbstractPath.java	Mon Jun 29 15:05:15 2009 +0100
+++ /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/src/share/classes/java/nio/file/spi/FileSystemProvider.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/nio/file/spi/FileSystemProvider.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/java/util/Scanner.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/java/util/Scanner.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/management/ManagementFactoryHelper.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/management/ManagementFactoryHelper.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/misc/JavaNioAccess.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/misc/JavaNioAccess.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Jun 29 15:08:52 2009 +0100
@@ -237,6 +237,8 @@
     /* try auth without calling Authenticator */
     private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();
     private boolean tryTransparentNTLMProxy = NTLMAuthentication.supportsTransparentAuth();
+    /* Used by Windows specific code */
+    Object authObj;
 
     /* Set if the user is manually setting the Authorization or Proxy-Authorization headers */
     boolean isUserServerAuth;
@@ -1219,6 +1221,7 @@
                             disconnectInternal ();
                             throw new IOException ("Authentication failure");
                         }
+                        authObj = null;
                         doingNTLMp2ndStage = false;
                         continue;
                     }
@@ -1295,6 +1298,7 @@
                             throw new IOException ("Authentication failure");
                         }
                         doingNTLM2ndStage = false;
+                        authObj = null;
                         setCookieHeader();
                         continue;
                     }
@@ -1646,6 +1650,7 @@
                             disconnectInternal();
                             throw new IOException ("Authentication failure");
                         }
+                        authObj = null;
                         doingNTLMp2ndStage = false;
                         continue;
                     }
--- a/src/share/classes/sun/nio/ch/FileChannelImpl.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ /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/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/AbstractPath.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/MimeType.java	Mon Jun 29 15:05:15 2009 +0100
+++ /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/src/share/classes/sun/nio/fs/PollingWatchService.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/classes/sun/nio/fs/PollingWatchService.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/classes/sun/nio/fs/Util.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/javavm/export/classfile_constants.h	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/javavm/export/classfile_constants.h	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/sample/nio/file/Copy.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/sample/nio/file/Copy.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/share/sample/nio/file/Xdd.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/share/sample/nio/file/Xdd.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Mon Jun 29 15:08:52 2009 +0100
@@ -26,6 +26,7 @@
 
 import java.net.InetAddress;
 import java.net.SocketAddress;
+import java.net.SocketException;
 import java.net.InetSocketAddress;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -122,6 +123,8 @@
 
     private Association association;
 
+    private Set<SocketAddress> remoteAddresses = Collections.EMPTY_SET;
+
     /* -- End of fields protected by stateLock -- */
 
     private SctpResultContainer commUpResultContainer;  /* null */
@@ -142,18 +145,32 @@
      */
     public SctpChannelImpl(SelectorProvider provider, FileDescriptor fd)
          throws IOException {
+        this(provider, fd, null);
+    }
+
+    /**
+     * Constructor for sockets obtained from branching
+     */
+    public SctpChannelImpl(SelectorProvider provider,
+                           FileDescriptor fd,
+                           Association association)
+            throws IOException {
         super(provider);
         this.fd = fd;
         this.fdVal = IOUtil.fdVal(fd);
         this.state = ChannelState.CONNECTED;
         port = (Net.localAddress(fd)).getPort();
 
-        /* Receive COMM_UP */
-        ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
-        try {
-            receive(buf, null, null, true);
-        } finally {
-            Util.releaseTemporaryDirectBuffer(buf);
+        if (association != null) { /* branched */
+            this.association = association;
+        } else { /* obtained from server channel */
+            /* Receive COMM_UP */
+            ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
+            try {
+                receive(buf, null, null, true);
+            } finally {
+                Util.releaseTemporaryDirectBuffer(buf);
+            }
         }
     }
 
@@ -391,6 +408,12 @@
                             } finally {
                                 Util.releaseTemporaryDirectBuffer(buf);
                             }
+
+                            /* cache remote addresses */
+                            try {
+                                remoteAddresses = getRemoteAddresses();
+                            } catch (IOException unused) { /* swallow exception */ }
+
                             return true;
                         }
                     } else  {
@@ -414,6 +437,7 @@
                            int maxOutStreams,
                            int maxInStreams)
             throws IOException {
+        ensureOpenAndUnconnected();
         return setOption(SCTP_INIT_MAXSTREAMS, InitMaxStreams.
                 create(maxInStreams, maxOutStreams)).connect(endpoint);
 
@@ -512,6 +536,12 @@
                         } finally {
                             Util.releaseTemporaryDirectBuffer(buf);
                         }
+
+                        /* cache remote addresses */
+                        try {
+                            remoteAddresses = getRemoteAddresses();
+                        } catch (IOException unused) { /* swallow exception */ }
+
                         return true;
                     }
                 }
@@ -966,7 +996,7 @@
         int pos = src.position();
         int lim = src.limit();
 
-        assert (pos <= lim && streamNumber > 0);
+        assert (pos <= lim && streamNumber >= 0);
         int rem = (pos <= lim ? lim - pos : 0);
 
         if (src instanceof DirectBuffer)
@@ -1043,10 +1073,15 @@
         synchronized (stateLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            if (!isConnected())
+            if (!isConnected() || isShutdown)
                 return Collections.EMPTY_SET;
 
-            return SctpNet.getRemoteAddresses(fdVal, 0/*unused*/);
+            try {
+                return SctpNet.getRemoteAddresses(fdVal, 0/*unused*/);
+            } catch (SocketException unused) {
+                /* an open connected channel should always have remote addresses */
+                return remoteAddresses;
+            }
         }
     }
 
--- a/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Mon Jun 29 15:08:52 2009 +0100
@@ -26,6 +26,7 @@
 
 import java.net.InetAddress;
 import java.net.SocketAddress;
+import java.net.SocketException;
 import java.net.InetSocketAddress;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -398,8 +399,8 @@
             if (!isOpen())
                 throw new ClosedChannelException();
 
-            SctpNet.setSocketOption(fdVal, name, value,
-                    association.associationID());
+            int assocId = association == null ? 0 : association.associationID();
+            SctpNet.setSocketOption(fdVal, name, value, assocId);
         }
         return this;
     }
@@ -414,12 +415,15 @@
             throw new UnsupportedOperationException("'" + name + "' not supported");
 
         synchronized (stateLock) {
-            checkAssociation(association);
+            if (association != null && (name.equals(SCTP_PRIMARY_ADDR) ||
+                    name.equals(SCTP_SET_PEER_PRIMARY_ADDR))) {
+                checkAssociation(association);
+            }
             if (!isOpen())
                 throw new ClosedChannelException();
 
-            return (T)SctpNet.getSocketOption(fdVal, name,
-                    association.associationID());
+            int assocId = association == null ? 0 : association.associationID();
+            return (T)SctpNet.getSocketOption(fdVal, name, assocId);
         }
     }
 
@@ -626,15 +630,19 @@
                 case ASSOCIATION_CHANGED :
                     result = absHandler.handleNotification(
                             resultContainer.getAssociationChanged(), attachment);
+                    break;
                 case PEER_ADDRESS_CHANGED :
                     result = absHandler.handleNotification(
                             resultContainer.getPeerAddressChanged(), attachment);
+                    break;
                 case SEND_FAILED :
                     result = absHandler.handleNotification(
                             resultContainer.getSendFailed(), attachment);
+                    break;
                 case SHUTDOWN :
                     result =  absHandler.handleNotification(
                             resultContainer.getShutdown(), attachment);
+                    break;
                 default :
                     /* implementation specific handlers */
                     result =  absHandler.handleNotification(
@@ -836,7 +844,7 @@
         int ppid = messageInfo.payloadProtocolID();
         int pos = src.position();
         int lim = src.limit();
-        assert (pos <= lim && streamNumber > 0);
+        assert (pos <= lim && streamNumber >= 0);
         int rem = (pos <= lim ? lim - pos : 0);
 
         if (src instanceof DirectBuffer)
@@ -914,7 +922,13 @@
             if (!isOpen())
                 throw new ClosedChannelException();
 
-            return SctpNet.getRemoteAddresses(fdVal, association.associationID());
+            try {
+                return SctpNet.getRemoteAddresses(fdVal, association.associationID());
+            } catch (SocketException se) {
+                /* a valid association should always have remote addresses */
+                Set<SocketAddress> addrs = associationMap.get(association);
+                return addrs != null ? addrs : Collections.EMPTY_SET;
+            }
         }
     }
 
@@ -922,7 +936,16 @@
     public SctpChannel branch(Association association)
             throws IOException {
         synchronized (stateLock) {
-            return null;  //TODO: implement
+            checkAssociation(association);
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            FileDescriptor bFd = SctpNet.branch(fdVal,
+                                                association.associationID());
+            /* successfully branched, we can now remove it from assoc list */
+            removeAssociation(association);
+
+            return new SctpChannelImpl(provider(), bFd, association);
         }
     }
 
--- a/src/solaris/classes/sun/nio/ch/SctpNet.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/ch/SctpNet.java	Mon Jun 29 15:08:52 2009 +0100
@@ -232,6 +232,11 @@
         shutdown0(fd, assocId);
     }
 
+    static FileDescriptor branch(int fd, int assocId) throws IOException {
+        int nativefd = branch0(fd, assocId);
+        return IOUtil.newFD(nativefd);
+    }
+
     /* Native Methods */
     static native int socket0(boolean oneToOne) throws IOException;
 
@@ -248,6 +253,8 @@
     static native SocketAddress[] getRemoteAddresses0(int fd, int assocId)
             throws IOException;
 
+    static native int branch0(int fd, int assocId) throws IOException;
+
     static native void setPrimAddrOption0(int fd, int assocId, InetAddress ia,
             int port) throws IOException;
 
--- a/src/solaris/classes/sun/nio/ch/SctpResultContainer.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/ch/SctpResultContainer.java	Mon Jun 29 15:08:52 2009 +0100
@@ -121,6 +121,8 @@
             case SHUTDOWN:             sb.append("SHUTDOWN");            break;
             default :                  sb.append("Unknown result type");
         }
-       return sb.append(", Value: ").append(value.toString()).toString();
+        sb.append(", Value: ");
+        sb.append((value == null) ? "null" : value.toString());
+        return sb.toString();
     }
 }
--- a/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Mon Jun 29 15:08:52 2009 +0100
@@ -407,7 +407,7 @@
             if (!isOpen())
                 throw new ClosedChannelException();
             if (!isBound())
-                return null;
+                return Collections.EMPTY_SET;
 
             return SctpNet.getLocalAddresses(fdVal);
         }
--- a/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/LinuxFileStore.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/LinuxFileStore.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/SolarisFileStore.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/SolarisFileStore.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixCopyFile.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixCopyFile.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileKey.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileKey.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileStore.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileStore.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileSystem.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileSystem.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixMountEntry.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixMountEntry.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixPath.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixPath.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/solaris/native/sun/nio/ch/Sctp.h	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/native/sun/nio/ch/Sctp.h	Mon Jun 29 15:08:52 2009 +0100
@@ -63,6 +63,8 @@
 typedef int sctp_getpaddrs_func(int sock, sctp_assoc_t id, void **addrs);
 typedef int sctp_freepaddrs_func(void *addrs);
 typedef int sctp_bindx_func(int sock, void *addrs, int addrcnt, int flags);
+typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
+
 
 
 #else /* __linux__ */
@@ -315,6 +317,8 @@
 typedef int sctp_getpaddrs_func(int sd, sctp_assoc_t id, struct sockaddr **addrs);
 typedef int sctp_freepaddrs_func(struct sockaddr *addrs);
 typedef int sctp_bindx_func(int sd, struct sockaddr *addrs, int addrcnt, int flags);
+typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
+
 
 #endif /* __linux__ */
 
@@ -323,6 +327,7 @@
 sctp_getpaddrs_func* nio_sctp_getpaddrs;
 sctp_freepaddrs_func* nio_sctp_freepaddrs;
 sctp_bindx_func* nio_sctp_bindx;
+sctp_peeloff_func* nio_sctp_peeloff;
 
 jboolean loadSocketExtensionFuncs(JNIEnv* env);
 
--- a/src/solaris/native/sun/nio/ch/SctpChannelImpl.c	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/native/sun/nio/ch/SctpChannelImpl.c	Mon Jun 29 15:08:52 2009 +0100
@@ -254,7 +254,6 @@
 
         if (remaining > 0) {
             if ((rv = recvmsg(fd, msg, 0)) < 0) {
-                fprintf(stdout, "\nNative: handleSFN: recvmsg failed: errno = %d  ", errno);
                 handleSocketError(env, errno);
                 return;
             }
@@ -269,7 +268,7 @@
 
     /* create SctpSendFailed */
     resultObj = (*env)->NewObject(env, ssf_class, ssf_ctrID, ssf->ssf_assoc_id,
-            sri->sinfo_stream, ssf->ssf_error, isaObj, bufferObj);
+            isaObj, bufferObj, ssf->ssf_error, sri->sinfo_stream);
     CHECK_NULL(resultObj);
     (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
     (*env)->SetIntField(env, resultContainerObj, src_typeID,
--- a/src/solaris/native/sun/nio/ch/SctpNet.c	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/native/sun/nio/ch/SctpNet.c	Mon Jun 29 15:08:52 2009 +0100
@@ -96,6 +96,13 @@
         return JNI_FALSE;
     }
 
+    if ((nio_sctp_peeloff = (sctp_peeloff_func*)
+            dlsym(RTLD_DEFAULT, "sctp_peeloff")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
     funcsLoaded = JNI_TRUE;
     return JNI_TRUE;
 }
@@ -440,12 +447,10 @@
 JNIEXPORT jobject JNICALL Java_sun_nio_ch_SctpNet_getPrimAddrOption0
   (JNIEnv *env, jclass klass, jint fd, jint assocId) {
     struct sctp_setprim prim;
-    struct sockaddr_storage ss;
-    int ss_len = sizeof(ss);
     unsigned int prim_len = sizeof(prim);
+    struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
 
     prim.ssp_assoc_id = assocId;
-    prim.ssp_addr = ss;
 
     if (getsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, &prim_len) < 0) {
         JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
@@ -453,7 +458,7 @@
         return NULL;
     }
 
-    return SockAddrToInetSocketAddress(env, (struct sockaddr*)&ss);
+    return SockAddrToInetSocketAddress(env, sap);
 }
 
 /*
@@ -464,16 +469,15 @@
 JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_setPrimAddrOption0
   (JNIEnv *env, jclass klass, jint fd, jint assocId, jobject iaObj, jint port) {
     struct sctp_setprim prim;
-    struct sockaddr_storage ss;
-    int ss_len = sizeof(ss);
+    struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
+    int sap_len;
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&ss,
-                                  &ss_len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
+                                  &sap_len, JNI_TRUE) != 0) {
         return;
     }
 
     prim.ssp_assoc_id = assocId;
-    prim.ssp_addr = ss;
 
     if (setsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, sizeof(prim)) < 0) {
         JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
@@ -607,3 +611,17 @@
     }
 }
 
+/*
+ * Class:     sun_nio_ch_SctpNet
+ * Method:    branch
+ * Signature: (II)I
+ */
+JNIEXPORT int JNICALL Java_sun_nio_ch_SctpNet_branch0
+  (JNIEnv *env, jclass klass, jint fd, jint assocId) {
+    int newfd = 0;
+    if ((newfd = nio_sctp_peeloff(fd, assocId)) < 0) {
+        handleSocketError(env, errno);
+    }
+
+    return newfd;
+}
--- a/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Mon Jun 29 15:08:52 2009 +0100
@@ -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, &times[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, &times[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/src/solaris/native/sun/nio/fs/genUnixConstants.c	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/solaris/native/sun/nio/fs/genUnixConstants.c	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsConstants.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsConstants.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsFileStore.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsFileStore.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsFileSystem.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsFileSystem.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/classes/sun/nio/fs/WindowsPath.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsPath.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Mon Jun 29 15:05:15 2009 +0100
+++ b/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/com/sun/nio/sctp/SctpChannel/Connect.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/com/sun/nio/sctp/SctpChannel/Connect.java	Mon Jun 29 15:08:52 2009 +0100
@@ -30,8 +30,8 @@
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.io.IOException;
+import java.util.Set;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
 import java.nio.channels.AlreadyConnectedException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.ConnectionPendingException;
@@ -48,47 +48,29 @@
  * getRemoteAddresses and association.
  */
 public class Connect {
-    final CountDownLatch finishedLatch = new CountDownLatch(1);
 
     void test(String[] args) {
-        SocketAddress address = null;
-        Server server = null;
-
         if (!Util.isSCTPSupported()) {
             out.println("SCTP protocol is not supported");
             out.println("Test cannot be run");
             return;
         }
 
-        if (args.length == 2) {
-            /* requested to connect to a specific address */
-            try {
-                int port = Integer.valueOf(args[1]);
-                address = new InetSocketAddress(args[0], port);
-            } catch (NumberFormatException nfe) {
-                err.println(nfe);
-            }
-        } else {
-            /* start server on local machine, default */
-            try {
-                server = new Server();
-                server.start();
-                address = server.address();
-                debug("Server started and listening on " + address);
-            } catch (IOException ioe) {
-                ioe.printStackTrace();
-                return;
-            }
-        }
-
-        doTest(address);
+        doTest();
     }
 
-    void doTest(SocketAddress addr) {
+    void doTest() {
         SctpChannel channel = null;
-        final SocketAddress peerAddress = addr;
+        SctpServerChannel ssc = null;
 
         try {
+            /* Create a server channel to connect to */
+            ssc = SctpServerChannel.open().bind(null);
+            Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
+            if (addrs.isEmpty())
+                debug("addrs should not be empty");
+            final SocketAddress peerAddress = (InetSocketAddress) addrs.iterator().next();
+
             channel = SctpChannel.open();
 
             /* TEST 0.5 Verify default values for new/unconnected channel */
@@ -118,6 +100,9 @@
                         "finishConnect should have returned true");
             }
 
+            ssc.accept();
+            ssc.close();
+
             /* TEST 1.5 Verify after connect */
             check(!channel.getRemoteAddresses().isEmpty(),
                     "empty set for connected channel");
@@ -136,6 +121,16 @@
                 unexpected(ioe);
             }
 
+            /* TEST 2.5: Verify AlreadyConnectedException thrown */
+            try {
+                channel.connect(peerAddress, 5, 5);
+                fail("should have thrown AlreadyConnectedException");
+            } catch (AlreadyConnectedException unused) {
+                pass();
+            }  catch (IOException ioe) {
+                unexpected(ioe);
+            }
+
             /* TEST 3: UnresolvedAddressException */
             channel.close();
             channel = SctpChannel.open();
@@ -200,9 +195,10 @@
         } catch (IOException ioe) {
             unexpected(ioe);
         } finally {
-            finishedLatch.countDown();
             try { if (channel != null) channel.close(); }
-            catch (IOException e) { unexpected(e);}
+            catch (IOException unused) {}
+            try { if (ssc != null) ssc.close(); }
+            catch (IOException unused) {}
         }
     }
 
@@ -219,47 +215,6 @@
         }
     }
 
-    class Server implements Runnable
-    {
-        final InetSocketAddress serverAddr;
-        private SctpServerChannel ssc;
-
-        public Server() throws IOException {
-            ssc = SctpServerChannel.open().bind(null);
-            java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
-            if (addrs.isEmpty())
-                debug("addrs should not be empty");
-
-            serverAddr = (InetSocketAddress) addrs.iterator().next();
-        }
-
-        public void start() {
-            (new Thread(this, "Server-"  + serverAddr.getPort())).start();
-        }
-
-        public InetSocketAddress address() {
-            return serverAddr;
-        }
-
-        @Override
-        public void run() {
-            SctpChannel sc = null;
-            try {
-                sc = ssc.accept();
-                finishedLatch.await();
-            } catch (IOException ioe) {
-                unexpected(ioe);
-            } catch (InterruptedException ie) {
-                unexpected(ie);
-            } finally {
-                try { if (ssc != null) ssc.close(); }
-                catch (IOException  ioe) { unexpected(ioe); }
-                try { if (sc != null) sc.close(); }
-                catch (IOException  ioe) { unexpected(ioe); }
-            }
-        }
-    }
-
         //--------------------- Infrastructure ---------------------------
     boolean debug = true;
     volatile int passed = 0, failed = 0;
--- a/test/com/sun/nio/sctp/SctpChannel/Shutdown.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/com/sun/nio/sctp/SctpChannel/Shutdown.java	Mon Jun 29 15:08:52 2009 +0100
@@ -151,6 +151,16 @@
             } catch (IOException ioe) {
                 unexpected(ioe);
             }
+
+            /* TEST 6: getRemoteAddresses */
+            debug("Test 6: getRemoteAddresses");
+            try {
+                java.util.Set<SocketAddress> remoteAddrs = channel.getRemoteAddresses();
+                check(remoteAddrs.isEmpty(),
+                         "A shutdown channel should not have remote addresses");
+            } catch (IOException ioe) {
+                unexpected(ioe);
+            }
         } catch (IOException ioe) {
             unexpected(ioe);
         } catch (InterruptedException ie) {
--- a/test/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java	Mon Jun 29 15:08:52 2009 +0100
@@ -29,15 +29,24 @@
 
 import java.io.IOException;
 import java.util.Set;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
 import java.util.List;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.nio.channels.ClosedChannelException;
 import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpServerChannel;
 import com.sun.nio.sctp.SctpSocketOption;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
 import static com.sun.nio.sctp.SctpStandardSocketOption.*;
 import static java.lang.System.out;
 
 public class SocketOptionTests {
+    final String osName = AccessController.doPrivileged(
+                    new GetPropertyAction("os.name"));
+
     <T> void checkOption(SctpChannel sc, SctpSocketOption<T> name,
             T expectedValue) throws IOException {
         T value = sc.getOption(name);
@@ -92,13 +101,6 @@
             optionalSupport(sc, SCTP_EXPLICIT_COMPLETE, true);
             optionalSupport(sc, SCTP_FRAGMENT_INTERLEAVE, 1);
 
-
-            //TODO: SCTP_PRIMARY_ADDR
-            //sc.bind(null);
-            //connect
-            //InetSocketAddress addr = new InetSocketAddress(0);
-            //sc.setOption(SCTP_PRIMARY_ADDR, addr);
-
             sc.setOption(SCTP_NODELAY, true);
             checkOption(sc, SCTP_NODELAY, true);
             sc.setOption(SO_SNDBUF, 16*1024);
@@ -107,6 +109,8 @@
             sc.setOption(SO_LINGER, 2000);
             checkOption(sc, SO_LINGER, 2000);
 
+            /* SCTP_PRIMARY_ADDR */
+            sctpPrimaryAddr();
 
             /* NullPointerException */
             try {
@@ -135,6 +139,60 @@
         }
     }
 
+    /* SCTP_PRIMARY_ADDR */
+    void sctpPrimaryAddr() throws IOException {
+        SocketAddress addrToSet = null;;
+
+        System.out.println("TESTING SCTP_PRIMARY_ADDR");
+        SctpChannel sc = SctpChannel.open();
+        SctpServerChannel ssc = SctpServerChannel.open().bind(null);
+        Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
+        if (addrs.isEmpty())
+            debug("addrs should not be empty");
+        debug("Listening on " + addrs);
+
+        InetSocketAddress serverAddr = (InetSocketAddress) addrs.iterator().next();
+        debug("connecting to " + serverAddr);
+        sc.connect(serverAddr);
+        SctpChannel peerChannel = ssc.accept();
+        ssc.close();
+        Set<SocketAddress> peerAddrs = peerChannel.getAllLocalAddresses();
+        debug("Peer local Addresses: ");
+        for (Iterator<SocketAddress> it = peerAddrs.iterator(); it.hasNext(); ) {
+            InetSocketAddress addr = (InetSocketAddress)it.next();
+            debug("\t" + addr);
+            addrToSet = addr;   // any of the peer addresses will do!
+        }
+
+        /* retrieval of SCTP_PRIMARY_ADDR is not supported on Solaris */
+        if ("SunOS".equals(osName)) {
+            /* For now do not set this option. There is a bug on Solaris 10 pre Update 5
+             * where setting this option returns Invalid argument */
+            //debug("Set SCTP_PRIMARY_ADDR with " + addrToSet);
+            //sc.setOption(SCTP_PRIMARY_ADDR, addrToSet);
+            return;
+        } else { /* Linux */
+            SocketAddress primaryAddr = sc.getOption(SCTP_PRIMARY_ADDR);
+            System.out.println("SCTP_PRIMARY_ADDR returned: " + primaryAddr);
+            /* Verify that this is one of the peer addresses */
+            boolean found = false;
+            addrToSet = primaryAddr; // may not have more than one addr
+            for (Iterator<SocketAddress> it = peerAddrs.iterator(); it.hasNext(); ) {
+                InetSocketAddress addr = (InetSocketAddress)it.next();
+                if (addr.equals(primaryAddr)) {
+                    found = true;
+                }
+                addrToSet = addr;
+            }
+            check(found, "SCTP_PRIMARY_ADDR returned bogus address!");
+
+            sc.setOption(SCTP_PRIMARY_ADDR, addrToSet);
+            System.out.println("SCTP_PRIMARY_ADDR set to: " + addrToSet);
+            primaryAddr = sc.getOption(SCTP_PRIMARY_ADDR);
+            System.out.println("SCTP_PRIMARY_ADDR returned: " + primaryAddr);
+            check(addrToSet.equals(primaryAddr),"SCTP_PRIMARY_ADDR not set correctly");
+        }
+    }
             //--------------------- Infrastructure ---------------------------
     boolean debug = true;
     volatile int passed = 0, failed = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/nio/sctp/SctpMultiChannel/Branch.java	Mon Jun 29 15:08:52 2009 +0100
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 4927640
+ * @summary Tests the SCTP protocol implementation
+ * @author chegar
+ */
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.io.IOException;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.nio.ByteBuffer;
+import com.sun.nio.sctp.AbstractNotificationHandler;
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.AssociationChangeNotification;
+import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
+import com.sun.nio.sctp.HandlerResult;
+import com.sun.nio.sctp.InvalidStreamException;
+import com.sun.nio.sctp.MessageInfo;
+import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpMultiChannel;
+import com.sun.nio.sctp.ShutdownNotification;
+import static java.lang.System.out;
+import static java.lang.System.err;
+
+public class Branch {
+    /* Latches used to synchronize between the client and server so that
+     * connections without any IO may not be closed without being accepted */
+    final CountDownLatch clientFinishedLatch = new CountDownLatch(1);
+    final CountDownLatch serverFinishedLatch = new CountDownLatch(1);
+
+    void test(String[] args) {
+        SocketAddress address = null;
+        Server server = null;
+
+        if (!Util.isSCTPSupported()) {
+            out.println("SCTP protocol is not supported");
+            out.println("Test cannot be run");
+            return;
+        }
+
+        if (args.length == 2) {
+            /* requested to connecct to a specific address */
+            try {
+                int port = Integer.valueOf(args[1]);
+                address = new InetSocketAddress(args[0], port);
+            } catch (NumberFormatException nfe) {
+                err.println(nfe);
+            }
+        } else {
+            /* start server on local machine, default */
+            try {
+                server = new Server();
+                server.start();
+                address = server.address();
+                debug("Server started and listening on " + address);
+            } catch (IOException ioe) {
+                ioe.printStackTrace();
+                return;
+            }
+        }
+
+        doTest(address);
+    }
+
+    void doTest(SocketAddress peerAddress) {
+        SctpMultiChannel channel = null;
+        ByteBuffer buffer = ByteBuffer.allocate(Util.LARGE_BUFFER);
+        MessageInfo info = MessageInfo.createOutgoing(null, 0);
+
+        try {
+            channel = SctpMultiChannel.open();
+
+            /* setup an association implicitly by sending a small message */
+            int streamNumber = 0;
+            debug("sending to " + peerAddress + " on stream number: " + streamNumber);
+            info = MessageInfo.createOutgoing(peerAddress, streamNumber);
+            buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
+            buffer.flip();
+            int position = buffer.position();
+            int remaining = buffer.remaining();
+
+            debug("sending small message: " + buffer);
+            int sent = channel.send(buffer, info);
+
+            check(sent == remaining, "sent should be equal to remaining");
+            check(buffer.position() == (position + sent),
+                    "buffers position should have been incremented by sent");
+
+            /* Receive the COMM_UP */
+            buffer.clear();
+            BranchNotificationHandler handler = new BranchNotificationHandler();
+            channel.configureBlocking(false);
+            info = channel.receive(buffer, null, handler);
+            check(handler.receivedCommUp(), "COMM_UP no received");
+            Set<Association> associations = channel.associations();
+            check(!associations.isEmpty(),"There should be some associations");
+            Association bassoc = associations.iterator().next();
+
+            /* TEST 1: branch */
+            SctpChannel bchannel = channel.branch(bassoc);
+
+            check(!bchannel.getAllLocalAddresses().isEmpty(),
+                                   "branched channel should be bound");
+            check(!bchannel.getRemoteAddresses().isEmpty(),
+                                   "branched channel should be connected");
+            check(channel.associations().isEmpty(),
+                  "there should be no associations since the only one was branched off");
+
+            buffer.clear();
+            info = bchannel.receive(buffer, null, null);
+            buffer.flip();
+            check(info != null, "info is null");
+            check(info.streamNumber() == streamNumber,
+                    "message not sent on the correct stream");
+            check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
+                  length, "bytes received not equal to message length");
+            check(info.bytes() == buffer.remaining(), "bytes != remaining");
+            check(Util.compare(buffer, Util.SMALL_MESSAGE),
+              "received message not the same as sent message");
+
+        } catch (IOException ioe) {
+            unexpected(ioe);
+        } finally {
+            clientFinishedLatch.countDown();
+            try { serverFinishedLatch.await(10L, TimeUnit.SECONDS); }
+            catch (InterruptedException ie) { unexpected(ie); }
+            if (channel != null) {
+                try { channel.close(); }
+                catch (IOException e) { unexpected (e);}
+            }
+        }
+    }
+
+    class Server implements Runnable
+    {
+        final InetSocketAddress serverAddr;
+        private SctpMultiChannel serverChannel;
+
+        public Server() throws IOException {
+            serverChannel = SctpMultiChannel.open().bind(null);
+            java.util.Set<SocketAddress> addrs = serverChannel.getAllLocalAddresses();
+            if (addrs.isEmpty())
+                debug("addrs should not be empty");
+
+            serverAddr = (InetSocketAddress) addrs.iterator().next();
+        }
+
+        public void start() {
+            (new Thread(this, "Server-"  + serverAddr.getPort())).start();
+        }
+
+        public InetSocketAddress address() {
+            return serverAddr;
+        }
+
+        @Override
+        public void run() {
+            ByteBuffer buffer = ByteBuffer.allocateDirect(Util.LARGE_BUFFER);
+            try {
+                MessageInfo info;
+
+                /* receive a small message */
+                do {
+                    info = serverChannel.receive(buffer, null, null);
+                    if (info == null) {
+                        fail("Server: unexpected null from receive");
+                            return;
+                    }
+                } while (!info.isComplete());
+
+                buffer.flip();
+                check(info != null, "info is null");
+                check(info.streamNumber() == 0,
+                        "message not sent on the correct stream");
+                check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
+                      length, "bytes received not equal to message length");
+                check(info.bytes() == buffer.remaining(), "bytes != remaining");
+                check(Util.compare(buffer, Util.SMALL_MESSAGE),
+                  "received message not the same as sent message");
+
+                check(info != null, "info is null");
+                Set<Association> assocs = serverChannel.associations();
+                check(assocs.size() == 1, "there should be only one association");
+
+                /* echo the message */
+                debug("Server: echoing first message");
+                buffer.flip();
+                int bytes = serverChannel.send(buffer, info);
+                debug("Server: sent " + bytes + "bytes");
+
+                clientFinishedLatch.await(10L, TimeUnit.SECONDS);
+                serverFinishedLatch.countDown();
+            } catch (IOException ioe) {
+                unexpected(ioe);
+            } catch (InterruptedException ie) {
+                unexpected(ie);
+            } finally {
+                try { if (serverChannel != null) serverChannel.close(); }
+                catch (IOException  unused) {}
+            }
+        }
+    }
+
+    class BranchNotificationHandler extends AbstractNotificationHandler<Object>
+    {
+        boolean receivedCommUp;  // false
+
+        boolean receivedCommUp() {
+            return receivedCommUp;
+        }
+
+        @Override
+        public HandlerResult handleNotification(
+                AssociationChangeNotification notification, Object attachment) {
+            AssocChangeEvent event = notification.event();
+            debug("AssociationChangeNotification");
+            debug("  Association: " + notification.association());
+            debug("  Event: " + event);
+
+            if (event.equals(AssocChangeEvent.COMM_UP))
+                receivedCommUp = true;
+
+            return HandlerResult.RETURN;
+        }
+
+        /* A ShutdownNotification handler is provided to ensure that no
+         * shutdown notification are being handled since we don't expect
+         * to receive them. This is not part of branch testing, it just
+         * fits here to test another bug. */
+        @Override
+        public HandlerResult handleNotification(
+                ShutdownNotification notification, Object attachment) {
+            debug("ShutdownNotification");
+            debug("  Association: " + notification.association());
+
+            fail("Shutdown should not be received");
+
+            return HandlerResult.RETURN;
+        }
+
+    }
+
+        //--------------------- Infrastructure ---------------------------
+    boolean debug = true;
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
+    void debug(String message) {if(debug) { System.out.println(message); }  }
+    public static void main(String[] args) throws Throwable {
+        Class<?> k = new Object(){}.getClass().getEnclosingClass();
+        try {k.getMethod("instanceMain",String[].class)
+                .invoke( k.newInstance(), (Object) args);}
+        catch (Throwable e) {throw e.getCause();}}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java	Mon Jun 29 15:08:52 2009 +0100
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 4927640
+ * @summary Tests the SCTP protocol implementation
+ * @author chegar
+ */
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.List;
+import java.util.Arrays;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import com.sun.nio.sctp.AbstractNotificationHandler;
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.AssociationChangeNotification;
+import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
+import com.sun.nio.sctp.HandlerResult;
+import com.sun.nio.sctp.MessageInfo;
+import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpMultiChannel;
+import com.sun.nio.sctp.SctpServerChannel;
+import com.sun.nio.sctp.SctpSocketOption;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+import static com.sun.nio.sctp.SctpStandardSocketOption.*;
+import static java.lang.System.out;
+
+public class SocketOptionTests {
+    final String osName = AccessController.doPrivileged(
+                    new GetPropertyAction("os.name"));
+
+    <T> void checkOption(SctpMultiChannel smc, SctpSocketOption<T> name,
+            T expectedValue) throws IOException {
+        T value = smc.getOption(name, null);
+        check(value.equals(expectedValue), name + ": value (" + value +
+                ") not as expected (" + expectedValue + ")");
+       }
+
+    <T> void optionalSupport(SctpMultiChannel smc, SctpSocketOption<T> name,
+            T value) {
+        try {
+            smc.setOption(name, value, null);
+            checkOption(smc, name, value);
+        } catch (IOException e) {
+            /* Informational only, not all options have native support */
+            out.println(name + " not supported. " + e);
+        }
+    }
+
+    void test(String[] args) {
+        if (!Util.isSCTPSupported()) {
+            out.println("SCTP protocol is not supported");
+            out.println("Test cannot be run");
+            return;
+        }
+
+        try {
+            SctpMultiChannel smc = SctpMultiChannel.open();
+
+            /* check supported options */
+            Set<SctpSocketOption<?>> options = smc.supportedOptions();
+            List<? extends SctpSocketOption<?>> expected = Arrays.<SctpSocketOption<?>>asList(
+                    SCTP_DISABLE_FRAGMENTS, SCTP_EXPLICIT_COMPLETE,
+                    SCTP_FRAGMENT_INTERLEAVE, SCTP_INIT_MAXSTREAMS,
+                    SCTP_NODELAY, SCTP_PRIMARY_ADDR, SCTP_SET_PEER_PRIMARY_ADDR,
+                    SO_SNDBUF, SO_RCVBUF, SO_LINGER);
+
+            for (SctpSocketOption opt: expected) {
+                if (!options.contains(opt))
+                    fail(opt.name() + " should be supported");
+            }
+
+            InitMaxStreams streams = InitMaxStreams.create(1024, 1024);
+            smc.setOption(SCTP_INIT_MAXSTREAMS, streams, null);
+            checkOption(smc, SCTP_INIT_MAXSTREAMS, streams);
+            streams = smc.getOption(SCTP_INIT_MAXSTREAMS, null);
+            check(streams.maxInStreams() == 1024, "Max in streams: value: "
+                    + streams.maxInStreams() + ", expected 1024 ");
+            check(streams.maxOutStreams() == 1024, "Max out streams: value: "
+                    + streams.maxOutStreams() + ", expected 1024 ");
+
+            optionalSupport(smc, SCTP_DISABLE_FRAGMENTS, true);
+            optionalSupport(smc, SCTP_EXPLICIT_COMPLETE, true);
+            optionalSupport(smc, SCTP_FRAGMENT_INTERLEAVE, 1);
+
+            smc.setOption(SCTP_NODELAY, true, null);
+            checkOption(smc, SCTP_NODELAY, true);
+            smc.setOption(SO_SNDBUF, 16*1024, null);
+            smc.setOption(SO_RCVBUF, 16*1024, null);
+
+            checkOption(smc, SO_LINGER, -1);  /* default should be negative */
+
+            /* Setting SO_LINGER not support for one-to-many on Solaris */
+            if (!"SunOS".equals(osName)) {
+                smc.setOption(SO_LINGER, 2000, null);
+                checkOption(smc, SO_LINGER, 2000);
+            }
+
+            /* SCTP_PRIMARY_ADDR */
+            sctpPrimaryAddr();
+
+            /* NullPointerException */
+            try {
+                smc.setOption(null, "value", null);
+                fail("NullPointerException not thrown for setOption");
+            } catch (NullPointerException unused) {
+                pass();
+            }
+            try {
+               smc.getOption(null, null);
+               fail("NullPointerException not thrown for getOption");
+            } catch (NullPointerException unused) {
+               pass();
+            }
+
+            /* ClosedChannelException */
+            smc.close();
+            try {
+               smc.setOption(SCTP_INIT_MAXSTREAMS, streams, null);
+               fail("ClosedChannelException not thrown");
+            } catch (ClosedChannelException unused) {
+                pass();
+            }
+        } catch (IOException ioe) {
+            unexpected(ioe);
+        }
+    }
+
+    /* SCTP_PRIMARY_ADDR */
+    void sctpPrimaryAddr() throws IOException {
+        SocketAddress addrToSet = null;
+        ByteBuffer buffer = ByteBuffer.allocate(Util.SMALL_BUFFER);
+
+        System.out.println("TESTING SCTP_PRIMARY_ADDR");
+
+        /* create listening channel */
+        SctpServerChannel ssc = SctpServerChannel.open().bind(null);
+        Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
+        if (addrs.isEmpty())
+            debug("addrs should not be empty");
+
+        InetSocketAddress serverAddr = (InetSocketAddress) addrs.iterator().next();
+
+        /* setup an association implicitly by sending a small message */
+        int streamNumber = 0;
+        debug("sending to " + serverAddr + " on stream number: " + streamNumber);
+        MessageInfo info = MessageInfo.createOutgoing(serverAddr, streamNumber);
+        buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
+        buffer.flip();
+
+        debug("sending small message: " + buffer);
+        SctpMultiChannel smc = SctpMultiChannel.open();
+        int sent = smc.send(buffer, info);
+
+        /* Receive the COMM_UP */
+        buffer.clear();
+        SOTNotificationHandler handler = new SOTNotificationHandler();
+        smc.configureBlocking(false);
+        info = smc.receive(buffer, null, handler);
+        check(handler.receivedCommUp(), "COMM_UP no received");
+        Set<Association> associations = smc.associations();
+        check(!associations.isEmpty(),"There should be some associations");
+        Association assoc = associations.iterator().next();
+
+        SctpChannel peerChannel = ssc.accept();
+        ssc.close();
+        Set<SocketAddress> peerAddrs = peerChannel.getAllLocalAddresses();
+        debug("Peer local Addresses: ");
+        for (Iterator<SocketAddress> it = peerAddrs.iterator(); it.hasNext(); ) {
+            InetSocketAddress addr = (InetSocketAddress)it.next();
+            debug("\t" + addr);
+            addrToSet = addr;   // any of the peer addresses will do!
+        }
+
+        /* retrieval of SCTP_PRIMARY_ADDR is not supported on Solaris */
+        if ("SunOS".equals(osName)) {
+            /* For now do not set this option. There is a bug on Solaris 10 pre Update 5
+             * where setting this option returns Invalid argument */
+            //debug("Set SCTP_PRIMARY_ADDR with " + addrToSet);
+            //smc.setOption(SCTP_PRIMARY_ADDR, addrToSet, assoc);
+            return;
+        } else { /* Linux */
+            SocketAddress primaryAddr = smc.getOption(SCTP_PRIMARY_ADDR, assoc);
+            System.out.println("SCTP_PRIMARY_ADDR returned: " + primaryAddr);
+            /* Verify that this is one of the peer addresses */
+            boolean found = false;
+            addrToSet = primaryAddr; // may not have more than one addr
+            for (Iterator<SocketAddress> it = peerAddrs.iterator(); it.hasNext(); ) {
+                InetSocketAddress addr = (InetSocketAddress)it.next();
+                if (addr.equals(primaryAddr)) {
+                    found = true;
+                }
+                addrToSet = addr;
+            }
+            check(found, "SCTP_PRIMARY_ADDR returned bogus address!");
+
+            smc.setOption(SCTP_PRIMARY_ADDR, addrToSet, assoc);
+            System.out.println("SCTP_PRIMARY_ADDR set to: " + addrToSet);
+            primaryAddr = smc.getOption(SCTP_PRIMARY_ADDR, assoc);
+            System.out.println("SCTP_PRIMARY_ADDR returned: " + primaryAddr);
+            check(addrToSet.equals(primaryAddr),"SCTP_PRIMARY_ADDR not set correctly");
+        }
+    }
+
+    class SOTNotificationHandler extends AbstractNotificationHandler<Object>
+    {
+        boolean receivedCommUp;  // false
+
+        boolean receivedCommUp() {
+            return receivedCommUp;
+        }
+
+        @Override
+        public HandlerResult handleNotification(
+                AssociationChangeNotification notification, Object attachment) {
+            AssocChangeEvent event = notification.event();
+            debug("AssociationChangeNotification");
+            debug("  Association: " + notification.association());
+            debug("  Event: " + event);
+
+            if (event.equals(AssocChangeEvent.COMM_UP))
+                receivedCommUp = true;
+
+            return HandlerResult.RETURN;
+        }
+    }
+
+            //--------------------- Infrastructure ---------------------------
+    boolean debug = true;
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
+    void debug(String message) {if(debug) { System.out.println(message); }  }
+    public static void main(String[] args) throws Throwable {
+        Class<?> k = new Object(){}.getClass().getEnclosingClass();
+        try {k.getMethod("instanceMain",String[].class)
+                .invoke( k.newInstance(), (Object) args);}
+        catch (Throwable e) {throw e.getCause();}}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/test/java/nio/file/DirectoryStream/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/DirectoryStream/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/DirectoryStream/Filters.java	Mon Jun 29 15:05:15 2009 +0100
+++ /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/test/java/nio/file/DirectoryStream/SecureDS.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/DirectoryStream/SecureDS.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/FileSystem/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/FileSystem/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Files/ContentType.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Files/ContentType.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Files/Misc.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Files/Misc.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Files/content_type.sh	Mon Jun 29 15:05:15 2009 +0100
+++ /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/test/java/nio/file/Path/CopyAndMove.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Path/CopyAndMove.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Path/FileAttributes.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Path/Links.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Path/Links.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Path/Misc.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Path/Misc.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Path/PathOps.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Path/PathOps.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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/test/java/nio/file/Path/TemporaryFiles.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/Path/TemporaryFiles.java	Mon Jun 29 15:08:52 2009 +0100
@@ -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);
+
+        // check directory is empty
+        DirectoryStream<Path> stream = dir.newDirectoryStream();
+        try {
+            if (stream.iterator().hasNext())
+                throw new RuntimeException("Tempory directory not empty");
+        } finally {
+            stream.close();
+        }
+
+        // check file permissions are 0700 or more secure
+        if (dir.getFileStore().supportsFileAttributeView("posix")) {
+            Set<PosixFilePermission> perms = Attributes
+                .readPosixFileAttributes(dir).permissions();
+            perms.remove(PosixFilePermission.OWNER_READ);
+            perms.remove(PosixFilePermission.OWNER_WRITE);
+            perms.remove(PosixFilePermission.OWNER_EXECUTE);
+            if (!perms.isEmpty())
+                throw new RuntimeException("Temporary directory is not secure");
+        }
+    }
+
     public static void main(String[] args) throws IOException {
-        Path file = File.createTempFile("blah", null, false).toPath();
+        Path file = File.createTemporaryFile("blah", null).toPath();
         try {
             checkFile(file);
         } finally {
             TestUtil.deleteUnchecked(file);
         }
-
-        // temporary file with deleteOnExit
-        file = File.createTempFile("blah", "tmp", true).toPath();
-        checkFile(file);
-        // write path to temporary file to file so that calling script can
-        // check that it is deleted
-        OutputStream out = Paths.get(args[0]).newOutputStream();
-        try {
-            out.write(file.toString().getBytes());
-        } finally {
-            out.close();
-        }
     }
 }
--- a/test/java/nio/file/Path/temporary_files.sh	Mon Jun 29 15:05:15 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-#
-# Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-# CA 95054 USA or visit www.sun.com if you need additional information or
-# have any questions.
-#
-
-# @test
-# @bug 4313887
-# @summary Unit test for File.createTempFile (to be be moved to test/java/io/File)
-# @library ..
-# @build TemporaryFiles
-# @run shell temporary_files.sh
-
-# if TESTJAVA isn't set then we assume an interactive run.
-
-if [ -z "$TESTJAVA" ]; then
-    TESTSRC=.
-    TESTCLASSES=.
-    JAVA=java
-else
-    JAVA="${TESTJAVA}/bin/java"
-fi
-
-OS=`uname -s`
-case "$OS" in
-    Windows_* )
-        CLASSPATH="${TESTCLASSES};${TESTSRC}"
-        ;;
-    * )
-        CLASSPATH=${TESTCLASSES}:${TESTSRC}
-        ;;
-esac
-export CLASSPATH
-
-TMPFILENAME="$$.tmp"
-$JAVA TemporaryFiles $TMPFILENAME 2>&1
-if [ $? != 0 ]; then exit 1; fi
-if [ ! -f $TMPFILENAME ]; then
-    echo "$TMPFILENAME not found"
-    exit 1
-fi
-TMPFILE=`cat $TMPFILENAME`
-if [ -f $TMPFILE ]; then
-    echo "$TMPFILE not deleted"
-    exit 1
-fi
-
-exit 0
--- a/test/java/nio/file/TestUtil.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/TestUtil.java	Mon Jun 29 15:08:52 2009 +0100
@@ -55,7 +55,7 @@
             @Override
             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                 try {
-                    file.delete(false);
+                    file.delete();
                 } catch (IOException x) {
                     System.err.format("Unable to delete %s: %s\n", file, x);
                 }
@@ -64,7 +64,7 @@
             @Override
             public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
                 try {
-                    dir.delete(false);
+                    dir.delete();
                 } catch (IOException x) {
                     System.err.format("Unable to delete %s: %s\n", dir, x);
                 }
@@ -78,7 +78,7 @@
         });
     }
 
-    static void deleteUnchecked(FileRef file) {
+    static void deleteUnchecked(Path file) {
         try {
             file.delete();
         } catch (IOException exc) {
@@ -114,7 +114,7 @@
         Path target = dir.resolve("testtarget");
         try {
             link.createSymbolicLink(target);
-            target.delete(false);
+            link.delete();
             return true;
         } catch (UnsupportedOperationException x) {
             return false;
--- a/test/java/nio/file/WatchService/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/WatchService/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.WatchService
  * @library ..
  * @run main/timeout=120 Basic
@@ -114,7 +114,7 @@
                 throw new RuntimeException("register did not return existing key");
 
             System.out.format("delete %s\n", file);
-            file.delete(false);
+            file.delete();
             takeExpectedKey(watcher, myKey);
             checkExpectedEvent(myKey.pollEvents(),
                 StandardWatchEventKind.ENTRY_DELETE, name);
@@ -137,7 +137,7 @@
                 throw new RuntimeException("register did not return existing key");
 
             System.out.format("update: %s\n", file);
-            OutputStream out = file.newOutputStream(EnumSet.of(StandardOpenOption.APPEND));
+            OutputStream out = file.newOutputStream(StandardOpenOption.APPEND);
             try {
                 out.write("I am a small file".getBytes("UTF-8"));
             } finally {
@@ -151,7 +151,7 @@
             System.out.println("OKAY");
 
             // done
-            file.delete(false);
+            file.delete();
 
         } finally {
             watcher.close();
@@ -190,7 +190,7 @@
             }
 
             // done
-            file.delete(false);
+            file.delete();
 
             System.out.println("OKAY");
 
@@ -216,7 +216,7 @@
                 new WatchEvent.Kind<?>[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY });
 
             System.out.format("delete: %s\n", subdir);
-            subdir.delete(false);
+            subdir.delete();
             takeExpectedKey(watcher, myKey);
 
             System.out.println("reset key");
@@ -439,7 +439,7 @@
                 throw new RuntimeException("key not expected");
 
             // delete gus1
-            file1.delete(false);
+            file1.delete();
 
             // check that key2 got ENTRY_DELETE
             takeExpectedKey(watcher2, key2);
--- a/test/java/nio/file/WatchService/FileTreeModifier.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/WatchService/FileTreeModifier.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Sanity test for Sun-specific FILE_TREE watch event modifier
  * @library ..
  */
@@ -85,7 +85,7 @@
             throw new RuntimeException("Existing key not returned");
 
         // delete a/b/c/foo and check we get delete event
-        file.delete(false);
+        file.delete();
         checkExpectedEvent(watcher, ENTRY_DELETE, top.relativize(file));
         key.reset();
 
--- a/test/java/nio/file/attribute/AclFileAttributeView/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/attribute/AclFileAttributeView/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.attribute.AclFileAttribueView
  * @library ../..
  */
@@ -147,7 +147,10 @@
     }
 
     public static void main(String[] args) throws IOException {
-        Path dir = TestUtil.createTemporaryDirectory();
+        // use work directory rather than system temporary directory to
+        // improve chances that ACLs are supported
+        Path dir = Paths.get("./work" + new Random().nextInt())
+            .createDirectory();
         try {
             if (!dir.getFileStore().supportsFileAttributeView("acl")) {
                 System.out.println("ACLs not supported - test skipped!");
--- a/test/java/nio/file/attribute/Attributes/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +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.attribute.Attributes
- * @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 Basic {
-
-    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));
-        }
-    }
-
-    // Exercise getAttribute/setAttribute/readAttributes on basic attributes
-    static void checkBasicAttributes(FileRef file, BasicFileAttributes attrs)
-        throws IOException
-    {
-        // getAttribute
-        checkEqual(attrs.size(), Attributes.getAttribute(file, "size"));
-        checkEqual(attrs.lastModifiedTime(),
-                   Attributes.getAttribute(file, "basic:lastModifiedTime"));
-        checkEqual(attrs.lastAccessTime(),
-                   Attributes.getAttribute(file, "lastAccessTime"));
-        checkEqual(attrs.creationTime(),
-                   Attributes.getAttribute(file, "basic:creationTime"));
-        assertTrue((Boolean)Attributes.getAttribute(file, "isRegularFile"));
-        assertTrue(!(Boolean)Attributes.getAttribute(file, "basic:isDirectory"));
-        assertTrue(!(Boolean)Attributes.getAttribute(file, "isSymbolicLink"));
-        assertTrue(!(Boolean)Attributes.getAttribute(file, "basic:isOther"));
-        checkEqual(attrs.linkCount(),
-                   (Integer)Attributes.getAttribute(file, "linkCount"));
-        checkEqual(attrs.fileKey(), Attributes.getAttribute(file, "basic:fileKey"));
-
-        // setAttribute
-        if (attrs.resolution() == TimeUnit.MILLISECONDS) {
-            long modTime = attrs.lastModifiedTime();
-            Attributes.setAttribute(file, "basic:lastModifiedTime", 0L);
-            assertTrue(Attributes.readBasicFileAttributes(file).lastModifiedTime() == 0L);
-            Attributes.setAttribute(file, "lastModifiedTime", modTime);
-            assertTrue(Attributes.readBasicFileAttributes(file).lastModifiedTime() == modTime);
-        }
-
-        // readAttributes
-        Map<String,?> map;
-        map = Attributes.readAttributes(file, "*");
-        assertTrue(map.size() >= 11);
-        checkEqual(attrs.isRegularFile(), map.get("isRegularFile")); // check one
-
-        map = Attributes.readAttributes(file, "basic:*");
-        assertTrue(map.size() >= 11);
-        checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); // check one
-
-        map = Attributes.readAttributes(file, "size,lastModifiedTime");
-        assertTrue(map.size() == 2);
-        checkEqual(attrs.size(), map.get("size"));
-        checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime"));
-
-        map = Attributes.readAttributes(file,
-            "basic:lastModifiedTime,lastAccessTime,linkCount,ShouldNotExist");
-        assertTrue(map.size() == 3);
-        checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime"));
-        checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime"));
-        checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime"));
-    }
-
-    // Exercise getAttribute/setAttribute/readAttributes on posix attributes
-    static void checkPosixAttributes(FileRef file, PosixFileAttributes attrs)
-        throws IOException
-    {
-        checkBasicAttributes(file, attrs);
-
-        // getAttribute
-        checkEqual(attrs.permissions(),
-                   Attributes.getAttribute(file, "posix:permissions"));
-        checkEqual(attrs.owner(),
-                   Attributes.getAttribute(file, "posix:owner"));
-        checkEqual(attrs.group(),
-                   Attributes.getAttribute(file, "posix:group"));
-
-        // 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);
-        Attributes.setAttribute(file, "posix:permissions", newPerms);
-        checkEqual(Attributes.readPosixFileAttributes(file).permissions(), newPerms);
-        Attributes.setAttribute(file, "posix:permissions", orig);
-        checkEqual(Attributes.readPosixFileAttributes(file).permissions(), orig);
-        Attributes.setAttribute(file, "posix:owner", attrs.owner());
-        Attributes.setAttribute(file, "posix:group", attrs.group());
-
-        // readAttributes
-        Map<String,?> map;
-        map = Attributes.readAttributes(file, "posix:*");
-        assertTrue(map.size() >= 14);
-        checkEqual(attrs.permissions(), map.get("permissions")); // check one
-
-        map = Attributes.readAttributes(file, "posix:size,owner,ShouldNotExist");
-        assertTrue(map.size() == 2);
-        checkEqual(attrs.size(), map.get("size"));
-        checkEqual(attrs.owner(), map.get("owner"));
-    }
-
-    // Exercise getAttribute/setAttribute/readAttributes on unix attributes
-    static void checkUnixAttributes(FileRef file) throws IOException {
-        // getAttribute
-        int mode = (Integer)Attributes.getAttribute(file, "unix:mode");
-        long ino = (Long)Attributes.getAttribute(file, "unix:ino");
-        long dev = (Long)Attributes.getAttribute(file, "unix:dev");
-        long rdev = (Long)Attributes.getAttribute(file, "unix:rdev");
-        int uid = (Integer)Attributes.getAttribute(file, "unix:uid");
-        int gid = (Integer)Attributes.getAttribute(file, "unix:gid");
-        long ctime = (Long)Attributes.getAttribute(file, "unix:ctime");
-
-        // readAttributes
-        Map<String,?> map;
-        map = Attributes.readAttributes(file, "unix:*");
-        assertTrue(map.size() >= 21);
-
-        map = Attributes.readAttributes(file, "unix:size,uid,gid,ShouldNotExist");
-        assertTrue(map.size() == 3);
-        checkEqual(map.get("size"),
-                   Attributes.readBasicFileAttributes(file).size());
-    }
-
-    // Exercise getAttribute/setAttribute/readAttributes on dos attributes
-    static void checkDosAttributes(FileRef file, DosFileAttributes attrs)
-        throws IOException
-    {
-        checkBasicAttributes(file, attrs);
-
-        // getAttribute
-        checkEqual(attrs.isReadOnly(),
-                   Attributes.getAttribute(file, "dos:readonly"));
-        checkEqual(attrs.isHidden(),
-                   Attributes.getAttribute(file, "dos:hidden"));
-        checkEqual(attrs.isSystem(),
-                   Attributes.getAttribute(file, "dos:system"));
-        checkEqual(attrs.isArchive(),
-                   Attributes.getAttribute(file, "dos:archive"));
-
-        // setAttribute
-        boolean value;
-
-        value = attrs.isReadOnly();
-        Attributes.setAttribute(file, "dos:readonly", !value);
-        checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), !value);
-        Attributes.setAttribute(file, "dos:readonly", value);
-        checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), value);
-
-        value = attrs.isHidden();
-        Attributes.setAttribute(file, "dos:hidden", !value);
-        checkEqual(Attributes.readDosFileAttributes(file).isHidden(), !value);
-        Attributes.setAttribute(file, "dos:hidden", value);
-        checkEqual(Attributes.readDosFileAttributes(file).isHidden(), value);
-
-        value = attrs.isSystem();
-        Attributes.setAttribute(file, "dos:system", !value);
-        checkEqual(Attributes.readDosFileAttributes(file).isSystem(), !value);
-        Attributes.setAttribute(file, "dos:system", value);
-        checkEqual(Attributes.readDosFileAttributes(file).isSystem(), value);
-
-        value = attrs.isArchive();
-        Attributes.setAttribute(file, "dos:archive", !value);
-        checkEqual(Attributes.readDosFileAttributes(file).isArchive(), !value);
-        Attributes.setAttribute(file, "dos:archive", value);
-        checkEqual(Attributes.readDosFileAttributes(file).isArchive(), value);
-
-        // readAttributes
-        Map<String,?> map;
-        map = Attributes.readAttributes(file, "dos:*");
-        assertTrue(map.size() >= 15);
-        checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one
-
-        map = Attributes.readAttributes(file, "dos:size,hidden,ShouldNotExist");
-        assertTrue(map.size() == 2);
-        checkEqual(attrs.size(), map.get("size"));
-        checkEqual(attrs.isHidden(), map.get("hidden"));
-    }
-
-    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));
-        } finally {
-            file.delete();
-        }
-    }
-
-
-    public static void main(String[] args) throws IOException {
-        Path dir = TestUtil.createTemporaryDirectory();
-        try {
-            doTests(dir);
-        } finally {
-            TestUtil.removeAll(dir);
-        }
-    }
-}
--- a/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.attribute.BasicFileAttributeView
  * @library ../..
  */
@@ -48,14 +48,11 @@
         check(!attrs.isRegularFile(), "is not a regular file");
         check(!attrs.isSymbolicLink(), "is not a link");
         check(!attrs.isOther(), "is not other");
-        check(attrs.linkCount() >= 1, "should be at least 1");
 
         // last-modified-time should match java.io.File
-        if (attrs.resolution() == TimeUnit.MILLISECONDS) {
-            File f = new File(dir.toString());
-            check(f.lastModified() == attrs.lastModifiedTime(),
-                "last-modified time should be the same");
-        }
+        File f = new File(dir.toString());
+        check(f.lastModified() == attrs.lastModifiedTime().toMillis(),
+              "last-modified time should be the same");
     }
 
     static void checkAttributesOfFile(Path dir, Path file)
@@ -66,30 +63,27 @@
         check(!attrs.isDirectory(), "is not a directory");
         check(!attrs.isSymbolicLink(), "is not a link");
         check(!attrs.isOther(), "is not other");
-        check(attrs.linkCount() >= 1, "should be at least 1");
 
         // size and last-modified-time should match java.io.File
         File f = new File(file.toString());
         check(f.length() == attrs.size(), "size should be the same");
-        if (attrs.resolution() == TimeUnit.MILLISECONDS) {
-            check(f.lastModified() == attrs.lastModifiedTime(),
-                "last-modified time should be the same");
-        }
+        check(f.lastModified() == attrs.lastModifiedTime().toMillis(),
+              "last-modified time should be the same");
 
         // copy last-modified time and file create time from directory to file,
         // re-read attribtues, and check they match
         BasicFileAttributeView view =
             file.getFileAttributeView(BasicFileAttributeView.class);
         BasicFileAttributes dirAttrs = Attributes.readBasicFileAttributes(dir);
-        view.setTimes(dirAttrs.lastModifiedTime(), null, null, dirAttrs.resolution());
-        if (dirAttrs.creationTime() != -1L) {
-            view.setTimes(null, null, dirAttrs.creationTime(), dirAttrs.resolution());
+        view.setTimes(dirAttrs.lastModifiedTime(), null, null);
+        if (dirAttrs.creationTime() != null) {
+            view.setTimes(null, null, dirAttrs.creationTime());
         }
         attrs = view.readAttributes();
-        check(attrs.lastModifiedTime() == dirAttrs.lastModifiedTime(),
+        check(attrs.lastModifiedTime().equals(dirAttrs.lastModifiedTime()),
             "last-modified time should be equal");
-        if (dirAttrs.creationTime() != -1L) {
-            check(attrs.creationTime() == dirAttrs.creationTime(),
+        if (dirAttrs.creationTime() != null) {
+            check(attrs.creationTime().equals(dirAttrs.creationTime()),
                 "create time should be the same");
         }
 
@@ -107,7 +101,6 @@
         check(!attrs.isDirectory(), "is a directory");
         check(!attrs.isRegularFile(), "is not a regular file");
         check(!attrs.isOther(), "is not other");
-        check(attrs.linkCount() >= 1, "should be at least 1");
     }
 
     static void attributeReadWriteTests(Path dir)
--- a/test/java/nio/file/attribute/DosFileAttributeView/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/attribute/DosFileAttributeView/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.attribute.DosFileAttributeView
  * @library ../..
  */
@@ -75,7 +75,7 @@
 
         // create "foo" and test that we can read/write each FAT attribute
         Path file = dir.resolve("foo");
-        file.newOutputStream().close();
+        file.createFile();
         try {
             testAttributes(file
                 .getFileAttributeView(DosFileAttributeView.class));
--- a/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.attribute.FileStoreAttributeView
  * @library ../..
  */
@@ -106,43 +106,10 @@
         checkWithin1GB(free, attrs.unallocatedSpace());
         checkWithin1GB(usable, attrs.usableSpace());
 
-        // get values by name (and in bulk)
-        FileStoreAttributeView view = fs.getFileStoreAttributeView("space");
-        checkWithin1GB(total, (Long)view.getAttribute("totalSpace"));
-        checkWithin1GB(free, (Long)view.getAttribute("unallocatedSpace"));
-        checkWithin1GB(usable, (Long)view.getAttribute("usableSpace"));
-        Map<String,?> map = view.readAttributes("*");
-        checkWithin1GB(total, (Long)map.get("totalSpace"));
-        checkWithin1GB(free, (Long)map.get("unallocatedSpace"));
-        checkWithin1GB(usable, (Long)map.get("usableSpace"));
-        map = view.readAttributes("totalSpace", "unallocatedSpace", "usableSpace");
-        checkWithin1GB(total, (Long)map.get("totalSpace"));
-        checkWithin1GB(free, (Long)map.get("unallocatedSpace"));
-        checkWithin1GB(usable, (Long)map.get("usableSpace"));
-    }
-
-    /**
-     * Check (Windows-specific) volume attributes
-     */
-    static void checkVolumeAttributes() throws IOException {
-        System.out.println(" -- volumes -- ");
-        for (FileStore store: FileSystems.getDefault().getFileStores()) {
-            FileStoreAttributeView view = store.getFileStoreAttributeView("volume");
-            if (view == null)
-                continue;
-            Map<String,?> attrs = view.readAttributes("*");
-            int vsn = (Integer)attrs.get("vsn");
-            boolean compressed = (Boolean)attrs.get("compressed");
-            boolean removable = (Boolean)attrs.get("removable");
-            boolean cdrom = (Boolean)attrs.get("cdrom");
-            String type;
-            if (removable) type = "removable";
-            else if (cdrom) type = "cdrom";
-            else type = "unknown";
-            System.out.format("%s (%s) vsn:%x compressed:%b%n", store.name(),
-                type, vsn, compressed);
-        }
-
+        // get values by name
+        checkWithin1GB(total, (Long)fs.getAttribute("space:totalSpace"));
+        checkWithin1GB(free, (Long)fs.getAttribute("space:unallocatedSpace"));
+        checkWithin1GB(usable, (Long)fs.getAttribute("space:usableSpace"));
     }
 
     public static void main(String[] args) throws IOException {
@@ -161,9 +128,6 @@
             Path file = dir.resolve("foo").createFile();
             checkSpace(file);
 
-            // volume attributes (Windows specific)
-            checkVolumeAttributes();
-
         } finally {
             TestUtil.removeAll(dir);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/file/attribute/FileTime/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6844313
+ * @summary Unit test for java.nio.file.FileTime
+ */
+
+import java.nio.file.attribute.FileTime;
+import java.util.concurrent.TimeUnit;
+import static java.util.concurrent.TimeUnit.*;
+import java.io.IOException;
+
+public class Basic {
+
+    public static void main(String[] args) throws IOException {
+        long now = System.currentTimeMillis();
+        long tomorrowInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) + 1;
+
+        // equals
+        eq(now, MILLISECONDS, now, MILLISECONDS);
+        eq(now, MILLISECONDS, now*1000L, MICROSECONDS);
+        neq(now, MILLISECONDS, 0, MILLISECONDS);
+        neq(now, MILLISECONDS, 0, MICROSECONDS);
+
+        // compareTo
+        cmp(now, MILLISECONDS, now, MILLISECONDS, 0);
+        cmp(now, MILLISECONDS, now*1000L, MICROSECONDS, 0);
+        cmp(now, MILLISECONDS, now-1234, MILLISECONDS, 1);
+        cmp(now, MILLISECONDS, now+1234, MILLISECONDS, -1);
+        cmp(tomorrowInDays, DAYS, now, MILLISECONDS, 1);
+        cmp(now, MILLISECONDS, tomorrowInDays, DAYS, -1);
+
+        // toString
+        ts(1L, DAYS, "1970-01-02T00:00:00Z");
+        ts(1L, HOURS, "1970-01-01T01:00:00Z");
+        ts(1L, MINUTES, "1970-01-01T00:01:00Z");
+        ts(1L, SECONDS, "1970-01-01T00:00:01Z");
+        ts(1L, MILLISECONDS, "1970-01-01T00:00:00.001Z");
+        ts(1L, MICROSECONDS, "1970-01-01T00:00:00.000001Z");
+        ts(1L, NANOSECONDS, "1970-01-01T00:00:00.000000001Z");
+
+        ts(-1L, DAYS, "1969-12-31T00:00:00Z");
+        ts(-1L, HOURS, "1969-12-31T23:00:00Z");
+        ts(-1L, MINUTES, "1969-12-31T23:59:00Z");
+        ts(-1L, SECONDS, "1969-12-31T23:59:59Z");
+        ts(-1L, MILLISECONDS, "1969-12-31T23:59:59.999Z");
+        ts(-1L, MICROSECONDS, "1969-12-31T23:59:59.999999Z");
+        ts(-1L, NANOSECONDS, "1969-12-31T23:59:59.999999999Z");
+
+        ts(-62135596799999L, MILLISECONDS, "0001-01-01T00:00:00.001Z");
+        ts(-62135596800000L, MILLISECONDS, "0001-01-01T00:00:00Z");
+        ts(-62135596800001L, MILLISECONDS, "-0001-12-31T23:59:59.999Z");
+
+        ts(253402300799999L, MILLISECONDS, "9999-12-31T23:59:59.999Z");
+        ts(-377642044800001L, MILLISECONDS, "-9999-12-31T23:59:59.999Z");
+
+        // NTFS epoch in usec.
+        ts(-11644473600000000L, MICROSECONDS, "1601-01-01T00:00:00Z");
+
+        // nulls
+        try {
+            FileTime.from(0L, null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException npe) { }
+        FileTime time = FileTime.fromMillis(now);
+        if (time.equals(null))
+            throw new RuntimeException("should not be equal to null");
+        try {
+            time.compareTo(null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException npe) { }
+    }
+
+    static void cmp(long v1, TimeUnit u1, long v2, TimeUnit u2, int expected) {
+        int result = FileTime.from(v1, u1).compareTo(FileTime.from(v2, u2));
+        if (result != expected)
+            throw new RuntimeException("unexpected order");
+    }
+
+    static void eq(long v1, TimeUnit u1, long v2, TimeUnit u2) {
+        FileTime t1 = FileTime.from(v1, u1);
+        FileTime t2 = FileTime.from(v2, u2);
+        if (!t1.equals(t2))
+            throw new RuntimeException("not equal");
+        if (t1.hashCode() != t2.hashCode())
+            throw new RuntimeException("hashCodes should be equal");
+    }
+
+    static void neq(long v1, TimeUnit u1, long v2, TimeUnit u2) {
+        FileTime t1 = FileTime.from(v1, u1);
+        FileTime t2 = FileTime.from(v2, u2);
+        if (t1.equals(t2))
+            throw new RuntimeException("should not be equal");
+    }
+
+    static void ts(long v, TimeUnit y, String expected) {
+        String s = FileTime.from(v, y).toString();
+        if (!s.equals(expected))
+            throw new RuntimeException("unexpected format");
+    }
+}
--- a/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.attribute.PosixFileAttributeView
  * @library ../..
  */
@@ -44,15 +44,14 @@
      * Use view to update permission to the given mode and check that the
      * permissions have been updated.
      */
-    static void testPermissions(PosixFileAttributeView view, String mode)
-        throws IOException
-    {
+    static void testPermissions(Path file, String mode) throws IOException {
         System.out.format("change mode: %s\n", mode);
         Set<PosixFilePermission> perms = PosixFilePermissions.fromString(mode);
 
         // change permissions and re-read them.
-        view.setPermissions(perms);
-        Set<PosixFilePermission> current = view.readAttributes().permissions();
+        Attributes.setPosixFilePermissions(file, perms);
+        Set<PosixFilePermission> current = Attributes
+            .readPosixFileAttributes(file).permissions();
         if (!current.equals(perms)) {
             throw new RuntimeException("Actual permissions: " +
                 PosixFilePermissions.toString(current) + ", expected: " +
@@ -60,8 +59,8 @@
         }
 
         // repeat test using setAttribute/getAttribute
-        view.setAttribute("permissions", perms);
-        current = (Set<PosixFilePermission>)view.getAttribute("permissions");
+        file.setAttribute("posix:permissions", perms);
+        current = (Set<PosixFilePermission>)file.getAttribute("posix:permissions");
         if (!current.equals(perms)) {
             throw new RuntimeException("Actual permissions: " +
                 PosixFilePermissions.toString(current) + ", expected: " +
@@ -98,17 +97,14 @@
         FileAttribute<Set<PosixFilePermission>> attr =
             PosixFilePermissions.asFileAttribute(requested);
         System.out.format("create file with mode: %s\n", mode);
-
-        EnumSet<StandardOpenOption> options = EnumSet.of(StandardOpenOption.CREATE_NEW,
-            StandardOpenOption.WRITE);
-        file.newOutputStream(options, attr).close();
+        file.createFile(attr);
         try {
             checkSecure(requested,  file
                 .getFileAttributeView(PosixFileAttributeView.class)
                 .readAttributes()
                 .permissions());
         } finally {
-            file.delete(false);
+            file.delete();
         }
 
         System.out.format("create directory with mode: %s\n", mode);
@@ -119,7 +115,7 @@
                 .readAttributes()
                 .permissions());
         } finally {
-            file.delete(false);
+            file.delete();
         }
     }
 
@@ -134,7 +130,7 @@
         // create file and test updating and reading its permissions
         Path file = dir.resolve("foo");
         System.out.format("create %s\n", file);
-        file.newOutputStream().close();
+        file.createFile();
         try {
             // get initial permissions so that we can restore them later
             PosixFileAttributeView view = file
@@ -144,32 +140,32 @@
 
             // test various modes
             try {
-                testPermissions(view, "---------");
-                testPermissions(view, "r--------");
-                testPermissions(view, "-w-------");
-                testPermissions(view, "--x------");
-                testPermissions(view, "rwx------");
-                testPermissions(view, "---r-----");
-                testPermissions(view, "----w----");
-                testPermissions(view, "-----x---");
-                testPermissions(view, "---rwx---");
-                testPermissions(view, "------r--");
-                testPermissions(view, "-------w-");
-                testPermissions(view, "--------x");
-                testPermissions(view, "------rwx");
-                testPermissions(view, "r--r-----");
-                testPermissions(view, "r--r--r--");
-                testPermissions(view, "rw-rw----");
-                testPermissions(view, "rwxrwx---");
-                testPermissions(view, "rw-rw-r--");
-                testPermissions(view, "r-xr-x---");
-                testPermissions(view, "r-xr-xr-x");
-                testPermissions(view, "rwxrwxrwx");
+                testPermissions(file, "---------");
+                testPermissions(file, "r--------");
+                testPermissions(file, "-w-------");
+                testPermissions(file, "--x------");
+                testPermissions(file, "rwx------");
+                testPermissions(file, "---r-----");
+                testPermissions(file, "----w----");
+                testPermissions(file, "-----x---");
+                testPermissions(file, "---rwx---");
+                testPermissions(file, "------r--");
+                testPermissions(file, "-------w-");
+                testPermissions(file, "--------x");
+                testPermissions(file, "------rwx");
+                testPermissions(file, "r--r-----");
+                testPermissions(file, "r--r--r--");
+                testPermissions(file, "rw-rw----");
+                testPermissions(file, "rwxrwx---");
+                testPermissions(file, "rw-rw-r--");
+                testPermissions(file, "r-xr-x---");
+                testPermissions(file, "r-xr-xr-x");
+                testPermissions(file, "rwxrwxrwx");
             } finally {
                 view.setPermissions(save);
             }
         } finally {
-            file.delete(false);
+            file.delete();
         }
 
         // create link (to file that doesn't exist) and test reading of
@@ -185,7 +181,7 @@
                     throw new RuntimeException("not a link");
                 }
             } finally {
-                link.delete(false);
+                link.delete();
             }
         }
 
@@ -239,7 +235,7 @@
         Path file = dir.resolve("gus");
         System.out.format("create %s\n", file);
 
-        file.newOutputStream().close();
+        file.createFile();
         try {
 
             // read attributes of directory to get owner/group
@@ -251,13 +247,14 @@
             view.setOwner(attrs.owner());
             view.setGroup(attrs.group());
 
-            // repeat test using setAttribute
-            Map<String,?> map = view.readAttributes("owner","group");
-            view.setAttribute("owner", map.get("owner"));
-            view.setAttribute("group", map.get("group"));
+            // repeat test using set/getAttribute
+            UserPrincipal owner = (UserPrincipal)file.getAttribute("posix:owner");
+            file.setAttribute("posix:owner", owner);
+            UserPrincipal group = (UserPrincipal)file.getAttribute("posix:group");
+            file.setAttribute("posix:group", group);
 
         } finally {
-            file.delete(false);
+            file.delete();
         }
 
         System.out.println("OKAY");
--- a/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java	Mon Jun 29 15:05:15 2009 +0100
+++ b/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java	Mon Jun 29 15:08:52 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.attribute.UserDefinedFileAttributeView
  * @library ../..
  */
@@ -129,23 +129,24 @@
             throw new RuntimeException("Attribute name in list");
 
         // Test: dynamic access
+        String name = "user:" + ATTR_NAME;
         byte[] valueAsBytes = ATTR_VALUE.getBytes();
-        view.setAttribute(ATTR_NAME, valueAsBytes);
-        byte[] actualAsBytes = (byte[])view.getAttribute(ATTR_NAME);
+        file.setAttribute(name, valueAsBytes);
+        byte[] actualAsBytes = (byte[])file.getAttribute(name);
         if (!Arrays.equals(valueAsBytes, actualAsBytes))
             throw new RuntimeException("Unexpected attribute value");
-        Map<String,?> map = view.readAttributes(ATTR_NAME);
+        Map<String,?> map = file.readAttributes(name);
         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
             throw new RuntimeException("Unexpected attribute value");
-        map = view.readAttributes(ATTR_NAME, "*");
+        map = file.readAttributes("user:*");
         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
             throw new RuntimeException("Unexpected attribute value");
-        map = view.readAttributes("DoesNotExist");
+        map = file.readAttributes("user:DoesNotExist");
         if (!map.isEmpty())
             throw new RuntimeException("Map expected to be empty");
     }
 
-    static void miscTests(Path file) throws IOException {
+    static void miscTests(final Path file) throws IOException {
         final UserDefinedFileAttributeView view = file
             .getFileAttributeView(UserDefinedFileAttributeView.class);
         view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
@@ -179,27 +180,31 @@
             }});
         expectNullPointerException(new Task() {
             public void run() throws IOException {
-                view.getAttribute(null);
+                file.getAttribute(null);
             }});
         expectNullPointerException(new Task() {
             public void run() throws IOException {
-                view.setAttribute(ATTR_NAME, null);
+                file.getAttribute("user:" + ATTR_NAME, (LinkOption[])null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                file.setAttribute("user:" + ATTR_NAME, null);
             }});
         expectNullPointerException(new Task() {
             public void run() throws IOException {
-                view.setAttribute(null, new byte[0]);
-            }});
-         expectNullPointerException(new Task() {
-            public void run() throws IOException {
-               view.readAttributes(null);
+                file.setAttribute(null, new byte[0]);
             }});
         expectNullPointerException(new Task() {
             public void run() throws IOException {
-                view.readAttributes("*", (String[])null);
+                file.setAttribute("user: " + ATTR_NAME, new byte[0], (LinkOption[])null);
             }});
         expectNullPointerException(new Task() {
             public void run() throws IOException {
-                view.readAttributes("*", ATTR_NAME, null);
+                file.readAttributes((String)null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                file.readAttributes("*", (LinkOption[])null);
             }});
 
         // Read-only buffer
@@ -224,7 +229,7 @@
         // create temporary directory to run tests
         Path dir = TestUtil.createTemporaryDirectory();
         try {
-            if (!dir.getFileStore().supportsFileAttributeView("xattr")) {
+            if (!dir.getFileStore().supportsFileAttributeView("user")) {
                 System.out.println("UserDefinedFileAttributeView not supported - skip test");
                 return;
             }