changeset 1566:2257885742d0

Initial import of NIO2. 2009-01-12 Andrew John Hughes <gnu_andrew@member.fsf.org> Initial import of NIO2 code. * patches/ecj/icedtea-pr261.patch: Moved to general patches. * Makefile.am: Add NIO2 patch. * configure.ac: Add --enable-nio2 option (on by default). * overlays/nio2/openjdk/jdk/make/mkdemo/nio/Makefile, * overlays/nio2/openjdk/jdk/make/mkdemo/nio/ZipFileSystem/Makefile, * overlays/nio2/openjdk/jdk/make/mksample/nio/aio/Makefile, * overlays/nio2/openjdk/jdk/make/mksample/nio/file/Makefile, * overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/File.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/FilePermission.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Inputs.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Outputs.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousByteChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/Channels.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/CompletionHandler.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileLock.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/exceptions, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/package-info.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/package.html, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessDeniedException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessMode.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AtomicMoveNotSupportedException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedDirectoryStreamException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedFileSystemException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedWatchServiceException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/CopyOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryNotEmptyException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStream.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStreamFilters.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAction.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAlreadyExistsException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileRef.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileStore.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystem.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemAlreadyExistsException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemNotFoundException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystems.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileTreeWalker.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitResult.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitor.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Files.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/InvalidPathException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkPermission.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NoSuchFileException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotDirectoryException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotLinkException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/OpenOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Path.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/PathMatcher.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Paths.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderMismatchException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderNotFoundException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ReadOnlyFileSystemException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SecureDirectoryStream.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SimpleFileVisitor.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardCopyOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardOpenOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardWatchEventKind.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchEvent.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchKey.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchService.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Watchable.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntry.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryFlag.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryPermission.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryType.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/Attributes.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributes.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributes.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttribute.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileOwnerAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributes.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/GroupPrincipal.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributes.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermission.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermissions.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipal.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalLookupService.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalNotFoundException.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/package-info.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/package-info.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/AbstractPath.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileTypeDetector.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/package-info.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/util/Scanner.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileLockImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Cancellable.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/FileLockTable.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Groupable.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Invoker.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/PendingFuture.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/ThreadPool.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Globs.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/MimeType.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Reflect.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/aio/EchoServer.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/AclEdit.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Chmod.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Copy.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/DiskUsage.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/FileType.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/WatchDir.java, * overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Xdd.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNamedAttributeView.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNamedAttributeView.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixException.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/EPollPort.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c, * overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/Iocp.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsException.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUriSupport.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java, * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java, * overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/Iocp.c, * overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c, * overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c, * overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c, * overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c, * overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c, * overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/Sanity.java, * overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/sanity.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/io/Inputs/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Attack.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Identity.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Restart.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Unbounded.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Lock.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/MyThreadFactory.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Leaky.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/Channels/Basic2.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Filters.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/SecureDS.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileStore/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileSystem/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ContentType.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/CreateFileTree.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ForceLoad.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/Misc.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/PrintFileTree.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SimpleFileTypeDetector.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SkipSiblings.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/TerminateWalk.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/content_type.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/walk_file_tree.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/CopyAndMove.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/DeleteOnClose.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Links.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Misc.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/PathOps.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/SBC.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/TemporaryFiles.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/UriImportExport.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/delete_on_close.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/temporary_files.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/PathMatcher/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/TestUtil.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/FileTreeModifier.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/WithSecurityManager.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/denyAll.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndOneLevel.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndTree.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirOnly.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/Attributes/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/SetDefaultProvider.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/TestProvider.java: Added. * patches/icedtea-nio2.patch: New patch. * patches/icedtea-pr261.patch: Moved from ecj-specific patches.
author Andrew John Hughes <gnu_andrew@member.fsf.org>
date Mon, 12 Jan 2009 21:46:12 +0000
parents e34ba0ba2281
children 981d5e01b698
files ChangeLog Makefile.am configure.ac overlays/nio2/openjdk/jdk/make/mkdemo/nio/Makefile overlays/nio2/openjdk/jdk/make/mkdemo/nio/ZipFileSystem/Makefile overlays/nio2/openjdk/jdk/make/mksample/nio/aio/Makefile overlays/nio2/openjdk/jdk/make/mksample/nio/file/Makefile overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/File.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/FilePermission.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Inputs.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Outputs.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousByteChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/Channels.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/CompletionHandler.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileLock.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/exceptions overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/package-info.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/package.html overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessDeniedException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessMode.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AtomicMoveNotSupportedException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedDirectoryStreamException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedFileSystemException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedWatchServiceException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/CopyOption.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryNotEmptyException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStream.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStreamFilters.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAction.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAlreadyExistsException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileRef.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileStore.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystem.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemAlreadyExistsException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemNotFoundException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystems.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileTreeWalker.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitOption.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitResult.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitor.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Files.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/InvalidPathException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkOption.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkPermission.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NoSuchFileException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotDirectoryException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotLinkException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/OpenOption.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Path.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/PathMatcher.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Paths.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderMismatchException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderNotFoundException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ReadOnlyFileSystemException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SecureDirectoryStream.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SimpleFileVisitor.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardCopyOption.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardOpenOption.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardWatchEventKind.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchEvent.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchKey.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchService.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Watchable.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntry.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryFlag.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryPermission.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryType.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/Attributes.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributes.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributes.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttribute.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileOwnerAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributes.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/GroupPrincipal.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributes.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermission.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermissions.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipal.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalLookupService.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalNotFoundException.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/package-info.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/package-info.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/AbstractPath.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileSystemProvider.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileTypeDetector.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/package-info.java overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/util/Scanner.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileLockImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Cancellable.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/FileLockTable.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Groupable.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Invoker.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/PendingFuture.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/ThreadPool.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Globs.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/MimeType.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Reflect.java overlays/nio2/openjdk/jdk/src/share/sample/nio/aio/EchoServer.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/AclEdit.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Chmod.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Copy.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/DiskUsage.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/FileType.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/WatchDir.java overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Xdd.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNamedAttributeView.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNamedAttributeView.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixException.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/EPollPort.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/Iocp.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsException.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUriSupport.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/Iocp.c overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/Sanity.java overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/sanity.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/io/Inputs/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Attack.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Identity.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Restart.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Unbounded.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Lock.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/MyThreadFactory.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Leaky.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/Channels/Basic2.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Filters.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/SecureDS.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileStore/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileSystem/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ContentType.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/CreateFileTree.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ForceLoad.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/Misc.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/PrintFileTree.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SimpleFileTypeDetector.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SkipSiblings.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/TerminateWalk.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/content_type.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/walk_file_tree.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/CopyAndMove.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/DeleteOnClose.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Links.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Misc.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/PathOps.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/SBC.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/TemporaryFiles.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/UriImportExport.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/delete_on_close.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/temporary_files.sh overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/PathMatcher/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/TestUtil.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/FileTreeModifier.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/WithSecurityManager.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/denyAll.policy overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndOneLevel.policy overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndTree.policy overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirOnly.policy overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/Attributes/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView/Basic.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/SetDefaultProvider.java overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/TestProvider.java patches/ecj/icedtea-pr261.patch patches/icedtea-nio2.patch patches/icedtea-pr261.patch
diffstat 317 files changed, 69760 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jan 12 17:29:21 2009 +0000
+++ b/ChangeLog	Mon Jan 12 21:46:12 2009 +0000
@@ -1,3 +1,323 @@
+2009-01-12  Andrew John Hughes  <gnu_andrew@member.fsf.org>
+
+	Initial import of NIO2 code.
+	* patches/ecj/icedtea-pr261.patch: Moved to general patches.
+	* Makefile.am: Add NIO2 patch.
+	* configure.ac: Add --enable-nio2 option (on by default).
+	* overlays/nio2/openjdk/jdk/make/mkdemo/nio/Makefile,
+	* overlays/nio2/openjdk/jdk/make/mkdemo/nio/ZipFileSystem/Makefile,
+	* overlays/nio2/openjdk/jdk/make/mksample/nio/aio/Makefile,
+	* overlays/nio2/openjdk/jdk/make/mksample/nio/file/Makefile,
+	* overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/File.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/FilePermission.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Inputs.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Outputs.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousByteChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/Channels.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/CompletionHandler.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileLock.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/exceptions,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/package-info.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/package.html,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessDeniedException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessMode.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AtomicMoveNotSupportedException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedDirectoryStreamException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedFileSystemException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedWatchServiceException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/CopyOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryNotEmptyException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStreamFilters.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAction.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAlreadyExistsException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileRef.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileStore.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemAlreadyExistsException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemNotFoundException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystems.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileTreeWalker.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitResult.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitor.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Files.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/InvalidPathException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkPermission.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NoSuchFileException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotDirectoryException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotLinkException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/OpenOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Path.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/PathMatcher.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Paths.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderMismatchException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderNotFoundException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ReadOnlyFileSystemException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SecureDirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SimpleFileVisitor.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardCopyOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardOpenOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardWatchEventKind.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchEvent.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchKey.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchService.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Watchable.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntry.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryFlag.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryPermission.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryType.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/Attributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttribute.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileOwnerAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/GroupPrincipal.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermission.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermissions.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipal.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalLookupService.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalNotFoundException.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/package-info.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/package-info.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/AbstractPath.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/package-info.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/util/Scanner.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileLockImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Cancellable.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/FileLockTable.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Groupable.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Invoker.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/PendingFuture.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/ThreadPool.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Globs.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/MimeType.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Reflect.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/aio/EchoServer.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/AclEdit.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Chmod.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Copy.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/DiskUsage.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/FileType.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/WatchDir.java,
+	* overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Xdd.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixException.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/EPollPort.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/Iocp.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsException.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUriSupport.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java,
+	* overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/Iocp.c,
+	* overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c,
+	* overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c,
+	* overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c,
+	* overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c,
+	* overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c,
+	* overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/Sanity.java,
+	* overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/sanity.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/io/Inputs/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Attack.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Identity.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Restart.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Unbounded.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Lock.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/MyThreadFactory.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Leaky.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/Channels/Basic2.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Filters.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/SecureDS.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileStore/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileSystem/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ContentType.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/CreateFileTree.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ForceLoad.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/Misc.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/PrintFileTree.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SimpleFileTypeDetector.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SkipSiblings.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/TerminateWalk.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/content_type.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/walk_file_tree.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/CopyAndMove.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/DeleteOnClose.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Links.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Misc.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/PathOps.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/SBC.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/TemporaryFiles.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/UriImportExport.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/delete_on_close.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/temporary_files.sh,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/PathMatcher/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/TestUtil.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/FileTreeModifier.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/WithSecurityManager.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/denyAll.policy,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndOneLevel.policy,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndTree.policy,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirOnly.policy,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/Attributes/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView/Basic.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/SetDefaultProvider.java,
+	* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/TestProvider.java: Added.
+	* patches/icedtea-nio2.patch: New patch.
+	* patches/icedtea-pr261.patch: Moved from ecj-specific patches.
+
 2009-01-12  Andrew Haley  <aph@redhat.com>
 
 	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp (SharkBlock::do_ldc):
--- a/Makefile.am	Mon Jan 12 17:29:21 2009 +0000
+++ b/Makefile.am	Mon Jan 12 21:46:12 2009 +0000
@@ -643,7 +643,8 @@
 	patches/icedtea-samejvm-safe.patch \
 	patches/icedtea-6728542-epoll.patch \
 	patches/icedtea-io_util-overflow.patch \
-	patches/icedtea-cc-interp-jvmti.patch
+	patches/icedtea-cc-interp-jvmti.patch \
+	patches/icedtea-pr261.patch
 
 if WITH_ALT_HSBUILD
 ICEDTEA_PATCHES += \
@@ -688,6 +689,10 @@
 ICEDTEA_PATCHES += $(sort $(subst $(abs_top_srcdir)/,,$(XRENDER_PATCH_FILES)))
 endif
 
+if ENABLE_NIO2
+ICEDTEA_PATCHES += patches/icedtea-nio2.patch
+endif
+
 ICEDTEA_PATCHES += \
 	$(DISTRIBUTION_PATCHES) \
 	patches/icedtea-a11y-property-change.patch \
@@ -883,8 +888,11 @@
 	fi
 
 stamps/overlay.stamp: stamps/patch.stamp
-	cp -r $(abs_top_srcdir)/overlays/openjdk/* openjdk/ \
-	  && touch stamps/overlay.stamp
+	cp -r $(abs_top_srcdir)/overlays/openjdk/* openjdk/
+if ENABLE_NIO2
+	cp -r $(abs_top_srcdir)/overlays/nio2/openjdk/* openjdk/
+endif
+	touch stamps/overlay.stamp
 
 # OpenJDK ecj Source Preparation Targets
 # ======================================
@@ -927,8 +935,7 @@
 ICEDTEA_ECJ_PATCHES = patches/ecj/icedtea.patch \
 	patches/ecj/icedtea-hotspot-$(HSBUILD).patch \
 	patches/ecj/icedtea-spp.patch \
-	patches/ecj/icedtea-jopt.patch \
-	patches/ecj/icedtea-pr261.patch
+	patches/ecj/icedtea-jopt.patch
 
 stamps/patch-ecj.stamp: stamps/extract-ecj.stamp
 	mkdir -p stamps; \
--- a/configure.ac	Mon Jan 12 17:29:21 2009 +0000
+++ b/configure.ac	Mon Jan 12 21:46:12 2009 +0000
@@ -149,6 +149,14 @@
 AM_CONDITIONAL([ENABLE_XRENDER], [test x$ENABLE_XRENDER = xyes])
 AC_MSG_RESULT(${ENABLE_XRENDER})
 
+AC_MSG_CHECKING(whether to include NIO2 support)
+AC_ARG_ENABLE([nio2],
+	      [AS_HELP_STRING([--disable-nio2],
+	      		      [Disable inclusion of backported NIO2])],
+	      [ENABLE_XRENDER="${enableval}"], [ENABLE_NIO2='yes'])
+AM_CONDITIONAL([ENABLE_NIO2], [test x$ENABLE_NIO2 = xyes])
+AC_MSG_RESULT(${ENABLE_NIO2})
+
 AC_MSG_CHECKING(whether to build VisualVM)
 AC_ARG_ENABLE([visualvm],
               [AS_HELP_STRING([--enable-visualvm],
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/make/mkdemo/nio/Makefile	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,37 @@
+#
+# Copyright 2007-2008 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.
+#
+
+#
+# Makefile for building the NIO demo(s)
+#
+
+BUILDDIR = ../..
+PRODUCT = demos
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = ZipFileSystem
+
+all build clean clobber::
+	$(SUBDIRS-loop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/make/mkdemo/nio/ZipFileSystem/Makefile	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,40 @@
+#
+# Copyright 2007-2008 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.
+#
+
+BUILDDIR = ../../..
+PRODUCT = demo/nio
+DEMONAME = ZipFileSystem
+include $(BUILDDIR)/common/Defs.gmk
+
+DEMO_ROOT       = $(SHARE_SRC)/demo/nio/$(DEMONAME)
+DEMO_TOPFILES   = ./README.txt
+DEMO_MAINCLASS  = $(DEMONAME)
+DEMO_DESTDIR    = $(DEMODIR)/nio/$(DEMONAME)
+
+#
+# Demo jar building rules.
+#
+include $(BUILDDIR)/common/Demo.gmk
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/make/mksample/nio/aio/Makefile	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+#
+# Copyright 2007-2008 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.
+#
+
+#
+# Makefile for the nio/aio sample code
+#
+
+BUILDDIR = ../../..
+
+PRODUCT = java
+
+include $(BUILDDIR)/common/Defs.gmk
+
+SAMPLE_SRC_DIR = $(SHARE_SRC)/sample/nio/aio
+SAMPLE_DST_DIR = $(SAMPLEDIR)/nio/aio
+
+SAMPLE_FILES =							\
+	$(SAMPLE_DST_DIR)/EchoServer.java
+
+all build: $(SAMPLE_FILES)
+
+$(SAMPLE_DST_DIR)/%: $(SAMPLE_SRC_DIR)/%
+	$(install-file)
+
+clean clobber:
+	$(RM) -r $(SAMPLE_DST_DIR)
+
+.PHONY: all build clean clobber
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/make/mksample/nio/file/Makefile	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,56 @@
+#
+# Copyright 2007 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.
+#
+
+#
+# Makefile for the nio/file sample code
+#
+
+BUILDDIR = ../../..
+
+PRODUCT = java
+
+include $(BUILDDIR)/common/Defs.gmk
+
+SAMPLE_SRC_DIR = $(SHARE_SRC)/sample/nio/file
+SAMPLE_DST_DIR = $(SAMPLEDIR)/nio/file
+
+SAMPLE_FILES =							\
+	$(SAMPLE_DST_DIR)/AclEdit.java				\
+	$(SAMPLE_DST_DIR)/Chmod.java				\
+	$(SAMPLE_DST_DIR)/Copy.java				\
+	$(SAMPLE_DST_DIR)/DiskUsage.java			\
+	$(SAMPLE_DST_DIR)/FileType.java				\
+	$(SAMPLE_DST_DIR)/WatchDir.java				\
+	$(SAMPLE_DST_DIR)/Xdd.java
+
+all build: $(SAMPLE_FILES)
+
+$(SAMPLE_DST_DIR)/%: $(SAMPLE_SRC_DIR)/%
+	$(install-file)
+
+clean clobber:
+	$(RM) -r $(SAMPLE_DST_DIR)
+
+.PHONY: all build clean clobber
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007-2008 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 com.sun.nio.file;
+
+import java.nio.file.CopyOption;
+
+/**
+ * Defines <em>extended</em> copy options supported on some platforms
+ * by Sun's provider implementation.
+ *
+ * @since 1.7
+ */
+
+public enum ExtendedCopyOption implements CopyOption {
+    /**
+     * The copy may be interrupted by the {@link Thread#interrupt interrupt}
+     * method.
+     */
+    INTERRUPTIBLE,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2008 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 com.sun.nio.file;
+
+import java.nio.file.OpenOption;
+
+/**
+ * Defines <em>extended</em> open options supported on some platforms
+ * by Sun's provider implementation.
+ *
+ * @since 1.7
+ */
+
+public enum ExtendedOpenOption implements OpenOption {
+    /**
+     * Prevent operations on the file that request read access.
+     */
+    NOSHARE_READ,
+    /**
+     * Prevent operations on the file that request write access.
+     */
+    NOSHARE_WRITE,
+    /**
+     * Prevent operations on the file that request delete access.
+     */
+    NOSHARE_DELETE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007-2008 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 com.sun.nio.file;
+
+import java.nio.file.WatchEvent.Modifier;
+
+/**
+ * Defines <em>extended</em> watch event modifiers supported on some platforms
+ * by Sun's provider implementation.
+ *
+ * @since 1.7
+ */
+
+public enum ExtendedWatchEventModifier implements Modifier {
+
+    /**
+     * Register a file tree instead of a single directory.
+     */
+    FILE_TREE,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/File.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,450 @@
+/*
+ * Copyright 1994-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.io;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+
+import java.io.IOException;
+import java.io.IOError;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+
+import org.classpath.icedtea.java.nio.file.FileAlreadyExistsException;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.FileSystems;
+import org.classpath.icedtea.java.nio.file.InvalidPathException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.Paths;
+
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermissions;
+
+import org.classpath.icedtea.misc.SharedSecrets;
+
+/**
+ * An abstract representation of file and directory pathnames.
+ *
+ * <p> User interfaces and operating systems use system-dependent <em>pathname
+ * strings</em> to name files and directories.  This class presents an
+ * abstract, system-independent view of hierarchical pathnames.  An
+ * <em>abstract pathname</em> has two components:
+ *
+ * <ol>
+ * <li> An optional system-dependent <em>prefix</em> string,
+ *      such as a disk-drive specifier, <code>"/"</code>&nbsp;for the UNIX root
+ *      directory, or <code>"\\\\"</code>&nbsp;for a Microsoft Windows UNC pathname, and
+ * <li> A sequence of zero or more string <em>names</em>.
+ * </ol>
+ *
+ * The first name in an abstract pathname may be a directory name or, in the
+ * case of Microsoft Windows UNC pathnames, a hostname.  Each subsequent name
+ * in an abstract pathname denotes a directory; the last name may denote
+ * either a directory or a file.  The <em>empty</em> abstract pathname has no
+ * prefix and an empty name sequence.
+ *
+ * <p> The conversion of a pathname string to or from an abstract pathname is
+ * inherently system-dependent.  When an abstract pathname is converted into a
+ * pathname string, each name is separated from the next by a single copy of
+ * the default <em>separator character</em>.  The default name-separator
+ * character is defined by the system property <code>file.separator</code>, and
+ * is made available in the public static fields <code>{@link
+ * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
+ * When a pathname string is converted into an abstract pathname, the names
+ * within it may be separated by the default name-separator character or by any
+ * other name-separator character that is supported by the underlying system.
+ *
+ * <p> A pathname, whether abstract or in string form, may be either
+ * <em>absolute</em> or <em>relative</em>.  An absolute pathname is complete in
+ * that no other information is required in order to locate the file that it
+ * denotes.  A relative pathname, in contrast, must be interpreted in terms of
+ * information taken from some other pathname.  By default the classes in the
+ * <code>java.io</code> package always resolve relative pathnames against the
+ * current user directory.  This directory is named by the system property
+ * <code>user.dir</code>, and is typically the directory in which the Java
+ * virtual machine was invoked.
+ *
+ * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
+ * the {@link #getParent} method of this class and consists of the pathname's
+ * prefix and each name in the pathname's name sequence except for the last.
+ * Each directory's absolute pathname is an ancestor of any <tt>File</tt>
+ * object with an absolute abstract pathname which begins with the directory's
+ * absolute pathname.  For example, the directory denoted by the abstract
+ * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the
+ * pathname <tt>"/usr/local/bin"</tt>.
+ *
+ * <p> The prefix concept is used to handle root directories on UNIX platforms,
+ * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
+ * as follows:
+ *
+ * <ul>
+ *
+ * <li> For UNIX platforms, the prefix of an absolute pathname is always
+ * <code>"/"</code>.  Relative pathnames have no prefix.  The abstract pathname
+ * denoting the root directory has the prefix <code>"/"</code> and an empty
+ * name sequence.
+ *
+ * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
+ * specifier consists of the drive letter followed by <code>":"</code> and
+ * possibly followed by <code>"\\"</code> if the pathname is absolute.  The
+ * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share
+ * name are the first two names in the name sequence.  A relative pathname that
+ * does not specify a drive has no prefix.
+ *
+ * </ul>
+ *
+ * <p> Instances of this class may or may not denote an actual file-system
+ * object such as a file or a directory.  If it does denote such an object
+ * then that object resides in a <i>partition</i>.  A partition is an
+ * operating system-specific portion of storage for a file system.  A single
+ * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may
+ * contain multiple partitions.  The object, if any, will reside on the
+ * partition <a name="partName">named</a> by some ancestor of the absolute
+ * form of this pathname.
+ *
+ * <p> A file system may implement restrictions to certain operations on the
+ * actual file-system object, such as reading, writing, and executing.  These
+ * restrictions are collectively known as <i>access permissions</i>.  The file
+ * system may have multiple sets of access permissions on a single object.
+ * For example, one set may apply to the object's <i>owner</i>, and another
+ * may apply to all other users.  The access permissions on an object may
+ * cause some methods in this class to fail.
+ *
+ * <p> Instances of the <code>File</code> class are immutable; that is, once
+ * created, the abstract pathname represented by a <code>File</code> object
+ * will never change.
+ *
+ * <h4>Interoperability with {@code java.nio.file} package</h4>
+ *
+ * <p> {@note new}
+ * The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
+ * package defines interfaces and classes for the Java virtual machine to access
+ * files, file attributes, and file systems. This API may be used to overcome
+ * many of the limitations of the {@code java.io.File} class.
+ * The {@link #toPath toPath} method may be used to obtain a {@link
+ * Path} that uses the abstract path represented by a {@code File} object to
+ * locate a file. The resulting {@code Path} provides more efficient and
+ * extensive access to file attributes, additional file operations, and I/O
+ * exceptions to help diagnose errors when an operation on a file fails.
+ *
+ * @author  unascribed
+ * @since   JDK1.0
+ */
+
+public class File
+  extends java.io.File
+{
+
+    /**
+     * Creates a new <code>File</code> instance by converting the given
+     * pathname string into an abstract pathname.  If the given string is
+     * the empty string, then the result is the empty abstract pathname.
+     *
+     * @param   pathname  A pathname string
+     * @throws  NullPointerException
+     *          If the <code>pathname</code> argument is <code>null</code>
+     */
+    @ConstructorProperties("path")
+    public File(String pathname) {
+      super(pathname);
+    }
+
+    /* Note: The two-argument File constructors do not interpret an empty
+       parent abstract pathname as the current user directory.  An empty parent
+       instead causes the child to be resolved against the system-dependent
+       directory defined by the FileSystem.getDefaultParent method.  On Unix
+       this default is "/", while on Microsoft Windows it is "\\".  This is required for
+       compatibility with the original behavior of this class. */
+
+    /**
+     * Creates a new <code>File</code> instance from a parent pathname string
+     * and a child pathname string.
+     *
+     * <p> If <code>parent</code> is <code>null</code> then the new
+     * <code>File</code> instance is created as if by invoking the
+     * single-argument <code>File</code> constructor on the given
+     * <code>child</code> pathname string.
+     *
+     * <p> Otherwise the <code>parent</code> pathname string is taken to denote
+     * a directory, and the <code>child</code> pathname string is taken to
+     * denote either a directory or a file.  If the <code>child</code> pathname
+     * string is absolute then it is converted into a relative pathname in a
+     * system-dependent way.  If <code>parent</code> is the empty string then
+     * the new <code>File</code> instance is created by converting
+     * <code>child</code> into an abstract pathname and resolving the result
+     * against a system-dependent default directory.  Otherwise each pathname
+     * string is converted into an abstract pathname and the child abstract
+     * pathname is resolved against the parent.
+     *
+     * @param   parent  The parent pathname string
+     * @param   child   The child pathname string
+     * @throws  NullPointerException
+     *          If <code>child</code> is <code>null</code>
+     */
+    public File(String parent, String child) {
+      super(parent, child);
+    }
+
+    /**
+     * Creates a new <code>File</code> instance from a parent abstract
+     * pathname and a child pathname string.
+     *
+     * <p> If <code>parent</code> is <code>null</code> then the new
+     * <code>File</code> instance is created as if by invoking the
+     * single-argument <code>File</code> constructor on the given
+     * <code>child</code> pathname string.
+     *
+     * <p> Otherwise the <code>parent</code> abstract pathname is taken to
+     * denote a directory, and the <code>child</code> pathname string is taken
+     * to denote either a directory or a file.  If the <code>child</code>
+     * pathname string is absolute then it is converted into a relative
+     * pathname in a system-dependent way.  If <code>parent</code> is the empty
+     * abstract pathname then the new <code>File</code> instance is created by
+     * converting <code>child</code> into an abstract pathname and resolving
+     * the result against a system-dependent default directory.  Otherwise each
+     * pathname string is converted into an abstract pathname and the child
+     * abstract pathname is resolved against the parent.
+     *
+     * @param   parent  The parent abstract pathname
+     * @param   child   The child pathname string
+     * @throws  NullPointerException
+     *          If <code>child</code> is <code>null</code>
+     */
+    public File(File parent, String child) {
+      super(parent, child);
+    }
+
+
+
+    /* -- Temporary files -- */
+
+    private static class TemporaryDirectory {
+        private TemporaryDirectory() { }
+
+        static final File valueAsFile =
+            new File(AccessController.doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+
+        // file name generation
+        private static final AtomicInteger counter =
+            new AtomicInteger(new Random().nextInt() & 0xffff);
+        static File generateFile(String prefix, String suffix, File dir) {
+            int n = counter.getAndIncrement();
+            return new File(dir, prefix + Integer.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(valueAsFile.getPath())
+                                .getFileStore().supportsFileAttributeView("posix");
+                        } catch (IOException e) {
+                            throw new IOError(e);
+                        }
+                    }
+                });
+        }
+    }
+
+    /**
+     * {@note new}
+     * 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.
+     *
+     * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
+     * attributes} to set atomically when creating the file. Each 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.
+     *
+     * @param   prefix
+     *          The prefix string to be used in generating the file's
+     *          name; must be at least three characters long
+     * @param   suffix
+     *          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
+     *
+     * @return  An abstract pathname denoting a newly-created empty file
+     *
+     * @throws  IllegalArgumentException
+     *          If the <code>prefix</code> argument contains fewer than three
+     *          characters
+     * @throws  UnsupportedOperationException
+     *          If the array contains an attribute that cannot be set atomically
+     *          when creating the file
+     * @throws  IOException
+     *          If a file could not be created
+     * @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.
+     * @since 1.7
+     */
+    public static File createTempFile(String prefix,
+                                      String suffix,
+                                      boolean deleteOnExit,
+                                      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)
+		  SharedSecrets.getJavaIODeleteOnExitAccess().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
+            }
+        }
+    }
+
+    // -- Integration with java.nio.file --
+
+    private volatile transient Path filePath;
+
+    /**
+     * {@note new}
+     * 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:
+     * <blockquote><pre>
+     * {@link FileSystems#getDefault FileSystems.getDefault}().{@link 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
+     * user directory.
+     *
+     * @return  A {@code Path} constructed from this abstract path. The resulting
+     *          {@code Path} is associated with the {@link FileSystems#getDefault
+     *          default-filesystem}.
+     *
+     * @throws  InvalidPathException
+     *          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) {
+            synchronized (this) {
+                if (filePath == null) {
+		    String path = getPath();
+                    if (path.length() == 0) {
+                        // assume default file system treats "." as current directory
+                        filePath = Paths.get(".");
+                    } else {
+                        filePath = Paths.get(path);
+                    }
+                }
+            }
+        }
+        return filePath;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/FilePermission.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,852 @@
+/*
+ * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.io;
+
+import java.security.*;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Vector;
+import java.util.Collections;
+import java.io.IOException;
+import java.io.ObjectStreamField;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import sun.security.util.SecurityConstants;
+
+/**
+ * This class represents access to a file or directory.  A FilePermission consists
+ * of a pathname and a set of actions valid for that pathname.
+ * <P>
+ * Pathname is the pathname of the file or directory granted the specified
+ * actions. A pathname that ends in "/*" (where "/" is
+ * the file separator character, <code>File.separatorChar</code>) indicates
+ * all the files and directories contained in that directory. A pathname
+ * that ends with "/-" indicates (recursively) all files
+ * and subdirectories contained in that directory. A pathname consisting of
+ * the special token "&lt;&lt;ALL FILES&gt;&gt;" matches <b>any</b> file.
+ * <P>
+ * Note: A pathname consisting of a single "*" indicates all the files
+ * in the current directory, while a pathname consisting of a single "-"
+ * indicates all the files in the current directory and
+ * (recursively) all files and subdirectories contained in the current
+ * directory.
+ * <P>
+ * {@note revised}
+ * The actions to be granted are passed to the constructor in a string containing
+ * a list of one or more comma-separated keywords. The possible keywords are
+ * "read", "write", "execute", "delete", and "readlink". Their meaning is
+ * defined as follows:
+ * <P>
+ * <DL>
+ *    <DT> read <DD> read permission
+ *    <DT> write <DD> write permission
+ *    <DT> execute
+ *    <DD> execute permission. Allows <code>Runtime.exec</code> to
+ *         be called. Corresponds to <code>SecurityManager.checkExec</code>.
+ *    <DT> delete
+ *    <DD> delete permission. Allows <code>File.delete</code> to
+ *         be called. Corresponds to <code>SecurityManager.checkDelete</code>.
+ *    <DT> readlink
+ *    <DD> read link permission. Allows the target of a
+ *         <a href="../nio/file/package-summary.html#links">symbolic link</a>
+ *         to be read by invoking the {@link java.nio.file.Path#readSymbolicLink
+ *         readSymbolicLink } method.
+ * </DL>
+ * <P>
+ * The actions string is converted to lowercase before processing.
+ * <P>
+ * Be careful when granting FilePermissions. Think about the implications
+ * of granting read and especially write access to various files and
+ * directories. The "&lt;&lt;ALL FILES>>" permission with write action is
+ * especially dangerous. This grants permission to write to the entire
+ * file system. One thing this effectively allows is replacement of the
+ * system binary, including the JVM runtime environment.
+ *
+ * <p>Please note: Code can always read a file from the same
+ * directory it's in (or a subdirectory of that directory); it does not
+ * need explicit permission to do so.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ *
+ *
+ * @author Marianne Mueller
+ * @author Roland Schemers
+ * @since 1.2
+ *
+ * @serial exclude
+ */
+
+public final class FilePermission extends Permission implements Serializable {
+
+    /**
+     * Execute action.
+     */
+    private final static int EXECUTE = 0x1;
+    /**
+     * Write action.
+     */
+    private final static int WRITE   = 0x2;
+    /**
+     * Read action.
+     */
+    private final static int READ    = 0x4;
+    /**
+     * Delete action.
+     */
+    private final static int DELETE  = 0x8;
+    /**
+     * Read link action.
+     */
+    private final static int READLINK    = 0x10;
+
+    /**
+     * All actions (read,write,execute,delete,readlink)
+     */
+    private final static int ALL     = READ|WRITE|EXECUTE|DELETE|READLINK;
+    /**
+     * No actions.
+     */
+    private final static int NONE    = 0x0;
+
+    // the actions mask
+    private transient int mask;
+
+    // does path indicate a directory? (wildcard or recursive)
+    private transient boolean directory;
+
+    // is it a recursive directory specification?
+    private transient boolean recursive;
+
+    /**
+     * the actions string.
+     *
+     * @serial
+     */
+    private String actions; // Left null as long as possible, then
+                            // created and re-used in the getAction function.
+
+    // canonicalized dir path. In the case of
+    // directories, it is the name "/blah/*" or "/blah/-" without
+    // the last character (the "*" or "-").
+
+    private transient String cpath;
+
+    // static Strings used by init(int mask)
+    private static final char RECURSIVE_CHAR = '-';
+    private static final char WILD_CHAR = '*';
+
+/*
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append("***\n");
+        sb.append("cpath = "+cpath+"\n");
+        sb.append("mask = "+mask+"\n");
+        sb.append("actions = "+getActions()+"\n");
+        sb.append("directory = "+directory+"\n");
+        sb.append("recursive = "+recursive+"\n");
+        sb.append("***\n");
+        return sb.toString();
+    }
+*/
+
+    private static final long serialVersionUID = 7930732926638008763L;
+
+    /**
+     * initialize a FilePermission object. Common to all constructors.
+     * Also called during de-serialization.
+     *
+     * @param mask the actions mask to use.
+     *
+     */
+    private void init(int mask)
+    {
+
+        if ((mask & ALL) != mask)
+                throw new IllegalArgumentException("invalid actions mask");
+
+        if (mask == NONE)
+                throw new IllegalArgumentException("invalid actions mask");
+
+        if ((cpath = getName()) == null)
+                throw new NullPointerException("name can't be null");
+
+        this.mask = mask;
+
+        if (cpath.equals("<<ALL FILES>>")) {
+            directory = true;
+            recursive = true;
+            cpath = "";
+            return;
+        }
+
+        // store only the canonical cpath if possible
+        cpath = AccessController.doPrivileged(new PrivilegedAction<String>() {
+            public String run() {
+                try {
+                    return sun.security.provider.PolicyFile.canonPath(cpath);
+                } catch (IOException ioe) {
+                    return cpath;
+                }
+            }
+        });
+
+        int len = cpath.length();
+        char last = ((len > 0) ? cpath.charAt(len - 1) : 0);
+
+        if (last == RECURSIVE_CHAR &&
+            cpath.charAt(len - 2) == File.separatorChar) {
+            directory = true;
+            recursive = true;
+            cpath = cpath.substring(0, --len);
+        } else if (last == WILD_CHAR &&
+            cpath.charAt(len - 2) == File.separatorChar) {
+            directory = true;
+            //recursive = false;
+            cpath = cpath.substring(0, --len);
+        } else {
+            // overkill since they are initialized to false, but
+            // commented out here to remind us...
+            //directory = false;
+            //recursive = false;
+        }
+
+        // XXX: at this point the path should be absolute. die if it isn't?
+    }
+
+    /**
+     * Creates a new FilePermission object with the specified actions.
+     * <i>path</i> is the pathname of a file or directory, and <i>actions</i>
+     * contains a comma-separated list of the desired actions granted on the
+     * file or directory. Possible actions are
+     * "read", "write", "execute", "delete", and "readlink".
+     *
+     * <p>A pathname that ends in "/*" (where "/" is
+     * the file separator character, <code>File.separatorChar</code>)
+     * indicates all the files and directories contained in that directory.
+     * A pathname that ends with "/-" indicates (recursively) all files and
+     * subdirectories contained in that directory. The special pathname
+     * "&lt;&lt;ALL FILES&gt;&gt;" matches any file.
+     *
+     * <p>A pathname consisting of a single "*" indicates all the files
+     * in the current directory, while a pathname consisting of a single "-"
+     * indicates all the files in the current directory and
+     * (recursively) all files and subdirectories contained in the current
+     * directory.
+     *
+     * <p>A pathname containing an empty string represents an empty path.
+     *
+     * @param path the pathname of the file/directory.
+     * @param actions the action string.
+     *
+     * @throws IllegalArgumentException
+     *          If actions is <code>null</code>, empty or contains an action
+     *          other than the specified possible actions.
+     */
+
+    public FilePermission(String path, String actions)
+    {
+        super(path);
+        init(getMask(actions));
+    }
+
+    /**
+     * Creates a new FilePermission object using an action mask.
+     * More efficient than the FilePermission(String, String) constructor.
+     * Can be used from within
+     * code that needs to create a FilePermission object to pass into the
+     * <code>implies</code> method.
+     *
+     * @param path the pathname of the file/directory.
+     * @param mask the action mask to use.
+     */
+
+    // package private for use by the FilePermissionCollection add method
+    FilePermission(String path, int mask)
+    {
+        super(path);
+        init(mask);
+    }
+
+    /**
+     * Checks if this FilePermission object "implies" the specified permission.
+     * <P>
+     * More specifically, this method returns true if:<p>
+     * <ul>
+     * <li> <i>p</i> is an instanceof FilePermission,<p>
+     * <li> <i>p</i>'s actions are a proper subset of this
+     * object's actions, and <p>
+     * <li> <i>p</i>'s pathname is implied by this object's
+     *      pathname. For example, "/tmp/*" implies "/tmp/foo", since
+     *      "/tmp/*" encompasses all files in the "/tmp" directory,
+     *      including the one named "foo".
+     * </ul>
+     *
+     * @param p the permission to check against.
+     *
+     * @return <code>true</code> if the specified permission is not
+     *                  <code>null</code> and is implied by this object,
+     *                  <code>false</code> otherwise.
+     */
+    public boolean implies(Permission p) {
+        if (!(p instanceof FilePermission))
+            return false;
+
+        FilePermission that = (FilePermission) p;
+
+        // we get the effective mask. i.e., the "and" of this and that.
+        // They must be equal to that.mask for implies to return true.
+
+        return ((this.mask & that.mask) == that.mask) && impliesIgnoreMask(that);
+    }
+
+    /**
+     * Checks if the Permission's actions are a proper subset of the
+     * this object's actions. Returns the effective mask iff the
+     * this FilePermission's path also implies that FilePermission's path.
+     *
+     * @param that the FilePermission to check against.
+     * @param exact return immediately if the masks are not equal
+     * @return the effective mask
+     */
+    boolean impliesIgnoreMask(FilePermission that) {
+        if (this.directory) {
+            if (this.recursive) {
+                // make sure that.path is longer then path so
+                // something like /foo/- does not imply /foo
+                if (that.directory) {
+                    return (that.cpath.length() >= this.cpath.length()) &&
+                            that.cpath.startsWith(this.cpath);
+                }  else {
+                    return ((that.cpath.length() > this.cpath.length()) &&
+                        that.cpath.startsWith(this.cpath));
+                }
+            } else {
+                if (that.directory) {
+                    // if the permission passed in is a directory
+                    // specification, make sure that a non-recursive
+                    // permission (i.e., this object) can't imply a recursive
+                    // permission.
+                    if (that.recursive)
+                        return false;
+                    else
+                        return (this.cpath.equals(that.cpath));
+                } else {
+                    int last = that.cpath.lastIndexOf(File.separatorChar);
+                    if (last == -1)
+                        return false;
+                    else {
+                        // this.cpath.equals(that.cpath.substring(0, last+1));
+                        // Use regionMatches to avoid creating new string
+                        return (this.cpath.length() == (last + 1)) &&
+                            this.cpath.regionMatches(0, that.cpath, 0, last+1);
+                    }
+                }
+            }
+        } else if (that.directory) {
+            // if this is NOT recursive/wildcarded,
+            // do not let it imply a recursive/wildcarded permission
+            return false;
+        } else {
+            return (this.cpath.equals(that.cpath));
+        }
+    }
+
+    /**
+     * Checks two FilePermission objects for equality. Checks that <i>obj</i> is
+     * a FilePermission, and has the same pathname and actions as this object.
+     * <P>
+     * @param obj the object we are testing for equality with this object.
+     * @return <code>true</code> if obj is a FilePermission, and has the same
+     *          pathname and actions as this FilePermission object,
+     *          <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+
+        if (! (obj instanceof FilePermission))
+            return false;
+
+        FilePermission that = (FilePermission) obj;
+
+        return (this.mask == that.mask) &&
+            this.cpath.equals(that.cpath) &&
+            (this.directory == that.directory) &&
+            (this.recursive == that.recursive);
+    }
+
+    /**
+     * Returns the hash code value for this object.
+     *
+     * @return a hash code value for this object.
+     */
+
+    public int hashCode() {
+        return this.cpath.hashCode();
+    }
+
+    /**
+     * Converts an actions String to an actions mask.
+     *
+     * @param action the action string.
+     * @return the actions mask.
+     */
+    private static int getMask(String actions) {
+
+        int mask = NONE;
+
+        // Null action valid?
+        if (actions == null) {
+            return mask;
+        }
+        // Check against use of constants (used heavily within the JDK)
+        if (actions == SecurityConstants.FILE_READ_ACTION) {
+            return READ;
+        } else if (actions == SecurityConstants.FILE_WRITE_ACTION) {
+            return WRITE;
+        } else if (actions == SecurityConstants.FILE_EXECUTE_ACTION) {
+            return EXECUTE;
+        } else if (actions == SecurityConstants.FILE_DELETE_ACTION) {
+            return DELETE;
+        } else if (actions == SecurityConstants.FILE_READLINK_ACTION) {
+            return READLINK;
+        }
+
+        char[] a = actions.toCharArray();
+
+        int i = a.length - 1;
+        if (i < 0)
+            return mask;
+
+        while (i != -1) {
+            char c;
+
+            // skip whitespace
+            while ((i!=-1) && ((c = a[i]) == ' ' ||
+                               c == '\r' ||
+                               c == '\n' ||
+                               c == '\f' ||
+                               c == '\t'))
+                i--;
+
+            // check for the known strings
+            int matchlen;
+
+            if (i >= 3 && (a[i-3] == 'r' || a[i-3] == 'R') &&
+                          (a[i-2] == 'e' || a[i-2] == 'E') &&
+                          (a[i-1] == 'a' || a[i-1] == 'A') &&
+                          (a[i] == 'd' || a[i] == 'D'))
+            {
+                matchlen = 4;
+                mask |= READ;
+
+            } else if (i >= 4 && (a[i-4] == 'w' || a[i-4] == 'W') &&
+                                 (a[i-3] == 'r' || a[i-3] == 'R') &&
+                                 (a[i-2] == 'i' || a[i-2] == 'I') &&
+                                 (a[i-1] == 't' || a[i-1] == 'T') &&
+                                 (a[i] == 'e' || a[i] == 'E'))
+            {
+                matchlen = 5;
+                mask |= WRITE;
+
+            } else if (i >= 6 && (a[i-6] == 'e' || a[i-6] == 'E') &&
+                                 (a[i-5] == 'x' || a[i-5] == 'X') &&
+                                 (a[i-4] == 'e' || a[i-4] == 'E') &&
+                                 (a[i-3] == 'c' || a[i-3] == 'C') &&
+                                 (a[i-2] == 'u' || a[i-2] == 'U') &&
+                                 (a[i-1] == 't' || a[i-1] == 'T') &&
+                                 (a[i] == 'e' || a[i] == 'E'))
+            {
+                matchlen = 7;
+                mask |= EXECUTE;
+
+            } else if (i >= 5 && (a[i-5] == 'd' || a[i-5] == 'D') &&
+                                 (a[i-4] == 'e' || a[i-4] == 'E') &&
+                                 (a[i-3] == 'l' || a[i-3] == 'L') &&
+                                 (a[i-2] == 'e' || a[i-2] == 'E') &&
+                                 (a[i-1] == 't' || a[i-1] == 'T') &&
+                                 (a[i] == 'e' || a[i] == 'E'))
+            {
+                matchlen = 6;
+                mask |= DELETE;
+
+            } else if (i >= 7 && (a[i-7] == 'r' || a[i-7] == 'R') &&
+                                 (a[i-6] == 'e' || a[i-6] == 'E') &&
+                                 (a[i-5] == 'a' || a[i-5] == 'A') &&
+                                 (a[i-4] == 'd' || a[i-4] == 'D') &&
+                                 (a[i-3] == 'l' || a[i-3] == 'L') &&
+                                 (a[i-2] == 'i' || a[i-2] == 'I') &&
+                                 (a[i-1] == 'n' || a[i-1] == 'N') &&
+                                 (a[i] == 'k' || a[i] == 'K'))
+            {
+                matchlen = 8;
+                mask |= READLINK;
+
+            } else {
+                // parse error
+                throw new IllegalArgumentException(
+                        "invalid permission: " + actions);
+            }
+
+            // make sure we didn't just match the tail of a word
+            // like "ackbarfaccept".  Also, skip to the comma.
+            boolean seencomma = false;
+            while (i >= matchlen && !seencomma) {
+                switch(a[i-matchlen]) {
+                case ',':
+                    seencomma = true;
+                    /*FALLTHROUGH*/
+                case ' ': case '\r': case '\n':
+                case '\f': case '\t':
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "invalid permission: " + actions);
+                }
+                i--;
+            }
+
+            // point i at the location of the comma minus one (or -1).
+            i -= matchlen;
+        }
+
+        return mask;
+    }
+
+    /**
+     * Return the current action mask. Used by the FilePermissionCollection.
+     *
+     * @return the actions mask.
+     */
+
+    int getMask() {
+        return mask;
+    }
+
+    /**
+     * Return the canonical string representation of the actions.
+     * Always returns present actions in the following order:
+     * read, write, execute, delete, readlink.
+     *
+     * @return the canonical string representation of the actions.
+     */
+    private static String getActions(int mask)
+    {
+        StringBuilder sb = new StringBuilder();
+        boolean comma = false;
+
+        if ((mask & READ) == READ) {
+            comma = true;
+            sb.append("read");
+        }
+
+        if ((mask & WRITE) == WRITE) {
+            if (comma) sb.append(',');
+            else comma = true;
+            sb.append("write");
+        }
+
+        if ((mask & EXECUTE) == EXECUTE) {
+            if (comma) sb.append(',');
+            else comma = true;
+            sb.append("execute");
+        }
+
+        if ((mask & DELETE) == DELETE) {
+            if (comma) sb.append(',');
+            else comma = true;
+            sb.append("delete");
+        }
+
+        if ((mask & READLINK) == READLINK) {
+            if (comma) sb.append(',');
+            else comma = true;
+            sb.append("readlink");
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Returns the "canonical string representation" of the actions.
+     * That is, this method always returns present actions in the following order:
+     * read, write, execute, delete, readlink. For example, if this FilePermission
+     * object allows both write and read actions, a call to <code>getActions</code>
+     * will return the string "read,write".
+     *
+     * @return the canonical string representation of the actions.
+     */
+    public String getActions()
+    {
+        if (actions == null)
+            actions = getActions(this.mask);
+
+        return actions;
+    }
+
+
+    /**
+     * Returns a new PermissionCollection object for storing FilePermission
+     * objects.
+     * <p>
+     * FilePermission objects must be stored in a manner that allows them
+     * to be inserted into the collection in any order, but that also enables the
+     * PermissionCollection <code>implies</code>
+     * method to be implemented in an efficient (and consistent) manner.
+     *
+     * <p>For example, if you have two FilePermissions:
+     * <OL>
+     * <LI>  <code>"/tmp/-", "read"</code>
+     * <LI>  <code>"/tmp/scratch/foo", "write"</code>
+     * </OL>
+     *
+     * <p>and you are calling the <code>implies</code> method with the FilePermission:
+     *
+     * <pre>
+     *   "/tmp/scratch/foo", "read,write",
+     * </pre>
+     *
+     * then the <code>implies</code> function must
+     * take into account both the "/tmp/-" and "/tmp/scratch/foo"
+     * permissions, so the effective permission is "read,write",
+     * and <code>implies</code> returns true. The "implies" semantics for
+     * FilePermissions are handled properly by the PermissionCollection object
+     * returned by this <code>newPermissionCollection</code> method.
+     *
+     * @return a new PermissionCollection object suitable for storing
+     * FilePermissions.
+     */
+
+    public PermissionCollection newPermissionCollection() {
+        return new FilePermissionCollection();
+    }
+
+    /**
+     * WriteObject is called to save the state of the FilePermission
+     * to a stream. The actions are serialized, and the superclass
+     * takes care of the name.
+     */
+    private void writeObject(ObjectOutputStream s)
+        throws IOException
+    {
+        // Write out the actions. The superclass takes care of the name
+        // call getActions to make sure actions field is initialized
+        if (actions == null)
+            getActions();
+        s.defaultWriteObject();
+    }
+
+    /**
+     * readObject is called to restore the state of the FilePermission from
+     * a stream.
+     */
+    private void readObject(ObjectInputStream s)
+         throws IOException, ClassNotFoundException
+    {
+        // Read in the actions, then restore everything else by calling init.
+        s.defaultReadObject();
+        init(getMask(actions));
+    }
+}
+
+/**
+ * A FilePermissionCollection stores a set of FilePermission permissions.
+ * FilePermission objects
+ * must be stored in a manner that allows them to be inserted in any
+ * order, but enable the implies function to evaluate the implies
+ * method.
+ * For example, if you have two FilePermissions:
+ * <OL>
+ * <LI> "/tmp/-", "read"
+ * <LI> "/tmp/scratch/foo", "write"
+ * </OL>
+ * And you are calling the implies function with the FilePermission:
+ * "/tmp/scratch/foo", "read,write", then the implies function must
+ * take into account both the /tmp/- and /tmp/scratch/foo
+ * permissions, so the effective permission is "read,write".
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ *
+ *
+ * @author Marianne Mueller
+ * @author Roland Schemers
+ *
+ * @serial include
+ *
+ */
+
+final class FilePermissionCollection extends PermissionCollection
+implements Serializable {
+
+    // Not serialized; see serialization section at end of class
+    private transient List<Permission> perms;
+
+    /**
+     * Create an empty FilePermissions object.
+     *
+     */
+
+    public FilePermissionCollection() {
+        perms = new ArrayList<Permission>();
+    }
+
+    /**
+     * Adds a permission to the FilePermissions. The key for the hash is
+     * permission.path.
+     *
+     * @param permission the Permission object to add.
+     *
+     * @exception IllegalArgumentException - if the permission is not a
+     *                                       FilePermission
+     *
+     * @exception SecurityException - if this FilePermissionCollection object
+     *                                has been marked readonly
+     */
+
+    public void add(Permission permission)
+    {
+        if (! (permission instanceof FilePermission))
+            throw new IllegalArgumentException("invalid permission: "+
+                                               permission);
+        if (isReadOnly())
+            throw new SecurityException(
+                "attempt to add a Permission to a readonly PermissionCollection");
+
+        synchronized (this) {
+            perms.add(permission);
+        }
+    }
+
+    /**
+     * Check and see if this set of permissions implies the permissions
+     * expressed in "permission".
+     *
+     * @param p the Permission object to compare
+     *
+     * @return true if "permission" is a proper subset of a permission in
+     * the set, false if not.
+     */
+
+    public boolean implies(Permission permission)
+    {
+        if (! (permission instanceof FilePermission))
+                return false;
+
+        FilePermission fp = (FilePermission) permission;
+
+        int desired = fp.getMask();
+        int effective = 0;
+        int needed = desired;
+
+        synchronized (this) {
+            int len = perms.size();
+            for (int i = 0; i < len; i++) {
+                FilePermission x = (FilePermission) perms.get(i);
+                if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) {
+                    effective |=  x.getMask();
+                    if ((effective & desired) == desired)
+                        return true;
+                    needed = (desired ^ effective);
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns an enumeration of all the FilePermission objects in the
+     * container.
+     *
+     * @return an enumeration of all the FilePermission objects.
+     */
+
+    public Enumeration elements() {
+        // Convert Iterator into Enumeration
+        synchronized (this) {
+            return Collections.enumeration(perms);
+        }
+    }
+
+    private static final long serialVersionUID = 2202956749081564585L;
+
+    // Need to maintain serialization interoperability with earlier releases,
+    // which had the serializable field:
+    //    private Vector permissions;
+
+    /**
+     * @serialField permissions java.util.Vector
+     *     A list of FilePermission objects.
+     */
+    private static final ObjectStreamField[] serialPersistentFields = {
+        new ObjectStreamField("permissions", Vector.class),
+    };
+
+    /**
+     * @serialData "permissions" field (a Vector containing the FilePermissions).
+     */
+    /*
+     * Writes the contents of the perms field out as a Vector for
+     * serialization compatibility with earlier releases.
+     */
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        // Don't call out.defaultWriteObject()
+
+        // Write out Vector
+        Vector<Permission> permissions = new Vector<Permission>(perms.size());
+        synchronized (this) {
+            permissions.addAll(perms);
+        }
+
+        ObjectOutputStream.PutField pfields = out.putFields();
+        pfields.put("permissions", permissions);
+        out.writeFields();
+    }
+
+    /*
+     * Reads in a Vector of FilePermissions and saves them in the perms field.
+     */
+    @SuppressWarnings("unchecked")
+    private void readObject(ObjectInputStream in) throws IOException,
+    ClassNotFoundException {
+        // Don't call defaultReadObject()
+
+        // Read in serialized fields
+        ObjectInputStream.GetField gfields = in.readFields();
+
+        // Get the one we want
+        Vector<Permission> permissions = (Vector<Permission>)gfields.get("permissions", null);
+        perms = new ArrayList<Permission>(permissions.size());
+        perms.addAll(permissions);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Inputs.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 conne02110-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 org.classpath.icedtea.java.io;
+
+import java.io.Closeable;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.channels.Channels;
+
+import java.util.Collections;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+
+import org.classpath.icedtea.java.util.Scanner;
+
+/**
+ * {@note experimental}
+ * This class consists exclusively of static methods that operate on input
+ * sources.
+ *
+ * <p> The methods to read lines of text defined by this class recognize the
+ * following as Unicode line terminators:
+ * <ul>
+ *   <li> <code>&#92;u000D</code> followed by <code>&#92;u000A</code>,
+ *     CARRIAGE RETURN followed by LINE FEED </li>
+ *   <li> <code>&#92;u000A</code>, LINE FEED </li>
+ *   <li> <code>&#92;u000D</code>, CARRIAGE RETURN </li>
+ *   <li> <code>&#92;u2028</code>, LINE SEPARATOR </li>
+ *   <li> <code>&#92;u2029</code>, PARAGRAPH SEPARATOR </li>
+ *   <li> <code>&#92;u0085</code>, NEXT LINE (NEL)</li>
+ * </ul>
+ *
+ * @since 1.7
+ */
+
+public final class Inputs {
+    private Inputs() { }
+
+    // initial buffer size when reading (or writing)
+    private static final int INITIAL_BUFFER_SIZE = 8192;
+
+    // checks that charset is supported
+    private static void ensureCharsetIsSupported(String csn) {
+        if (csn == null)
+            throw new NullPointerException("'csn' is null");
+        if (!Charset.isSupported(csn))
+            throw new UnsupportedCharsetException(csn);
+    }
+
+    /**
+     * Closes the given data source by invoking its {@link Closeable#close close}
+     * method. If the {@code close} method throws an {@code IOException} then it
+     * is silently ignored. If the source is already closed then invoking this
+     * method has no effect.
+     *
+     * <p> This method should not be used to close destinations or output
+     * streams that may be buffered. An I/O error may occur when flushing
+     * buffered data.
+     *
+     * @param   source
+     *          The data source
+     */
+    public static void closeUnchecked(Closeable source) {
+        try {
+            source.close();
+        } catch (IOException ignore) { }
+    }
+
+    /**
+     * Read all bytes from the specified file. When all bytes have been read, or
+     * an I/O error occurs, then the file is closed.
+     *
+     * @param   source
+     *          The data source
+     *
+     * @return  A byte array containing the bytes read from the file
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  OutOfMemoryError
+     *          If the required array size is too large
+     */
+    public static byte[] readAllBytes(FileRef source) throws IOException {
+        long size = Attributes.readBasicFileAttributes(source).size();
+        if (size > (long)Integer.MAX_VALUE)
+            throw new OutOfMemoryError("Required array size too large");
+        InputStream in = Channels.newInputStream(source.newByteChannel());
+        try {
+            return implReadAllBytes(in, Math.min((int)size, INITIAL_BUFFER_SIZE));
+        } finally {
+            in.close();
+        }
+    }
+
+    /**
+     * Read all bytes from the specified file. When all bytes have been read, or
+     * an I/O error occurs, then the file is closed.
+     *
+     * @param   source
+     *          The data source
+     *
+     * @return  A byte array containing the bytes read from the file
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  OutOfMemoryError
+     *          If the required array size is too large
+     */
+    public static byte[] readAllBytes(File source) throws IOException {
+        InputStream in = new FileInputStream(source);
+        try {
+            return implReadAllBytes(in, INITIAL_BUFFER_SIZE);
+        } finally {
+            in.close();
+        }
+    }
+
+    /**
+     * Read all bytes from the specified input stream.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we want to open a connection to a resource identified by a URI,
+     * and read all bytes:
+     * <pre>
+     *   URI uri = ...
+     *   byte[] content = InputOutput.readAllBytes(uri.toURL().openStream());
+     * </pre>
+     *
+     * <p> On return, the input stream will be at end of stream.
+     *
+     * @param   source
+     *          The data source
+     *
+     * @return  A byte array containing the bytes read from the source
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  OutOfMemoryError
+     *          If the required array size is too large
+     */
+    public static byte[] readAllBytes(InputStream source) throws IOException {
+        return implReadAllBytes(source, INITIAL_BUFFER_SIZE);
+    }
+
+    private static byte[] implReadAllBytes(InputStream source, int initialSize)
+        throws IOException
+    {
+        byte[] buf = new byte[initialSize];
+        int nread = 0;
+        int rem = buf.length;
+        int n;
+        while ((n = source.read(buf, nread, rem)) > 0) {
+            nread += n;
+            rem -= n;
+            if (rem <= 0) {
+                int newSize = buf.length << 1;
+                if (newSize <= buf.length) {
+                    if (buf.length == Integer.MAX_VALUE)
+                        throw new OutOfMemoryError("Required array size too large");
+                    newSize = Integer.MAX_VALUE;
+                }
+                rem = newSize - buf.length;
+                buf = Arrays.copyOf(buf, newSize);
+            }
+        }
+        return (buf.length == nread) ? buf : Arrays.copyOf(buf, nread);
+    }
+
+    /**
+     * Read all lines from the specified file. Bytes from the file are
+     * converted into characters using the specified charset. When all lines
+     * have been read, or an I/O error occurs, then the file is closed.
+     *
+     * @param   source
+     *          The data source
+     * @param   csn
+     *          The name of the charset to be used
+     *
+     * @throws  java.nio.charset.UnsupportedCharsetException
+     *          If no support for the named charset is available
+     *          in this instance of the Java virtual machine
+     * @throws  java.nio.charset.MalformedInputException
+     *          If the file contains a byte sequence that is not legal for the
+     *          charset
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(FileRef source, String csn)
+        throws IOException
+    {
+        ensureCharsetIsSupported(csn);
+        Scanner s = new Scanner(source, csn);
+        try {
+            return implReadAllLines(s);
+        } finally {
+            s.close();
+        }
+    }
+
+    /**
+     * Read all lines from the specified file. Bytes from the file are
+     * converted into characters using the underlying platform's {@linkplain
+     * java.nio.charset.Charset#defaultCharset() default charset}. When all lines
+     * have been read, or an I/O error occurs, then the file is closed.
+     *
+     * @param   source
+     *          The data source
+     *
+     * @throws  java.nio.charset.MalformedInputException
+     *          If the file contains a byte sequence that is not legal for the
+     *          default charset
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(FileRef source) throws IOException {
+        Scanner s = new Scanner(source);
+        try {
+            return implReadAllLines(s);
+        } finally {
+            s.close();
+        }
+    }
+
+    /**
+     * Read all lines from the specified file. Bytes from the file are
+     * converted into characters using the specified charset. When all lines
+     * have been read, or an I/O error occurs, then the file is closed.
+     *
+     * @param   source
+     *          The data source
+     * @param   csn
+     *          The name of the charset to be used
+     *
+     * @throws  UnsupportedCharsetException
+     *          If no support for the named charset is available
+     *          in this instance of the Java virtual machine
+     * @throws  java.nio.charset.MalformedInputException
+     *          If the file contains a byte sequence that is not legal for the
+     *          charset
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(File source, String csn)
+        throws IOException
+    {
+        ensureCharsetIsSupported(csn);
+        Scanner s = new Scanner(source, csn);
+        try {
+            return implReadAllLines(s);
+        } finally {
+            s.close();
+        }
+    }
+
+    /**
+     * Read all lines from the specified file. Bytes from the file are
+     * converted into characters using the underlying platform's {@linkplain
+     * Charset#defaultCharset() default charset}. When all lines have been read,
+     * or an I/O error occurs, then the file is closed.
+     *
+     * @param   source
+     *          The data source
+     * @throws  java.nio.charset.MalformedInputException
+     *          If the file contains a byte sequence that is not legal for the
+     *          default charset
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(File source) throws IOException {
+        Scanner s = new Scanner(source);
+        try {
+            return implReadAllLines(s);
+        } finally {
+            s.close();
+        }
+    }
+
+    /**
+     * Read all lines from the specified input stream. Bytes from the stream are
+     * converted into characters using the specified charset.
+     *
+     * <p> On return, the input stream will be at end of stream.
+     *
+     * @param   source
+     *          The input stream to read from
+     * @param   csn
+     *          The name of the charset to be used
+     *
+     * @throws  UnsupportedCharsetException
+     *          If no support for the named charset is available
+     *          in this instance of the Java virtual machine
+     * @throws  java.nio.charset.MalformedInputException
+     *          If a byte sequence that is not legal for the charset is read
+     *          from the input
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(InputStream source, String csn)
+        throws IOException
+    {
+        ensureCharsetIsSupported(csn);
+        return implReadAllLines(new Scanner(source, csn));
+    }
+
+    /**
+     * Read all lines from the specified input stream. Bytes from the stream are
+     * converted into characters using the underlying platform's {@linkplain
+     * Charset#defaultCharset() default charset}.
+     *
+     * <p> On return, the input stream will be at end of stream.
+     *
+     * @param   source
+     *          The input stream to read from
+     *
+     * @return  An unmodifiable list of the lines read from the input stream
+     *
+     * @throws  java.nio.charset.MalformedInputException
+     *          If a byte sequence that is not legal for the default charset is
+     *          read from the input
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(InputStream source) throws IOException {
+        return implReadAllLines(new Scanner(source));
+    }
+
+    /**
+     * Read all lines from the from the specified source.
+     *
+     * <p> On return, the input source will be at end of stream.
+     *
+     * @param   source
+     *          The input stream to read from
+     *
+     * @return  An unmodifiable list of the lines read from source
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static List<String> readAllLines(Readable source) throws IOException {
+        return implReadAllLines(new Scanner(source));
+    }
+
+    private static List<String> implReadAllLines(Scanner s) throws IOException {
+        try {
+            List<String> result = new ArrayList<String>();
+            while (s.hasNextLine()) {
+                result.add(s.nextLine());
+            }
+            return Collections.unmodifiableList(result);
+        } finally {
+            IOException ioe = s.ioException();
+            if (ioe != null)
+                throw ioe;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/io/Outputs.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 conne02110-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 org.classpath.icedtea.java.io;
+
+import java.io.BufferedWriter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+import java.util.Arrays;
+import java.util.List;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+import static org.classpath.icedtea.java.nio.file.StandardOpenOption.CREATE;
+import static org.classpath.icedtea.java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static org.classpath.icedtea.java.nio.file.StandardOpenOption.WRITE;
+
+/**
+ * {@note experimental}
+ * This class consists exclusively of static methods that operate on output
+ * destinations.
+ *
+ * <p> The methods to write lines of text output a line terminator following
+ * each line. The line terminator that is output is platform line terminated,
+ * as defined by the {@code line.separator} system property.
+ *
+ * @since 1.7
+ */
+
+public final class Outputs {
+    private Outputs() { }
+
+    // checks that charset is supported
+    private static void ensureCharsetIsSupported(String csn) {
+        if (csn == null)
+            throw new NullPointerException("'csn' is null");
+        if (!Charset.isSupported(csn))
+            throw new UnsupportedCharsetException(csn);
+    }
+
+    /**
+     * Writes a byte array to a file. The file is created if it does not exist.
+     * If the file already exists, it is first truncated.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void write(FileRef file, byte[] bytes) throws IOException {
+        write(file, bytes, 0, bytes.length);
+    }
+
+    /**
+     * Writes a byte array to a file. The file is created if it does not exist.
+     * If the file already exists, it is first truncated.
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} or {@code len} is negative, or {@code off+len}
+     *          is greater than the length of the array
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void write(FileRef file, byte[] bytes, int off, int len)
+        throws IOException
+    {
+        WritableByteChannel wbc = file.newByteChannel(WRITE, CREATE, TRUNCATE_EXISTING);
+        try {
+            int pos = off;
+            while (pos < len) {
+                int size = Math.min(len-pos, 8192);
+                ByteBuffer bb = ByteBuffer.wrap(bytes, pos, size);
+                int n = wbc.write(bb);
+                pos += n;
+            }
+        } finally {
+            wbc.close();
+        }
+    }
+
+    /**
+     * Writes the given lines of text to the specified file. The characters in
+     * each line are encoded into bytes using the specified charset. When all
+     * lines have been written, or an I/O error occurs, then the file is closed.
+     *
+     * @param   file
+     *          The file
+     * @param   lines
+     *          The list of lines to write (in order)
+     * @param   csn
+     *          The name of the charset to be used
+     *
+     * @throws  java.nio.charset.UnsupportedCharsetException
+     *          If no support for the named charset is available
+     *          in this instance of the Java virtual machine
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(FileRef file, List<String> lines, String csn)
+        throws IOException
+    {
+        ensureCharsetIsSupported(csn);
+        WritableByteChannel wbc = file.newByteChannel(WRITE, CREATE, TRUNCATE_EXISTING);
+        BufferedWriter writer = new BufferedWriter(Channels.newWriter(wbc, csn));
+        try {
+            implWriteLines(writer, lines);
+        } finally {
+            writer.close();
+        }
+    }
+
+    /**
+     * Writes the given lines of text to the specified file. The characters in
+     * each line are encoded into bytes using the underlying platform's {@linkplain
+     * Charset#defaultCharset() default charset}. When all lines have been
+     * written, or an I/O error occurs, then the file is closed.
+     *
+     * @param   file
+     *          The file
+     * @param   lines
+     *          The list of lines to write (in order)
+     *
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(FileRef file, List<String> lines)
+        throws IOException
+    {
+        writeLines(file, lines, Charset.defaultCharset().name());
+    }
+
+    /**
+     * Writes the given lines of text to the specified file. The characters in
+     * each line are encoded into bytes using the underlying platform's {@linkplain
+     * Charset#defaultCharset() default charset}. When all lines have been
+     * written, or an I/O error occurs, then the file is closed.
+     *
+     * @param   file
+     *          The file
+     * @param   lines
+     *          The array of lines to write (in order)
+     *
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(FileRef file, String... lines)
+        throws IOException
+    {
+        writeLines(file, Arrays.asList(lines), Charset.defaultCharset().name());
+    }
+
+    /**
+     * Writes a byte array to a file. The file is created if it does not exist.
+     * If the file already exists, it is first truncated.
+     *
+     * @param   file
+     *          The file
+     * @param   bytes
+     *          The byte array to write to the file
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void write(File file, byte[] bytes) throws IOException {
+        write(file, bytes, 0, bytes.length);
+    }
+
+    /**
+     * Writes a byte array to a file. The file is created if it does not exist.
+     * If the file already exists, it is first truncated.
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} or {@code len} is negative, or {@code off+len}
+     *          is greater than the length of the array
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void write(File file, byte[] bytes, int off, int len)
+        throws IOException
+    {
+        FileOutputStream out = new FileOutputStream(file);
+        try {
+            out.write(bytes, off, len);
+        } finally {
+            out.close();
+        }
+    }
+
+    /**
+     * Writes the given lines of text to the specified file. The characters in
+     * each line are encoded into bytes using the specified charset. When all
+     * lines have been written, or an I/O error occurs, then the file is closed.
+     *
+     * @param   file
+     *          The file
+     * @param   lines
+     *          The list of lines to write (in order)
+     * @param   csn
+     *          The name of the charset to be used
+     *
+     * @throws  java.nio.charset.UnsupportedCharsetException
+     *          If no support for the named charset is available
+     *          in this instance of the Java virtual machine
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(File file, List<String> lines, String csn)
+        throws IOException
+    {
+        ensureCharsetIsSupported(csn);
+        FileOutputStream out = new FileOutputStream(file);
+        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, csn));
+        try {
+            implWriteLines(writer, lines);
+        } finally {
+            writer.close();
+        }
+    }
+
+    /**
+     * Writes the given lines of text to the specified file. The characters in
+     * each line are encoded into bytes using the underlying platform's {@linkplain
+     * Charset#defaultCharset() default charset}. When all lines have been
+     * written, or an I/O error occurs, then the file is closed.
+     *
+     * @param   file
+     *          The file
+     * @param   lines
+     *          The list of lines to write (in order)
+     *
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(File file, List<String> lines)
+        throws IOException
+    {
+        writeLines(file, lines, Charset.defaultCharset().name());
+    }
+
+    /**
+     * Writes the given lines of text to the specified file. The characters in
+     * each line are encoded into bytes using the underlying platform's {@linkplain
+     * Charset#defaultCharset() default charset}. When all lines have been
+     * written, or an I/O error occurs, then the file is closed.
+     *
+     * @param   file
+     *          The file
+     * @param   lines
+     *          The array of lines to write (in order)
+     *
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(File file, String... lines)
+        throws IOException
+    {
+        writeLines(file, Arrays.asList(lines), Charset.defaultCharset().name());
+    }
+
+    /**
+     * Writes the given lines of text to the specified output stream. The
+     * characters in each line are encoded into bytes using the specified charset.
+     *
+     * @param   out
+     *          The output stream
+     * @param   lines
+     *          The list of lines to write (in order)
+     * @param   csn
+     *          The name of the charset to be used
+     *
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(OutputStream out, List<String> lines, String csn)
+        throws IOException
+    {
+        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, csn));
+        implWriteLines(writer, lines);
+        writer.flush();
+    }
+
+    /**
+     * Writes the given lines of text to the specified output stream. The
+     * characters in each line are encoded into bytes using the underlying
+     * platform's {@linkplain Charset#defaultCharset() default charset}.
+     *
+     * @param   out
+     *          The output stream
+     * @param   lines
+     *          The list of lines to write (in order)
+     *
+     * @throws  java.nio.charset.UnmappableCharacterException
+     *          Where a line contains a character that cannot be mapped to an
+     *          output byte sequence
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static void writeLines(OutputStream out, List<String> lines)
+        throws IOException
+    {
+        writeLines(out, lines, Charset.defaultCharset().name());
+    }
+
+    private static void implWriteLines(BufferedWriter writer, List<String> lines)
+        throws IOException
+    {
+        for (String line: lines) {
+            writer.write(line);
+            writer.newLine();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousByteChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.Future;
+
+/**
+ * An asynchronous channel that can read and write bytes.
+ *
+ * <p> Some channels may not allow more than one read to be outstanding at any
+ * given time. If a thread invokes a read method before a previous read
+ * operation has completed then a {@link ReadPendingException} will be thrown.
+ * Similarly, if a write method is invoked before a previous write has completed
+ * then {@link WritePendingException} is thrown. Whether or not other kinds of
+ * I/O operations may proceed concurrently with a read operation depends upon
+ * the type of the channel.
+ *
+ * <p> Note that {@link java.nio.ByteBuffer ByteBuffers} are not safe for use by
+ * multiple concurrent threads. When a read or write operation is initiated then
+ * care must be taken to ensure that the buffer is not accessed until the
+ * operation completes.
+ *
+ * @see Channels#newInputStream(AsynchronousByteChannel)
+ * @see Channels#newOutputStream(AsynchronousByteChannel)
+ *
+ * @since 1.7
+ */
+
+public interface AsynchronousByteChannel
+    extends AsynchronousChannel
+{
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> This method initiates an operation to read a sequence of bytes from
+     * this channel into the given buffer. The method returns a {@link Future}
+     * representing the pending result of the operation. The result of the
+     * operation, obtained by invoking the {@code Future} 's {@link
+     * Future#get() get} method, is the number of bytes read or {@code -1} if
+     * all bytes have been read and the channel has reached end-of-stream.
+     *
+     * <p> This method initiates a read operation to read up to <i>r</i> bytes
+     * from the channel, where <i>r</i> is the number of bytes remaining in the
+     * buffer, that is, {@code dst.remaining()} at the time that the read is
+     * attempted. Where <i>r</i> is 0, the read operation completes immediately
+     * with a result of {@code 0} without initiating an I/O operation.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is read, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * This byte sequence will be transferred into the buffer so that the first
+     * byte in the sequence is at index <i>p</i> and the last byte is at index
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>,
+     * where <i>p</i> is the buffer's position at the moment the read is
+     * performed. Upon completion the buffer's position will be equal to
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
+     *
+     * <p> Buffers are not safe for use by multiple concurrent threads so care
+     * should be taken to not to access the buffer until the operaton has completed.
+     *
+     * <p> This method may be invoked at any time. Some channel types may not
+     * allow more than one read to be outstanding at any given time. If a thread
+     * initiates a read operation before a previous read operation has
+     * completed then a {@link ReadPendingException} will be thrown.
+     *
+     * <p> The <tt>handler</tt> parameter is used to specify a {@link
+     * CompletionHandler}. When the read operation completes the handler's
+     * {@link CompletionHandler#completed completed} method is executed.
+     *
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The completion handler object; can be {@code null}
+     *
+     * @return  A Future representing the result of the operation
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ReadPendingException
+     *          If the channel does not allow more than one read to be outstanding
+     *          and a previous read has not completed
+     */
+    <A> Future<Integer> read(ByteBuffer dst,
+                             A attachment,
+                             CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> An invocation of this method of the form <tt>c.read(dst)</tt>
+     * behaves in exactly the same manner as the invocation
+     * <blockquote><pre>
+     * c.read(dst, null, null);</pre></blockquote>
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     *
+     * @return  A Future representing the result of the operation
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ReadPendingException
+     *          If the channel does not allow more than one read to be outstanding
+     *          and a previous read has not completed
+     */
+    Future<Integer> read(ByteBuffer dst);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> This method initiates an operation to write a sequence of bytes to
+     * this channel from the given buffer. This method returns a {@link
+     * Future} representing the pending result of the operation. The result
+     * of the operation, obtained by invoking the <tt>Future</tt>'s {@link
+     * Future#get() get} method, is the number of bytes written, possibly zero.
+     *
+     * <p> This method initiates a write operation to write up to <i>r</i> bytes
+     * to the channel, where <i>r</i> is the number of bytes remaining in the
+     * buffer, that is, {@code src.remaining()}  at the moment the write is
+     * attempted. Where <i>r</i> is 0, the write operation completes immediately
+     * with a result of {@code 0} without initiating an I/O operation.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is written, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * This byte sequence will be transferred from the buffer starting at index
+     * <i>p</i>, where <i>p</i> is the buffer's position at the moment the
+     * write is performed; the index of the last byte written will be
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>.
+     * Upon completion the buffer's position will be equal to
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
+     *
+     * <p> Buffers are not safe for use by multiple concurrent threads so care
+     * should be taken to not to access the buffer until the operaton has completed.
+     *
+     * <p> This method may be invoked at any time. Some channel types may not
+     * allow more than one write to be outstanding at any given time. If a thread
+     * initiates a write operation before a previous write operation has
+     * completed then a {@link WritePendingException} will be thrown.
+     *
+     * <p> The <tt>handler</tt> parameter is used to specify a {@link
+     * CompletionHandler}. When the write operation completes the handler's
+     * {@link CompletionHandler#completed completed} method is executed.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The completion handler object; can be {@code null}
+     *
+     * @return  A Future representing the result of the operation
+     *
+     * @throws  WritePendingException
+     *          If the channel does not allow more than one write to be outstanding
+     *          and a previous write has not completed
+     */
+    <A> Future<Integer> write(ByteBuffer src,
+                              A attachment,
+                              CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> An invocation of this method of the form <tt>c.write(src)</tt>
+     * behaves in exactly the same manner as the invocation
+     * <blockquote><pre>
+     * c.write(src, null, null);</pre></blockquote>
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     *
+     * @return A Future representing the result of the operation
+     *
+     * @throws  WritePendingException
+     *          If the channel does not allow more than one write to be outstanding
+     *          and a previous write has not completed
+     */
+    Future<Integer> write(ByteBuffer src);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.Channel;
+import java.util.concurrent.Future;  // javadoc
+
+/**
+ * A channel that supports asynchronous I/O operations. Asynchronous I/O
+ * operations will usually take one of two forms:
+ *
+ * <ol>
+ * <li><pre>{@link Future}&lt;V&gt; <em>operation</em>(<em>...</em>)</pre></li>
+ * <li><pre>Future&lt;V&gt; <em>operation</em>(<em>...</em> A attachment, {@link CompletionHandler}&lt;V,? super A&gt handler)</pre></li>
+ * </ol>
+ *
+ * where <i>operation</i> is the name of the I/O operation (read or write for
+ * example), <i>V</i> is the result type of the I/O operation, and <i>A</i> is
+ * the type of an object attached to the I/O operation to provide context when
+ * consuming the result. The attachment is important for cases where a
+ * <em>state-less</em> {@code CompletionHandler} is used to consume the result
+ * of many I/O operations.
+ *
+ * <p> In the first form, the methods defined by the {@link Future Future}
+ * interface may be used to check if the operation has completed, wait for its
+ * completion, and to retrieve the result. In the second form, a {@link
+ * CompletionHandler} is invoked to consume the result of the I/O operation when
+ * it completes, fails, or is cancelled.
+ *
+ * <p> A channel that implements this interface is <em>asynchronously
+ * closeable</em>: If an I/O operation is outstanding on the channel and the
+ * channel's {@link #close close} method is invoked, then the I/O operation
+ * fails with the exception {@link AsynchronousCloseException}.
+ *
+ * <p> Asynchronous channels are safe for use by multiple concurrent threads.
+ * Some channel implementations may support concurrent reading and writing, but
+ * may not allow more than one read and one write operation to be outstanding at
+ * any given time.
+ *
+ * <h4>Cancellation</h4>
+ *
+ * <p> The {@code Future} interface defines the {@link Future#cancel cancel}
+ * method to cancel execution of a task.
+ *
+ * <p> Where the {@code cancel} method is invoked with the {@code
+ * mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
+ * may be interrupted by closing the channel. This will cause any other I/O
+ * operations outstanding on the channel to complete with the exception {@link
+ * AsynchronousCloseException}.
+ *
+ * <p> If a {@code CompletionHandler} is specified when initiating an I/O
+ * operation, and the {@code cancel} method is invoked to cancel the I/O
+ * operation before it completes, then the {@code CompletionHandler}'s {@link
+ * CompletionHandler#cancelled cancelled} method is invoked.
+ *
+ * <p> If an implementation of this interface supports a means to cancel I/O
+ * operations, and where cancellation may leave the channel, or the entity to
+ * which it is connected, in an inconsistent state, then the channel is put into
+ * an implementation specific <em>error state</em> that prevents further
+ * attempts to initiate I/O operations on the channel. For example, if a read
+ * operation is cancelled but the implementation cannot guarantee that bytes
+ * have not been read from the channel then it puts the channel into error state
+ * state; further attempts to initiate a {@code read} operation causes an
+ * unspecified runtime exception to be thrown.
+ *
+ * <p> Where the {@code cancel} method is invoked to cancel read or write
+ * operations then it recommended that all buffers used in the I/O operations be
+ * discarded or care taken to ensure that the buffers are not accessed while the
+ * channel remains open.
+ *
+ *  @since 1.7
+ */
+
+public interface AsynchronousChannel
+    extends Channel
+{
+    /**
+     * Closes this channel.
+     *
+     * <p> Any outstanding asynchronous operations upon this channel will
+     * complete with the exception {@link AsynchronousCloseException}. After a
+     * channel is closed then further attempts to initiate asynchronous I/O
+     * operations complete immediately with cause {@link ClosedChannelException}.
+     *
+     * <p>  This method otherwise behaves exactly as specified by the {@link
+     * Channel} interface.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+
+    void close() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.IOException;
+import java.util.concurrent.*;
+
+/**
+ * A grouping of asynchronous channels for the purpose of resource sharing.
+ *
+ * <p> An asynchronous channel group encapsulates the mechanics required to
+ * handle the completion of I/O operations initiated by {@link AsynchronousChannel
+ * asynchronous channels} that are bound to the group. A group has an associated
+ * thread pool to which tasks are submitted to handle I/O events and dispatch to
+ * {@link CompletionHandler completion-handlers} that consume the result of
+ * asynchronous operations performed on channels in the group. In addition to
+ * handling I/O events, the pooled threads may also execute other tasks required
+ * to support the execution of asynchronous I/O operations.
+ *
+ * <p> An asynchronous channel group is created by invoking the {@link
+ * #withFixedThreadPool withFixedThreadPool} or {@link #withCachedThreadPool
+ * withCachedThreadPool} methods with the appropriate thread pool. Channels are
+ * bound to a group by specifying the group when constructing the channel. The
+ * group <em>takes ownership</em> of the thread pool; termination of the group
+ * results in the shutdown of the thread pool.
+ *
+ * <p> In addition to groups created explicitly, the Java virtual machine
+ * maintains a system-wide <em>default group</em> that is constructed
+ * automatically. Asynchronous channels that do not specify a group at
+ * construction time are bound to the default group. The default group has an
+ * associated thread pool that creates new threads as needed. The default group
+ * may be configured by means of system properties defined in the table below.
+ * Where the {@link java.util.concurrent.ThreadFactory ThreadFactory} for the
+ * default group is not configured then the pooled threads of the default group
+ * are {@link Thread#isDaemon daemon} threads.
+ *
+ * <table border>
+ *   <tr>
+ *     <th>System property</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *   <tr>
+ *     <td> {@code java.nio.channels.DefaultThreadPool.threadFactory} </td>
+ *     <td> The value of this property is taken to be the fully-qualified name
+ *     of a concrete {@link java.util.concurrent.ThreadFactory ThreadFactory}
+ *     class. The class is loaded using the system class loader and instantiated.
+ *     The factory's {@link java.util.concurrent.ThreadFactory#newThread
+ *     newThread} method is invoked to create each thread for the default
+ *     group's thread pool. If the process to load and instantiate the value
+ *     of the property fails then an unspecified error is thrown during the
+ *     construction of the default group. </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@code java.nio.channels.DefaultThreadPool.initialSize} </td>
+ *     <td> The value of the {@code initialSize} parameter for the default
+ *     group (see {@link #withCachedThreadPool withCachedThreadPool}).
+ *     The value of the property is taken to be the {@code String}
+ *     representation of an {@code Integer} that is the initial size parameter.
+ *     If the value cannot be parsed as an {@code Integer} it causes an
+ *     unspecified error to be thrown during the construction of the default
+ *     group. </td>
+ *   </tr>
+ * </table>
+ *
+ * <a name="threading"><h4>Threading</h4></a>
+ *
+ * <p> The completion handler for an I/O operation initiated on a channel bound
+ * to a group is guaranteed to be invoked by one of the pooled threads in the
+ * group. This ensures that the completion handler is run by a thread with the
+ * expected <em>identity</em>.
+ *
+ * <p> Where an I/O operation completes immediately, and the initiating thread
+ * is one of the pooled threads in the group then the completion handler may
+ * be invoked directly by the initiating thread. To avoid stack overflow, an
+ * implementation may impose a limit as to the number of activations on the
+ * thread stack. Some I/O operations may prohibit invoking the completion
+ * handler directly by the initiating thread (see {@link
+ * AsynchronousServerSocketChannel#accept(Object,CompletionHandler) accept}).
+ *
+ * <a name="shutdown"><h4>Shutdown and Termination</h4></a>
+ *
+ * <p> The {@link #shutdown() shutdown} method is used to initiate an <em>orderly
+ * shutdown</em> of the group. An orderly shutdown marks the group as shutdown;
+ * further attempts to construct a channel that binds to the group will throw
+ * {@link ShutdownChannelGroupException}. Whether or not a group is shutdown can
+ * be tested using the {@link #isShutdown() isShutdown} method. Once shutdown, a
+ * group <em>terminates</em> when all asynchronous channels that are bound to the
+ * group are closed, all actively executing completion handlers have run to
+ * completion, and resources used by the group are released. No attempt is made
+ * to stop or interrupt threads that are executing completion handlers. The
+ * {@link #isTerminated() isTerminated} method is used to test if the group has
+ * terminated, and the {@link #awaitTermination awaitTermination} method can be
+ * used to block until the group has terminated.
+ *
+ * <p> The {@link #shutdownNow() shutdownNow} method can be used to initiate a
+ * <em>forceful shutdown</em> of the group. In addition to the actions performed
+ * by an orderly shutdown, the {@code shutdownNow} method closes all open channels
+ * in the group as if by invoking the {@link AsynchronousChannel#close close}
+ * method.
+ *
+ * @since 1.7
+ *
+ * @see AsynchronousSocketChannel#open
+ * @see AsynchronousServerSocketChannel#open
+ */
+
+public abstract class AsynchronousChannelGroup {
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initialize a new instance of this class.
+     *
+     * @param   provider
+     *          The asynchronous channel provider for this group
+     */
+    protected AsynchronousChannelGroup(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel group.
+     *
+     * @return  The provider that created this channel group
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Creates an asynchronous channel group with a fixed thread pool.
+     *
+     * <p> The {@code executor} parameter is an {@code ExecutorService} that
+     * reuses a fixed number of threads operating off a shared unbounded queue.
+     * At any point, at most {@code nThreads} threads will be active processing
+     * tasks that are submitted to handle I/O events and dispatch completion
+     * results for operations initiated on asynchronous channels in the group.
+     *
+     * <p> The executor is intended to be used for the exclusive use of the
+     * resulting asynchronous channel group. Adjusting the maximum allowed
+     * number of threads or other policy parameters after the channel group is
+     * created is not recommended. Termination of the group results in the orderly
+     * {@link ExecutorService#shutdown shutdown} of the executor service.
+     * Shutting down the executor service by other means results in unspecified
+     * behavior.
+     *
+     * <p> The group is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousChannelGroup
+     * openAsynchronousChannelGroup} method of the system-wide default {@link
+     * AsynchronousChannelProvider} object.
+     *
+     * @param   executor
+     *          The thread pool for the resulting group
+     * @param   nThreads
+     *          The number of threads in the pool
+     *
+     * @return  A new asynchronous channel group
+     *
+     * @throws  IllegalArgumentException
+     *          If {@code nThreads <= 0}
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see Executors#newFixedThreadPool
+     */
+    public static AsynchronousChannelGroup withFixedThreadPool(ExecutorService executor,
+                                                               int nThreads)
+        throws IOException
+    {
+        return AsynchronousChannelProvider.provider()
+            .openAsynchronousChannelGroup(AsynchronousChannelProvider.ThreadPoolType.FIXED,
+                                          executor,
+                                          nThreads);
+    }
+
+    /**
+     * Creates an asynchronous channel group that creates new threads as needed.
+     *
+     * <p> The {@code executor} parameter is an {@code ExecutorService} that
+     * creates new threads as needed to execute tasks that are submitted to
+     * handle I/O events and dispatch completion results for operations initiated
+     * on asynchronous channels in the group. It may reuse previously constructed
+     * threads when they are available.
+     *
+     * <p> The {@code initialSize} parameter may be used by the implementation
+     * as a <em>hint</em> as to the initial number of tasks it may submit. For
+     * example, it may be used to indictae the initial number of threads that
+     * wait on I/O events.
+     *
+     * <p> The executor is intended to be used for the exclusive use of the
+     * resulting asynchronous channel group. Termination of the group results in
+     * the orderly  {@link ExecutorService#shutdown shutdown} of the executor
+     * service. Shutting down the executor service by other means results in
+     * unspecified behavior.
+     *
+     * <p> The group is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousChannelGroup
+     * openAsynchronousChannelGroup} method of the system-wide default {@link
+     * AsynchronousChannelProvider} object.
+     *
+     * @param   executor
+     *          The thread pool for the resulting group
+     * @param   initialSize
+     *          A value {@code >=0} or a negative value for implementation
+     *          specific default
+     *
+     * @return  A new asynchronous channel group
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see Executors#newCachedThreadPool
+     */
+    public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,
+                                                                int initialSize)
+        throws IOException
+    {
+        return AsynchronousChannelProvider.provider()
+            .openAsynchronousChannelGroup(AsynchronousChannelProvider.ThreadPoolType.CACHED,
+                                          executor,
+                                          initialSize);
+    }
+
+    /**
+     * Tells whether or not this asynchronous channel group is shutdown.
+     *
+     * @return  {@code true} if this asynchronous channel group is shutdown or
+     *          has been marked for shutdown.
+     */
+    public abstract boolean isShutdown();
+
+    /**
+     * Tells whether or not this group has terminated.
+     *
+     * <p> Where this method returns {@code true}, then the associated has
+     * also {@link ExecutorService#isTerminated terminated}.
+     *
+     * @return  {@code true} if this group has terminated
+     */
+    public abstract boolean isTerminated();
+
+    /**
+     * Initiates an orderly shutdown of the group.
+     *
+     * <p> This method marks the group as shutdown. Further attempts to construct
+     * channel that binds to this group will throw {@link ShutdownChannelGroupException}.
+     * The group terminates when all asynchronous channels in the group are
+     * closed, all actively executing completion handlers have run to completion,
+     * and all resources have been released. This method has no effect if the
+     * group is already shutdown.
+     */
+    public abstract void shutdown();
+
+    /**
+     * Shuts down the group and closes all open channels in the group.
+     *
+     * <p> In addition to the actions performed by the {@link #shutdown() shutdown}
+     * method, this method invokes the {@link AsynchronousChannel#close close}
+     * method on all open channels in the group. This method does not attempt to
+     * stop or interrupt threads that are executing completion handlers. The
+     * group terminates when all actively executing completion handlers have run
+     * to completion and all resources have been released. This method may be
+     * invoked at any time. If some other thread has already invoked it, then
+     * another invocation will block until the first invocation is complete,
+     * after which it will return without effect.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract void shutdownNow() throws IOException;
+
+    /**
+     * Awaits termination of the group.
+
+     * <p> This method blocks until the group has terminated, or the timeout
+     * occurs, or the current thread is interrupted, whichever happens first.
+     *
+     * @param   timeout
+     *          The maximum time to wait, or zero or less to not wait
+     * @param   unit
+     *          The time unit of the timeout argument
+     *
+     * @return  {@code true} if the group has terminated; {@code false} if the
+     *          timeout elapsed before termination
+     *
+     * @throws  InterruptedException
+     *          If interrupted while waiting
+     */
+    public abstract boolean awaitTermination(long timeout, TimeUnit unit)
+        throws InterruptedException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,705 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.channels.spi.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Future;
+import java.io.IOException;
+import java.net.SocketOption;
+import java.net.SocketAddress;
+import java.net.ProtocolFamily;
+import java.nio.ByteBuffer;
+
+/**
+ * An asynchronous channel for datagram-oriented sockets.
+ *
+ * <p> An asynchronous datagram channel is created by invoking one of the {@link
+ * #open open} methods defined by this class. It is not possible to create a channel
+ * for an arbitrary, pre-existing datagram socket. A newly-created asynchronous
+ * datagram channel is open but not connected. It need not be connected in order
+ * for the {@link #send send} and {@link #receive receive} methods to be used.
+ * A datagram channel may be connected, by invoking its {@link #connect connect}
+ * method, in order to avoid the overhead of the security checks that are otherwise
+ * performed as part of every send and receive operation when a security manager
+ * is set. The channel must be connected in order to use the {@link #read read}
+ * and {@link #write write} methods, since those methods do not accept or return
+ * socket addresses. Once connected, an asynchronous datagram channel remains
+ * connected until it is disconnected or closed.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. An asynchronous datagram channel to an Internet Protocol
+ * (IP) socket supports the following options:
+ * <blockquote>
+ * <table border>
+ *   <tr>
+ *     <th>Option Name</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
+ *     <td> The size of the socket send buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ *     <td> The size of the socket receive buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ *     <td> Re-use address </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
+ *     <td> Allow transmission of broadcast datagrams </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
+ *     <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
+ *     <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
+ *       IP_MULTICAST_TTL} </td>
+ *     <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
+ *       datagrams </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
+ *       IP_MULTICAST_LOOP} </td>
+ *     <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
+ *   </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
+ * <p> <b>Usage Example:</b>
+ * <pre>
+ *  final AsynchronousDatagramChannel dc = AsynchronousDatagramChannel.open()
+ *      .bind(new InetSocketAddress(4000));
+ *
+ *  // print the source address of all packets that we receive
+ *  dc.receive(buffer, buffer, new CompletionHandler&lt;SocketAddress,ByteBuffer&gt;() {
+ *      public void completed(SocketAddress sa, ByteBuffer buffer) {
+ *          try {
+ *               System.out.println(sa);
+ *
+ *               buffer.clear();
+ *               dc.receive(buffer, buffer, this);
+ *           } catch (...) { ... }
+ *      }
+ *      public void failed(Throwable exc, ByteBuffer buffer) {
+ *          ...
+ *      }
+ *      public void cancelled(ByteBuffer buffer) {
+ *          ...
+ *      }
+ *  });
+ * </pre>
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousDatagramChannel
+    implements AsynchronousByteChannel, MulticastChannel
+{
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousDatagramChannel(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel.
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Opens an asynchronous datagram channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousDatagramChannel
+     * openAsynchronousDatagramChannel} method on the {@link
+     * java.nio.channels.spi.AsynchronousChannelProvider} object that created
+     * the given group. If the group parameter is <tt>null</tt> then the
+     * resulting channel is created by the system-wide default provider, and
+     * bound to the <em>default group</em>.
+     *
+     * <p> The <tt>family</tt> parameter is used to specify the {@link ProtocolFamily}.
+     * If the datagram channel is to be used for Internet Protocol {@link
+     * MulticastChannel multicasting} then this parameter should correspond to
+     * the address type of the multicast groups that this channel will join.
+     *
+     * @param   family
+     *          The protocol family, or <tt>null</tt> to use the default protocol
+     *          family
+     * @param   group
+     *          The group to which the newly constructed channel should be bound,
+     *          or <tt>null</tt> for the default group
+     *
+     * @return  A new asynchronous datagram channel
+     *
+     * @throws  UnsupportedOperationException
+     *          If the specified protocol family is not supported. For example,
+     *          suppose the parameter is specified as {@link
+     *          java.net.StandardProtocolFamily#INET6 INET6} but IPv6 is not
+     *          enabled on the platform.
+     * @throws  ShutdownChannelGroupException
+     *          The specified group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousDatagramChannel open(ProtocolFamily family,
+                                                   AsynchronousChannelGroup group)
+        throws IOException
+    {
+        AsynchronousChannelProvider provider = (group == null) ?
+            AsynchronousChannelProvider.provider() : group.provider();
+        return provider.openAsynchronousDatagramChannel(family, group);
+    }
+
+    /**
+     * Opens an asynchronous datagram channel.
+     *
+     * <p> This method returns an asynchronous datagram channel that is
+     * bound to the <em>default group</em>. This method is equivalent to evaluating
+     * the expression:
+     * <blockquote><pre>
+     * open((ProtocolFamily)null,&nbsp;(AsynchronousChannelGroup)null);
+     * </pre></blockquote>
+     *
+     * @return  A new asynchronous datagram channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousDatagramChannel open()
+        throws IOException
+    {
+        return open(null, null);
+    }
+
+    // -- Socket-specific operations --
+
+    /**
+     * @throws  AlreadyBoundException               {@inheritDoc}
+     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  ClosedChannelException              {@inheritDoc}
+     * @throws  IOException                         {@inheritDoc}
+     * @throws  SecurityException
+     *          If a security manager has been installed and its {@link
+     *          SecurityManager#checkListen checkListen} method denies the
+     *          operation
+     */
+
+    public abstract AsynchronousDatagramChannel bind(SocketAddress local)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     */
+
+    public abstract <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * Returns the remote address to which this channel is connected.
+     *
+     * <p> Where the channel is connected to an Internet Protocol socket address
+     * then the return value from this method is of type {@link
+     * java.net.InetSocketAddress}.
+     *
+     * @return  The remote address; {@code null} if the channel's socket is not
+     *          connected
+     *
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract SocketAddress getRemoteAddress() throws IOException;
+
+    /**
+     * Connects this channel's socket.
+     *
+     * <p> The channel's socket is configured so that it only receives
+     * datagrams from, and sends datagrams to, the given remote <i>peer</i>
+     * address.  Once connected, datagrams may not be received from or sent to
+     * any other address.  A datagram socket remains connected until it is
+     * explicitly disconnected or until it is closed.
+     *
+     * <p> This method performs exactly the same security checks as the {@link
+     * java.net.DatagramSocket#connect connect} method of the {@link
+     * java.net.DatagramSocket} class.  That is, if a security manager has been
+     * installed then this method verifies that its {@link
+     * java.lang.SecurityManager#checkAccept checkAccept} and {@link
+     * java.lang.SecurityManager#checkConnect checkConnect} methods permit
+     * datagrams to be received from and sent to, respectively, the given
+     * remote address.
+     *
+     * <p> This method may be invoked at any time. Whether it has any effect
+     * on outstanding read or write operations is implementation specific and
+     * therefore not specified.
+     *
+     * @param  remote
+     *         The remote address to which this channel is to be connected
+     *
+     * @return  This datagram channel
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote address
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousDatagramChannel connect(SocketAddress remote)
+        throws IOException;
+
+    /**
+     * Disconnects this channel's socket.
+     *
+     * <p> The channel's socket is configured so that it can receive datagrams
+     * from, and sends datagrams to, any remote address so long as the security
+     * manager, if installed, permits it.
+     *
+     * <p> This method may be invoked at any time.  It will not have any effect
+     * on read or write operations that are already in progress at the moment
+     * that it is invoked.
+     *
+     * <p> This method may be invoked at any time. Whether it has any effect
+     * on outstanding read or write operations is implementation specific and
+     * therefore not specified.
+     *
+     * @return  This datagram channel
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousDatagramChannel disconnect() throws IOException;
+
+    /**
+     * Receives a datagram via this channel.
+     *
+     * <p> This method initiates the receiving of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The <tt>Future</tt>'s {@link Future#get() get} method returns
+     * the source address of the datagram upon successful completion.
+     *
+     * <p> The datagram is transferred into the given byte buffer starting at
+     * its current position, as if by a regular {@link AsynchronousByteChannel#read
+     * read} operation. If there are fewer bytes remaining in the buffer
+     * than are required to hold the datagram then the remainder of the datagram
+     * is silently discarded.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}.
+     *
+     * <p> When a security manager has been installed and the channel is not
+     * connected, then it verifies that the source's address and port number are
+     * permitted by the security manager's {@link SecurityManager#checkAccept
+     * checkAccept} method. The permission check is performed with privileges that
+     * are restricted by the calling context of this method. If the permission
+     * check fails then the operation completes with a {@link SecurityException}.
+     * The overhead of this security check can be avoided by first connecting the
+     * socket via the {@link #connect connect} method.
+     *
+     * @param   dst
+     *          The buffer into which the datagram is to be transferred
+     * @param   timeout
+     *          The timeout, or <tt>0L</tt> for no timeout
+     * @param   unit
+     *          The time unit of the <tt>timeout</tt> argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the timeout is negative or the buffer is read-only
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<SocketAddress> receive(ByteBuffer dst,
+                                                      long timeout,
+                                                      TimeUnit unit,
+                                                      A attachment,
+                                                      CompletionHandler<SocketAddress,? super A> handler);
+
+    /**
+     * Receives a datagram via this channel.
+     *
+     * <p> This method initiates the receiving of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The <tt>Future</tt>'s {@link Future#get() get} method returns
+     * the source address of the datagram upon successful completion.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
+     * timeout of <tt>0L</tt>.
+     *
+     * @param   dst
+     *          The buffer into which the datagram is to be transferred
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public final <A> Future<SocketAddress> receive(ByteBuffer dst,
+                                                   A attachment,
+                                                   CompletionHandler<SocketAddress,? super A> handler)
+    {
+        return receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * Receives a datagram via this channel.
+     *
+     * <p> This method initiates the receiving of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The <tt>Future</tt>'s {@link Future#get() get} method returns
+     * the source address of the datagram upon successful completion.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
+     * timeout of {@code 0L}, and an attachment and completion handler
+     * of {@code null}.
+     *
+     * @param   dst
+     *          The buffer into which the datagram is to be transferred
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     */
+    public final <A> Future<SocketAddress> receive(ByteBuffer dst) {
+        return receive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Sends a datagram via this channel.
+     *
+     * <p> This method initiates sending of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The operation sends the remaining bytes in the given buffer as a single
+     * datagram to the given target address. The result of the operation, obtained
+     * by invoking the <tt>Future</tt>'s {@link Future#get() get}
+     * method, is the number of bytes sent.
+     *
+     * <p> The datagram is transferred from the byte buffer as if by a regular
+     * {@link AsynchronousByteChannel#write write} operation.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}.
+     *
+     * <p> If there is a security manager installed and the the channel is not
+     * connected then this method verifies that the target address and port number
+     * are permitted by the security manager's {@link SecurityManager#checkConnect
+     * checkConnect} method.  The overhead of this security check can be avoided
+     * by first connecting the socket via the {@link #connect connect} method.
+     *
+     * @param   src
+     *          The buffer containing the datagram to be sent
+     * @param   target
+     *          The address to which the datagram is to be sent
+     * @param   timeout
+     *          The timeout, or <tt>0L</tt> for no timeout
+     * @param   unit
+     *          The time unit of the <tt>timeout</tt> argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  IllegalArgumentException
+     *          If the channel's socket is connected and is connected to an
+     *          address that is not equal to {@code target}
+     * @throws  SecurityException
+     *          If a security manager has been installed and it does not permit
+     *          datagrams to be sent to the given address
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> send(ByteBuffer src,
+                                             SocketAddress target,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Sends a datagram via this channel.
+     *
+     * <p> This method initiates sending of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The operation sends the remaining bytes in the given buffer as a single
+     * datagram to the given target address. The result of the operation, obtained
+     * by invoking the <tt>Future</tt>'s {@link Future#get() get}
+     * method, is the number of bytes sent.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)}
+     * with a timeout of <tt>0L</tt>.
+     *
+     * @param   src
+     *          The buffer containing the datagram to be sent
+     * @param   target
+     *          The address to which the datagram is to be sent
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  IllegalArgumentException
+     *          If the channel's socket is connected and is connected to an
+     *          address that is not equal to {@code target}
+     * @throws  SecurityException
+     *          If a security manager has been installed and it does not permit
+     *          datagrams to be sent to the given address
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public final <A> Future<Integer> send(ByteBuffer src,
+                                          SocketAddress target,
+                                          A attachment,
+                                          CompletionHandler<Integer,? super A> handler)
+    {
+        return send(src, target, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * Sends a datagram via this channel.
+     *
+     * <p> This method initiates sending of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The operation sends the remaining bytes in the given buffer as a single
+     * datagram to the given target address. The result of the operation, obtained
+     * by invoking the <tt>Future</tt>'s {@link Future#get() get}
+     * method, is the number of bytes sent.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)}
+     * with a timeout of {@code 0L} and an attachment and completion handler
+     * of {@code null}.
+     *
+     * @param   src
+     *          The buffer containing the datagram to be sent
+     * @param   target
+     *          The address to which the datagram is to be sent
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  IllegalArgumentException
+     *          If the channel's socket is connected and is connected to an
+     *          address that is not equal to {@code target}
+     * @throws  SecurityException
+     *          If a security manager has been installed and it does not permit
+     *          datagrams to be sent to the given address
+     */
+    public final Future<Integer> send(ByteBuffer src, SocketAddress target) {
+        return send(src, target, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Receives a datagram via this channel.
+     *
+     * <p> This method initiates the receiving of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The <tt>Future</tt>'s {@link Future#get() get} method returns
+     * the number of bytes transferred upon successful completion.
+     *
+     * <p> This method may only be invoked if this channel is connected, and it
+     * only accepts datagrams from the peer that the channel is connected too.
+     * The datagram is transferred into the given byte buffer starting at
+     * its current position and exactly as specified in the {@link
+     * AsynchronousByteChannel} interface. If there are fewer bytes
+     * remaining in the buffer than are required to hold the datagram then the
+     * remainder of the datagram is silently discarded.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}.
+     *
+     * @param   dst
+     *          The buffer into which the datagram is to be transferred
+     * @param   timeout
+     *          The timeout, or <tt>0L</tt> for no timeout
+     * @param   unit
+     *          The time unit of the <tt>timeout</tt> argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the timeout is negative or buffer is read-only
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> read(ByteBuffer dst,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+
+    public final <A> Future<Integer> read(ByteBuffer dst,
+                                          A attachment,
+                                          CompletionHandler<Integer,? super A> handler)
+    {
+        return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     */
+
+    public final Future<Integer> read(ByteBuffer dst) {
+        return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Writes a datagram to this channel.
+     *
+     * <p> This method initiates sending of a datagram, returning a
+     * <tt>Future</tt> representing the pending result of the operation.
+     * The operation sends the remaining bytes in the given buffer as a single
+     * datagram. The result of the operation, obtained by invoking the
+     * <tt>Future</tt>'s {@link Future#get() get} method, is the
+     * number of bytes sent.
+     *
+     * <p> The datagram is transferred from the byte buffer as if by a regular
+     * {@link AsynchronousByteChannel#write write} operation.
+     *
+     * <p> This method may only be invoked if this channel is connected,
+     * in which case it sends datagrams directly to the socket's peer.  Otherwise
+     * it behaves exactly as specified in the {@link
+     * AsynchronousByteChannel} interface.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}.
+     *
+     * @param   src
+     *          The buffer containing the datagram to be sent
+     * @param   timeout
+     *          The timeout, or <tt>0L</tt> for no timeout
+     * @param   unit
+     *          The time unit of the <tt>timeout</tt> argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a <tt>Future</tt> object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the timeout is negative
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> write(ByteBuffer src,
+                                              long timeout,
+                                              TimeUnit unit,
+                                              A attachment,
+                                              CompletionHandler<Integer,? super A> handler);
+    /**
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+
+    public final <A> Future<Integer> write(ByteBuffer src,
+                                           A attachment,
+                                           CompletionHandler<Integer,? super A> handler)
+    {
+        return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     */
+
+    public final Future<Integer> write(ByteBuffer src) {
+        return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,775 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.file.*;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.spi.*;
+import java.nio.ByteBuffer;
+import java.io.IOException;
+import java.util.concurrent.Future;
+import java.util.concurrent.ExecutorService;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+/**
+ * An asynchronous channel for reading, writing, and manipulating a file.
+ *
+ * <p> An asynchronous file channel is created when a file is opened by invoking
+ * one of the {@link #open open} methods defined by this class. The file contains
+ * a variable-length sequence of bytes that can be read and written and whose
+ * current size can be {@link #size() queried}. The size of the file increases
+ * when bytes are written beyond its  current size; the size of the file decreases
+ * when it is {@link #truncate truncated}.
+ *
+ * <p> An asynchronous file channel does not have a <i>current position</i>
+ * within the file. Instead, the file position is specified to each read and
+ * write operation.
+ *
+ * <p> In addition to read and write operations, this class defines the
+ * following operations: </p>
+ *
+ * <ul>
+ *
+ *   <li><p> Updates made to a file may be {@link #force <i>forced
+ *   out</i>} to the underlying storage device, ensuring that data are not
+ *   lost in the event of a system crash.  </p></li>
+ *
+ *   <li><p> A region of a file may be {@link FileLock <i>locked</i>}
+ *   against access by other programs.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> The {@link #read read}, {@link #write write}, and {@link #lock lock}
+ * methods defined by this class are asynchronous  and return a {@link Future}
+ * to represent the pending result of the operation. This may be used to check
+ * if the operation has completed, to wait for its completion, and to retrieve
+ * the result. These method may optionally specify a {@link CompletionHandler}
+ * that is invoked to consume the result of the I/O operation when it completes.
+ *
+ * <p> An {@code AsynchronousFileChannel} is associated with a thread pool to
+ * which tasks are submitted to handle I/O events and dispatch to completion
+ * handlers that consume the results of I/O operations on the channel. The
+ * completion handler for an I/O operation initiated on a channel is guaranteed
+ * to be invoked by one threads in the thread pool (This ensures that the
+ * completion handler is run by a thread with the expected <em>identity</em>).
+ * Where an I/O operation completes immediately, and the initiating thread is
+ * itself a thread in the thread pool, then the completion handler may be invoked
+ * directly by the initiating thread. When an {@code AsynchronousFileChannel} is
+ * created without specifying a thread pool then the channel is associated with
+ * a system-dependent and default thread pool that may be shared with other
+ * channels. The default thread pool is configured by the system properties
+ * defined by the {@link AsynchronousChannelGroup} class.
+ *
+ * <p> Channels of this type are safe for use by multiple concurrent threads. The
+ * {@link Channel#close close} method may be invoked at any time, as specified
+ * by the {@link Channel} interface. This causes all outstanding asynchronous
+ * operations on the channel to complete with the exception {@link
+ * AsynchronousCloseException}. Multiple read and write operations may be
+ * outstanding at the same time. When multiple read and write operations are
+ * outstanding then the ordering of the I/O operations, and the order that the
+ * completion handlers are invoked, is not specified; they are not, in particular,
+ * guaranteed to execute in the order that the operations were initiated. The
+ * {@link java.nio.ByteBuffer ByteBuffers} used when reading or writing are not
+ * safe for use by multiple concurrent I/O operations. Furthermore, after an I/O
+ * operation is initiated then care should be taken to ensure that the buffer is
+ * not accessed until after the operation has completed.
+ *
+ * <p> As with {@link FileChannel}, the view of a file provided by an instance of
+ * this class is guaranteed to be consistent with other views of the same file
+ * provided by other instances in the same program.  The view provided by an
+ * instance of this class may or may not, however, be consistent with the views
+ * seen by other concurrently-running programs due to caching performed by the
+ * underlying operating system and delays induced by network-filesystem protocols.
+ * This is true regardless of the language in which these other programs are
+ * written, and whether they are running on the same machine or on some other
+ * machine.  The exact nature of any such inconsistencies are system-dependent
+ * and are therefore unspecified.
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousFileChannel
+    implements AsynchronousChannel
+{
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousFileChannel() {
+    }
+
+    /**
+     * Closes this channel.
+     *
+     * <p> If this channel is associated with its own thread pool then closing
+     * the channel causes the thread pool to shutdown after all actively
+     * executing completion handlers have completed. No attempt is made to stop
+     * or interrupt actively completion handlers.
+     *
+     * <p> This method otherwise behaves exactly as specified by the {@link
+     * AsynchronousChannel} interface.
+     *
+     * @throws  IOException     {@inheritDoc}
+     */
+
+    public abstract void close() throws IOException;
+
+    /**
+     * Opens or creates a file for reading and/or writing, returning an
+     * asynchronous file channel to access the file.
+     *
+     * <p> The {@code options} parameter determines how the file is opened.
+     * The {@link StandardOpenOption#READ READ} and {@link StandardOpenOption#WRITE
+     * WRITE} options determines if the file should be opened for reading and/or
+     * writing. If neither option is contained in the array then an existing file
+     * is opened for  reading.
+     *
+     * <p> In addition to {@code READ} and {@code WRITE}, the following options
+     * may be present:
+     *
+     * <table border=1 cellpadding=5 summary="">
+     * <tr> <th>Option</th> <th>Description</th> </tr>
+     * <tr>
+     *   <td> {@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} </td>
+     *   <td> When opening an existing file, the file is first 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#CREATE_NEW CREATE_NEW} </td>
+     *   <td> If this option is present then a new file is created, failing if
+     *   the file already exists. When creating a file the check for the
+     *   existence of the file and the creation of the file if it does not exist
+     *   is atomic with respect to other file system operations. This option is
+     *   ignored when the file is opened only for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td > {@link StandardOpenOption#CREATE CREATE} </td>
+     *   <td> If this option is present then an existing file is opened if it
+     *   exists, otherwise a new file is created. When creating a file the check
+     *   for the existence of the file and the creation of the file if it does
+     *   not exist is atomic with respect to other file system operations. This
+     *   option is ignored if the {@code CREATE_NEW} option is also present or
+     *   the file is opened only for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </td>
+     *   <td> When this option is present then the implementation makes a
+     *   <em>best effort</em> attempt to delete the file when closed by the
+     *   the {@link #close close} method. If the {@code close} method is not
+     *   invoked then a <em>best effort</em> attempt is made to delete the file
+     *   when the Java virtual machine terminates. </td>
+     * </tr>
+     * <tr>
+     *   <td>{@link StandardOpenOption#SPARSE SPARSE} </td>
+     *   <td> When creating a new file this option is a <em>hint</em> that the
+     *   new file will be sparse. This option is ignored when not creating
+     *   a new file. </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="../file/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="../file/package-summary.html#integrity"> Synchronized I/O file
+     *   integrity</a>). </td>
+     * </tr>
+     * </table>
+     *
+     * <p> An implementation may also support additional options.
+     *
+     * <p> The {@code executor} parameter is the {@link ExecutorService} to
+     * which tasks are submitted to handle I/O events and dispatch completion
+     * results for operations initiated on resulting channel.
+     * The nature of these tasks is highly implementation specific and so care
+     * should be taken when configuring the {@code Executor}. Minimally it
+     * should support an unbounded work queue and should not run tasks on the
+     * caller thread of the {@link ExecutorService#execute execute} method.
+     * {@link #close Closing} the channel results in the orderly {@link
+     * ExecutorService#shutdown shutdown} of the executor service. Shutting down
+     * the executor service by other means results in unspecified behavior.
+     *
+     * <p> The {@code attrs} parameter is an optional array of file {@link
+     * FileAttribute file-attributes} to set atomically when creating the file.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * FileSystemProvider#newFileChannel newFileChannel} method on the
+     * provider that created the {@code Path}.
+     *
+     * @param   file
+     *          The path of the file to open or create
+     * @param   options
+     *          Options specifying how the file is opened
+     * @param   executor
+     *          The thread pool or {@code null} to associate the channel with
+     *          the default thread pool
+     * @param   attrs
+     *          An optional list of file attributes to set atomically when
+     *          creating the file
+     *
+     * @return  A new asynchronous file channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If the {@code file} is associated with a provider that does not
+     *          support creating asynchronous file channels, or an unsupported
+     *          open option is specified, or the array contains an attribute that
+     *          cannot be set atomically when creating the file
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an
+     *          unspecified permission required by the implementation.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String)} method is invoked to check
+     *          read access if the file is opened for reading. The {@link
+     *          SecurityManager#checkWrite(String)} method is invoked to check
+     *          write access if the file is opened for writing
+     */
+    public static AsynchronousFileChannel open(Path file,
+                                               Set<? extends OpenOption> options,
+                                               ExecutorService executor,
+                                               FileAttribute<?>... attrs)
+        throws IOException
+    {
+        FileSystemProvider provider = file.getFileSystem().provider();
+        return provider.newAsynchronousFileChannel(file, options, executor, attrs);
+    }
+
+    private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
+
+    /**
+     * Opens or creates a file for reading and/or writing, returning an
+     * asynchronous file channel to access the file.
+     *
+     * <p> An invocation of this method behaves in exactly the same way as the
+     * invocation
+     * <pre>
+     *     ch.{@link #open(Path,Set,ExecutorService,FileAttribute[]) open}(file, opts, null, new FileAttribute&lt;?&gt;[0]);
+     * </pre>
+     * where {@code opts} is a {@code Set} containing the options specified to
+     * this method.
+     *
+     * <p> The resulting channel is associated with default thread pool to which
+     * tasks are submitted to handle I/O events and dispatch to completion
+     * handlers that consume the result of asynchronous operations performed on
+     * the resulting channel.
+     *
+     * @param   file
+     *          The path of the file to open or create
+     * @param   options
+     *          Options specifying how the file is opened
+     *
+     * @return  A new asynchronous file channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If the {@code file} is associated with a provider that does not
+     *          support creating file channels, or an unsupported open option is
+     *          specified
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an
+     *          unspecified permission required by the implementation.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String)} method is invoked to check
+     *          read access if the file is opened for reading. The {@link
+     *          SecurityManager#checkWrite(String)} method is invoked to check
+     *          write access if the file is opened for writing
+     */
+    public static AsynchronousFileChannel open(Path file, OpenOption... options)
+        throws IOException
+    {
+        Set<OpenOption> set = new HashSet<OpenOption>(options.length);
+        Collections.addAll(set, options);
+        return open(file, set, null, NO_ATTRIBUTES);
+    }
+
+    /**
+     * Returns the current size of this channel's file.
+     *
+     * @return  The current size of this channel's file, measured in bytes
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract long size() throws IOException;
+
+    /**
+     * Truncates this channel's file to the given size.
+     *
+     * <p> If the given size is less than the file's current size then the file
+     * is truncated, discarding any bytes beyond the new end of the file.  If
+     * the given size is greater than or equal to the file's current size then
+     * the file is not modified. </p>
+     *
+     * @param  size
+     *         The new size, a non-negative byte count
+     *
+     * @return  This file channel
+     *
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IllegalArgumentException
+     *          If the new size is negative
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousFileChannel truncate(long size) throws IOException;
+
+    /**
+     * Forces any updates to this channel's file to be written to the storage
+     * device that contains it.
+     *
+     * <p> If this channel's file resides on a local storage device then when
+     * this method returns it is guaranteed that all changes made to the file
+     * since this channel was created, or since this method was last invoked,
+     * will have been written to that device.  This is useful for ensuring that
+     * critical information is not lost in the event of a system crash.
+     *
+     * <p> If the file does not reside on a local device then no such guarantee
+     * is made.
+     *
+     * <p> The {@code metaData} parameter can be used to limit the number of
+     * I/O operations that this method is required to perform.  Passing
+     * {@code false} for this parameter indicates that only updates to the
+     * file's content need be written to storage; passing {@code true}
+     * indicates that updates to both the file's content and metadata must be
+     * written, which generally requires at least one more I/O operation.
+     * Whether this parameter actually has any effect is dependent upon the
+     * underlying operating system and is therefore unspecified.
+     *
+     * <p> Invoking this method may cause an I/O operation to occur even if the
+     * channel was only opened for reading.  Some operating systems, for
+     * example, maintain a last-access time as part of a file's metadata, and
+     * this time is updated whenever the file is read.  Whether or not this is
+     * actually done is system-dependent and is therefore unspecified.
+     *
+     * <p> This method is only guaranteed to force changes that were made to
+     * this channel's file via the methods defined in this class.
+     *
+     * @param   metaData
+     *          If {@code true} then this method is required to force changes
+     *          to both the file's content and metadata to be written to
+     *          storage; otherwise, it need only force content changes to be
+     *          written
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract void force(boolean metaData) throws IOException;
+
+    /**
+     * Acquires a lock on the given region of this channel's file.
+     *
+     * <p> This method initiates an operation to acquire a lock on the given region
+     * of this channel's file. The method returns a {@code Future} representing
+     * the pending result of the operation. Its {@link Future#get() get}
+     * method returns the {@link FileLock} on successful completion.
+     *
+     * <p> The region specified by the {@code position} and {@code size}
+     * parameters need not be contained within, or even overlap, the actual
+     * underlying file.  Lock regions are fixed in size; if a locked region
+     * initially contains the end of the file and the file grows beyond the
+     * region then the new portion of the file will not be covered by the lock.
+     * If a file is expected to grow in size and a lock on the entire file is
+     * required then a region starting at zero, and no smaller than the
+     * expected maximum size of the file, should be locked.  The two-argument
+     * {@link #lock(Object,CompletionHandler)} method simply locks a region
+     * of size {@link Long#MAX_VALUE}. If a lock that overlaps the requested
+     * region is already held by this Java virtual machine, or this method has
+     * been invoked to lock an overlapping region and that operation has not
+     * completed, then this method throws {@link OverlappingFileLockException}.
+     *
+     * <p> Some operating systems do not support a mechanism to acquire a file
+     * lock in an asynchronous manner. Consequently an implementation may
+     * acquire the file lock in a background thread or from a task executed by
+     * a thread in the associated thread pool. If there are many lock operations
+     * outstanding then it may consume threads in the Java virtual machine for
+     * indefinite periods.
+     *
+     * <p> Some operating systems do not support shared locks, in which case a
+     * request for a shared lock is automatically converted into a request for
+     * an exclusive lock.  Whether the newly-acquired lock is shared or
+     * exclusive may be tested by invoking the resulting lock object's {@link
+     * FileLock#isShared() isShared} method.
+     *
+     * <p> File locks are held on behalf of the entire Java virtual machine.
+     * They are not suitable for controlling access to a file by multiple
+     * threads within the same virtual machine.
+     *
+     * @param   position
+     *          The position at which the locked region is to start; must be
+     *          non-negative
+     * @param   size
+     *          The size of the locked region; must be non-negative, and the sum
+     *          {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
+     * @param   shared
+     *          {@code true} to request a shared lock, in which case this
+     *          channel must be open for reading (and possibly writing);
+     *          {@code false} to request an exclusive lock, in which case this
+     *          channel must be open for writing (and possibly reading)
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a {@code Future} object representing the pending result
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or there is already a pending attempt
+     *          to lock an overlapping region
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     * @throws  NonReadableChannelException
+     *          If {@code shared} is true this channel but was not opened for reading
+     * @throws  NonWritableChannelException
+     *          If {@code shared} is false but this channel was not opened for writing
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, the channel is closed, and the channel
+     *          was originally created with its own thread pool
+     */
+    public abstract <A> Future<FileLock> lock(long position,
+                                              long size,
+                                              boolean shared,
+                                              A attachment,
+                                              CompletionHandler<FileLock,? super A> handler);
+
+    /**
+     * Acquires an exclusive lock on this channel's file.
+     *
+     * <p> This method initiates an operation to acquire an exclusive lock on this
+     * channel's file. The method returns a {@code Future} representing
+     * the pending result of the operation. Its {@link Future#get() get}
+     * method returns the {@link FileLock} on successful completion.
+     *
+     * <p> An invocation of this method of the form {@code ch.lock(att,handler)}
+     * behaves in exactly the same way as the invocation
+     * <pre>
+     *     ch.{@link #lock(long,long,boolean,Object,CompletionHandler) lock}(0L, Long.MAX_VALUE, false, att, handler)
+     * </pre>
+     *
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  a {@code Future} object representing the pending result
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock is already held by this Java virtual machine, or there
+     *          is already a pending attempt to lock a region
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, the channel is closed, and the channel
+     *          was originally created with its own thread pool
+     */
+    public final <A> Future<FileLock> lock(A attachment,
+                                           CompletionHandler<FileLock,? super A> handler)
+    {
+        return lock(0L, Long.MAX_VALUE, false, attachment, handler);
+    }
+
+    /**
+     * Acquires an exclusive lock on this channel's file.
+     *
+     * <p> This method initiates an operation to acquire an exclusive lock on this
+     * channel's file. The method returns a {@code Future} representing the
+     * pending result of the operation. Its {@link Future#get() get} method
+     * returns the {@link FileLock} on successful completion.
+     *
+     * <p> An invocation of this method behaves in exactly the same way as the
+     * invocation
+     * <pre>
+     *     ch.{@link #lock(long,long,boolean,Object,CompletionHandler) lock}(0L, Long.MAX_VALUE, false, null, null)
+     * </pre>
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock is already held by this Java virtual machine, or there
+     *          is already a pending attempt to lock a region
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     */
+    public final Future<FileLock> lock() {
+        return lock(0L, Long.MAX_VALUE, false, null, null);
+    }
+
+    /**
+     * Attempts to acquire a lock on the given region of this channel's file.
+     *
+     * <p> This method does not block. An invocation always returns immediately,
+     * either having acquired a lock on the requested region or having failed to
+     * do so.  If it fails to acquire a lock because an overlapping lock is held
+     * by another program then it returns {@code null}.  If it fails to acquire
+     * a lock for any other reason then an appropriate exception is thrown.
+     *
+     * @param  position
+     *         The position at which the locked region is to start; must be
+     *         non-negative
+     *
+     * @param  size
+     *         The size of the locked region; must be non-negative, and the sum
+     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
+     *
+     * @param  shared
+     *         {@code true} to request a shared lock,
+     *         {@code false} to request an exclusive lock
+     *
+     * @return  A lock object representing the newly-acquired lock,
+     *          or {@code null} if the lock could not be acquired
+     *          because another program holds an overlapping lock
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or if another thread is already
+     *          blocked in this method and is attempting to lock an overlapping
+     *          region of the same file
+     * @throws  NonReadableChannelException
+     *          If {@code shared} is true this channel but was not opened for reading
+     * @throws  NonWritableChannelException
+     *          If {@code shared} is false but this channel was not opened for writing
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     *
+     * @see     #lock(Object,CompletionHandler)
+     * @see     #lock(long,long,boolean,Object,CompletionHandler)
+     * @see     #tryLock()
+     */
+    public abstract FileLock tryLock(long position, long size, boolean shared)
+        throws IOException;
+
+    /**
+     * Attempts to acquire an exclusive lock on this channel's file.
+     *
+     * <p> An invocation of this method of the form {@code ch.tryLock()}
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     ch.{@link #tryLock(long,long,boolean) tryLock}(0L, Long.MAX_VALUE, false) </pre>
+     *
+     * @return  A lock object representing the newly-acquired lock,
+     *          or {@code null} if the lock could not be acquired
+     *          because another program holds an overlapping lock
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or if another thread is already
+     *          blocked in this method and is attempting to lock an overlapping
+     *          region
+     * @throws  NonWritableChannelException
+     *          If {@code shared} is false but this channel was not opened for writing
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     *
+     * @see     #lock(Object,CompletionHandler)
+     * @see     #lock(long,long,boolean,Object,CompletionHandler)
+     * @see     #tryLock(long,long,boolean)
+     */
+    public final FileLock tryLock() throws IOException {
+        return tryLock(0L, Long.MAX_VALUE, false);
+    }
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer,
+     * starting at the given file position.
+     *
+     * <p> This method initiates the reading of a sequence of bytes from this
+     * channel into the given buffer, starting at the given file position. This
+     * method returns a {@code Future} representing the pending result of the
+     * operation. The Future's {@link Future#get() get} method returns the
+     * number of bytes read or {@code -1} if the given position is greater than
+     * or equal to the file's size at the time that the read is attempted.
+     *
+     * <p> This method works in the same manner as the {@link
+     * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)}
+     * method, except that bytes are read starting at the given file position.
+     * If the given file position is greater than the file's size at the time
+     * that the read is attempted then no bytes are read.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   position
+     *          The file position at which the transfer is to begin;
+     *          must be non-negative
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the position is negative or the buffer is read-only
+     * @throws  NonReadableChannelException
+     *          If this channel was not opened for reading
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, the channel is closed, and the channel
+     *          was originally created with its own thread pool
+     */
+    public abstract <A> Future<Integer> read(ByteBuffer dst,
+                                             long position,
+                                             A attachment,
+                                             CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer,
+     * starting at the given file position.
+     *
+     * <p> This method initiates the reading of a sequence of bytes from this
+     * channel into the given buffer, starting at the given file position. This
+     * method returns a {@code Future} representing the pending result of the
+     * operation. The Future's {@link Future#get() get} method returns the
+     * number of bytes read or {@code -1} if the given position is greater
+     * than or equal to the file's size at the time that the read is attempted.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #read(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment}
+     * and handler parameters set to {@code null}.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   position
+     *          The file position at which the transfer is to begin;
+     *          must be non-negative
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the position is negative or the buffer is read-only
+     * @throws  NonReadableChannelException
+     *          If this channel was not opened for reading
+     */
+    public final Future<Integer> read(ByteBuffer dst, long position) {
+        return read(dst, position, null, null);
+    }
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer, starting
+     * at the given file position.
+     *
+     * <p> This method initiates the writing of a sequence of bytes to this channel
+     * from the given buffer, starting at the given file position. The method
+     * returns a {@code Future} representing the pending result of the write
+     * operation. The Future's {@link Future#get() get} method returns the
+     * number of bytes written.
+     *
+     * <p> This method works in the same manner as the {@link
+     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
+     * method, except that bytes are written starting at the given file position.
+     * If the given position is greater than the file's size, at the time that
+     * the write is attempted, then the file will be grown to accommodate the new
+     * bytes; the values of any bytes between the previous end-of-file and the
+     * newly-written bytes are unspecified.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be transferred
+     * @param   position
+     *          The file position at which the transfer is to begin;
+     *          must be non-negative
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the position is negative
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, the channel is closed, and the channel
+     *          was originally created with its own thread pool
+     */
+    public abstract <A> Future<Integer> write(ByteBuffer src,
+                                              long position,
+                                              A attachment,
+                                              CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer, starting
+     * at the given file position.
+     *
+     * <p> This method initiates the writing of a sequence of bytes to this channel
+     * from the given buffer, starting at the given file position. The method
+     * returns a {@code Future} representing the pending result of the write
+     * operation. The Future's {@link Future#get() get} method returns the
+     * number of bytes written.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #write(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment}
+     * and handler parameters set to {@code null}.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be transferred
+     * @param   position
+     *          The file position at which the transfer is to begin;
+     *          must be non-negative
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the position is negative
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     */
+    public final Future<Integer> write(ByteBuffer src, long position) {
+        return write(src, position, null, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.channels.spi.*;
+import java.net.SocketOption;
+import java.net.SocketAddress;
+import java.util.concurrent.Future;
+import java.io.IOException;
+
+/**
+ * An asynchronous channel for stream-oriented listening sockets.
+ *
+ * <p> An asynchronous server-socket channel is created by invoking the
+ * {@link #open open} method of this class.
+ * A newly-created asynchronous server-socket channel is open but not yet bound.
+ * It can be bound to a local address and configured to listen for connections
+ * by invoking the {@link #bind(SocketAddress,int) bind} method. Once bound,
+ * the {@link #accept(Object,CompletionHandler) accept} method
+ * is used to initiate the accepting of connections to the channel's socket.
+ * An attempt to invoke the <tt>accept</tt> method on an unbound channel will
+ * cause a {@link NotYetBoundException} to be thrown.
+ *
+ * <p> Channels of this type are safe for use by multiple concurrent threads
+ * though at most one accept operation can be outstanding at any time.
+ * If a thread initiates an accept operation before a previous accept operation
+ * has completed then an {@link AcceptPendingException} will be thrown.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Channels of this type support the following options:
+ * <blockquote>
+ * <table border>
+ *   <tr>
+ *     <th>Option Name</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ *     <td> The size of the socket receive buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ *     <td> Re-use address </td>
+ *   </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
+ * <p> <b>Usage Example:</b>
+ * <pre>
+ *  final AsynchronousServerSocketChannel listener =
+ *      AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
+ *
+ *  listener.accept(null, new CompletionHandler&lt;AsynchronousSocketChannel,Void&gt;() {
+ *      public void completed(AsynchronousSocketChannel ch, Void att) {
+ *          // accept the next connection
+ *          listener.accept(null, this);
+ *
+ *          // handle this connection
+ *          handle(ch);
+ *      }
+ *      public void failed(Throwable exc, Void att) {
+ *          ...
+ *      }
+ *      public void cancelled(Void att) {
+ *          ...
+ *      }
+ *  });
+ * </pre>
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousServerSocketChannel
+    implements AsynchronousChannel, NetworkChannel
+{
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousServerSocketChannel(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel.
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Opens an asynchronous server-socket channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousServerSocketChannel
+     * openAsynchronousServerSocketChannel} method on the {@link
+     * java.nio.channels.spi.AsynchronousChannelProvider} object that created
+     * the given group. If the group parameter is <tt>null</tt> then the
+     * resulting channel is created by the system-wide default provider, and
+     * bound to the <em>default group</em>.
+     *
+     * @param   group
+     *          The group to which the newly constructed channel should be bound,
+     *          or <tt>null</tt> for the default group
+     *
+     * @return  A new asynchronous server socket channel
+     *
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousServerSocketChannel open(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        AsynchronousChannelProvider provider = (group == null) ?
+            AsynchronousChannelProvider.provider() : group.provider();
+        return provider.openAsynchronousServerSocketChannel(group);
+    }
+
+    /**
+     * Opens an asynchronous server-socket channel.
+     *
+     * <p> This method returns an asynchronous server socket channel that is
+     * bound to the <em>default group</em>. This method is equivalent to evaluating
+     * the expression:
+     * <blockquote><pre>
+     * open((AsynchronousChannelGroup)null);
+     * </pre></blockquote>
+     *
+     * @return  A new asynchronous server socket channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousServerSocketChannel open()
+        throws IOException
+    {
+        return open(null);
+    }
+
+    /**
+     * Binds the channel's socket to a local address and configures the socket to
+     * listen for connections.
+     *
+     * <p> An invocation of this method is equivalent to the following:
+     * <blockquote><pre>
+     * bind(local, 0);
+     * </pre></blockquote>
+     *
+     * @param   local
+     *          The local address to bind the socket, or <tt>null</tt> to bind
+     *          to an automatically assigned socket address
+     *
+     * @return  This channel
+     *
+     * @throws  AlreadyBoundException               {@inheritDoc}
+     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  SecurityException                   {@inheritDoc}
+     * @throws  ClosedChannelException              {@inheritDoc}
+     * @throws  IOException                         {@inheritDoc}
+     */
+    public final AsynchronousServerSocketChannel bind(SocketAddress local)
+        throws IOException
+    {
+        return bind(local, 0);
+    }
+
+    /**
+     * Binds the channel's socket to a local address and configures the socket to
+     * listen for connections.
+     *
+     * <p> This method is used to establish an association between the socket and
+     * a local address. Once an association is established then the socket remains
+     * bound until the associated channel is closed.
+     *
+     * <p> The {@code backlog} parameter is the maximum number of pending
+     * connections on the socket. Its exact semantics are implementation specific.
+     * In particular, an implementation may impose a maximum length or may choose
+     * to ignore the parameter altogther. If the {@code backlog} parameter has
+     * the value {@code 0}, or a negative value, then an implementation specific
+     * default is used.
+     *
+     * @param   local
+     *          The local address to bind the socket, or {@code null} to bind
+     *          to an automatically assigned socket address
+     * @param   backlog
+     *          The maximum number of pending connections
+     *
+     * @return  This channel
+     *
+     * @throws  AlreadyBoundException
+     *          If the socket is already bound
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given address is not supported
+     * @throws  SecurityException
+     *          If a security manager has been installed and its {@link
+     *          SecurityManager#checkListen checkListen} method denies the operation
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousServerSocketChannel bind(SocketAddress local, int backlog)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     */
+    public abstract <T> AsynchronousServerSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * Accepts a connection.
+     *
+     * <p> This method initiates accepting a connection made to this channel's
+     * socket, returning a {@link Future} representing the pending result
+     * of the operation. The {@code Future}'s {@link Future#get() get}
+     * method will return the {@link AsynchronousSocketChannel} for the new
+     * connection on successful completion.
+     *
+     * <p> When a new connection is accepted then the resulting {@code
+     * AsynchronousSocketChannel} will be bound to the same {@link
+     * AsynchronousChannelGroup} as this channel. If the group is {@link
+     * AsynchronousChannelGroup#isShutdown shutdown} and a connection is accepted,
+     * then the connection is closed, and the operation completes with an {@code
+     * IOException} and cause {@link ShutdownChannelGroupException}.
+     *
+     * <p> To allow for concurrent handling of new connections, the completion
+     * handler is not invoked directly by the initiating thread when a new
+     * connection is accepted immediately (see <a
+     * href="AsynchronousChannelGroup.html#threading">Threading<a>).
+     *
+     * <p> If a security manager has been installed then it verifies that the
+     * address and port number of the connection's remote endpoint are permitted
+     * by the security manager's {@link SecurityManager#checkAccept checkAccept}
+     * method. The permission check is performed with privileges that are restricted
+     * by the calling context of this method. If the permission check fails then
+     * the connection is closed and the operation completes with a {@link
+     * SecurityException}.
+     *
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  an <tt>Future</tt> object representing the pending result
+     *
+     * @throws  AcceptPendingException
+     *          If an accept operation is already in progress on this channel
+     * @throws  NotYetBoundException
+     *          If this channel's socket has not yet been bound
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<AsynchronousSocketChannel>
+        accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler);
+
+    /**
+     * Accepts a connection.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #accept(Object,CompletionHandler)} with the {@code attachment}
+     * and {@code handler} parameters set to {@code null}.
+     *
+     * @return  an <tt>Future</tt> object representing the pending result
+     *
+     * @throws  AcceptPendingException
+     *          If an accept operation is already in progress on this channel
+     * @throws  NotYetBoundException
+     *          If this channel's socket has not yet been bound
+     */
+    public final Future<AsynchronousSocketChannel> accept() {
+        return accept(null, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,671 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.channels.spi.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Future;
+import java.io.IOException;
+import java.net.SocketOption;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * An asynchronous channel for stream-oriented connecting sockets.
+ *
+ * <p> Asynchronous socket channels are created in one of two ways. A newly-created
+ * {@code AsynchronousSocketChannel} is created by invoking one of the {@link
+ * #open open} methods defined by this class. A newly-created channel is open but
+ * not yet connected. A connected {@code AsynchronousSocketChannel} is created
+ * when a connection is made to the socket of an {@link AsynchronousServerSocketChannel}.
+ * It is not possible to create an asynchronous socket channel for an arbitrary,
+ * pre-existing {@link java.net.Socket socket}.
+ *
+ * <p> A newly-created channel is connected by invoking its {@link #connect connect}
+ * method; once connected, a channel remains connected until it is closed.  Whether
+ * or not a socket channel is connected may be determined by invoking its {@link
+ * #getRemoteAddress getRemoteAddress} method. An attempt to invoke an I/O
+ * operation upon an unconnected channel will cause a {@link NotYetConnectedException}
+ * to be thrown.
+ *
+ * <p> Channels of this type are safe for use by multiple concurrent threads.
+ * They support concurrent reading and writing, though at most one read operation
+ * and one write operation can be outstanding at any time.
+ * If a thread initiates a read operation before a previous read operation has
+ * completed then a {@link ReadPendingException} will be thrown. Similarly, an
+ * attempt to initiate a write operation before a previous write has completed
+ * will throw a {@link WritePendingException}.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Asynchronous socket channels support the following options:
+ * <blockquote>
+ * <table border>
+ *   <tr>
+ *     <th>Option Name</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
+ *     <td> The size of the socket send buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ *     <td> The size of the socket receive buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_KEEPALIVE SO_KEEPALIVE} </td>
+ *     <td> Keep connection alive </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ *     <td> Re-use address </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#TCP_NODELAY TCP_NODELAY} </td>
+ *     <td> Disable the Nagle algorithm </td>
+ *   </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
+ * <h4>Timeouts</h4>
+ *
+ * <p> The {@link #read(ByteBuffer,long,TimeUnit,Object,CompletionHandler) read}
+ * and {@link #write(ByteBuffer,long,TimeUnit,Object,CompletionHandler) write}
+ * methods defined by this class allow a timeout to be specified when initiating
+ * a read or write operation. If the timeout elapses before an operation completes
+ * then the operation completes with the exception {@link
+ * InterruptedByTimeoutException}. A timeout may leave the channel, or the
+ * underlying connection, in an inconsistent state. Where the implementation
+ * cannot guarantee that bytes have not been read from the channel then it puts
+ * the channel into an implementation specific <em>error state</em>. A subsequent
+ * attempt to initiate a {@code read} operation causes an unspecified runtime
+ * exception to be thrown. Similarly if a {@code write} operation times out and
+ * the implementation cannot guarantee bytes have not been written to the
+ * channel then further attempts to {@code write} to the channel cause an
+ * unspecified runtime exception to be thrown. When a timeout elapses then the
+ * state of the {@link ByteBuffer}, or the sequence of buffers, for the I/O
+ * operation is not defined. Buffers should be discarded or at least care must
+ * be taken to ensure that the buffers are not accessed while the channel remains
+ * open.
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousSocketChannel
+    implements AsynchronousByteChannel, NetworkChannel
+{
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousSocketChannel(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel.
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousSocketChannel
+     * openAsynchronousSocketChannel} method on the {@link
+     * AsynchronousChannelProvider} that created the group. If the group parameter
+     * is {@code null} then the resulting channel is created by the system-wide
+     * default provider, and bound to the <em>default group</em>.
+     *
+     * @param   group
+     *          The group to which the newly constructed channel should be bound,
+     *          or {@code null} for the default group
+     *
+     * @return  A new asynchronous socket channel
+     *
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousSocketChannel open(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        AsynchronousChannelProvider provider = (group == null) ?
+            AsynchronousChannelProvider.provider() : group.provider();
+        return provider.openAsynchronousSocketChannel(group);
+    }
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * <p> This method returns an asynchronous socket channel that is bound to
+     * the <em>default group</em>.This method is equivalent to evaluating the
+     * expression:
+     * <blockquote><pre>
+     * open((AsynchronousChannelGroup)null);
+     * </pre></blockquote>
+     *
+     * @return  A new asynchronous socket channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousSocketChannel open()
+        throws IOException
+    {
+        return open(null);
+    }
+
+
+    // -- socket options and related --
+
+    /**
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  AlreadyBoundException               {@inheritDoc}
+     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  ClosedChannelException              {@inheritDoc}
+     * @throws  IOException                         {@inheritDoc}
+     */
+
+    public abstract AsynchronousSocketChannel bind(SocketAddress local)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     */
+
+    public abstract <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * Shutdown the connection for reading without closing the channel.
+     *
+     * <p> Once shutdown for reading then further reads on the channel will
+     * return {@code -1}, the end-of-stream indication. If the input side of the
+     * connection is already shutdown then invoking this method has no effect.
+     * The effect on an outstanding read operation is system dependent and
+     * therefore not specified. The effect, if any, when there is data in the
+     * socket receive buffer that has not been read, or data arrives subsequently,
+     * is also system dependent.
+     *
+     * @return  The channel
+     *
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel shutdownInput() throws IOException;
+
+    /**
+     * Shutdown the connection for writing without closing the channel.
+     *
+     * <p> Once shutdown for writing then further attempts to write to the
+     * channel will throw {@link ClosedChannelException}. If the output side of
+     * the connection is already shutdown then invoking this method has no
+     * effect. The effect on an outstanding write operation is system dependent
+     * and therefore not specified.
+     *
+     * @return  The channel
+     *
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel shutdownOutput() throws IOException;
+
+    // -- state --
+
+    /**
+     * Returns the remote address to which this channel's socket is connected.
+     *
+     * <p> Where the channel is bound and connected to an Internet Protocol
+     * socket address then the return value from this method is of type {@link
+     * java.net.InetSocketAddress}.
+     *
+     * @return  The remote address; {@code null} if the channel's socket is not
+     *          connected
+     *
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract SocketAddress getRemoteAddress() throws IOException;
+
+    // -- asynchronous operations --
+
+    /**
+     * Connects this channel.
+     *
+     * <p> This method initiates an operation to connect this channel, returning
+     * a {@code Future} representing the pending result of the operation. If
+     * the connection is successfully established then the {@code Future}'s
+     * {@link Future#get() get} method will return {@code null}. If the
+     * connection cannot be established then the channel is closed. In that case,
+     * invoking the {@code get} method throws {@link
+     * java.util.concurrent.ExecutionException} with an {@code IOException} as
+     * the cause.
+     *
+     * <p> This method performs exactly the same security checks as the {@link
+     * java.net.Socket} class.  That is, if a security manager has been
+     * installed then this method verifies that its {@link
+     * java.lang.SecurityManager#checkConnect checkConnect} method permits
+     * connecting to the address and port number of the given remote endpoint.
+     *
+     * @param   remote
+     *          The remote address to which this channel is to be connected
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote endpoint
+     *
+     * @see #getRemoteAddress
+     */
+    public abstract <A> Future<Void> connect(SocketAddress remote,
+                                             A attachment,
+                                             CompletionHandler<Void,? super A> handler);
+
+    /**
+     * Connects this channel.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment}
+     * and handler parameters set to {@code null}.
+     *
+     * @param   remote
+     *          The remote address to which this channel is to be connected
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote endpoint
+     */
+    public final Future<Void> connect(SocketAddress remote) {
+        return connect(remote, null, null);
+    }
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> This method initiates the reading of a sequence of bytes from this
+     * channel into the given buffer, returning a {@code Future} representing
+     * the pending result of the operation. The {@code Future}'s {@link
+     * Future#get() get} method returns the number of bytes read or {@code -1}
+     * if all bytes have been read and channel has reached end-of-stream.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been read, or will not
+     * be read from the channel into the given buffer, then further attempts to
+     * read from the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)}
+     * method.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative or the buffer is
+     *          read-only
+     * @throws  ReadPendingException
+     *          If a read operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> read(ByteBuffer dst,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  ReadPendingException            {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+
+    public final <A> Future<Integer> read(ByteBuffer dst,
+                                          A attachment,
+                                          CompletionHandler<Integer,? super A> handler)
+    {
+        return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  ReadPendingException            {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     */
+
+    public final Future<Integer> read(ByteBuffer dst) {
+        return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Reads a sequence of bytes from this channel into a subsequence of the
+     * given buffers. This operation, sometimes called a <em>scattering read</em>,
+     * is often useful when implementing network protocols that group data into
+     * segments consisting of one or more fixed-length headers followed by a
+     * variable-length body.
+     *
+     * <p> This method initiates a read of up to <i>r</i> bytes from this channel,
+     * where <i>r</i> is the total number of bytes remaining in the specified
+     * subsequence of the given buffer array, that is,
+     *
+     * <blockquote><pre>
+     * dsts[offset].remaining()
+     *     + dsts[offset+1].remaining()
+     *     + ... + dsts[offset+length-1].remaining()</pre></blockquote>
+     *
+     * at the moment that the read is attempted.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is read, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * Up to the first <tt>dsts[offset].remaining()</tt> bytes of this sequence
+     * are transferred into buffer <tt>dsts[offset]</tt>, up to the next
+     * <tt>dsts[offset+1].remaining()</tt> bytes are transferred into buffer
+     * <tt>dsts[offset+1]</tt>, and so forth, until the entire byte sequence
+     * is transferred into the given buffers.  As many bytes as possible are
+     * transferred into each buffer, hence the final position of each updated
+     * buffer, except the last updated buffer, is guaranteed to be equal to
+     * that buffer's limit. The underlying operating system may impose a limit
+     * on the number of buffers that may be used in an I/O operation. Where the
+     * number of buffers (with bytes remaining), exceeds this limit, then the
+     * I/O operation is performed with the maximum number of buffers allowed by
+     * the operating system.
+     *
+     * <p> The return value from this method is a {@code Future} representing
+     * the pending result of the operation. The {@code Future}'s {@link
+     * Future#get() get} method returns the number of bytes read or {@code -1L}
+     * if all bytes have been read and the channel has reached end-of-stream.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been read, or will not
+     * be read from the channel into the given buffers, then further attempts to
+     * read from the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * @param   dsts
+     *          The buffers into which bytes are to be transferred
+     * @param   offset
+     *          The offset within the buffer array of the first buffer into which
+     *          bytes are to be transferred; must be non-negative and no larger than
+     *          {@code dsts.length}
+     * @param   length
+     *          The maximum number of buffers to be accessed; must be non-negative
+     *          and no larger than {@code dsts.length - offset}
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the pre-conditions for the {@code offset}  and {@code length}
+     *          parameter aren't met
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative, or a buffer is
+     *          read-only
+     * @throws  ReadPendingException
+     *          If a read operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Long> read(ByteBuffer[] dsts,
+                                          int offset,
+                                          int length,
+                                          long timeout,
+                                          TimeUnit unit,
+                                          A attachment,
+                                          CompletionHandler<Long,? super A> handler);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> This method initiates the writing of a sequence of bytes to this channel
+     * from the given buffer, returning a {@code Future} representing the
+     * pending result of the operation. The {@code Future}'s {@link Future#get()
+     * get} method will return the number of bytes written.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been written, or will
+     * not be written to the channel from the given buffer, then further attempts
+     * to write to the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
+     * method.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative
+     * @throws  WritePendingException
+     *          If a write operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> write(ByteBuffer src,
+                                              long timeout,
+                                              TimeUnit unit,
+                                              A attachment,
+                                              CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  WritePendingException          {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+
+    public final <A> Future<Integer> write(ByteBuffer src,
+                                           A attachment,
+                                           CompletionHandler<Integer,? super A> handler)
+
+    {
+        return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  WritePendingException       {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     */
+
+    public final Future<Integer> write(ByteBuffer src) {
+        return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Writes a sequence of bytes to this channel from a subsequence of the given
+     * buffers. This operation, sometimes called a <em>gathering write</em>, is
+     * often useful when implementing network protocols that group data into
+     * segments consisting of one or more fixed-length headers followed by a
+     * variable-length body.
+     *
+     * <p> This method initiates a write of up to <i>r</i> bytes to this channel,
+     * where <i>r</i> is the total number of bytes remaining in the specified
+     * subsequence of the given buffer array, that is,
+     *
+     * <blockquote><pre>
+     * srcs[offset].remaining()
+     *     + srcs[offset+1].remaining()
+     *     + ... + srcs[offset+length-1].remaining()</pre></blockquote>
+     *
+     * at the moment that the write is attempted.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is written, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * Up to the first <tt>srcs[offset].remaining()</tt> bytes of this sequence
+     * are written from buffer <tt>srcs[offset]</tt>, up to the next
+     * <tt>srcs[offset+1].remaining()</tt> bytes are written from buffer
+     * <tt>srcs[offset+1]</tt>, and so forth, until the entire byte sequence is
+     * written.  As many bytes as possible are written from each buffer, hence
+     * the final position of each updated buffer, except the last updated
+     * buffer, is guaranteed to be equal to that buffer's limit. The underlying
+     * operating system may impose a limit on the number of buffers that may be
+     * used in an I/O operation. Where the number of buffers (with bytes
+     * remaining), exceeds this limit, then the I/O operation is performed with
+     * the maximum number of buffers allowed by the operating system.
+     *
+     * <p> The return value from this method is a {@code Future} representing
+     * the pending result of the operation. The {@code Future}'s {@link
+     * Future#get() get} method will return the number of bytes written.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been written, or will
+     * not be written to the channel from the given buffers, then further attempts
+     * to write to the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * @param   srcs
+     *          The buffers from which bytes are to be retrieved
+     * @param   offset
+     *          The offset within the buffer array of the first buffer from which
+     *          bytes are to be retrieved; must be non-negative and no larger
+     *          than {@code srcs.length}
+     * @param   length
+     *          The maximum number of buffers to be accessed; must be non-negative
+     *          and no larger than {@code srcs.length - offset}
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the pre-conditions for the {@code offset}  and {@code length}
+     *          parameter aren't met
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative
+     * @throws  WritePendingException
+     *          If a write operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Long> write(ByteBuffer[] srcs,
+                                           int offset,
+                                           int length,
+                                           long timeout,
+                                           TimeUnit unit,
+                                           A attachment,
+                                           CompletionHandler<Long,? super A> handler);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/Channels.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.util.concurrent.ExecutionException;
+import sun.nio.ch.ChannelInputStream;
+import sun.nio.cs.StreamDecoder;
+import sun.nio.cs.StreamEncoder;
+
+
+/**
+ * Utility methods for channels and streams.
+ *
+ * <p> This class defines static methods that support the interoperation of the
+ * stream classes of the <tt>{@link java.io}</tt> package with the channel
+ * classes of this package.  </p>
+ *
+ *
+ * @author Mark Reinhold
+ * @author Mike McCloskey
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ */
+
+public final class Channels {
+
+    private Channels() { }              // No instantiation
+
+    /**
+     * {@note new}
+     * Constructs a stream that reads bytes from the given channel.
+     *
+     * <p> The stream will not be buffered, and it will not support the {@link
+     * InputStream#mark mark} or {@link InputStream#reset reset} methods.  The
+     * stream will be safe for access by multiple concurrent threads.  Closing
+     * the stream will in turn cause the channel to be closed.  </p>
+     *
+     * @param  ch
+     *         The channel from which bytes will be read
+     *
+     * @return  A new input stream
+     *
+     * @since 1.7
+     */
+    public static InputStream newInputStream(final AsynchronousByteChannel ch) {
+        return new InputStream() {
+
+            private ByteBuffer bb = null;
+            private byte[] bs = null;           // Invoker's previous array
+            private byte[] b1 = null;
+
+
+            public synchronized int read() throws IOException {
+                if (b1 == null)
+                    b1 = new byte[1];
+                int n = this.read(b1);
+                if (n == 1)
+                    return b1[0] & 0xff;
+                return -1;
+            }
+
+
+            public synchronized int read(byte[] bs, int off, int len)
+                throws IOException
+            {
+                if ((off < 0) || (off > bs.length) || (len < 0) ||
+                    ((off + len) > bs.length) || ((off + len) < 0)) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0)
+                    return 0;
+
+                ByteBuffer bb = ((this.bs == bs)
+                                 ? this.bb
+                                 : ByteBuffer.wrap(bs));
+                bb.position(off);
+                bb.limit(Math.min(off + len, bb.capacity()));
+                this.bb = bb;
+                this.bs = bs;
+
+                boolean interrupted = false;
+                try {
+                    for (;;) {
+                        try {
+                            return ch.read(bb).get();
+                        } catch (ExecutionException ee) {
+                            throw new IOException(ee.getCause());
+                        } catch (InterruptedException ie) {
+                            interrupted = true;
+                        }
+                    }
+                } finally {
+                    if (interrupted)
+                        Thread.currentThread().interrupt();
+                }
+            }
+
+
+            public void close() throws IOException {
+                ch.close();
+            }
+        };
+    }
+
+    /**
+     * {@note new}
+     * Constructs a stream that writes bytes to the given channel.
+     *
+     * <p> The stream will not be buffered. The stream will be safe for access
+     * by multiple concurrent threads.  Closing the stream will in turn cause
+     * the channel to be closed.  </p>
+     *
+     * @param  ch
+     *         The channel to which bytes will be written
+     *
+     * @return  A new output stream
+     *
+     * @since 1.7
+     */
+    public static OutputStream newOutputStream(final AsynchronousByteChannel ch) {
+        return new OutputStream() {
+
+            private ByteBuffer bb = null;
+            private byte[] bs = null;   // Invoker's previous array
+            private byte[] b1 = null;
+
+
+            public synchronized void write(int b) throws IOException {
+               if (b1 == null)
+                    b1 = new byte[1];
+                b1[0] = (byte)b;
+                this.write(b1);
+            }
+
+
+            public synchronized void write(byte[] bs, int off, int len)
+                throws IOException
+            {
+                if ((off < 0) || (off > bs.length) || (len < 0) ||
+                    ((off + len) > bs.length) || ((off + len) < 0)) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0) {
+                    return;
+                }
+                ByteBuffer bb = ((this.bs == bs)
+                                 ? this.bb
+                                 : ByteBuffer.wrap(bs));
+                bb.limit(Math.min(off + len, bb.capacity()));
+                bb.position(off);
+                this.bb = bb;
+                this.bs = bs;
+
+                boolean interrupted = false;
+                try {
+                    while (bb.remaining() > 0) {
+                        try {
+                            ch.write(bb).get();
+                        } catch (ExecutionException ee) {
+                            throw new IOException(ee.getCause());
+                        } catch (InterruptedException ie) {
+                            interrupted = true;
+                        }
+                    }
+                } finally {
+                    if (interrupted)
+                        Thread.currentThread().interrupt();
+                }
+            }
+
+
+            public void close() throws IOException {
+                ch.close();
+            }
+        };
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/CompletionHandler.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+/**
+ * A handler for consuming the result of an asynchronous I/O operation.
+ *
+ * <p> The asynchronous channels defined in this package allow a completion
+ * handler to be specified to consume the result of an asynchronous operation.
+ * The {@link #completed completed} method is invoked when the I/O operation
+ * completes successfully. The {@link #failed failed} method is invoked if the
+ * I/O operations fails. The {@link #cancelled cancelled} method is invoked when
+ * the I/O operation is cancelled by invoking the {@link
+ * java.util.concurrent.Future#cancel cancel} method. The implementations of
+ * these methods should complete in a timely manner so as to avoid keeping the
+ * invoking thread from dispatching to other completion handlers.
+ *
+ * @param   <V>     The result type of the I/O operation
+ * @param   <A>     The type of the object attached to the I/O operation
+ *
+ * @since 1.7
+ */
+
+public interface CompletionHandler<V,A> {
+
+    /**
+     * Invoked when an operation has completed.
+     *
+     * @param   result
+     *          The result of the I/O operation.
+     * @param   attachment
+     *          The object attached to the I/O operation when it was initiated.
+     */
+    void completed(V result, A attachment);
+
+    /**
+     * Invoked when an operation fails.
+     *
+     * @param   exc
+     *          The exception
+     * @param   attachment
+     *          The object attached to the I/O operation when it was initiated.
+     */
+    void failed(Throwable exc, A attachment);
+
+    /**
+     * Invoked when an operation is cancelled by invoking the {@link
+     * java.util.concurrent.Future#cancel cancel} method.
+     *
+     * @param   attachment
+     *          The object attached to the I/O operation when it was initiated.
+     */
+    void cancelled(A attachment);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1160 @@
+/*
+ * Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.nio.file.*;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.spi.*;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+/**
+ * A channel for reading, writing, mapping, and manipulating a file.
+ *
+ * <p> {@note revised}
+ * A file channel is a {@link SeekableByteChannel} that is connected to
+ * a file. It has a current <i>position</i> within its file which can
+ * be both {@link #position() <i>queried</i>} and {@link #position(long)
+ * <i>modified</i>}.  The file itself contains a variable-length sequence
+ * of bytes that can be read and written and whose current {@link #size
+ * <i>size</i>} can be queried.  The size of the file increases
+ * when bytes are written beyond its current size; the size of the file
+ * decreases when it is {@link #truncate </code><i>truncated</i><code>}.  The
+ * file may also have some associated <i>metadata</i> such as access
+ * permissions, content type, and last-modification time; this class does not
+ * define methods for metadata access.
+ *
+ * <p> In addition to the familiar read, write, and close operations of byte
+ * channels, this class defines the following file-specific operations: </p>
+ *
+ * <ul>
+ *
+ *   <li><p> Bytes may be {@link #read(ByteBuffer, long) read} or
+ *   {@link #write(ByteBuffer, long) <i>written</i>} at an absolute
+ *   position in a file in a way that does not affect the channel's current
+ *   position.  </p></li>
+ *
+ *   <li><p> A region of a file may be {@link #map <i>mapped</i>}
+ *   directly into memory; for large files this is often much more efficient
+ *   than invoking the usual <tt>read</tt> or <tt>write</tt> methods.
+ *   </p></li>
+ *
+ *   <li><p> Updates made to a file may be {@link #force <i>forced
+ *   out</i>} to the underlying storage device, ensuring that data are not
+ *   lost in the event of a system crash.  </p></li>
+ *
+ *   <li><p> Bytes can be transferred from a file {@link #transferTo <i>to
+ *   some other channel</i>}, and {@link #transferFrom <i>vice
+ *   versa</i>}, in a way that can be optimized by many operating systems
+ *   into a very fast transfer directly to or from the filesystem cache.
+ *   </p></li>
+ *
+ *   <li><p> A region of a file may be {@link FileLock <i>locked</i>}
+ *   against access by other programs.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> File channels are safe for use by multiple concurrent threads.  The
+ * {@link Channel#close close} method may be invoked at any time, as specified
+ * by the {@link Channel} interface.  Only one operation that involves the
+ * channel's position or can change its file's size may be in progress at any
+ * given time; attempts to initiate a second such operation while the first is
+ * still in progress will block until the first operation completes.  Other
+ * operations, in particular those that take an explicit position, may proceed
+ * concurrently; whether they in fact do so is dependent upon the underlying
+ * implementation and is therefore unspecified.
+ *
+ * <p> The view of a file provided by an instance of this class is guaranteed
+ * to be consistent with other views of the same file provided by other
+ * instances in the same program.  The view provided by an instance of this
+ * class may or may not, however, be consistent with the views seen by other
+ * concurrently-running programs due to caching performed by the underlying
+ * operating system and delays induced by network-filesystem protocols.  This
+ * is true regardless of the language in which these other programs are
+ * written, and whether they are running on the same machine or on some other
+ * machine.  The exact nature of any such inconsistencies are system-dependent
+ * and are therefore unspecified.
+ *
+ * <p> A file channel is created by invoking one of the {@link #open open}
+ * methods defined by this class. A file channel can also be obtained from an
+ * existing {@link java.io.FileInputStream#getChannel FileInputStream}, {@link
+ * java.io.FileOutputStream#getChannel FileOutputStream}, or {@link
+ * java.io.RandomAccessFile#getChannel RandomAccessFile} object by invoking
+ * that object's <tt>getChannel</tt> method, which returns a file channel that
+ * is connected to the same underlying file. Where the file channel is obtained
+ * from an existing stream or random access file then the state of the file
+ * channel is intimately connected to that of the object whose <tt>getChannel</tt>
+ * method returned the channel.  Changing the channel's position, whether
+ * explicitly or by reading or writing bytes, will change the file position of
+ * the originating object, and vice versa. Changing the file's length via the
+ * file channel will change the length seen via the originating object, and vice
+ * versa.  Changing the file's content by writing bytes will change the content
+ * seen by the originating object, and vice versa.
+ *
+ * <a name="open-mode"></a> <p> At various points this class specifies that an
+ * instance that is "open for reading," "open for writing," or "open for
+ * reading and writing" is required.  A channel obtained via the {@link
+ * java.io.FileInputStream#getChannel getChannel} method of a {@link
+ * java.io.FileInputStream} instance will be open for reading.  A channel
+ * obtained via the {@link java.io.FileOutputStream#getChannel getChannel}
+ * method of a {@link java.io.FileOutputStream} instance will be open for
+ * writing.  Finally, a channel obtained via the {@link
+ * java.io.RandomAccessFile#getChannel getChannel} method of a {@link
+ * java.io.RandomAccessFile} instance will be open for reading if the instance
+ * was created with mode <tt>"r"</tt> and will be open for reading and writing
+ * if the instance was created with mode <tt>"rw"</tt>.
+ *
+ * <a name="append-mode"></a><p> A file channel that is open for writing may be in
+ * <i>append mode</i>, for example if it was obtained from a file-output stream
+ * that was created by invoking the {@link
+ * java.io.FileOutputStream#FileOutputStream(java.io.File,boolean)
+ * FileOutputStream(File,boolean)} constructor and passing <tt>true</tt> for
+ * the second parameter.  In this mode each invocation of a relative write
+ * operation 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.
+ *
+ * @see java.io.FileInputStream#getChannel()
+ * @see java.io.FileOutputStream#getChannel()
+ * @see java.io.RandomAccessFile#getChannel()
+ *
+ * @author Mark Reinhold
+ * @author Mike McCloskey
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ * @updated 1.7
+ */
+
+public abstract class FileChannel
+    extends AbstractInterruptibleChannel
+    implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel
+{
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected FileChannel() { }
+
+    /**
+     * {@note new}
+     * Opens or creates a file, returning a file channel to access 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:
+     *
+     * <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#CREATE_NEW CREATE_NEW} </td>
+     *   <td> If this option is present then a new file is created, failing if
+     *   the file already exists. When creating a file the check for the
+     *   existence of the file and the creation of the file if it does not exist
+     *   is atomic with respect to other file system operations. This option is
+     *   ignored when the file is opened only for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td > {@link StandardOpenOption#CREATE CREATE} </td>
+     *   <td> If this option is present then an existing file is opened if it
+     *   exists, otherwise a new file is created. When creating a file the check
+     *   for the existence of the file and the creation of the file if it does
+     *   not exist is atomic with respect to other file system operations. This
+     *   option is ignored if the {@code CREATE_NEW} option is also present or
+     *   the file is opened only for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </td>
+     *   <td> When this option is present then the implementation makes a
+     *   <em>best effort</em> attempt to delete the file when closed by the
+     *   the {@link #close close} method. If the {@code close} method is not
+     *   invoked then a <em>best effort</em> attempt is made to delete the file
+     *   when the Java virtual machine terminates. </td>
+     * </tr>
+     * <tr>
+     *   <td>{@link StandardOpenOption#SPARSE SPARSE} </td>
+     *   <td> When creating a new file this option is a <em>hint</em> that the
+     *   new file will be sparse. This option is ignored when not creating
+     *   a new file. </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="../file/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="../file/package-summary.html#integrity"> Synchronized I/O file
+     *   integrity</a>). </td>
+     * </tr>
+     * </table>
+     *
+     * <p> An implementation may also support additional options.
+     *
+     * <p> The {@code attrs} parameter is an optional array of file {@link
+     * FileAttribute file-attributes} to set atomically when creating the file.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * FileSystemProvider#newFileChannel newFileChannel} method on the
+     * provider that created the {@code Path}.
+     *
+     * @param   file
+     *          The path of the file to open or create
+     * @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 file channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If the {@code file} is associated with a provider that does not
+     *          support creating file channels, or an unsupported open option is
+     *          specified, or the array contains an attribute that cannot be set
+     *          atomically when creating the file
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an
+     *          unspecified permission required by the implementation.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String)} method is invoked to check
+     *          read access if the file is opened for reading. The {@link
+     *          SecurityManager#checkWrite(String)} method is invoked to check
+     *          write access if the file is opened for writing
+     *
+     * @since   1.7
+     */
+    public static FileChannel open(Path file,
+                                   Set<? extends OpenOption> options,
+                                   FileAttribute<?>... attrs)
+        throws IOException
+    {
+        FileSystemProvider provider = file.getFileSystem().provider();
+        return provider.newFileChannel(file, options, attrs);
+    }
+
+    private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
+
+    /**
+     * {@note new}
+     * Opens or creates a file, returning a file channel to access the file.
+     *
+     * <p> An invocation of this method behaves in exactly the same way as the
+     * invocation
+     * <pre>
+     *     fc.{@link #open(Path,Set,FileAttribute[]) open}(file, options, new FileAttribute&lt;?&gt;[0]);
+     * </pre>
+     *
+     * @param   file
+     *          The path of the file to open or create
+     * @param   options
+     *          Options specifying how the file is opened
+     *
+     * @return  A new file channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If the {@code file} is associated with a provider that does not
+     *          support creating file channels, or an unsupported open option is
+     *          specified
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an
+     *          unspecified permission required by the implementation.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String)} method is invoked to check
+     *          read access if the file is opened for reading. The {@link
+     *          SecurityManager#checkWrite(String)} method is invoked to check
+     *          write access if the file is opened for writing
+     *
+     * @since   1.7
+     */
+    public static FileChannel open(Path file, OpenOption... options)
+        throws IOException
+    {
+        Set<OpenOption> set = new HashSet<OpenOption>(options.length);
+        Collections.addAll(set, options);
+        return open(file, set, NO_ATTRIBUTES);
+    }
+
+    // -- Channel operations --
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> Bytes are read starting at this channel's current file position, and
+     * then the file position is updated with the number of bytes actually
+     * read.  Otherwise this method behaves exactly as specified in the {@link
+     * ReadableByteChannel} interface. </p>
+     */
+    public abstract int read(ByteBuffer dst) throws IOException;
+
+    /**
+     * Reads a sequence of bytes from this channel into a subsequence of the
+     * given buffers.
+     *
+     * <p> Bytes are read starting at this channel's current file position, and
+     * then the file position is updated with the number of bytes actually
+     * read.  Otherwise this method behaves exactly as specified in the {@link
+     * ScatteringByteChannel} interface.  </p>
+     */
+    public abstract long read(ByteBuffer[] dsts, int offset, int length)
+        throws IOException;
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffers.
+     *
+     * <p> Bytes are read starting at this channel's current file position, and
+     * then the file position is updated with the number of bytes actually
+     * read.  Otherwise this method behaves exactly as specified in the {@link
+     * ScatteringByteChannel} interface.  </p>
+     */
+    public final long read(ByteBuffer[] dsts) throws IOException {
+        return read(dsts, 0, dsts.length);
+    }
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> Bytes are written starting at this channel's current file position
+     * unless the channel is in append mode, in which case the position is
+     * first advanced to the end of the file.  The file is grown, if necessary,
+     * to accommodate the written bytes, and then the file position is updated
+     * with the number of bytes actually written.  Otherwise this method
+     * behaves exactly as specified by the {@link WritableByteChannel}
+     * interface. </p>
+     */
+    public abstract int write(ByteBuffer src) throws IOException;
+
+    /**
+     * Writes a sequence of bytes to this channel from a subsequence of the
+     * given buffers.
+     *
+     * <p> Bytes are written starting at this channel's current file position
+     * unless the channel is in append mode, in which case the position is
+     * first advanced to the end of the file.  The file is grown, if necessary,
+     * to accommodate the written bytes, and then the file position is updated
+     * with the number of bytes actually written.  Otherwise this method
+     * behaves exactly as specified in the {@link GatheringByteChannel}
+     * interface.  </p>
+     */
+    public abstract long write(ByteBuffer[] srcs, int offset, int length)
+        throws IOException;
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffers.
+     *
+     * <p> Bytes are written starting at this channel's current file position
+     * unless the channel is in append mode, in which case the position is
+     * first advanced to the end of the file.  The file is grown, if necessary,
+     * to accommodate the written bytes, and then the file position is updated
+     * with the number of bytes actually written.  Otherwise this method
+     * behaves exactly as specified in the {@link GatheringByteChannel}
+     * interface.  </p>
+     */
+    public final long write(ByteBuffer[] srcs) throws IOException {
+        return write(srcs, 0, srcs.length);
+    }
+
+
+    // -- Other operations --
+
+    /**
+     * Returns this channel's file position.  </p>
+     *
+     * @return  This channel's file position,
+     *          a non-negative integer counting the number of bytes
+     *          from the beginning of the file to the current position
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract long position() throws IOException;
+
+    /**
+     * Sets this channel's file position.
+     *
+     * <p> Setting the position to a value that is greater than the file's
+     * current size is legal but does not change the size of the file.  A later
+     * attempt to read bytes at such a position will immediately return an
+     * end-of-file indication.  A later attempt to write bytes at such a
+     * position will cause the file to be grown to accommodate the new bytes;
+     * the values of any bytes between the previous end-of-file and the
+     * newly-written bytes are unspecified.  </p>
+     *
+     * @param  newPosition
+     *         The new position, a non-negative integer counting
+     *         the number of bytes from the beginning of the file
+     *
+     * @return  This file channel
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IllegalArgumentException
+     *          If the new position is negative
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract FileChannel position(long newPosition) throws IOException;
+
+    /**
+     * Returns the current size of this channel's file.  </p>
+     *
+     * @return  The current size of this channel's file,
+     *          measured in bytes
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract long size() throws IOException;
+
+    /**
+     * Truncates this channel's file to the given size.
+     *
+     * <p> If the given size is less than the file's current size then the file
+     * is truncated, discarding any bytes beyond the new end of the file.  If
+     * the given size is greater than or equal to the file's current size then
+     * the file is not modified.  In either case, if this channel's file
+     * position is greater than the given size then it is set to that size.
+     * </p>
+     *
+     * @param  size
+     *         The new size, a non-negative byte count
+     *
+     * @return  This file channel
+     *
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IllegalArgumentException
+     *          If the new size is negative
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract FileChannel truncate(long size) throws IOException;
+
+    /**
+     * Forces any updates to this channel's file to be written to the storage
+     * device that contains it.
+     *
+     * <p> If this channel's file resides on a local storage device then when
+     * this method returns it is guaranteed that all changes made to the file
+     * since this channel was created, or since this method was last invoked,
+     * will have been written to that device.  This is useful for ensuring that
+     * critical information is not lost in the event of a system crash.
+     *
+     * <p> If the file does not reside on a local device then no such guarantee
+     * is made.
+     *
+     * <p> The <tt>metaData</tt> parameter can be used to limit the number of
+     * I/O operations that this method is required to perform.  Passing
+     * <tt>false</tt> for this parameter indicates that only updates to the
+     * file's content need be written to storage; passing <tt>true</tt>
+     * indicates that updates to both the file's content and metadata must be
+     * written, which generally requires at least one more I/O operation.
+     * Whether this parameter actually has any effect is dependent upon the
+     * underlying operating system and is therefore unspecified.
+     *
+     * <p> Invoking this method may cause an I/O operation to occur even if the
+     * channel was only opened for reading.  Some operating systems, for
+     * example, maintain a last-access time as part of a file's metadata, and
+     * this time is updated whenever the file is read.  Whether or not this is
+     * actually done is system-dependent and is therefore unspecified.
+     *
+     * <p> This method is only guaranteed to force changes that were made to
+     * this channel's file via the methods defined in this class.  It may or
+     * may not force changes that were made by modifying the content of a
+     * {@link MappedByteBuffer <i>mapped byte buffer</i>} obtained by
+     * invoking the {@link #map map} method.  Invoking the {@link
+     * MappedByteBuffer#force force} method of the mapped byte buffer will
+     * force changes made to the buffer's content to be written.  </p>
+     *
+     * @param   metaData
+     *          If <tt>true</tt> then this method is required to force changes
+     *          to both the file's content and metadata to be written to
+     *          storage; otherwise, it need only force content changes to be
+     *          written
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract void force(boolean metaData) throws IOException;
+
+    /**
+     * Transfers bytes from this channel's file to the given writable byte
+     * channel.
+     *
+     * <p> An attempt is made to read up to <tt>count</tt> bytes starting at
+     * the given <tt>position</tt> in this channel's file and write them to the
+     * target channel.  An invocation of this method may or may not transfer
+     * all of the requested bytes; whether or not it does so depends upon the
+     * natures and states of the channels.  Fewer than the requested number of
+     * bytes are transferred if this channel's file contains fewer than
+     * <tt>count</tt> bytes starting at the given <tt>position</tt>, or if the
+     * target channel is non-blocking and it has fewer than <tt>count</tt>
+     * bytes free in its output buffer.
+     *
+     * <p> This method does not modify this channel's position.  If the given
+     * position is greater than the file's current size then no bytes are
+     * transferred.  If the target channel has a position then bytes are
+     * written starting at that position and then the position is incremented
+     * by the number of bytes written.
+     *
+     * <p> This method is potentially much more efficient than a simple loop
+     * that reads from this channel and writes to the target channel.  Many
+     * operating systems can transfer bytes directly from the filesystem cache
+     * to the target channel without actually copying them.  </p>
+     *
+     * @param  position
+     *         The position within the file at which the transfer is to begin;
+     *         must be non-negative
+     *
+     * @param  count
+     *         The maximum number of bytes to be transferred; must be
+     *         non-negative
+     *
+     * @param  target
+     *         The target channel
+     *
+     * @return  The number of bytes, possibly zero,
+     *          that were actually transferred
+     *
+     * @throws IllegalArgumentException
+     *         If the preconditions on the parameters do not hold
+     *
+     * @throws  NonReadableChannelException
+     *          If this channel was not opened for reading
+     *
+     * @throws  NonWritableChannelException
+     *          If the target channel was not opened for writing
+     *
+     * @throws  ClosedChannelException
+     *          If either this channel or the target channel is closed
+     *
+     * @throws  AsynchronousCloseException
+     *          If another thread closes either channel
+     *          while the transfer is in progress
+     *
+     * @throws  ClosedByInterruptException
+     *          If another thread interrupts the current thread while the
+     *          transfer is in progress, thereby closing both channels and
+     *          setting the current thread's interrupt status
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract long transferTo(long position, long count,
+                                    WritableByteChannel target)
+        throws IOException;
+
+    /**
+     * Transfers bytes into this channel's file from the given readable byte
+     * channel.
+     *
+     * <p> An attempt is made to read up to <tt>count</tt> bytes from the
+     * source channel and write them to this channel's file starting at the
+     * given <tt>position</tt>.  An invocation of this method may or may not
+     * transfer all of the requested bytes; whether or not it does so depends
+     * upon the natures and states of the channels.  Fewer than the requested
+     * number of bytes will be transferred if the source channel has fewer than
+     * <tt>count</tt> bytes remaining, or if the source channel is non-blocking
+     * and has fewer than <tt>count</tt> bytes immediately available in its
+     * input buffer.
+     *
+     * <p> This method does not modify this channel's position.  If the given
+     * position is greater than the file's current size then no bytes are
+     * transferred.  If the source channel has a position then bytes are read
+     * starting at that position and then the position is incremented by the
+     * number of bytes read.
+     *
+     * <p> This method is potentially much more efficient than a simple loop
+     * that reads from the source channel and writes to this channel.  Many
+     * operating systems can transfer bytes directly from the source channel
+     * into the filesystem cache without actually copying them.  </p>
+     *
+     * @param  src
+     *         The source channel
+     *
+     * @param  position
+     *         The position within the file at which the transfer is to begin;
+     *         must be non-negative
+     *
+     * @param  count
+     *         The maximum number of bytes to be transferred; must be
+     *         non-negative
+     *
+     * @return  The number of bytes, possibly zero,
+     *          that were actually transferred
+     *
+     * @throws IllegalArgumentException
+     *         If the preconditions on the parameters do not hold
+     *
+     * @throws  NonReadableChannelException
+     *          If the source channel was not opened for reading
+     *
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     *
+     * @throws  ClosedChannelException
+     *          If either this channel or the source channel is closed
+     *
+     * @throws  AsynchronousCloseException
+     *          If another thread closes either channel
+     *          while the transfer is in progress
+     *
+     * @throws  ClosedByInterruptException
+     *          If another thread interrupts the current thread while the
+     *          transfer is in progress, thereby closing both channels and
+     *          setting the current thread's interrupt status
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract long transferFrom(ReadableByteChannel src,
+                                      long position, long count)
+        throws IOException;
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer,
+     * starting at the given file position.
+     *
+     * <p> This method works in the same manner as the {@link
+     * #read(ByteBuffer)} method, except that bytes are read starting at the
+     * given file position rather than at the channel's current position.  This
+     * method does not modify this channel's position.  If the given position
+     * is greater than the file's current size then no bytes are read.  </p>
+     *
+     * @param  dst
+     *         The buffer into which bytes are to be transferred
+     *
+     * @param  position
+     *         The file position at which the transfer is to begin;
+     *         must be non-negative
+     *
+     * @return  The number of bytes read, possibly zero, or <tt>-1</tt> if the
+     *          given position is greater than or equal to the file's current
+     *          size
+     *
+     * @throws  IllegalArgumentException
+     *          If the position is negative
+     *
+     * @throws  NonReadableChannelException
+     *          If this channel was not opened for reading
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  AsynchronousCloseException
+     *          If another thread closes this channel
+     *          while the read operation is in progress
+     *
+     * @throws  ClosedByInterruptException
+     *          If another thread interrupts the current thread
+     *          while the read operation is in progress, thereby
+     *          closing the channel and setting the current thread's
+     *          interrupt status
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract int read(ByteBuffer dst, long position) throws IOException;
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer,
+     * starting at the given file position.
+     *
+     * <p> This method works in the same manner as the {@link
+     * #write(ByteBuffer)} method, except that bytes are written starting at
+     * the given file position rather than at the channel's current position.
+     * This method does not modify this channel's position.  If the given
+     * position is greater than the file's current size then the file will be
+     * grown to accommodate the new bytes; the values of any bytes between the
+     * previous end-of-file and the newly-written bytes are unspecified.  </p>
+     *
+     * @param  src
+     *         The buffer from which bytes are to be transferred
+     *
+     * @param  position
+     *         The file position at which the transfer is to begin;
+     *         must be non-negative
+     *
+     * @return  The number of bytes written, possibly zero
+     *
+     * @throws  IllegalArgumentException
+     *          If the position is negative
+     *
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  AsynchronousCloseException
+     *          If another thread closes this channel
+     *          while the write operation is in progress
+     *
+     * @throws  ClosedByInterruptException
+     *          If another thread interrupts the current thread
+     *          while the write operation is in progress, thereby
+     *          closing the channel and setting the current thread's
+     *          interrupt status
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract int write(ByteBuffer src, long position) throws IOException;
+
+
+    // -- Memory-mapped buffers --
+
+    /**
+     * A typesafe enumeration for file-mapping modes.
+     *
+     * @since 1.4
+     *
+     * @see java.nio.channels.FileChannel#map
+     */
+    public static class MapMode {
+
+        /**
+         * Mode for a read-only mapping.
+         */
+        public static final MapMode READ_ONLY
+            = new MapMode("READ_ONLY");
+
+        /**
+         * Mode for a read/write mapping.
+         */
+        public static final MapMode READ_WRITE
+            = new MapMode("READ_WRITE");
+
+        /**
+         * Mode for a private (copy-on-write) mapping.
+         */
+        public static final MapMode PRIVATE
+            = new MapMode("PRIVATE");
+
+        private final String name;
+
+        private MapMode(String name) {
+            this.name = name;
+        }
+
+        /**
+         * Returns a string describing this file-mapping mode.
+         *
+         * @return  A descriptive string
+         */
+        public String toString() {
+            return name;
+        }
+
+    }
+
+    /**
+     * Maps a region of this channel's file directly into memory.
+     *
+     * <p> A region of a file may be mapped into memory in one of three modes:
+     * </p>
+     *
+     * <ul type=disc>
+     *
+     *   <li><p> <i>Read-only:</i> Any attempt to modify the resulting buffer
+     *   will cause a {@link java.nio.ReadOnlyBufferException} to be thrown.
+     *   ({@link MapMode#READ_ONLY MapMode.READ_ONLY}) </p></li>
+     *
+     *   <li><p> <i>Read/write:</i> Changes made to the resulting buffer will
+     *   eventually be propagated to the file; they may or may not be made
+     *   visible to other programs that have mapped the same file.  ({@link
+     *   MapMode#READ_WRITE MapMode.READ_WRITE}) </p></li>
+     *
+     *   <li><p> <i>Private:</i> Changes made to the resulting buffer will not
+     *   be propagated to the file and will not be visible to other programs
+     *   that have mapped the same file; instead, they will cause private
+     *   copies of the modified portions of the buffer to be created.  ({@link
+     *   MapMode#PRIVATE MapMode.PRIVATE}) </p></li>
+     *
+     * </ul>
+     *
+     * <p> For a read-only mapping, this channel must have been opened for
+     * reading; for a read/write or private mapping, this channel must have
+     * been opened for both reading and writing.
+     *
+     * <p> The {@link MappedByteBuffer <i>mapped byte buffer</i>}
+     * returned by this method will have a position of zero and a limit and
+     * capacity of <tt>size</tt>; its mark will be undefined.  The buffer and
+     * the mapping that it represents will remain valid until the buffer itself
+     * is garbage-collected.
+     *
+     * <p> A mapping, once established, is not dependent upon the file channel
+     * that was used to create it.  Closing the channel, in particular, has no
+     * effect upon the validity of the mapping.
+     *
+     * <p> Many of the details of memory-mapped files are inherently dependent
+     * upon the underlying operating system and are therefore unspecified.  The
+     * behavior of this method when the requested region is not completely
+     * contained within this channel's file is unspecified.  Whether changes
+     * made to the content or size of the underlying file, by this program or
+     * another, are propagated to the buffer is unspecified.  The rate at which
+     * changes to the buffer are propagated to the file is unspecified.
+     *
+     * <p> For most operating systems, mapping a file into memory is more
+     * expensive than reading or writing a few tens of kilobytes of data via
+     * the usual {@link #read read} and {@link #write write} methods.  From the
+     * standpoint of performance it is generally only worth mapping relatively
+     * large files into memory.  </p>
+     *
+     * @param  mode
+     *         One of the constants {@link MapMode#READ_ONLY READ_ONLY}, {@link
+     *         MapMode#READ_WRITE READ_WRITE}, or {@link MapMode#PRIVATE
+     *         PRIVATE} defined in the {@link MapMode} class, according to
+     *         whether the file is to be mapped read-only, read/write, or
+     *         privately (copy-on-write), respectively
+     *
+     * @param  position
+     *         The position within the file at which the mapped region
+     *         is to start; must be non-negative
+     *
+     * @param  size
+     *         The size of the region to be mapped; must be non-negative and
+     *         no greater than {@link java.lang.Integer#MAX_VALUE}
+     *
+     * @return  The mapped byte buffer
+     *
+     * @throws NonReadableChannelException
+     *         If the <tt>mode</tt> is {@link MapMode#READ_ONLY READ_ONLY} but
+     *         this channel was not opened for reading
+     *
+     * @throws NonWritableChannelException
+     *         If the <tt>mode</tt> is {@link MapMode#READ_WRITE READ_WRITE} or
+     *         {@link MapMode#PRIVATE PRIVATE} but this channel was not opened
+     *         for both reading and writing
+     *
+     * @throws IllegalArgumentException
+     *         If the preconditions on the parameters do not hold
+     *
+     * @throws IOException
+     *         If some other I/O error occurs
+     *
+     * @see java.nio.channels.FileChannel.MapMode
+     * @see java.nio.MappedByteBuffer
+     */
+    public abstract MappedByteBuffer map(MapMode mode,
+                                         long position, long size)
+        throws IOException;
+
+
+    // -- Locks --
+
+    /**
+     * Acquires a lock on the given region of this channel's file.
+     *
+     * <p> An invocation of this method will block until the region can be
+     * locked, this channel is closed, or the invoking thread is interrupted,
+     * whichever comes first.
+     *
+     * <p> If this channel is closed by another thread during an invocation of
+     * this method then an {@link AsynchronousCloseException} will be thrown.
+     *
+     * <p> If the invoking thread is interrupted while waiting to acquire the
+     * lock then its interrupt status will be set and a {@link
+     * FileLockInterruptionException} will be thrown.  If the invoker's
+     * interrupt status is set when this method is invoked then that exception
+     * will be thrown immediately; the thread's interrupt status will not be
+     * changed.
+     *
+     * <p> The region specified by the <tt>position</tt> and <tt>size</tt>
+     * parameters need not be contained within, or even overlap, the actual
+     * underlying file.  Lock regions are fixed in size; if a locked region
+     * initially contains the end of the file and the file grows beyond the
+     * region then the new portion of the file will not be covered by the lock.
+     * If a file is expected to grow in size and a lock on the entire file is
+     * required then a region starting at zero, and no smaller than the
+     * expected maximum size of the file, should be locked.  The zero-argument
+     * {@link #lock()} method simply locks a region of size {@link
+     * Long#MAX_VALUE}.
+     *
+     * <p> Some operating systems do not support shared locks, in which case a
+     * request for a shared lock is automatically converted into a request for
+     * an exclusive lock.  Whether the newly-acquired lock is shared or
+     * exclusive may be tested by invoking the resulting lock object's {@link
+     * FileLock#isShared() isShared} method.
+     *
+     * <p> File locks are held on behalf of the entire Java virtual machine.
+     * They are not suitable for controlling access to a file by multiple
+     * threads within the same virtual machine.  </p>
+     *
+     * @param  position
+     *         The position at which the locked region is to start; must be
+     *         non-negative
+     *
+     * @param  size
+     *         The size of the locked region; must be non-negative, and the sum
+     *         <tt>position</tt>&nbsp;+&nbsp;<tt>size</tt> must be non-negative
+     *
+     * @param  shared
+     *         <tt>true</tt> to request a shared lock, in which case this
+     *         channel must be open for reading (and possibly writing);
+     *         <tt>false</tt> to request an exclusive lock, in which case this
+     *         channel must be open for writing (and possibly reading)
+     *
+     * @return  A lock object representing the newly-acquired lock
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  AsynchronousCloseException
+     *          If another thread closes this channel while the invoking
+     *          thread is blocked in this method
+     *
+     * @throws  FileLockInterruptionException
+     *          If the invoking thread is interrupted while blocked in this
+     *          method
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or if another thread is already
+     *          blocked in this method and is attempting to lock an overlapping
+     *          region
+     *
+     * @throws  NonReadableChannelException
+     *          If <tt>shared</tt> is <tt>true</tt> this channel was not
+     *          opened for reading
+     *
+     * @throws  NonWritableChannelException
+     *          If <tt>shared</tt> is <tt>false</tt> but this channel was not
+     *          opened for writing
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     *
+     * @see     #lock()
+     * @see     #tryLock()
+     * @see     #tryLock(long,long,boolean)
+     */
+    public abstract FileLock lock(long position, long size, boolean shared)
+        throws IOException;
+
+    /**
+     * Acquires an exclusive lock on this channel's file.
+     *
+     * <p> An invocation of this method of the form <tt>fc.lock()</tt> behaves
+     * in exactly the same way as the invocation
+     *
+     * <pre>
+     *     fc.{@link #lock(long,long,boolean) lock}(0L, Long.MAX_VALUE, false) </pre>
+     *
+     * @return  A lock object representing the newly-acquired lock
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  AsynchronousCloseException
+     *          If another thread closes this channel while the invoking
+     *          thread is blocked in this method
+     *
+     * @throws  FileLockInterruptionException
+     *          If the invoking thread is interrupted while blocked in this
+     *          method
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or if another thread is already
+     *          blocked in this method and is attempting to lock an overlapping
+     *          region of the same file
+     *
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     *
+     * @see     #lock(long,long,boolean)
+     * @see     #tryLock()
+     * @see     #tryLock(long,long,boolean)
+     */
+    public final FileLock lock() throws IOException {
+        return lock(0L, Long.MAX_VALUE, false);
+    }
+
+    /**
+     * Attempts to acquire a lock on the given region of this channel's file.
+     *
+     * <p> This method does not block.  An invocation always returns
+     * immediately, either having acquired a lock on the requested region or
+     * having failed to do so.  If it fails to acquire a lock because an
+     * overlapping lock is held by another program then it returns
+     * <tt>null</tt>.  If it fails to acquire a lock for any other reason then
+     * an appropriate exception is thrown.
+     *
+     * <p> The region specified by the <tt>position</tt> and <tt>size</tt>
+     * parameters need not be contained within, or even overlap, the actual
+     * underlying file.  Lock regions are fixed in size; if a locked region
+     * initially contains the end of the file and the file grows beyond the
+     * region then the new portion of the file will not be covered by the lock.
+     * If a file is expected to grow in size and a lock on the entire file is
+     * required then a region starting at zero, and no smaller than the
+     * expected maximum size of the file, should be locked.  The zero-argument
+     * {@link #tryLock()} method simply locks a region of size {@link
+     * Long#MAX_VALUE}.
+     *
+     * <p> Some operating systems do not support shared locks, in which case a
+     * request for a shared lock is automatically converted into a request for
+     * an exclusive lock.  Whether the newly-acquired lock is shared or
+     * exclusive may be tested by invoking the resulting lock object's {@link
+     * FileLock#isShared() isShared} method.
+     *
+     * <p> File locks are held on behalf of the entire Java virtual machine.
+     * They are not suitable for controlling access to a file by multiple
+     * threads within the same virtual machine.  </p>
+     *
+     * @param  position
+     *         The position at which the locked region is to start; must be
+     *         non-negative
+     *
+     * @param  size
+     *         The size of the locked region; must be non-negative, and the sum
+     *         <tt>position</tt>&nbsp;+&nbsp;<tt>size</tt> must be non-negative
+     *
+     * @param  shared
+     *         <tt>true</tt> to request a shared lock,
+     *         <tt>false</tt> to request an exclusive lock
+     *
+     * @return  A lock object representing the newly-acquired lock,
+     *          or <tt>null</tt> if the lock could not be acquired
+     *          because another program holds an overlapping lock
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or if another thread is already
+     *          blocked in this method and is attempting to lock an overlapping
+     *          region of the same file
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     *
+     * @see     #lock()
+     * @see     #lock(long,long,boolean)
+     * @see     #tryLock()
+     */
+    public abstract FileLock tryLock(long position, long size, boolean shared)
+        throws IOException;
+
+    /**
+     * Attempts to acquire an exclusive lock on this channel's file.
+     *
+     * <p> An invocation of this method of the form <tt>fc.tryLock()</tt>
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     fc.{@link #tryLock(long,long,boolean) tryLock}(0L, Long.MAX_VALUE, false) </pre>
+     *
+     * @return  A lock object representing the newly-acquired lock,
+     *          or <tt>null</tt> if the lock could not be acquired
+     *          because another program holds an overlapping lock
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock that overlaps the requested region is already held by
+     *          this Java virtual machine, or if another thread is already
+     *          blocked in this method and is attempting to lock an overlapping
+     *          region
+     *
+     * @throws  IOException
+     *          If some other I/O error occurs
+     *
+     * @see     #lock()
+     * @see     #lock(long,long,boolean)
+     * @see     #tryLock(long,long,boolean)
+     */
+    public final FileLock tryLock() throws IOException {
+        return tryLock(0L, Long.MAX_VALUE, false);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileLock.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.io.IOException;
+
+/**
+ * A token representing a lock on a region of a file.
+ *
+ * <p> A file-lock object is created each time a lock is acquired on a file via
+ * one of the {@link FileChannel#lock(long,long,boolean) lock} or {@link
+ * FileChannel#tryLock(long,long,boolean) tryLock} methods of the
+ * {@link FileChannel} class, or the {@link
+ * AsynchronousFileChannel#lock(long,long,boolean,Object,CompletionHandler) lock}
+ * or {@link AsynchronousFileChannel#tryLock(long,long,boolean) tryLock}
+ * methods of the {@link AsynchronousFileChannel} class.
+ *
+ * <p> A file-lock object is initially valid.  It remains valid until the lock
+ * is released by invoking the {@link #release release} method, by closing the
+ * channel that was used to acquire it, or by the termination of the Java
+ * virtual machine, whichever comes first.  The validity of a lock may be
+ * tested by invoking its {@link #isValid isValid} method.
+ *
+ * <p> A file lock is either <i>exclusive</i> or <i>shared</i>.  A shared lock
+ * prevents other concurrently-running programs from acquiring an overlapping
+ * exclusive lock, but does allow them to acquire overlapping shared locks.  An
+ * exclusive lock prevents other programs from acquiring an overlapping lock of
+ * either type.  Once it is released, a lock has no further effect on the locks
+ * that may be acquired by other programs.
+ *
+ * <p> Whether a lock is exclusive or shared may be determined by invoking its
+ * {@link #isShared isShared} method.  Some platforms do not support shared
+ * locks, in which case a request for a shared lock is automatically converted
+ * into a request for an exclusive lock.
+ *
+ * <p> The locks held on a particular file by a single Java virtual machine do
+ * not overlap.  The {@link #overlaps overlaps} method may be used to test
+ * whether a candidate lock range overlaps an existing lock.
+ *
+ * <p> A file-lock object records the file channel upon whose file the lock is
+ * held, the type and validity of the lock, and the position and size of the
+ * locked region.  Only the validity of a lock is subject to change over time;
+ * all other aspects of a lock's state are immutable.
+ *
+ * <p> File locks are held on behalf of the entire Java virtual machine.
+ * They are not suitable for controlling access to a file by multiple
+ * threads within the same virtual machine.
+ *
+ * <p> File-lock objects are safe for use by multiple concurrent threads.
+ *
+ *
+ * <a name="pdep"><h4> Platform dependencies </h4></a>
+ *
+ * <p> This file-locking API is intended to map directly to the native locking
+ * facility of the underlying operating system.  Thus the locks held on a file
+ * should be visible to all programs that have access to the file, regardless
+ * of the language in which those programs are written.
+ *
+ * <p> Whether or not a lock actually prevents another program from accessing
+ * the content of the locked region is system-dependent and therefore
+ * unspecified.  The native file-locking facilities of some systems are merely
+ * <i>advisory</i>, meaning that programs must cooperatively observe a known
+ * locking protocol in order to guarantee data integrity.  On other systems
+ * native file locks are <i>mandatory</i>, meaning that if one program locks a
+ * region of a file then other programs are actually prevented from accessing
+ * that region in a way that would violate the lock.  On yet other systems,
+ * whether native file locks are advisory or mandatory is configurable on a
+ * per-file basis.  To ensure consistent and correct behavior across platforms,
+ * it is strongly recommended that the locks provided by this API be used as if
+ * they were advisory locks.
+ *
+ * <p> On some systems, acquiring a mandatory lock on a region of a file
+ * prevents that region from being {@link java.nio.channels.FileChannel#map
+ * <i>mapped into memory</i>}, and vice versa.  Programs that combine
+ * locking and mapping should be prepared for this combination to fail.
+ *
+ * <p> On some systems, closing a channel releases all locks held by the Java
+ * virtual machine on the underlying file regardless of whether the locks were
+ * acquired via that channel or via another channel open on the same file.  It
+ * is strongly recommended that, within a program, a unique channel be used to
+ * acquire all locks on any given file.
+ *
+ * <p> Some network filesystems permit file locking to be used with
+ * memory-mapped files only when the locked regions are page-aligned and a
+ * whole multiple of the underlying hardware's page size.  Some network
+ * filesystems do not implement file locks on regions that extend past a
+ * certain position, often 2<sup>30</sup> or 2<sup>31</sup>.  In general, great
+ * care should be taken when locking files that reside on network filesystems.
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ * @updated 1.7
+ */
+
+public abstract class FileLock {
+
+    private final Channel channel;
+    private final long position;
+    private final long size;
+    private final boolean shared;
+
+    /**
+     * Initializes a new instance of this class.  </p>
+     *
+     * @param  channel
+     *         The file channel upon whose file this lock is held
+     *
+     * @param  position
+     *         The position within the file at which the locked region starts;
+     *         must be non-negative
+     *
+     * @param  size
+     *         The size of the locked region; must be non-negative, and the sum
+     *         <tt>position</tt>&nbsp;+&nbsp;<tt>size</tt> must be non-negative
+     *
+     * @param  shared
+     *         <tt>true</tt> if this lock is shared,
+     *         <tt>false</tt> if it is exclusive
+     *
+     * @throws IllegalArgumentException
+     *         If the preconditions on the parameters do not hold
+     */
+    protected FileLock(FileChannel channel,
+                       long position, long size, boolean shared)
+    {
+        if (position < 0)
+            throw new IllegalArgumentException("Negative position");
+        if (size < 0)
+            throw new IllegalArgumentException("Negative size");
+        if (position + size < 0)
+            throw new IllegalArgumentException("Negative position + size");
+        this.channel = channel;
+        this.position = position;
+        this.size = size;
+        this.shared = shared;
+    }
+
+    /**
+     * {@note new} Initializes a new instance of this class.
+     *
+     * @param  channel
+     *         The channel upon whose file this lock is held
+     *
+     * @param  position
+     *         The position within the file at which the locked region starts;
+     *         must be non-negative
+     *
+     * @param  size
+     *         The size of the locked region; must be non-negative, and the sum
+     *         <tt>position</tt>&nbsp;+&nbsp;<tt>size</tt> must be non-negative
+     *
+     * @param  shared
+     *         <tt>true</tt> if this lock is shared,
+     *         <tt>false</tt> if it is exclusive
+     *
+     * @throws IllegalArgumentException
+     *         If the preconditions on the parameters do not hold
+     *
+     * @since 1.7
+     */
+    protected FileLock(AsynchronousFileChannel channel,
+                       long position, long size, boolean shared)
+    {
+        if (position < 0)
+            throw new IllegalArgumentException("Negative position");
+        if (size < 0)
+            throw new IllegalArgumentException("Negative size");
+        if (position + size < 0)
+            throw new IllegalArgumentException("Negative position + size");
+        this.channel = channel;
+        this.position = position;
+        this.size = size;
+        this.shared = shared;
+    }
+
+    /**
+     * {@note revised}
+     * Returns the file channel upon whose file this lock was acquired.
+     *
+     * <p> This method has been superseded by the {@link #acquiredBy acquiredBy}
+     * method.
+     *
+     * @return  The file channel, or {@code null} if the file lock was not
+     *          acquired by a file channel.
+     */
+    public final FileChannel channel() {
+        return (channel instanceof FileChannel) ? (FileChannel)channel : null;
+    }
+
+    /**
+     * {@note new}
+     * Returns the channel upon whose file this lock was acquired.
+     *
+     * @return  The channel upon whose file this lock was acquired.
+     *
+     * @since 1.7
+     */
+    public Channel acquiredBy() {
+        return channel;
+    }
+
+    /**
+     * Returns the position within the file of the first byte of the locked
+     * region.
+     *
+     * <p> A locked region need not be contained within, or even overlap, the
+     * actual underlying file, so the value returned by this method may exceed
+     * the file's current size.  </p>
+     *
+     * @return  The position
+     */
+    public final long position() {
+        return position;
+    }
+
+    /**
+     * Returns the size of the locked region in bytes.
+     *
+     * <p> A locked region need not be contained within, or even overlap, the
+     * actual underlying file, so the value returned by this method may exceed
+     * the file's current size.  </p>
+     *
+     * @return  The size of the locked region
+     */
+    public final long size() {
+        return size;
+    }
+
+    /**
+     * Tells whether this lock is shared.  </p>
+     *
+     * @return <tt>true</tt> if lock is shared,
+     *         <tt>false</tt> if it is exclusive
+     */
+    public final boolean isShared() {
+        return shared;
+    }
+
+    /**
+     * Tells whether or not this lock overlaps the given lock range.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this lock and the given lock
+     *          range overlap by at least one byte
+     */
+    public final boolean overlaps(long position, long size) {
+        if (position + size <= this.position)
+            return false;               // That is below this
+        if (this.position + this.size <= position)
+            return false;               // This is below that
+        return true;
+    }
+
+    /**
+     * Tells whether or not this lock is valid.
+     *
+     * <p> A lock object remains valid until it is released or the associated
+     * file channel is closed, whichever comes first.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this lock is valid
+     */
+    public abstract boolean isValid();
+
+    /**
+     * Releases this lock.
+     *
+     * <p> If this lock object is valid then invoking this method releases the
+     * lock and renders the object invalid.  If this lock object is invalid
+     * then invoking this method has no effect.  </p>
+     *
+     * @throws  ClosedChannelException
+     *          If the channel that was used to acquire this lock
+     *          is no longer open
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract void release() throws IOException;
+
+    /**
+     * Returns a string describing the range, type, and validity of this lock.
+     *
+     * @return  A descriptive string
+     */
+    public final String toString() {
+        return (this.getClass().getName()
+                + "[" + position
+                + ":" + size
+                + " " + (shared ? "shared" : "exclusive")
+                + " " + (isValid() ? "valid" : "invalid")
+                + "]");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.io.IOException;
+
+/**
+ * A byte channel that maintains a current <i>position</i> and allows the
+ * position to be changed.
+ *
+ * <p> A seekable byte channel is connected to an entity, typically a file,
+ * that contains a variable-length sequence of bytes that can be read and
+ * written. The current position can be {@link #position() <i>queried</i>} and
+ * {@link #position(long) <i>modified</i>}. The channel also provides access to
+ * the current <i>size</i> of the entity to which the channel is connected. The
+ * size increases when bytes are written beyond its current size; the size
+ * decreases when it is {@link #truncate <i>truncated</i>}.
+ *
+ * <p> The {@link #position(long) position} and {@link #truncate truncate} methods
+ * which do not otherwise have a value to return are specified to return the
+ * channel upon which they are invoked. This allows method invocations to be
+ * chained. Implementations of this interface should specialize the return type
+ * so that method invocations on the implementation class can be chained.
+ *
+ * @since 1.7
+ * @see java.nio.file.FileRef#newByteChannel
+ */
+
+public interface SeekableByteChannel
+    extends ByteChannel
+{
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> Bytes are read starting at this channel's current position, and
+     * then the position is updated with the number of bytes actually read.
+     * Otherwise this method behaves exactly as specified in the {@link
+     * ReadableByteChannel} interface.
+     */
+
+    int read(ByteBuffer dst) throws IOException;
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> Bytes are written starting at this channel's current position, unless
+     * the channel is connected to an entity such as a file that is opened with
+     * the {@link java.nio.file.StandardOpenOption#APPEND APPEND} option, in
+     * which case the position is first advanced to the end. The entity to which
+     * the channel is connected is grown, if necessary, to accommodate the
+     * written bytes, and then the position is updated with the number of bytes
+     * actually written. Otherwise this method behaves exactly as specified by
+     * the {@link WritableByteChannel} interface.
+     */
+
+    int write(ByteBuffer src) throws IOException;
+
+    /**
+     * Returns this channel's position.
+     *
+     * @return  This channel's position,
+     *          a non-negative integer counting the number of bytes
+     *          from the beginning of the entity to the current position
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    long position() throws IOException;
+
+    /**
+     * Sets this channel's position.
+     *
+     * <p> Setting the position to a value that is greater than the current size
+     * is legal but does not change the size of the entity.  A later attempt to
+     * read bytes at such a position will immediately return an end-of-file
+     * indication.  A later attempt to write bytes at such a position will cause
+     * the entity to grow to accommodate the new bytes; the values of any bytes
+     * between the previous end-of-file and the newly-written bytes are
+     * unspecified.
+     *
+     * <p> Setting the channel's position is not recommended when connected to
+     * an entity, typically a file, that is opened with the {@link
+     * java.nio.file.StandardOpenOption#APPEND APPEND} option. When opened for
+     * append, the position is first advanced to the end before writing.
+     *
+     * @param  newPosition
+     *         The new position, a non-negative integer counting
+     *         the number of bytes from the beginning of the entity
+     *
+     * @return  This channel
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IllegalArgumentException
+     *          If the new position is negative
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    SeekableByteChannel position(long newPosition) throws IOException;
+
+    /**
+     * Returns the current size of entity to which this channel is connected.
+     *
+     * @return  The current size, measured in bytes
+     *
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    long size() throws IOException;
+
+    /**
+     * Truncates the entity, to which this channel is connected, to the given
+     * size.
+     *
+     * <p> If the given size is less than the current size then the entity is
+     * truncated, discarding any bytes beyond the new end. If the given size is
+     * greater than or equal to the current size then the entity is not modified.
+     * In either case, if the current position is greater than the given size
+     * then it is set to that size.
+     *
+     * <p> An implementation of this interface may prohibit truncation when
+     * connected to an entity, typically a file, opened with the {@link
+     * java.nio.file.StandardOpenOption#APPEND APPEND} option.
+     *
+     * @param  size
+     *         The new size, a non-negative byte count
+     *
+     * @return  This channel
+     *
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IllegalArgumentException
+     *          If the new size is negative
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    SeekableByteChannel truncate(long size) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/exceptions	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,68 @@
+#
+# Copyright 2000-2008 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.
+#
+
+# Generated exception classes for java.nio.channels
+
+PACKAGE=java.nio.channels
+# This year should only change if the generated source is modified.
+COPYRIGHT_YEARS=2000-2007
+SINCE=1.7
+ 
+SUPER=java.io.IOException
+
+gen InterruptedByTimeoutException "
+ * Checked exception received by a thread when a timeout elapses before an
+ * asynchronous operation completes." \
+ -4268008601014042947L
+
+SUPER=IllegalArgumentException
+
+gen IllegalChannelGroupException "
+ * Unchecked exception thrown when an attempt is made to open a channel
+ * in a group that was not created by the same provider. " \
+ -2495041211157744253L
+ 
+SUPER=IllegalStateException
+
+gen AcceptPendingException "
+ * Unchecked exception thrown when an attempt is made to initiate an accept
+ * operation on a channel and a previous accept operation has not completed." \
+ 2721339977965416421L
+
+gen ReadPendingException "
+ * Unchecked exception thrown when an attempt is made to read from an
+ * asynchronous socket channel and a previous read has not completed." \
+ 1986315242191227217L
+
+gen WritePendingException "
+ * Unchecked exception thrown when an attempt is made to write to an
+ * asynchronous socket channel and a previous write has not completed." \
+ 7031871839266032276L
+
+gen ShutdownChannelGroupException "
+ * Unchecked exception thrown when an attempt is made to construct a channel in 
+ * a group that is shutdown or the completion handler for an I/O operation 
+ * cannot be invoked because the channel group is shutdown." \
+ -3903801676350154157L
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/package-info.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2001-2008 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.
+ */
+
+/**
+ * Defines channels, which represent connections to entities that are capable of
+ * performing I/O operations, such as files and sockets; defines selectors, for
+ * multiplexed, non-blocking I/O operations.
+ *
+ * <a name="channels"></a>
+ *
+ * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists channels and their descriptions">
+ * <tr><th><p align="left">Channels</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><td valign=top><tt><i>{@link java.nio.channels.Channel}</i></tt></td>
+ *     <td>A nexus for I/O operations</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ReadableByteChannel}</i></tt></td>
+ *     <td>Can read into a buffer</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.ScatteringByteChannel}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read into a sequence of&nbsp;buffers</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.WritableByteChannel}</i></tt></td>
+ *     <td>Can write from a buffer</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.GatheringByteChannel}</i></tt></td>
+ *     <td>Can write from a sequence of&nbsp;buffers</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ByteChannel}</i></tt></td>
+ *     <td>Can read/write to/from a&nbsp;buffer</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.SeekableByteChannel}</i></tt></td>
+ *     <td>A {@code ByteChannel} connected to an entity that contains a variable-length sequence of bytes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.AsynchronousChannel}</i></tt></td>
+ *     <td>Supports asynchronous I/O operations.</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.AsynchronousByteChannel}</i></tt></td>
+ *     <td>Can read and write bytes asynchronously</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.NetworkChannel}</i></tt></td>
+ *     <td>A channel to a network socket</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.MulticastChannel}</i></tt></td>
+ *     <td>Can join Internet Protocol (IP) multicast groups</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.Channels}</tt></td>
+ *     <td>Utility methods for channel/stream interoperation</td></tr>
+ * </table></blockquote>
+ *
+ * <p> A <i>channel</i> represents an open connection to an entity such as a
+ * hardware device, a file, a network socket, or a program component that is
+ * capable of performing one or more distinct I/O operations, for example reading
+ * or writing.  As specified in the {@link java.nio.channels.Channel} interface,
+ * channels are either open or closed, and they are both <i>asynchronously
+ * closeable</i> and <i>interruptible</i>.
+ *
+ * <p> The {@link java.nio.channels.Channel} interface is extended by several
+ * other interfaces.
+ *
+ * <p> The {@link java.nio.channels.ReadableByteChannel} interface specifies a
+ * {@link java.nio.channels.ReadableByteChannel#read read} method that reads bytes
+ * from the channel into a buffer; similarly, the {@link
+ * java.nio.channels.WritableByteChannel} interface specifies a {@link
+ * java.nio.channels.WritableByteChannel#write write} method that writes bytes
+ * from a buffer to the channel. The {@link java.nio.channels.ByteChannel}
+ * interface unifies these two interfaces for the common case of channels that can
+ * both read and write bytes. The {@link java.nio.channels.SeekableByteChannel}
+ * interface extends the {@code ByteChannel} interface with methods to {@link
+ * java.nio.channels.SeekableByteChannel#position() query} and {@link
+ * java.nio.channels.SeekableByteChannel#position(long) modify} the channel's
+ * current position, and its {@link java.nio.channels.SeekableByteChannel#size
+ * size}.
+ *
+ * <p> The {@link java.nio.channels.ScatteringByteChannel} and {@link
+ * java.nio.channels.GatheringByteChannel} interfaces extend the {@link
+ * java.nio.channels.ReadableByteChannel} and {@link
+ * java.nio.channels.WritableByteChannel} interfaces, respectively, adding {@link
+ * java.nio.channels.ScatteringByteChannel#read read} and {@link
+ * java.nio.channels.GatheringByteChannel#write write} methods that take a
+ * sequence of buffers rather than a single buffer.
+ *
+ * <p> The {@link java.nio.channels.NetworkChannel} interface specifies methods
+ * to {@link java.nio.channels.NetworkChannel#bind bind} the channel's socket,
+ * obtain the address to which the socket is bound, and methods to {@link
+ * java.nio.channels.NetworkChannel#getOption get} and {@link
+ * java.nio.channels.NetworkChannel#setOption set} socket options. The {@link
+ * java.nio.channels.MulticastChannel} interface specifies methods to join
+ * Internet Protocol (IP) multicast groups.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.channels.Channels} utility class defines static methods
+ * that support the interoperation of the stream classes of the <tt>{@link
+ * java.io}</tt> package with the channel classes of this package.  An appropriate
+ * channel can be constructed from an {@link java.io.InputStream} or an {@link
+ * java.io.OutputStream}, and conversely an {@link java.io.InputStream} or an
+ * {@link java.io.OutputStream} can be constructed from a channel.  A {@link
+ * java.io.Reader} can be constructed that uses a given charset to decode bytes
+ * from a given readable byte channel, and conversely a {@link java.io.Writer} can
+ * be constructed that uses a given charset to encode characters into bytes and
+ * write them to a given writable byte channel.
+ *
+ * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists file channels and their descriptions">
+ * <tr><th><p align="left">File channels</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.FileChannel}</tt></td>
+ *     <td>Reads, writes, maps, and manipulates files</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.FileLock}</tt></td>
+ *     <td>A lock on a (region of a) file</td></tr>
+ * <tr><td valign=top><tt>{@link java.nio.MappedByteBuffer}/{@link java.nio.MappedBigByteBuffer}&nbsp;&nbsp;</tt></td>
+ *     <td>A direct byte buffer or big byte buffer mapped to a region of a&nbsp;file</td></tr>
+ * </table></blockquote>
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.channels.FileChannel} class supports the usual
+ * operations of reading bytes from, and writing bytes to, a channel connected to
+ * a file, as well as those of querying and modifying the current file position
+ * and truncating the file to a specific size.  It defines methods for acquiring
+ * locks on the whole file or on a specific region of a file; these methods return
+ * instances of the {@link org.classpath.icedtea.java.nio.channels.FileLock} class.  Finally, it defines
+ * methods for forcing updates to the file to be written to the storage device that
+ * contains it, for efficiently transferring bytes between the file and other
+ * channels, and for mapping a region of the file directly into memory.
+ *
+ * <p> A {@code FileChannel} is created by invoking one of its static {@link
+ * java.nio.channels.FileChannel#open open} methods, or by invoking the {@code
+ * getChannel} method of a {@link java.io.FileInputStream}, {@link
+ * java.io.FileOutputStream}, or {@link java.io.RandomAccessFile} to return a
+ * file channel connected to the same underlying file as the <tt>{@link java.io}</tt>
+ * class.
+ *
+ * <a name="multiplex"></a>
+ * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists multiplexed, non-blocking channels and their descriptions">
+ * <tr><th><p align="left">Multiplexed, non-blocking I/O</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><td valign=top><tt>{@link java.nio.channels.SelectableChannel}</tt></td>
+ *     <td>A channel that can be multiplexed</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.DatagramChannel}</tt></td>
+ *     <td>A channel to a datagram-oriented socket</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.Pipe.SinkChannel}</tt></td>
+ *     <td>The write end of a pipe</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.Pipe.SourceChannel}</tt></td>
+ *     <td>The read end of a pipe</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.ServerSocketChannel}&nbsp;&nbsp;</tt></td>
+ *     <td>A channel to a stream-oriented listening socket</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.SocketChannel}</tt></td>
+ *     <td>A channel for a stream-oriented connecting socket</td></tr>
+ * <tr><td valign=top><tt>{@link java.nio.channels.Selector}</tt></td>
+ *     <td>A multiplexor of selectable channels</td></tr>
+ * <tr><td valign=top><tt>{@link java.nio.channels.SelectionKey}</tt></td>
+ *     <td>A token representing the registration <br> of a channel
+ *     with&nbsp;a&nbsp;selector</td></tr>
+ * <tr><td valign=top><tt>{@link java.nio.channels.Pipe}</tt></td>
+ *     <td>Two channels that form a unidirectional&nbsp;pipe</td></tr>
+ * </table></blockquote>
+ *
+ * <p> Multiplexed, non-blocking I/O, which is much more scalable than
+ * thread-oriented, blocking I/O, is provided by <i>selectors</i>, <i>selectable
+ * channels</i>, and <i>selection keys</i>.
+ *
+ * <p> A <a href="Selector.html"><i>selector</i></a> is a multiplexor of <a
+ * href="SelectableChannel.html"><i>selectable channels</i></a>, which in turn are
+ * a special type of channel that can be put into <a
+ * href="SelectableChannel.html#bm"><i>non-blocking mode</i></a>.  To perform
+ * multiplexed I/O operations, one or more selectable channels are first created,
+ * put into non-blocking mode, and {@link
+ * java.nio.channels.SelectableChannel#register <i>registered</i>}
+ * with a selector.  Registering a channel specifies the set of I/O operations
+ * that will be tested for readiness by the selector, and returns a <a
+ * href="SelectionKey.html"><i>selection key</i></a> that represents the
+ * registration.
+ *
+ * <p> Once some channels have been registered with a selector, a <a
+ * href="Selector.html#selop"><i>selection operation</i></a> can be performed in
+ * order to discover which channels, if any, have become ready to perform one or
+ * more of the operations in which interest was previously declared.  If a channel
+ * is ready then the key returned when it was registered will be added to the
+ * selector's <i>selected-key set</i>.  The key set, and the keys within it, can
+ * be examined in order to determine the operations for which each channel is
+ * ready.  From each key one can retrieve the corresponding channel in order to
+ * perform whatever I/O operations are required.
+ *
+ * <p> That a selection key indicates that its channel is ready for some operation
+ * is a hint, but not a guarantee, that such an operation can be performed by a
+ * thread without causing the thread to block.  It is imperative that code that
+ * performs multiplexed I/O be written so as to ignore these hints when they prove
+ * to be incorrect.
+ *
+ * <p> This package defines selectable-channel classes corresponding to the {@link
+ * java.net.DatagramSocket}, {@link java.net.ServerSocket}, and {@link
+ * java.net.Socket} classes defined in the <tt>{@link java.net}</tt> package.
+ * Minor changes to these classes have been made in order to support sockets that
+ * are associated with channels.  This package also defines a simple class that
+ * implements unidirectional pipes.  In all cases, a new selectable channel is
+ * created by invoking the static <tt>open</tt> method of the corresponding class.
+ * If a channel needs an associated socket then a socket will be created as a side
+ * effect of this operation.
+ *
+ * <p> The implementation of selectors, selectable channels, and selection keys
+ * can be replaced by "plugging in" an alternative definition or instance of the
+ * {@link java.nio.channels.spi.SelectorProvider} class defined in the <tt>{@link
+ * java.nio.channels.spi}</tt> package.  It is not expected that many developers
+ * will actually make use of this facility; it is provided primarily so that
+ * sophisticated users can take advantage of operating-system-specific
+ * I/O-multiplexing mechanisms when very high performance is required.
+ *
+ * <p> Much of the bookkeeping and synchronization required to implement the
+ * multiplexed-I/O abstractions is performed by the {@link
+ * java.nio.channels.spi.AbstractInterruptibleChannel}, {@link
+ * java.nio.channels.spi.AbstractSelectableChannel}, {@link
+ * java.nio.channels.spi.AbstractSelectionKey}, and {@link
+ * java.nio.channels.spi.AbstractSelector} classes in the <tt>{@link
+ * java.nio.channels.spi}</tt> package.  When defining a custom selector provider,
+ * only the {@link java.nio.channels.spi.AbstractSelector} and {@link
+ * java.nio.channels.spi.AbstractSelectionKey} classes should be subclassed
+ * directly; custom channel classes should extend the appropriate {@link
+ * java.nio.channels.SelectableChannel} subclasses defined in this package.
+ *
+ * <a name="async"></a>
+ *
+ * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists asynchronous channels and their descriptions">
+ * <tr><th><p align="left">Asynchronous I/O</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel}</tt></td>
+ *     <td>An asynchronous channel for reading, writing, and manipulating a file</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel}</tt></td>
+ *     <td>An asynchronous channel to a stream-oriented connecting socket</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td>
+ *     <td>An asynchronous channel to a stream-oriented listening socket</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.AsynchronousDatagramChannel}</tt></td>
+ *     <td>An asynchronous channel to a datagram-oriented socket</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.CompletionHandler}</tt></td>
+ *     <td>A handler for consuming the result of an asynchronous operation</td></tr>
+ * <tr><td valign=top><tt>{@link org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup}</tt></td>
+ *     <td>A grouping of asynchronous channels for the purpose of resource sharing</td></tr>
+ * </table></blockquote>
+ *
+ * <p> {@link org.classpath.icedtea.java.nio.channels.AsynchronousChannel Asynchronous channels} are a
+ * special type of channel capable of asynchronous I/O operations. Asynchronous
+ * channels are non-blocking and define methods to initiate asynchronous
+ * operations, returning a {@link java.util.concurrent.Future} representing the
+ * pending result of each operation. The {@code Future} can be used to poll or
+ * wait for the result of the operation. Asynchronous I/O operations can also
+ * specify a {@link org.classpath.icedtea.java.nio.channels.CompletionHandler} to invoke when the
+ * operation completes. A completion handler is user provided code that is executed
+ * to consume the result of I/O operation.
+ *
+ * <p> This package defines asynchronous-channel classes that are connected to
+ * a stream-oriented connecting or listening socket, or a datagram-oriented socket.
+ * It also defines the {@link org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel} class
+ * for asynchronous reading, writing, and manipulating a file. As with the {@link
+ * org.classpath.icedtea.java.nio.channels.FileChannel} it supports operations to truncate the file
+ * to a specific size, force updates to the file to be written to the storage
+ * device, or acquire locks on the whole file or on a specific region of the file.
+ * Unlike the {@code FileChannel} it does not define methods for mapping a
+ * region of the file directly into memory. Where memory mapped I/O is required,
+ * then a {@code FileChannel} can be used.
+ *
+ * <p> Asynchronous channels are bound to an asynchronous channel group for the
+ * purpose of resource sharing. A group has an associated {@link
+ * java.util.concurrent.ExecutorService} to which tasks are submitted to handle
+ * I/O events and dispatch to completion handlers that consume the result of
+ * asynchronous operations performed on channels in the group. The group can
+ * optionally be specified when creating the channel or the channel can be bound
+ * to a <em>default group</em>. Sophisticated users may wish to create their
+ * own asynchronous channel groups or configure the {@code ExecutorService}
+ * that will be used for the default group.
+ *
+ * <p> As with selectors, the implementatin of asynchronous channels can be
+ * replaced by "plugging in" an alternative definition or instance of the {@link
+ * java.nio.channels.spi.AsynchronousChannelProvider} class defined in the
+ * <tt>{@link java.nio.channels.spi}</tt> package.  It is not expected that many
+ * developers will actually make use of this facility; it is provided primarily
+ * so that sophisticated users can take advantage of operating-system-specific
+ * asynchronous I/O mechanisms when very high performance is required.
+ *
+ * <hr width="80%">
+ * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
+ * or method in any class or interface in this package will cause a {@link
+ * java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * @since 1.4
+ * @updated 1.7
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ */
+
+package org.classpath.icedtea.java.nio.channels;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.channels.spi;
+
+import java.nio.channels.*;
+import java.net.ProtocolFamily;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+import java.util.ServiceConfigurationError;
+import java.util.concurrent.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Service-provider class for asynchronous channels.
+ *
+ * <p> An asynchronous channel provider is a concrete subclass of this class that
+ * has a zero-argument constructor and implements the abstract methods specified
+ * below.  A given invocation of the Java virtual machine maintains a single
+ * system-wide default provider instance, which is returned by the {@link
+ * #provider() provider} method.  The first invocation of that method will locate
+ * the default provider as specified below.
+ *
+ * <p> All of the methods in this class are safe for use by multiple concurrent
+ * threads.  </p>
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousChannelProvider {
+
+    private static final Object lock = new Object();
+    private static AsynchronousChannelProvider provider = null;
+
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(new RuntimePermission("asynchronousChannelProvider"));
+        return null;
+    }
+    private AsynchronousChannelProvider(Void ignore) { }
+
+    /**
+     * Initializes a new instance of this class.
+     *
+     * @throws  SecurityException
+     *          If a security manager has been installed and it denies
+     *          {@link RuntimePermission}<tt>("asynchronousChannelProvider")</tt>
+     */
+    protected AsynchronousChannelProvider() {
+        this(checkPermission());
+    }
+
+    private static boolean loadProviderFromProperty() {
+        String cn = System.getProperty("org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider");
+        if (cn == null)
+            return false;
+        try {
+            Class<?> c = Class.forName(cn, true,
+                                       ClassLoader.getSystemClassLoader());
+            provider = (AsynchronousChannelProvider)c.newInstance();
+            return true;
+        } catch (ClassNotFoundException x) {
+            throw new ServiceConfigurationError(null, x);
+        } catch (IllegalAccessException x) {
+            throw new ServiceConfigurationError(null, x);
+        } catch (InstantiationException x) {
+            throw new ServiceConfigurationError(null, x);
+        } catch (SecurityException x) {
+            throw new ServiceConfigurationError(null, x);
+        }
+    }
+
+    private static boolean loadProviderAsService() {
+
+        ServiceLoader<AsynchronousChannelProvider> sl =
+            ServiceLoader.load(AsynchronousChannelProvider.class,
+                               ClassLoader.getSystemClassLoader());
+        Iterator<AsynchronousChannelProvider> i = sl.iterator();
+        for (;;) {
+            try {
+                if (!i.hasNext())
+                    return false;
+                provider = i.next();
+                return true;
+            } catch (ServiceConfigurationError sce) {
+                if (sce.getCause() instanceof SecurityException) {
+                    // Ignore the security exception, try the next provider
+                    continue;
+                }
+                throw sce;
+            }
+        }
+    }
+
+    /**
+     * Returns the system-wide default asynchronous channel provider for this
+     * invocation of the Java virtual machine.
+     *
+     * <p> The first invocation of this method locates the default provider
+     * object as follows: </p>
+     *
+     * <ol>
+     *
+     *   <li><p> If the system property
+     *   <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> is defined
+     *   then it is taken to be the fully-qualified name of a concrete provider class.
+     *   The class is loaded and instantiated; if this process fails then an
+     *   unspecified error is thrown.  </p></li>
+     *
+     *   <li><p> If a provider class has been installed in a jar file that is
+     *   visible to the system class loader, and that jar file contains a
+     *   provider-configuration file named
+     *   <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> in the resource
+     *   directory <tt>META-INF/services</tt>, then the first class name
+     *   specified in that file is taken.  The class is loaded and
+     *   instantiated; if this process fails then an unspecified error is
+     *   thrown.  </p></li>
+     *
+     *   <li><p> Finally, if no provider has been specified by any of the above
+     *   means then the system-default provider class is instantiated and the
+     *   result is returned.  </p></li>
+     *
+     * </ol>
+     *
+     * <p> Subsequent invocations of this method return the provider that was
+     * returned by the first invocation.  </p>
+     *
+     * @return  The system-wide default AsynchronousChannel provider
+     */
+    public static AsynchronousChannelProvider provider() {
+        synchronized (lock) {
+            if (provider != null) {
+                return provider;
+            }
+            return AccessController
+                .doPrivileged(new PrivilegedAction<AsynchronousChannelProvider>() {
+                    public AsynchronousChannelProvider run() {
+                            if (loadProviderFromProperty())
+                                return provider;
+                            if (loadProviderAsService())
+                                return provider;
+                            provider = sun.nio.ch.DefaultAsynchronousChannelProvider.create();
+                            return provider;
+                        }
+                    });
+        }
+    }
+
+    /**
+     * The types of thread pool that an asynchronous channel group can be
+     * constructed with.
+     *
+     * @since 1.7
+     */
+    public static enum ThreadPoolType {
+        /**
+         * Fixed thread pool.
+         *
+         * @see Executors#newFixedThreadPool
+         */
+        FIXED,
+        /**
+         * Cached thread pool.
+         *
+         * @see Executors#newCachedThreadPool
+         */
+        CACHED;
+    }
+
+    /**
+     * Constructs a new asynchronous channel group.
+     *
+     * @param   poolType
+     *          The type of thread pool
+     * @param   executor
+     *          The thread pool
+     * @param   nThreads
+     *          The number of threads or initial size, depending on the thread
+     *          pool type.
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code nThreads} parameter is invalid for the thread
+     *          pool type
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public AsynchronousChannelGroup openAsynchronousChannelGroup
+        (ThreadPoolType poolType, ExecutorService executor, int nThreads) throws IOException
+    {
+        return null;
+    }
+
+    /**
+     * Opens an asynchronous server-socket channel.
+     *
+     * @param   group
+     *          The group to which the channel is bound, or {@code null} to
+     *          bind to the default group
+     *
+     * @return  The new channel
+     *
+     * @throws  IllegalChannelGroupException
+     *          If the provider that created the group differs from this provider
+     * @throws  ShutdownChannelGroupException
+     *          The group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract AsynchronousServerSocketChannel openAsynchronousServerSocketChannel
+        (AsynchronousChannelGroup group) throws IOException;
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * @param   group
+     *          The group to which the channel is bound, or {@code null} to
+     *          bind to the default group
+     *
+     * @return  The new channel
+     *
+     * @throws  IllegalChannelGroupException
+     *          If the provider that created the group differs from this provider
+     * @throws  ShutdownChannelGroupException
+     *          The group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
+        (AsynchronousChannelGroup group) throws IOException;
+
+    /**
+     * Opens an asynchronous datagram channel.
+     *
+     * @param   family
+     *          The protocol family, or {@code null} for the default protocol
+     *          family
+     * @param   group
+     *          The group to which the channel is bound, or {@code null} to
+     *          bind to the default group
+     *
+     * @return  The new channel
+     *
+     * @throws  IllegalChannelGroupException
+     *          If the provider that created the group differs from this provider
+     * @throws  ShutdownChannelGroupException
+     *          The group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel
+        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/package.html	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,46 @@
+<!--
+ Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ Copyright 2009 Red Hat, Inc.
+ 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.
+-->
+
+<!doctype html public "-//IETF//DTD HTML//EN">
+<html>
+<body bgcolor="white">
+
+Service-provider classes for the <tt>{@link org.classpath.icedtea.java.nio.channels}</tt> package.
+
+<p> Only developers who are defining new asynchronous channel providers should need
+to make direct use of this package.  </p>
+
+<p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
+or method in any class or interface in this package will cause a {@link
+java.lang.NullPointerException NullPointerException} to be thrown.
+
+
+@since 1.7
+@author Mark Reinhold
+@author JSR-51 Expert Group
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessDeniedException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when a file system operation is denied, typically
+ * due to a file permission or other access check.
+ *
+ * <p> This exception is not related to the {@link
+ * java.security.AccessControlException AccessControlException} or {@link
+ * SecurityException} thrown by access controllers or security managers when
+ * access to a file is denied.
+ *
+ * @since 1.7
+ */
+
+public class AccessDeniedException
+    extends FileSystemException
+{
+    private static final long serialVersionUID = 4943049599949219617L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     */
+    public AccessDeniedException(String file) {
+        super(file);
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     * @param   other
+     *          A string identifying the other file or {@code null} if not known.
+     * @param   reason
+     *          A reason message with additional information or {@code null}
+     */
+    public AccessDeniedException(String file, String other, String reason) {
+        super(file, other, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AccessMode.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Defines access modes used to test the accessibility of a file.
+ *
+ * @since 1.7
+ *
+ * @see FileRef#checkAccess
+ */
+
+public enum AccessMode {
+    /**
+     * Test read access.
+     */
+    READ,
+    /**
+     * Test write access.
+     */
+    WRITE,
+    /**
+     * Test execute access.
+     */
+    EXECUTE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/AtomicMoveNotSupportedException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when a file cannot be moved as an atomic file system
+ * operation.
+ *
+ * @since 1.7
+ */
+
+public class AtomicMoveNotSupportedException
+    extends FileSystemException
+{
+    static final long serialVersionUID = 5402760225333135579L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   source
+     *          A string identifying the source file or {@code null} if not known.
+     * @param   target
+     *          A string identifying the target file or {@code null} if not known.
+     * @param   reason
+     *          A reason message with additional information
+     */
+    public AtomicMoveNotSupportedException(String source,
+                                           String target,
+                                           String reason)
+    {
+        super(source, target, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedDirectoryStreamException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Unchecked exception thrown when an attempt is made to invoke an operation on
+ * a directory stream that is closed.
+ *
+ * @since 1.7
+ */
+
+public class ClosedDirectoryStreamException
+    extends IllegalStateException
+{
+    static final long serialVersionUID = 4228386650900895400L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ClosedDirectoryStreamException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedFileSystemException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Unchecked exception thrown when an attempt is made to invoke an operation on
+ * a file and the file system is closed.
+ */
+
+public class ClosedFileSystemException
+    extends IllegalStateException
+{
+    static final long serialVersionUID = -8158336077256193488L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ClosedFileSystemException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ClosedWatchServiceException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Unchecked exception thrown when an attempt is made to invoke an operation on
+ * a watch service that is closed.
+ */
+
+public class ClosedWatchServiceException
+    extends IllegalStateException
+{
+    static final long serialVersionUID = 1853336266231677732L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ClosedWatchServiceException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/CopyOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * An object that configures how to copy or move a file.
+ *
+ * <p> Objects of this type may be used with the {@link Path#copyTo copyTo} and
+ * {@link Path#moveTo moveTo} methods to configure how a file is copied or moved.
+ *
+ * <p> The {@link StandardCopyOption} enumeration type defines the
+ * <i>standard</i> options.
+ *
+ * @since 1.7
+ */
+
+public interface CopyOption {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryNotEmptyException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when a file system operation fails because a
+ * directory is not empty.
+ *
+ * @since 1.7
+ */
+
+public class DirectoryNotEmptyException
+    extends FileSystemException
+{
+    static final long serialVersionUID = 3056667871802779003L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   dir
+     *          A string identifying the directory or {@code null} if not known.
+     */
+    public DirectoryNotEmptyException(String dir) {
+        super(dir);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStream.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.util.Iterator;
+import java.io.Closeable;
+
+/**
+ * An object to iterate over the entries in a directory. A directory stream
+ * allows for convenient use of the for-each construct:
+ * <pre>
+ *   Path dir = ...
+ *   DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream();
+ *   try {
+ *       for (Path entry: stream) {
+ *         ..
+ *       }
+ *   } finally {
+ *       stream.close();
+ *   }
+ * </pre>
+ *
+ * <p><b> A {@code DirectoryStream} is not a general-purpose {@code Iterable}.
+ * While this interface extends {@code Iterable}, the {@code iterator} method
+ * may only be invoked once to obtain the iterator; a second, or subsequent,
+ * call to the {@code iterator} method throws {@code IllegalStateException}. </b>
+ *
+ * <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}.
+ *
+ * <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
+ * directory, and another thread invokes the {@code close} method then it may
+ * require to block until the read operation is complete.
+ *
+ * <p> The {@link Iterator#hasNext() hasNext} and {@link Iterator#next() next}
+ * methods can encounter an I/O error when iterating over the directory in which
+ * case {@code ConcurrentModificationException} is thrown with cause
+ * {@link java.io.IOException}. The {@code hasNext} method is guaranteed to
+ * read-ahead by at least one element. This means that if the {@code hasNext}
+ * method returns {@code true} and is followed by a call to the {@code next}
+ * method then it is guaranteed not to fail with a {@code
+ * ConcurrentModificationException}.
+ *
+ * <p> The elements returned by the iterator are in no specific order. Some file
+ * systems maintain special links to the directory itself and the directory's
+ * parent directory. Entries representing these links are not returned by the
+ * iterator.
+ *
+ * <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
+ * security exception occurs then {@code ConcurrentModificationException} is
+ * thrown with the cause.
+ *
+ * <p> The iterator is <i>weakly consistent</i>. It is thread safe but does not
+ * freeze the directory while iterating, so it may (or may not) reflect updates
+ * to the directory that occur after the {@code DirectoryStream} is created.
+ *
+ * @param   <T>     The type of element returned by the iterator
+ *
+ * @since 1.7
+ *
+ * @see Path#newDirectoryStream
+ */
+
+public interface DirectoryStream<T>
+    extends Closeable, Iterable<T>
+{
+    /**
+     * An interface that is implemented by objects that decide if a directory
+     * entry should be accepted or filtered. A {@code Filter} is passed as the
+     * parameter to the {@link Path#newDirectoryStream(DirectoryStream.Filter)
+     * 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
+     */
+    public static interface Filter<T> {
+        /**
+         * Decides if the given directory entry should be accept or filtered.
+         *
+         * @param   entry
+         *          The directory entry to be tested
+         *
+         * @return  {@code true} if the directory entry should be accepted
+         */
+        boolean accept(T entry);
+    }
+
+    /**
+     * Returns the iterator associated with this {@code DirectoryStream}.
+     *
+     * @return  The iterator associated with this {@code DirectoryStream}
+     *
+     * @throws  IllegalStateException
+     *          If this directory stream is closed or the iterator has already
+     *          been returned
+     */
+
+    Iterator<T> iterator();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/DirectoryStreamFilters.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.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>() {
+
+            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>() {
+
+            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>() {
+
+            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>() {
+
+            public boolean accept(T entry) {
+                return !filter.accept(entry);
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAction.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileAlreadyExistsException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when an attempt is made to create a file or
+ * directory and a file of that name already exists.
+ *
+ * @since 1.7
+ */
+
+public class FileAlreadyExistsException
+    extends FileSystemException
+{
+    static final long serialVersionUID = 7579540934498831181L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     */
+    public FileAlreadyExistsException(String file) {
+        super(file);
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     * @param   other
+     *          A string identifying the other file or {@code null} if not known.
+     * @param   reason
+     *          A reason message with additional information or {@code null}
+     */
+    public FileAlreadyExistsException(String file, String other, String reason) {
+        super(file, other, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileRef.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+
+/**
+ * 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.
+ *
+ * @since 1.7
+ */
+
+public interface FileRef {
+
+    /**
+     * Opens the file referenced by this object, returning a seekable byte
+     * channel to access 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:
+     *
+     * <table border=1 cellpadding=5 summary="">
+     * <tr> <th>Option</th> <th>Description</th> </tr>
+     * <tr>
+     *   <td> {@link StandardOpenOption#APPEND APPEND} </td>
+     *   <td> If this option is present then the file is opened for writing and
+     *     each invocation of the channel's {@code write} method first advances
+     *     the position to the end of the file and then writes the requested
+     *     data. Whether the advancement of the position and the writing of the
+     *     data are done in a single atomic operation is system-dependent and
+     *     therefore unspecified. This option may not be used in conjunction
+     *     with the {@code READ} or {@code TRUNCATE_EXISTING} options. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} </td>
+     *   <td> If this option is present then the existing file is truncated to
+     *   a size of 0 bytes. This option is ignored when the file is opened only
+     *   for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@link StandardOpenOption#SYNC SYNC} </td>
+     *   <td> Requires that every update to the file's content or metadata be
+     *   written synchronously to the underlying storage device. (see <a
+     *   href="package-summary.html#integrity"> Synchronized I/O file
+     *   integrity</a>). </td>
+     * </tr>
+     * <tr>
+     *   <td> {@link StandardOpenOption#DSYNC DSYNC} </td>
+     *   <td> Requires that every update to the file's content be written
+     *   synchronously to the underlying storage device. (see <a
+     *   href="package-summary.html#integrity"> Synchronized I/O file
+     *   integrity</a>). </td>
+     * </tr>
+     * </table>
+     *
+     * <p> An implementation of this interface may support additional options
+     * defined by the {@link StandardOpenOption} enumeration type or other
+     * implementation specific options.
+     *
+     * <p> The {@link java.nio.channels.Channels} utility classes defines methods
+     * to construct input and output streams where inter-operation with the
+     * {@link java.io} package is required.
+     *
+     * @param   options
+     *          Options specifying how the file is opened
+     *
+     * @return  a new seekable byte channel
+     *
+     * @throws  IllegalArgumentException
+     *          If an invalid combination of options is specified
+     * @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#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.
+     */
+    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.
+     */
+    FileStore getFileStore() throws IOException;
+
+    /**
+     * Checks the existence and optionally the accessibility of the file
+     * referenced by this object.
+     *
+     * <p> This method checks the existence of a file and that this Java virtual
+     * 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.
+     */
+    void checkAccess(AccessMode... modes) throws IOException;
+
+    /**
+     * Returns a file attribute view of a given type.
+     *
+     * <p> A file attribute view provides a read-only or updatable view of the
+     * file attributes that is supports. This method is intended to be used where
+     * the file attribute view defines type-safe methods to read or update the
+     * file attributes. The {@code type} parameter is the type of the attribute
+     * view required and the method returns an instance of that type if
+     * supported. The {@link BasicFileAttributeView} type supports access to the
+     * basic attributes of a file. Invoking this method to select a file
+     * attribute view of that type will always return an instance of that class.
+     *
+     * <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.
+     *
+     * @param   type
+     *          The {@code Class} object corresponding to the file attribute view
+     * @param   options
+     *          Options indicating how symbolic links are handled
+     *
+     * @return  A file attribute view of the specified type, or {@code null} if
+     *          the attribute view type 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.
+     *
+     * @see Attributes#readBasicFileAttributes
+     */
+    <V extends FileAttributeView> V getFileAttributeView(Class<V> type, LinkOption... options);
+
+    /**
+     * Returns a file attribute view of the given name.
+     *
+     * <p> A file attribute view provides a read-only or updatable view of the
+     * file attributes that is supports. 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 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.
+     *
+     * @param   name
+     *          The name of the file attribute view
+     * @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
+     *
+     * @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
+     */
+    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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileStore.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.util.Set;
+
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreAttributeView;
+
+/**
+ * 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
+ * stores can be enumerated by invoking the {@link FileSystem#getFileStores
+ * getFileStores} method.
+ *
+ * <p> In addition to the methods defined by this class, a file store may support
+ * one or more {@link FileStoreAttributeView FileStoreAttributeView} classes
+ * that provide a read-only or updatable view of a set of file store attributes.
+ * File stores associated with the default provider support the {@link
+ * FileStoreSpaceAttributeView} to read the space related attributes of the
+ * file store.
+ *
+ * @since 1.7
+ */
+
+public abstract class FileStore {
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected FileStore() {
+    }
+
+    /**
+     * Returns the name of this file store. The format of the name is highly
+     * implementation specific. It will typically be the name of the storage
+     * pool or volume.
+     *
+     * <p> The string returned by this method may differ from the string
+     * returned by the {@link Object#toString() toString} method.
+     *
+     * @return  The name of this file store
+     */
+    public abstract String name();
+
+    /**
+     * Returns the <em>type</em> of this file store. The format of the string
+     * returned by this method is highly implementation specific. It may
+     * indicate, for example, the format used or if the file store is local
+     * or remote.
+     *
+     * @return  A string representing the type of this file store
+     */
+    public abstract String type();
+
+    /**
+     * Tells whether this file store is read-only. A file store is read-only if
+     * it does not support write operations or other changes to files. Any
+     * attempt to create a file, open an existing file for writing etc. causes
+     * an {@code IOException} to be thrown.
+     *
+     * @return  {@code true} if, and only if, this file store is read-only
+     */
+    public abstract boolean isReadOnly();
+
+    /**
+     * Tells whether or not this file store supports the file attributes
+     * identified by the given file attribute view.
+     *
+     * <p> Invoking this method to test if the file store supports {@link
+     * BasicFileAttributeView} will always return {@code true}. In the case of
+     * the default provider, this method cannot guarantee to give the correct
+     * result when the file store is not a local storage device. The reasons for
+     * this are implementation specific and therefore unspecified.
+     *
+     * @param   type
+     *          The file attribute view type
+     *
+     * @return  {@code true} if, and only if, the file attribute view is
+     *          supported
+     */
+    public abstract boolean supportsFileAttributeView(Class<? extends FileAttributeView> type);
+
+    /**
+     * Tells whether or not this file store supports the file attributes
+     * identified by the given file attribute view.
+     *
+     * <p> Invoking this method to test if the file store supports {@link
+     * BasicFileAttributeView}, identified by the name "{@code basic}" will
+     * always return {@code true}. In the case of the default provider, this
+     * method cannot guarantee to give the correct result when the file store is
+     * not a local storage device. The reasons for this are implementation
+     * specific and therefore unspecified.
+     *
+     * @param   name
+     *          The {@link FileAttributeView#name name} of file attribute view
+     *
+     * @return  {@code true} if, and only if, the file attribute view is
+     *          supported
+     */
+    public abstract boolean supportsFileAttributeView(String name);
+
+    /**
+     * Returns a {@code FileStoreAttributeView} of the given type.
+     *
+     * <p> This method is intended to be used where the file store attribute
+     * view defines type-safe methods to read or update the file store attributes.
+     * The {@code type} parameter is the type of the attribute view required and
+     * the method returns an instance of that type if supported.
+     *
+     * <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 FileStoreSpaceAttributeView.class} will
+     * always return an instance of that class.
+     *
+     * @param   type
+     *          The {@code Class} object corresponding to the attribute view
+     *
+     * @return  A file store attribute view of the specified type or
+     *          {@code null} if the attribute view is not available
+     */
+    public abstract <V extends FileStoreAttributeView> V
+        getFileStoreAttributeView(Class<V> type);
+
+    /**
+     * Returns a {@code FileStoreAttributeView} of the given name.
+     *
+     * <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> 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.
+     *
+     * @param   name
+     *          The name of the attribute view
+     *
+     * @return  A file store attribute view of the given name, or {@code null}
+     *          if the attribute view is not available
+     */
+    public abstract FileStoreAttributeView getFileStoreAttributeView(String name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystem.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.util.Set;
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipalLookupService;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Provides an interface to a file system and is the factory for objects to
+ * access files and other objects in the file system.
+ *
+ * <p> The default file system, obtained by invoking the {@link FileSystems#getDefault
+ * FileSystems.getDefault} method, provides access to the file system that is
+ * accessible to the Java virtual machine. The {@link FileSystems} class defines
+ * methods to create file systems that provide access to other types of file
+ * systems.
+ *
+ * <p> A file system is the factory for several types of objects:
+ *
+ * <ul>
+ *   <li><p> The {@link #getPath getPath} method converts a system dependent
+ *     <em>path string</em>, returning a {@link Path} object that may be used
+ *     to locate and access a file. </p></li>
+ *   <li><p> The {@link #getNameMatcher  getNameMatcher} method is used
+ *     to create a {@link PathMatcher} that performs match operations on
+ *     file names. </p></li>
+ *   <li><p> The {@link #getFileStores getFileStores} method returns an iterator
+ *     over the underlying {@link FileStore file-stores}. </p></li>
+ *   <li><p> The {@link #getUserPrincipalLookupService getUserPrincipalLookupService}
+ *     method returns the {@link UserPrincipalLookupService} to lookup users or
+ *     groups by name. </p></li>
+ *   <li><p> The {@link #newWatchService newWatchService} method creates a
+ *     {@link WatchService} that may be used to watch objects for changes and
+ *     events. </p></li>
+ * </ul>
+ *
+ * <p> File systems vary greatly. In some cases the file system is a single
+ * hierarchy of files with one top-level root directory. In other cases it may
+ * have several distinct file hierarchies, each with its own top-level root
+ * directory. The {@link #getRootDirectories getRootDirectories} method may be
+ * used to iterate over the root directories in the file system. A file system
+ * is typically composed of one or more underlying {@link FileStore file-stores}
+ * that provide the storage for the files. Theses file stores can also vary in
+ * the features they support, and the file attributes or <em>meta-data</em> that
+ * they associate with files.
+ *
+ * <p> A file system is open upon creation and can be closed by invoking its
+ * {@link #close() close} method. Once closed, any further attempt to access
+ * objects in the file system cause {@link ClosedFileSystemException} to be
+ * thrown. File systems created by the default {@link FileSystemProvider provider}
+ * cannot be closed.
+ *
+ * <p> A {@code FileSystem} can provide read-only or read-write access to the
+ * file system. Whether or not a file system provides read-only access is
+ * established when the {@code FileSystem} is created and can be tested by invoking
+ * its {@link #isReadOnly() isReadOnly} method. Attempts to write to file stores
+ * by means of an object associated with a read-only file system throws {@link
+ * ReadOnlyFileSystemException}.
+ *
+ * <p> File systems are safe for use by multiple concurrent threads. The {@link
+ * #close close} method may be invoked at any time to close a file system but
+ * whether a file system is <i>asynchronously closeable</i> is provider specific
+ * and therefore unspecified. In other words, if a thread is accessing an
+ * object in a file system, and another thread invokes the {@code close} method
+ * then it may require to block until the first operation is complete. Closing
+ * a file system causes all open channels, watch services, and other {@link
+ * Closeable closeable} objects associated with the file system to be closed.
+ *
+ * @since 1.7
+ */
+
+public abstract class FileSystem
+    implements Closeable
+{
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected FileSystem() {
+    }
+
+    /**
+     * Returns the provider that created this file system.
+     *
+     * @return  The provider that created this file system.
+     */
+    public abstract FileSystemProvider provider();
+
+    /**
+     * Closes this file system.
+     *
+     * <p> After a file system is closed then all subsequent access to the file
+     * system, either by methods defined by this class or on objects associated
+     * with this file system, throw {@link ClosedFileSystemException}. If the
+     * file system is already closed then invoking this method has no effect.
+     *
+     * <p> Closing a file system will close all open {@link
+     * java.nio.channels.Channel channels}, {@link DirectoryStream directory-streams},
+     * {@link WatchService watch-service}, and other closeable objects associated
+     * with this file system. The {@link FileSystems#getDefault default} file
+     * system cannot be closed.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  UnsupportedOperationException
+     *          Thrown in the case of the default file system
+     */
+
+    public abstract void close() throws IOException;
+
+    /**
+     * Tells whether or not this file system is open.
+     *
+     * <p> File systems created by the default provider are always open.
+     *
+     * @return  {@code true} if, and only if, this file system is open
+     */
+    public abstract boolean isOpen();
+
+    /**
+     * Tells whether or not this file system allows only read-only access to
+     * its file stores.
+     *
+     * @return  {@code true} if, and only if, this file system provides
+     *          read-only access
+     */
+    public abstract boolean isReadOnly();
+
+    /**
+     * Returns the name separator, represented as a string.
+     *
+     * <p> The name separator is used to separate names in a path string. An
+     * implementation may support multiple name separators in which case this
+     * method returns an implementation specific <em>default</em> name separator.
+     * This separator is used when creating path strings by invoking the {@link
+     * Path#toString() toString()} method.
+     *
+     * <p> In the case of the default provider, this method returns the same
+     * separator as {@link java.io.File#separator}.
+     *
+     * @return  The name separator
+     */
+    public abstract String getSeparator();
+
+    /**
+     * Returns an object to iterate over the paths of the root directories.
+     *
+     * <p> A file system provides access to a file store that may be composed
+     * of a number of distinct file hierarchies, each with its own top-level
+     * root directory. Unless denied by the security manager, each element in
+     * the returned iterator corresponds to the root directory of a distinct
+     * file hierarchy. The order of the elements is not defined. The file
+     * hierarchies may change during the lifetime of the Java virtual machine.
+     * For example, in some implementations, the insertion of removable media
+     * may result in the creation of a new file hierarchy with its own
+     * top-level directory.
+     *
+     * <p> When a security manager is installed, it is invoked to check access
+     * to the each root directory. If denied, the root directory is not returned
+     * by the iterator. In the case of the default provider, the {@link
+     * SecurityManager#checkRead(String)} method is invoked to check read access
+     * to each root directory. It is system dependent if the permission checks
+     * are done when the iterator is obtained or during iteration.
+     *
+     * @return  An object to iterate over the root directories
+     */
+    public abstract Iterable<Path> getRootDirectories();
+
+    /**
+     * Returns an object to iterate over the underlying file stores.
+     *
+     * <p> The elements of the returned iterator are the {@link
+     * FileStore FileStores} for this file system. The order of the elements is
+     * not defined and the file stores may change during the lifetime of the
+     * Java virtual machine. When an I/O error occurs, perhaps because a file
+     * store is not accessible, then it is not returned by the iterator.
+     *
+     * <p> When a security manager is installed, it is invoked to check access
+     * to each file store. If denied, the file store is not returned by the
+     * iterator. In the case of the default provider, the {@link
+     * SecurityManager#checkRead(String)} method is invoked to check read access
+     * to the file store's <em>top-most</em> directory. It is system dependent
+     * if the permission checks are done when the iterator is obtained or during
+     * iteration.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we want to print the space usage for all file stores:
+     * <pre>
+     *     for (FileStore store: FileSystems.getDefault().getFileStores()) {
+     *         FileStoreSpaceAttributes attrs = Attributes.readFileStoreSpaceAttributes(store);
+     *         long total = attrs.totalSpace() / 1024;
+     *         long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / 1024;
+     *         long avail = attrs.usableSpace() / 1024;
+     *         System.out.format("%-20s %12d %12d %12d%n", store, total, used, avail);
+     *     }
+     * </pre>
+     *
+     * @return  An object to iterate over the backing file stores
+     */
+    public abstract Iterable<FileStore> getFileStores();
+
+    /**
+     * Returns the set of the {@link FileAttributeView#name names} of the file
+     * attribute views supported by this {@code FileSystem}.
+     *
+     * <p> The {@link BasicFileAttributeView} is required to be supported and
+     * therefore the set contains at least one element, "basic".
+     *
+     * <p> The {@link FileStore#supportsFileAttributeView(String)
+     * supportsFileAttributeView(String)} method may be used to test if an
+     * underlying {@link FileStore} supports the file attributes identified by a
+     * file attribute view.
+     *
+     * @return  An unmodifiable set of the names of the supported file attribute
+     *          views
+     */
+    public abstract Set<String> supportedFileAttributeViews();
+
+    /**
+     * Converts a path string to a {@code Path}.
+     *
+     * <p> The parsing and conversion to a path object is inherently
+     * implementation dependent. In the simplest case, the path string is rejected,
+     * and {@link InvalidPathException} thrown, if the path string contains
+     * characters that cannot be converted to characters that are <em>legal</em>
+     * to the file store. For example, on UNIX systems, the NUL (&#92;u0000)
+     * character is not allowed to be present in a path. An implementation may
+     * choose to reject path strings that contain names that are longer than those
+     * allowed by any file store, and where an implementation supports a complex
+     * path syntax, it may choose to reject path strings that are <em>badly
+     * formed</em>.
+     *
+     * <p> In the case of the default provider, path strings are parsed based
+     * on the definition of paths at the platform or virtual file system level.
+     * For example, an operating system may not allow specific characters to be
+     * present in a file name, but a specific underlying file store may impose
+     * different or additional restrictions on the set of legal
+     * characters.
+     *
+     * <p> This method throws {@link InvalidPathException} when the path string
+     * cannot be converted to a path. Where possible, and where applicable,
+     * the exception is created with an {@link InvalidPathException#getIndex
+     * index} value indicating the first position in the {@code path} parameter
+     * that caused the path string to be rejected.
+     *
+     * <p> Invoking this method with an empty path string throws
+     * {@code InvalidPathException}.
+     *
+     * @param   path
+     *          The path string
+     *
+     * @return  A {@code Path} object
+     *
+     * @throws  InvalidPathException
+     *          If the path string cannot be converted
+     */
+    public abstract Path getPath(String path);
+
+    /**
+     * Returns a {@code PathMatcher} that performs match operations on file
+     * {@link Path#getName names} by interpreting a given pattern.
+     *
+     * <p> The {@code syntax} parameter identifies the syntax. This method
+     * supports the "{@code glob}" and "{@code regex}" syntaxes, and may
+     * support others. The value of the syntax component is compared without
+     * regard to case.
+     *
+     * <p> When the syntax is "{@code glob}" then the {@code String}
+     * representation of the file name is matched using a limited pattern
+     * language that resembles regular expressions but with a simpler syntax.
+     * For example:
+     *
+     * <blockquote>
+     * <table border="0">
+     * <tr>
+     *   <td>{@code *.java}</td>
+     *   <td>Matches file names ending in {@code .java}</td>
+     * </tr>
+     * <tr>
+     *   <td>{@code *.*}</td>
+     *   <td>Matches file names containing a dot</td>
+     * </tr>
+     * <tr>
+     * <tr>
+     *   <td>{@code *.{java,class}}</td>
+     *   <td>Matches file names ending with {@code .java} or {@code .class}</td>
+     * </tr>
+     * <tr>
+     *   <td>{@code foo.?}</td>
+     *   <td>Matches file names starting with {@code foo.} and a single
+     *   character extension</td>
+     * </tr>
+     * </table>
+     * </blockquote>
+     *
+     * <p> The following rules are used to interprete glob patterns:
+     *
+     * <p> <ul>
+     *   <li><p> The {@code *} character matches zero or more {@link Character
+     *   characters}. </p></li>
+     *
+     *   <li><p> The {@code ?} character matches exactly one character. </p></li>
+     *
+     *   <li><p> The backslash character ({@code \}) is used to escape characters
+     *   that would otherwise be interpreted as special characters. The expression
+     *   {@code \\} matches a single backslash and "\{" matches a left brace
+     *   for example.  </p></li>
+     *
+     *   <li><p> The {@code [ ]} characters are a <i>bracket expression</i> and
+     *   match a single character that is contained within the brackets. For
+     *   example, {@code [abc]} matches {@code "a"}, {@code "b"}, or {@code "c"}.
+     *   The hyphen ({@code -}) may be used to specify a range so {@code [a-z]}
+     *   specifies a range that matches from {@code "a"} to {@code "z"} (inclusive).
+     *   These forms can be mixed so [abce-g] matches {@code "a"}, {@code "b"},
+     *   {@code "c"}, {@code "e"}, {@code "f"} or {@code "g"}. If the character
+     *   after the {@code [} is a {@code !} then it is used for negation so {@code
+     *   [!a-c]} matches any character except {@code "a"}, {@code "b"}, or {@code
+     *   "c"}.
+     *   <p> Within a bracket expression the {@code *}, {@code ?} and {@code \}
+     *   characters match themselves. The ({@code -}) character matches itself if
+     *   it is the first character within the brackets, or the first character
+     *   after the {@code !} if negating.</p></li>
+     *
+     *   <li><p> The {@code { }} characters are a group of subpatterns, where
+     *   the group matches if any subpattern in the group matches. The {@code ","}
+     *   character is used to separate the subpatterns. Groups cannot be nested.
+     *   </p></li>
+     *
+     *   <li><p>All other characters match themselves in an implementation
+     *   dependent manner. </p></li>
+     * </ul>
+     *
+     * <p> When the syntax is "{@code regex}" then the pattern component is a
+     * regular expression as defined by the {@link java.util.regex.Pattern}
+     * class.
+     *
+     * <p> For both the glob and regex syntaxes then whether matching is case
+     * sensitive, and other matching details, are implementation-dependent.
+     *
+     * <p> The {@code PathMatcher} returned by this method matches on the {@link
+     * Path#getName name} component of a {@code Path}. If the {@link
+     * PathMatcher#matches matches} method is invoked with a {@code Path} that
+     * does not have a {@code name} component then it returns {@code false}.
+     *
+     * @param   syntax
+     *          The pattern syntax
+     * @param   pattern
+     *          The pattern
+     *
+     * @return  A file name matcher that matches file names against the pattern
+     *
+     * @throws  java.util.regex.PatternSyntaxException
+     *          If the pattern is invalid
+     * @throws  UnsupportedOperationException
+     *          If the pattern syntax is not known to the implementation
+     *
+     * @see Path#newDirectoryStream(String)
+     */
+    public abstract PathMatcher getNameMatcher(String syntax, String pattern);
+
+    /**
+     * Returns the {@code UserPrincipalLookupService} for this file system
+     * <i>(optional operation)</i>. The resulting lookup service may be used to
+     * lookup user or group names.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we want to make "joe" the owner of a file:
+     * <pre>
+     *     Path file = ...
+     *     UserPrincipal joe = file.getFileSystem().getUserPrincipalLookupService()
+     *         .lookupPrincipalByName("joe");
+     *     Attributes.setOwner(file, joe);
+     * </pre>
+     *
+     * @throws  UnsupportedOperationException
+     *          If this {@code FileSystem} does not does have a lookup service
+     *
+     * @return  The {@code UserPrincipalLookupService} for this file system
+     */
+    public abstract UserPrincipalLookupService getUserPrincipalLookupService();
+
+    /**
+     * Constructs a new {@link WatchService} <i>(optional operation)</i>.
+     *
+     * <p> This method constructs a new watch service that may be used to watch
+     * registered objects for changes and events.
+     *
+     * @return  a new watch service
+     *
+     * @throws  UnsupportedOperationException
+     *          If this {@code FileSystem} does not support watching file system
+     *          objects for changes and events. This exception is not thrown
+     *          by {@code FileSystems} created by the default provider.
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract WatchService newWatchService() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemAlreadyExistsException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Runtime exception thrown an attempt is made to create a file system that
+ * already exists.
+ */
+
+public class FileSystemAlreadyExistsException
+    extends RuntimeException
+{
+    static final long serialVersionUID = -5438419127181131148L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public FileSystemAlreadyExistsException() {
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   msg
+     *          The detail message
+     */
+    public FileSystemAlreadyExistsException(String msg) {
+        super(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a file system operation fails on one or two files. This class is
+ * the general class for file system exceptions.
+ *
+ * @since 1.7
+ */
+
+public class FileSystemException
+    extends IOException
+{
+    static final long serialVersionUID = -3055425747967319812L;
+
+    private final String file;
+    private final String other;
+
+    /**
+     * Constructs an instance of this class. This constructor should be used
+     * when an operation involving one file fails and there isn't any additional
+     * information to explain the reason.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     */
+    public FileSystemException(String file) {
+        super((String)null);
+        this.file = file;
+        this.other = null;
+    }
+
+    /**
+     * Constructs an instance of this class. This constructor should be used
+     * when an operation involving two files fails, or there is additional
+     * information to explain the reason.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     * @param   other
+     *          A string identifying the other file or {@code null} if there
+     *          isn't another file or if not known
+     * @param   reason
+     *          A reason message with additional information or {@code null}
+     */
+    public FileSystemException(String file, String other, String reason) {
+        super(reason);
+        this.file = file;
+        this.other = other;
+    }
+
+    /**
+     * Returns the file used to create this exception.
+     *
+     * @return  The file (can be {@code null})
+     */
+    public String getFile() {
+        return file;
+    }
+
+    /**
+     * Returns the other file used to create this exception.
+     *
+     * @return  The other file (can be {@code null})
+     */
+    public String getOtherFile() {
+        return other;
+    }
+
+    /**
+     * Returns the string explaining why the file system operation failed.
+     *
+     * @return  The string explaining why the file system operation failed
+     */
+    public String getReason() {
+        return super.getMessage();
+    }
+
+    /**
+     * Returns the detail message string.
+     */
+
+    public String getMessage() {
+        if (file == null && other == null)
+            return getReason();
+        StringBuilder sb = new StringBuilder();
+        if (file != null)
+            sb.append(file);
+        if (other != null) {
+            sb.append(" -> ");
+            sb.append(other);
+        }
+        if (getReason() != null) {
+            sb.append(": ");
+            sb.append(getReason());
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystemNotFoundException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Runtime exception thrown when a file system cannot be found.
+ */
+
+public class FileSystemNotFoundException
+    extends RuntimeException
+{
+    static final long serialVersionUID = 7999581764446402397L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public FileSystemNotFoundException() {
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   msg
+     *          The detail message
+     */
+    public FileSystemNotFoundException(String msg) {
+        super(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileSystems.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.spi.FileSystemProvider;
+import java.net.URI;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.lang.reflect.Constructor;
+
+/**
+ * Factory methods for file systems. This class defines the {@link #getDefault
+ * getDefault} method to get the default file system and factory methods to
+ * construct other types of file systems.
+ *
+ * <p> The first invocation of any of the methods defined by this class causes
+ * the default {@link FileSystemProvider provider} to be loaded. The default
+ * provider, identified by the URI scheme "file", creates the {@link FileSystem}
+ * that provides access to the file systems accessible to the Java virtual
+ * machine. If the process of loading or initializing the default provider fails
+ * then an unspecified error is thrown.
+ *
+ * <p> The first invocation of the {@link FileSystemProvider#installedProviders
+ * installedProviders} method, by way of invoking any of the {@code
+ * newFileSystem} methods defined by this class, locates and loads all
+ * installed file system providers. Installed providers are loaded using the
+ * service-provider loading facility defined by the {@link ServiceLoader} class.
+ * Installed providers are loaded using the system class loader. If the
+ * system class loader cannot be found then the extension class loader is used;
+ * if there is no extension class loader then the bootstrap class loader is used.
+ * Providers are typically installed by placing them in a JAR file on the
+ * application class path or in the extension directory, the JAR file contains a
+ * provider-configuration file named {@code java.nio.file.spi.FileSystemProvider}
+ * in the resource directory {@code META-INF/services}, and the file lists one or
+ * more fully-qualified names of concrete subclass of {@link FileSystemProvider}
+ * that have a zero argument constructor.
+ * The ordering that installed providers are located is implementation specific.
+ * If a provider is instantiated and its {@link FileSystemProvider#getScheme()
+ * getScheme} returns the same URI scheme of a provider that was previously
+ * instantiated then the most recently instantiated duplicate is discarded. URI
+ * schemes are compared without regard to case. During construction a provider
+ * may safely access files associated with the default provider but care needs
+ * to be taken to avoid circular loading of other installed providers. If
+ * circular loading of installed providers is detected then an unspecified error
+ * is thrown.
+ *
+ * <p> This class also defines factory methods that allow a {@link ClassLoader}
+ * to be specified when locating a provider. As with installed providers, the
+ * provider classes are identified by placing the provider configuration file
+ * in the resource directory {@code META-INF/services}.
+ *
+ * <p> If a thread initiates the loading of the installed file system providers
+ * and another thread invokes a method that also attempts to load the providers
+ * then the method will block until the loading completes.
+ *
+ * @since 1.7
+ */
+
+public final class FileSystems {
+    private FileSystems() {
+    }
+
+    // lazy initialization of default file system
+    private static class LazyInitialization {
+        static final FileSystem defaultFileSystem = defaultFileSystem();
+
+        // returns default file system
+        private static FileSystem defaultFileSystem() {
+            // load default provider
+            FileSystemProvider provider = AccessController
+                .doPrivileged(new PrivilegedAction<FileSystemProvider>() {
+                    public FileSystemProvider run() {
+                        return getDefaultProvider();
+                    }
+                });
+
+            // return file system
+            return provider.getFileSystem(URI.create("file:///"));
+        }
+
+        // returns default provider
+        private static FileSystemProvider getDefaultProvider() {
+            FileSystemProvider provider = sun.nio.fs.DefaultFileSystemProvider.create();
+
+            // if the property java.nio.file.spi.DefaultFileSystemProvider is
+            // set then its value is the name of the default provider (or a list)
+            String propValue = System
+                .getProperty("java.nio.file.spi.DefaultFileSystemProvider");
+            if (propValue != null) {
+                for (String cn: propValue.split(",")) {
+                    try {
+                        Class<?> c = Class
+                            .forName(cn, true, ClassLoader.getSystemClassLoader());
+                        Constructor<?> ctor = c
+                            .getDeclaredConstructor(FileSystemProvider.class);
+                        provider = (FileSystemProvider)ctor.newInstance(provider);
+
+                        // must be "file"
+                        if (!provider.getScheme().equals("file"))
+                            throw new Error("Default provider must use scheme 'file'");
+
+                    } catch (Exception x) {
+                        throw new Error(x);
+                    }
+                }
+            }
+            return provider;
+        }
+    }
+
+    /**
+     * Returns the default {@code FileSystem}. The default file system creates
+     * objects that provide access to the file systems accessible to the Java
+     * virtual machine. The <em>working directory</em> of the file system is
+     * the current user directory, named by the system property {@code user.dir}.
+     * This allows for interoperability with the {@link java.io.File java.io.File}
+     * class.
+     *
+     * <p> The first invocation of any of the methods defined by this class
+     * locates the default {@link FileSystemProvider provider} object. Where the
+     * system property {@code java.nio.file.spi.DefaultFileSystemProvider} is
+     * not defined then the default provider is a system-default provider that
+     * is invoked to create the default file system.
+     *
+     * <p> If the system property {@code java.nio.file.spi.DefaultFileSystemProvider}
+     * is defined then it is taken to be a list of one or more fully-qualified
+     * names of concrete provider classes identified by the URI scheme
+     * {@code "file"}. Where the property is a list of more than one name then
+     * the names are separated by a comma. Each class is loaded, using the system
+     * class loader, and instantiated by invoking a one argument constructor
+     * whose formal parameter type is {@code FileSystemProvider}. The providers
+     * are loaded and instantiated in the order they are listed in the property.
+     * If this process fails or a provider's scheme is not equal to {@code "file"}
+     * then an unspecified error is thrown. URI schemes are normally compared
+     * without regard to case but for the default provider, the scheme is
+     * required to be {@code "file"}. The first provider class is instantiated
+     * by invoking it with a reference to the system-default provider.
+     * The second provider class is instantiated by invoking it with a reference
+     * to the first provider instance. The third provider class is instantiated
+     * by invoking it with a reference to the second instance, and so on. The
+     * last provider to be instantiated becomes the default provider; its {@code
+     * getFileSystem} method is invoked with the URI {@code "file:///"} to create
+     * the default file system.
+     *
+     * <p> Subsequent invocations of this method return the file system that was
+     * returned by the first invocation.
+     *
+     * @return  the default file system
+     */
+    public static FileSystem getDefault() {
+        return LazyInitialization.defaultFileSystem;
+    }
+
+    /**
+     * Returns a reference to an existing {@code FileSystem}.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers to locate the provider that is identified by the URI
+     * {@link URI#getScheme scheme} of the given URI. URI schemes are compared
+     * without regard to case. The exact form of the URI is highly provider
+     * dependent. If found, the provider's {@link FileSystemProvider#getFileSystem
+     * getFileSystem} method is invoked to obtain a reference to the {@code
+     * FileSystem}.
+     *
+     * <p> Once a file system created by this provider is {@link FileSystem#close
+     * closed} it is provider-dependent if this method returns a reference to
+     * the closed file system or throws {@link FileSystemNotFoundException}.
+     * If the provider allows a new file system to be created with the same URI
+     * as a file system it previously created then this method throws the
+     * exception if invoked after the file system is closed (and before a new
+     * instance is created by the {@link #newFileSystem newFileSystem} method).
+     *
+     * <p> If a security manager is installed then a provider implementation
+     * may require to check a permission before returning a reference to an
+     * existing file system. In the case of the {@link FileSystems#getDefault
+     * default} file system, no permission check is required.
+     *
+     * @throws  IllegalArgumentException
+     *          If the pre-conditions for the {@code uri} parameter aren't met
+     * @throws  FileSystemNotFoundException
+     *          If the file system, identified by the URI, does not exist
+     * @throws  ProviderNotFoundException
+     *          If a provider supporting the URI scheme is not installed
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission.
+     */
+    public static FileSystem getFileSystem(URI uri) {
+        String scheme = uri.getScheme();
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (scheme.equalsIgnoreCase(provider.getScheme())) {
+                return provider.getFileSystem(uri);
+            }
+        }
+        throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found");
+    }
+
+    /**
+     * Constructs a new file system that is identified by a {@link URI}
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers to locate the provider that is identified by the URI
+     * {@link URI#getScheme scheme} of the given URI. URI schemes are compared
+     * without regard to case. The exact form of the URI is highly provider
+     * dependent. If found, the provider's {@link FileSystemProvider#newFileSystem(URI,Map)
+     * newFileSystem(URI,Map)} method is invoked to construct the new file system.
+     *
+     * <p> Once a file system is {@link FileSystem#close closed} it is
+     * provider-dependent if the provider allows a new file system to be created
+     * with the same URI as a file system it previously created.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose there is a provider identified by the scheme {@code "memory"}
+     * installed:
+     * <pre>
+     *   Map&lt;String,String&gt; env = new HashMap&lt;String,String&gt;();
+     *   env.put("capacity", "16G");
+     *   env.put("blockSize", "4k");
+     *   FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env);
+     * </pre>
+     *
+     * @param   uri
+     *          The URI identifying the file system
+     * @param   env
+     *          A map of provider specific properties to configure the file system;
+     *          may be empty
+     *
+     * @return  A new file system
+     *
+     * @throws  IllegalArgumentException
+     *          If the pre-conditions for the {@code uri} parameter aren't met,
+     *          or the {@code env} parameter does not contain properties required
+     *          by the provider, or a property value is invalid
+     * @throws  FileSystemAlreadyExistsException
+     *          If the file system has already been created
+     * @throws  ProviderNotFoundException
+     *          If a provider supporting the URI scheme is not installed
+     * @throws  IOException
+     *          An I/O error occurs creating the file system
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission required by the file system provider implementation
+     */
+    public static FileSystem newFileSystem(URI uri, Map<String,?> env)
+        throws IOException
+    {
+        return newFileSystem(uri, env, null);
+    }
+
+    /**
+     * Constructs a new file system that is identified by a {@link URI}
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)}
+     * method. If none of the installed providers support the URI scheme then an
+     * attempt is made to locate the provider using the given class loader. If a
+     * provider supporting the URI scheme is located then its {@link
+     * FileSystemProvider#newFileSystem(URI,Map) newFileSystem(URI,Map)} is
+     * invoked to construct the new file system.
+     *
+     * @param   uri
+     *          The URI identifying the file system
+     * @param   env
+     *          A map of provider specific properties to configure the file system;
+     *          may be empty
+     * @param   loader
+     *          The class loader to locate the provider or {@code null} to only
+     *          attempt to locate an installed provider
+     *
+     * @return  A new file system
+     *
+     * @throws  IllegalArgumentException
+     *          If the pre-conditions for the {@code uri} parameter aren't met,
+     *          or the {@code env} parameter does not contain properties required
+     *          by the provider, or a property value is invalid
+     * @throws  FileSystemAlreadyExistsException
+     *          If the URI scheme identifies an installed provider and the file
+     *          system has already been created
+     * @throws  ProviderNotFoundException
+     *          If a provider supporting the URI scheme is not found
+     * @throws  ServiceConfigurationError
+     *          When an error occurs while loading a service provider
+     * @throws  IOException
+     *          An I/O error occurs creating the file system
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission required by the file system provider implementation
+     */
+    public static FileSystem newFileSystem(URI uri, Map<String,?> env, ClassLoader loader)
+        throws IOException
+    {
+        String scheme = uri.getScheme();
+
+        // check installed providers
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (scheme.equalsIgnoreCase(provider.getScheme())) {
+                return provider.newFileSystem(uri, env);
+            }
+        }
+
+        // if not found, use service-provider loading facility
+        if (loader != null) {
+            ServiceLoader<FileSystemProvider> sl = ServiceLoader
+                .load(FileSystemProvider.class, loader);
+            for (FileSystemProvider provider: sl) {
+                if (scheme.equalsIgnoreCase(provider.getScheme())) {
+                    return provider.newFileSystem(uri, env);
+                }
+            }
+        }
+
+        throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found");
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system. The {@code file} parameter is a reference to an existing file
+     * and the {@code env} parameter is a map of provider specific properties to
+     * configure the file system.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers. It invokes, in turn, each provider's {@link
+     * FileSystemProvider#newFileSystem(FileRef,Map) newFileSystem(FileRef,Map)} method.
+     * If a provider returns a file system then the iteration terminates
+     * and the file system is returned. If none of the installed providers return
+     * a {@code FileSystem} then an attempt is made to locate the provider using
+     * the given class loader. If a provider returns a file system then the lookup
+     * terminates and the file system is returned.
+     *
+     * @param   file
+     *          A reference to a file
+     * @param   env
+     *          A map of provider specific properties to configure the file system;
+     *          may be empty
+     * @param   loader
+     *          The class loader to locate the provider or {@code null} to only
+     *          attempt to locate an installed provider
+     *
+     * @return  A new file system
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code env} parameter does not contain properties required
+     *          by the provider, or a property value is invalid
+     * @throws  ProviderNotFoundException
+     *          If a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          When an error occurs while loading a service provider
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission.
+     */
+    public static FileSystem newFileSystem(FileRef file,
+                                           Map<String,?> env,
+                                           ClassLoader loader)
+        throws IOException
+    {
+        if (file == null)
+            throw new NullPointerException();
+
+        // check installed providers
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            try {
+                return provider.newFileSystem(file, env);
+            } catch (UnsupportedOperationException uoe) {
+            }
+        }
+
+        // if not found, use service-provider loading facility
+        if (loader != null) {
+            ServiceLoader<FileSystemProvider> sl = ServiceLoader
+                .load(FileSystemProvider.class, loader);
+            for (FileSystemProvider provider: sl) {
+                try {
+                    return provider.newFileSystem(file, env);
+                } catch (UnsupportedOperationException uoe) {
+                }
+            }
+        }
+
+        throw new ProviderNotFoundException("Provider not found");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileTreeWalker.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Simple file tree walker that works in a similar manner to nftw(3C).
+ *
+ * @see Files#walkFileTree
+ */
+
+class FileTreeWalker {
+    private final boolean followLinks;
+    private final boolean detectCycles;
+    private final LinkOption[] linkOptions;
+    private final FileVisitor<? super Path> visitor;
+
+    FileTreeWalker(Set<FileVisitOption> options, FileVisitor<? super Path> visitor) {
+        boolean fl = false;
+        boolean dc = false;
+        for (FileVisitOption option: options) {
+            switch (option) {
+                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");
+            }
+        }
+        this.followLinks = fl;
+        this.detectCycles = fl | dc;
+        this.linkOptions = (fl) ? new LinkOption[0] :
+            new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
+        this.visitor = visitor;
+    }
+
+    /**
+     * Walk file tree starting at the given file
+     */
+    void walk(Path start, int maxDepth) {
+        FileVisitResult result = walk(start,
+                                      maxDepth,
+                                      new ArrayList<AncestorDirectory>());
+        if (result == null) {
+            throw new NullPointerException("Visitor returned 'null'");
+        }
+    }
+
+    /**
+     * @param   file
+     *          The directory to visit
+     * @param   path
+     *          list of directories that is relative path from starting file
+     * @param   depth
+     *          Depth remaining
+     * @param   ancestors
+     *          use when cycle detection is enabled
+     */
+    private FileVisitResult walk(Path file,
+                                 int depth,
+                                 List<AncestorDirectory> ancestors)
+    {
+        // depth check
+        if (depth-- < 0)
+            return FileVisitResult.CONTINUE;
+
+        BasicFileAttributes attrs = null;
+        IOException exc = null;
+
+        // attempt to get attributes of file. If fails and we are following
+        // links then a link target might not exist so get attributes of link
+        try {
+            try {
+                attrs = Attributes.readBasicFileAttributes(file, linkOptions);
+            } catch (IOException x1) {
+                if (followLinks) {
+                    try {
+                        attrs = Attributes
+                            .readBasicFileAttributes(file, LinkOption.NOFOLLOW_LINKS);
+                    } catch (IOException x2) {
+                        exc = x2;
+                    }
+                } else {
+                    exc = x1;
+                }
+            }
+        } catch (SecurityException x) {
+            return FileVisitResult.CONTINUE;
+        }
+
+        // unable to get attributes of file
+        if (exc != null) {
+            return visitor.visitFileFailed(file, exc);
+        }
+
+        // file is not a directory so invoke visitFile method
+        if (!attrs.isDirectory()) {
+            return visitor.visitFile(file, attrs);
+        }
+
+        // check for cycles
+        if (detectCycles) {
+            Object key = attrs.fileKey();
+
+            // if this directory and ancestor has a file key then we compare
+            // them; otherwise we use less efficient isSameFile test.
+            for (AncestorDirectory ancestor: ancestors) {
+                Object ancestorKey = ancestor.fileKey();
+                if (key != null && ancestorKey != null) {
+                    if (key.equals(ancestorKey)) {
+                        // cycle detected
+                        return visitor.visitFile(file, attrs);
+                    }
+                } else {
+                    try {
+                        if (file.isSameFile(ancestor.file())) {
+                            // cycle detected
+                            return visitor.visitFile(file, attrs);
+                        }
+                    } catch (IOException x) {
+                        // ignore
+                    } catch (SecurityException x) {
+                        // ignore
+                    }
+                }
+            }
+
+            ancestors.add(new AncestorDirectory(file, key));
+        }
+
+        // visit directory
+        try {
+            DirectoryStream<Path> stream = null;
+            FileVisitResult result;
+
+            // open the directory
+            try {
+                stream = file.newDirectoryStream();
+            } catch (IOException x) {
+                return visitor.preVisitDirectoryFailed(file, x);
+            } catch (SecurityException x) {
+                // ignore, as per spec
+                return FileVisitResult.CONTINUE;
+            }
+
+            // the exception notified to the postVisitDirectory method
+            IOException ioe = null;
+
+            // invoke preVisitDirectory and then visit each entry
+            try {
+                result = visitor.preVisitDirectory(file);
+                if (result != FileVisitResult.CONTINUE) {
+                    return result;
+                }
+
+                // if an I/O occurs during iteration then a CME is thrown. We
+                // need to distinguish this from a CME thrown by the visitor.
+                boolean inAction = false;
+
+                try {
+                    for (Path entry: stream) {
+                        inAction = true;
+                        result = walk(entry, depth, ancestors);
+                        inAction = false;
+
+                        // returning null will cause NPE to be thrown
+                        if (result == null || result == FileVisitResult.TERMINATE)
+                            return result;
+
+                        // skip remaining siblings in this directory
+                        if (result == FileVisitResult.SKIP_SIBLINGS)
+                            break;
+                    }
+                } catch (ConcurrentModificationException x) {
+                    // if CME thrown because the iteration failed then remember
+                    // the IOException so that it is notified to postVisitDirectory
+                    if (!inAction) {
+                        // iteration failed
+                        Throwable t = x.getCause();
+                        if (t instanceof IOException)
+                            ioe = (IOException)t;
+                    }
+                    if (ioe == null)
+                        throw x;
+                }
+            } finally {
+                try {
+                    stream.close();
+                } catch (IOException x) { }
+            }
+
+            // invoke postVisitDirectory last
+            return visitor.postVisitDirectory(file, ioe);
+
+        } finally {
+            // remove key from trail if doing cycle detection
+            if (detectCycles) {
+                ancestors.remove(ancestors.size()-1);
+            }
+        }
+    }
+
+    private static class AncestorDirectory {
+        private final FileRef dir;
+        private final Object key;
+        AncestorDirectory(FileRef dir, Object key) {
+            this.dir = dir;
+            this.key = key;
+        }
+        FileRef file() {
+            return dir;
+        }
+        Object fileKey() {
+            return key;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Defines the file tree traversal options.
+ *
+ * @since 1.7
+ *
+ * @see Files#walkFileTree
+ */
+
+public enum FileVisitOption {
+    /**
+     * Follow symbolic links.
+     */
+    FOLLOW_LINKS,
+    /**
+     * Detect cycles in the file tree.
+     */
+    DETECT_CYCLES;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitResult.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * The result type of a {@link FileVisitor FileVisitor}.
+ *
+ * @since 1.7
+ *
+ * @see Files#walkFileTree
+ */
+
+public enum FileVisitResult {
+    /**
+     * Continue. When returned from a {@link FileVisitor#preVisitDirectory
+     * preVisitDirectory} method then the entries in the directory should also
+     * be visited.
+     */
+    CONTINUE,
+    /**
+     * Terminate.
+     */
+    TERMINATE,
+    /**
+     * Continue without visiting the entries in this directory. This result
+     * is only meaningful when returned from the {@link
+     * FileVisitor#preVisitDirectory preVisitDirectory} method; otherwise
+     * this result type is the same as returning {@link #CONTINUE}.
+     */
+    SKIP_SUBTREE,
+    /**
+     * Continue without visiting the <em>siblings</em> of this file or directory.
+     * If returned from the {@link FileVisitor#preVisitDirectory
+     * preVisitDirectory} method then the entries in the directory are also
+     * skipped and the {@link FileVisitor#postVisitDirectory postVisitDirectory}
+     * method is not invoked.
+     */
+    SKIP_SIBLINGS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/FileVisitor.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.io.IOException;
+
+/**
+ * A visitor of files. An implementation of this interface is provided to the
+ * {@link Files#walkFileTree walkFileTree} utility method to visit each file
+ * in a tree.
+ *
+ * <p> <b>Usage Examples:</b>
+ * Suppose we want to delete a file tree. In that case, each directory should
+ * be deleted after the entries in the directory are deleted.
+ * <pre>
+ *     Path start = ...
+ *     Files.walkFileTree(start, new SimpleFileVisitor&lt;Path&gt;() {
+ *         &#64;Override
+ *         public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+ *             try {
+ *                 file.delete(false);
+ *             } catch (IOException exc) {
+ *                 // failed to delete
+ *             }
+ *             return FileVisitResult.CONTINUE;
+ *         }
+ *         &#64;Override
+ *         public FileVisitResult postVisitDirectory(Path dir, IOException e) {
+ *             if (e == null) {
+ *                 try {
+ *                     dir.delete(false);
+ *                 } catch (IOException exc) {
+ *                     // failed to delete
+ *                 }
+ *             } else {
+ *                 // directory iteration failed
+ *             }
+ *             return FileVisitResult.CONTINUE;
+ *         }
+ *     });
+ * </pre>
+ * <p> Furthermore, suppose we want to copy a file tree rooted at a source
+ * directory to a target location. In that case, symbolic links should be
+ * followed and the target directory should be created before the entries in
+ * the directory are copied.
+ * <pre>
+ *     final Path source = ...
+ *     final Path target = ...
+ *
+ *     Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
+ *         new SimpleFileVisitor&lt;Path&gt;() {
+ *             &#64;Override
+ *             public FileVisitResult preVisitDirectory(Path dir) {
+ *                 try {
+ *                     dir.copyTo(target.resolve(source.relativize(dir)));
+ *                 } catch (FileAlreadyExistsException e) {
+ *                      // ignore
+ *                 } catch (IOException e) {
+ *                     // copy failed, skip rest of directory and descendants
+ *                     return SKIP_SUBTREE;
+ *                 }
+ *                 return CONTINUE;
+ *             }
+ *             &#64;Override
+ *             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+ *                 try {
+ *                     file.copyTo(target.resolve(source.relativize(file)));
+ *                 } catch (IOException e) {
+ *                     // copy failed
+ *                 }
+ *                 return CONTINUE;
+ *             }
+ *         });
+ * </pre>
+ *
+ * @since 1.7
+ */
+
+public interface FileVisitor<T extends FileRef> {
+
+    /**
+     * Invoked for a directory before entries in the directory are visited.
+     *
+     * <p> If this method returns {@link FileVisitResult#CONTINUE CONTINUE},
+     * then entries in the directory are visited. If this method returns {@link
+     * FileVisitResult#SKIP_SUBTREE SKIP_SUBTREE} or {@link
+     * FileVisitResult#SKIP_SIBLINGS SKIP_SIBLINGS} then entries in the
+     * directory (and any descendants) will not be visited.
+     *
+     * @param   dir
+     *          A reference to the directory
+     *
+     * @return  the visit result
+     */
+    FileVisitResult preVisitDirectory(T dir);
+
+    /**
+     * Invoked for a directory that could not be opened.
+     *
+     * @param   dir
+     *          A reference to the directory
+     * @param   exc
+     *          The I/O exception thrown from the attempt to open the directory
+     *
+     * @return  the visit result
+     */
+    FileVisitResult preVisitDirectoryFailed(T dir, IOException exc);
+
+    /**
+     * Invoked for a file in a directory.
+     *
+     * @param   file
+     *          A reference to the file
+     * @param   attrs
+     *          The file's basic attributes
+     *
+     * @return  the visit result
+     */
+    FileVisitResult visitFile(T file, BasicFileAttributes attrs);
+
+    /**
+     * Invoked for a file when its basic file attributes could not be read.
+     *
+     * @param   file
+     *          A reference to the file
+     * @param   exc
+     *          The I/O exception thrown from the attempt to read the file
+     *          attributes
+     *
+     * @return  the visit result
+     */
+    FileVisitResult visitFileFailed(T file, IOException exc);
+
+    /**
+     * Invoked for a directory after entries in the directory, and all of their
+     * descendants, have been visited. This method is also invoked when iteration
+     * of the directory completes prematurely (by a {@link #visitFile visitFile}
+     * method returning {@link FileVisitResult#SKIP_SIBLINGS SKIP_SIBLINGS},
+     * or an I/O error when iterating over the directory).
+     *
+     * @param   dir
+     *          A reference to the directory
+     * @param   exc
+     *          {@code null} if the iteration of the directory completes without
+     *          an error; otherwise the I/O exception that caused the iteration
+     *          of the directory to complete prematurely
+     *
+     * @return  the visit result
+     */
+    FileVisitResult postVisitDirectory(T dir, IOException exc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Files.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,404 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.spi.FileTypeDetector;
+import java.io.IOException;
+import java.util.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Utility methods for files and directories.
+ *
+ * @since 1.7
+ */
+
+public final class Files {
+    private Files() { }
+
+    // lazy loading of default and installed file type detectors
+    private static class LazyInitialization {
+        static final FileTypeDetector defaultFileTypeDetector =
+            sun.nio.fs.DefaultFileTypeDetector.create();
+        static final List<FileTypeDetector> installeDetectors =
+            loadInstalledDetectors();
+
+        // loads all installed file type detectors
+        private static List<FileTypeDetector> loadInstalledDetectors() {
+            return AccessController
+                .doPrivileged(new PrivilegedAction<List<FileTypeDetector>>() {
+ public List<FileTypeDetector> run() {
+                        List<FileTypeDetector> list = new ArrayList<FileTypeDetector>();
+                        ServiceLoader<FileTypeDetector> loader = ServiceLoader
+                            .load(FileTypeDetector.class, ClassLoader.getSystemClassLoader());
+                        for (FileTypeDetector detector: loader) {
+                            list.add(detector);
+                        }
+                        return list;
+                }});
+        }
+    }
+
+    /**
+     * Probes the content type of a file.
+     *
+     * <p> This method uses the installed {@link FileTypeDetector} implementations
+     * to probe the given file to determine its content type. Each file type
+     * detector's {@link FileTypeDetector#probeContentType probeContentType} is
+     * invoked, in turn, to probe the file type. If the file is recognized then
+     * the content type is returned. If the file is not recognized by any of the
+     * installed file type detectors then a system-default file type detector is
+     * invoked to guess the content type.
+     *
+     * <p> A given invocation of the Java virtual machine maintains a system-wide
+     * list of file type detectors. Installed file type detectors are loaded
+     * using the service-provider loading facility defined by the {@link ServiceLoader}
+     * class. Installed file type detectors are loaded using the system class
+     * loader. If the system class loader cannot be found then the extension class
+     * loader is used; If the extension class loader cannot be found then the
+     * bootstrap class loader is used. File type detectors are typically installed
+     * by placing them in a JAR file on the application class path or in the
+     * extension directory, the JAR file contains a provider-configuration file
+     * named {@code java.nio.file.spi.FileTypeDetector} in the resource directory
+     * {@code META-INF/services}, and the file lists one or more fully-qualified
+     * names of concrete subclass of {@code FileTypeDetector } that have a zero
+     * argument constructor. If the process of locating or instantiating the
+     * installed file type detectors fails then an unspecified error is thrown.
+     * The ordering that installed providers are located is implementation
+     * specific.
+     *
+     * <p> The return value of this method is the string form of 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>. The string is guaranteed to be parsable according
+     * to the grammar in the RFC.
+     *
+     * @param   file
+     *          The file reference
+     *
+     * @return  The content type of the file, or {@code null} if the content
+     *          type cannot be determined
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @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
+    {
+        // try installed file type detectors
+        for (FileTypeDetector detector: LazyInitialization.installeDetectors) {
+            String result = detector.probeContentType(file);
+            if (result != null)
+                return result;
+        }
+
+        // fallback to default
+        return LazyInitialization.defaultFileTypeDetector.probeContentType(file);
+    }
+
+    /**
+     * Invokes a {@link FileAction} for each entry in a directory accepted
+     * by a given {@link java.nio.file.DirectoryStream.Filter filter}.
+     *
+     * <p> This method opens the given directory and invokes the file action's
+     * {@link FileAction#invoke invoke} method for each entry accepted by the
+     * filter. When iteration is completed then the directory is closed. If the
+     * {@link DirectoryStream#close close} method throws an {@code IOException}
+     * then it is silently ignored.
+     *
+     * <p> If the {@code FileAction}'s {@code invoke} method terminates due
+     * to an uncaught {@link IOException}, {@code Error} or {@code RuntimeException}
+     * then the exception is propagated by this method after closing the
+     * directory.
+     *
+     * @param   dir
+     *          The directory
+     * @param   filter
+     *          The filter, or {@code null} to accept all entries
+     * @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#getNameMatcher getNameMatcher} 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
+    {
+        final PathMatcher matcher = dir.getFileSystem().getNameMatcher("glob", glob);
+        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
+
+            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
+     * file tree traversal is <em>depth-first</em> with the given {@link
+     * FileVisitor} invoked for each file encountered. File tree traversal
+     * completes when all accessible files in the tree have been visited, a
+     * visitor returns a result of {@link FileVisitResult#TERMINATE TERMINATE},
+     * or the visitor terminates due to an uncaught {@code Error} or {@code
+     * RuntimeException}.
+     *
+     * <p> For each file encountered this method attempts to gets its {@link
+     * java.nio.file.attribute.BasicFileAttributes}. If the file is not a
+     * directory then the {@link FileVisitor#visitFile visitFile} method is
+     * invoked with the file attributes. If the file attributes cannot be read,
+     * due to an I/O exception, then the {@link FileVisitor#visitFileFailed
+     * visitFileFailed} method is invoked with the I/O exception.
+     *
+     * <p> Where the file is a directory, this method attempts to open it by
+     * invoking its {@link Path#newDirectoryStream newDirectoryStream} method.
+     * Where the directory could not be opened, due to an {@code IOException},
+     * then the {@link FileVisitor#preVisitDirectoryFailed preVisitDirectoryFailed}
+     * method is invoked with the I/O exception, after which, the file tree walk
+     * continues, by default, at the next <em>sibling</em> of the directory.
+     *
+     * <p> Where the directory is opened successfully, then the entries in the
+     * directory, and their <em>descendants</em> are visited. When all entries
+     * have been visited, or an I/O error occurs during iteration of the
+     * directory, then the directory is closed and the visitor's {@link
+     * FileVisitor#postVisitDirectory postVisitDirectory} method is invoked.
+     * The file tree walk then continues, by default, at the next <em>sibling</em>
+     * of the directory.
+     *
+     * <p> By default, symbolic links are not automatically followed by this
+     * method. If the {@code options} parameter contains the {@link
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
+     * followed. When following links, and the attributes of the target cannot
+     * be read, then this method attempts to get the {@code BasicFileAttributes}
+     * of the link. If they can be read then the {@code visitFile} method is
+     * invoked with the attributes of the link (otherwise the {@code visitFileFailed}
+     * method is invoked as specified above).
+     *
+     * <p> If the {@code options} parameter contains the {@link
+     * FileVisitOption#DETECT_CYCLES DETECT_CYCLES} or {@link
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} options then this method keeps
+     * track of directories visited so that cycles can be detected. A cycle
+     * 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
+     * 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
+     * java.nio.file.attribute.BasicFileAttributes#isDirectory isDirectory}
+     * method may be used to test if the file is a directory and that a cycle is
+     * detected. The {@code preVisitDirectory} and {@code postVisitDirectory}
+     * methods are not invoked.
+     *
+     * <p> The {@code maxDepth} parameter is the maximum number of levels of
+     * directories to visit. A value of {@code 0} means that only the starting
+     * file is visited, unless denied by the security manager. A value of
+     * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
+     * levels should be visited.
+     *
+     * <p> If a visitor returns a result of {@code null} then {@code
+     * NullPointerException} is thrown.
+     *
+     * <p> When a security manager is installed and it denies access to a file
+     * (or directory), then it is ignored and the visitor is not invoked for
+     * that file (or directory).
+     *
+     * @param   start
+     *          The starting file
+     * @param   options
+     *          Options to configure the traversal
+     * @param   maxDepth
+     *          The maximum number of directory levels to visit
+     * @param   visitor
+     *          The file visitor to invoke for each file
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code maxDepth} parameter is negative
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          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 walkFileTree(Path start,
+                                    Set<FileVisitOption> options,
+                                    int maxDepth,
+                                    FileVisitor<? super Path> visitor)
+    {
+        if (maxDepth < 0)
+            throw new IllegalArgumentException("'maxDepth' is negative");
+        new FileTreeWalker(options, visitor).walk(start, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Walks a file tree.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <blockquote><pre>
+     * walkFileTree(start, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, visitor)
+     * </pre></blockquote>
+     *
+     * @param   start
+     *          The starting file
+     * @param   visitor
+     *          The file visitor to invoke for each file
+     *
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          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 walkFileTree(Path start, FileVisitor<? super Path> visitor) {
+        walkFileTree(start,
+                     EnumSet.noneOf(FileVisitOption.class),
+                     Integer.MAX_VALUE,
+                     visitor);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/InvalidPathException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Unchecked exception thrown when path string cannot be converted into a
+ * {@link Path} because the path string contains invalid characters, or
+ * the path string is invalid for other file system specific reasons.
+ */
+
+public class InvalidPathException
+    extends IllegalArgumentException
+{
+    static final long serialVersionUID = 4355821422286746137L;
+
+    private String input;
+    private int index;
+
+    /**
+     * Constructs an instance from the given input string, reason, and error
+     * index.
+     *
+     * @param  input   The input string
+     * @param  reason  A string explaining why the input was rejected
+     * @param  index   The index at which the error occurred,
+     *                 or <tt>-1</tt> if the index is not known
+     *
+     * @throws  NullPointerException
+     *          If either the input or reason strings are <tt>null</tt>
+     *
+     * @throws  IllegalArgumentException
+     *          If the error index is less than <tt>-1</tt>
+     */
+    public InvalidPathException(String input, String reason, int index) {
+        super(reason);
+        if ((input == null) || (reason == null))
+            throw new NullPointerException();
+        if (index < -1)
+            throw new IllegalArgumentException();
+        this.input = input;
+        this.index = index;
+    }
+
+    /**
+     * Constructs an instance from the given input string and reason.  The
+     * resulting object will have an error index of <tt>-1</tt>.
+     *
+     * @param  input   The input string
+     * @param  reason  A string explaining why the input was rejected
+     *
+     * @throws  NullPointerException
+     *          If either the input or reason strings are <tt>null</tt>
+     */
+    public InvalidPathException(String input, String reason) {
+        this(input, reason, -1);
+    }
+
+    /**
+     * Returns the input string.
+     *
+     * @return  The input string
+     */
+    public String getInput() {
+        return input;
+    }
+
+    /**
+     * Returns a string explaining why the input string was rejected.
+     *
+     * @return  The reason string
+     */
+    public String getReason() {
+        return super.getMessage();
+    }
+
+    /**
+     * Returns an index into the input string of the position at which the
+     * error occurred, or <tt>-1</tt> if this position is not known.
+     *
+     * @return  The error index
+     */
+    public int getIndex() {
+        return index;
+    }
+
+    /**
+     * Returns a string describing the error.  The resulting string
+     * consists of the reason string followed by a colon character
+     * (<tt>':'</tt>), a space, and the input string.  If the error index is
+     * defined then the string <tt>" at index "</tt> followed by the index, in
+     * decimal, is inserted after the reason string and before the colon
+     * character.
+     *
+     * @return  A string describing the error
+     */
+    public String getMessage() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(getReason());
+        if (index > -1) {
+            sb.append(" at index ");
+            sb.append(index);
+        }
+        sb.append(": ");
+        sb.append(input);
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Defines the options as to how symbolic links are handled.
+ *
+ * @since 1.7
+ */
+
+public enum LinkOption implements OpenOption, CopyOption {
+    /**
+     * Do not follow symbolic links.
+     *
+     * @see FileRef#getFileAttributeView(Class,LinkOption[])
+     * @see Path#copyTo
+     * @see SecureDirectoryStream#newByteChannel
+     */
+    NOFOLLOW_LINKS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/LinkPermission.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.security.BasicPermission;
+
+/**
+ * The {@code Permission} class for link creation operations.
+ *
+ * <p> The following table provides a summary description of what the permission
+ * allows, and discusses the risks of granting code the permission.
+ *
+ * <table border=1 cellpadding=5
+ *        summary="Table shows permission target name, what the permission allows, and associated risks">
+ * <tr>
+ * <th>Permission Target Name</th>
+ * <th>What the Permission Allows</th>
+ * <th>Risks of Allowing this Permission</th>
+ * </tr>
+ * <tr>
+ *   <td>hard</td>
+ *   <td> Ability to add an existing file to a directory. This is sometimes
+ *   known as creating a link, or hard link. </td>
+ *   <td> Extreme care should be taken when granting this permission. It allows
+ *   linking to any file or directory in the file system thus allowing the
+ *   attacker to access to all files. </td>
+ * </tr>
+ * <tr>
+ *   <td>symbolic</td>
+ *   <td> Ability to create symbolic links. </td>
+ *   <td> Extreme care should be taken when granting this permission. It allows
+ *   linking to any file or directory in the file system thus allowing the
+ *   attacker to access to all files. </td>
+ * </tr>
+ * </table>
+ *
+ * @since 1.7
+ *
+ * @see Path#createLink
+ * @see Path#createSymbolicLink
+ */
+public final class LinkPermission extends BasicPermission {
+    static final long serialVersionUID = -1441492453772213220L;
+
+    private void checkName(String name) {
+        if (!name.equals("hard") && !name.equals("symbolic")) {
+            throw new IllegalArgumentException("name: " + name);
+        }
+    }
+
+    /**
+     * Constructs a {@code LinkPermission} with the specified name.
+     *
+     * @param   name
+     *          The name of the permission. It must be "hard" or "symbolic".
+     *
+     * @throws  IllegalArgumentException
+     *          If name is empty or invalid.
+     */
+    public LinkPermission(String name) {
+        super(name);
+        checkName(name);
+    }
+
+    /**
+     * Constructs a {@code LinkPermission} with the specified name.
+     *
+     * @param   name
+     *          The name of the permission; must be "hard" or "symbolic".
+     * @param   actions
+     *          The actions for the permission; must be the empty string or
+     *          {@code null}
+     *
+     * @throws  IllegalArgumentException
+     *          If name is empty or invalid.
+     */
+    public LinkPermission(String name, String actions) {
+        super(name);
+        checkName(name);
+        if (actions != null && actions.length() > 0) {
+            throw new IllegalArgumentException("actions: " + actions);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NoSuchFileException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when an attempt is made to access a file that does
+ * not exist.
+ *
+ * @since 1.7
+ */
+
+public class NoSuchFileException
+    extends FileSystemException
+{
+    static final long serialVersionUID = -1390291775875351931L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     */
+    public NoSuchFileException(String file) {
+        super(file);
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     * @param   other
+     *          A string identifying the other file or {@code null} if not known.
+     * @param   reason
+     *          A reason message with additional information or {@code null}
+     */
+    public NoSuchFileException(String file, String other, String reason) {
+        super(file, other, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotDirectoryException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when a file system operation, intended for a
+ * directory, fails because the file is not a directory.
+ *
+ * @since 1.7
+ */
+
+public class NotDirectoryException
+    extends FileSystemException
+{
+    private static final long serialVersionUID = -9011457427178200199L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     */
+    public NotDirectoryException(String file) {
+        super(file);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/NotLinkException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Checked exception thrown when a file system operation fails because a file
+ * is not a link.
+ *
+ * @since 1.7
+ */
+
+public class NotLinkException
+    extends FileSystemException
+{
+    static final long serialVersionUID = -388655596416518021L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     */
+    public NotLinkException(String file) {
+        super(file);
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          A string identifying the file or {@code null} if not known.
+     * @param   other
+     *          A string identifying the other file or {@code null} if not known.
+     * @param   reason
+     *          A reason message with additional information or {@code null}
+     */
+    public NotLinkException(String file, String other, String reason) {
+        super(file, other, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/OpenOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * An object that configures how to open or create a file.
+ *
+ * <p> Objects of this type are used by methods such as {@link
+ * Path#newOutputStream(OpenOption[]) newOutputStream}, {@link
+ * FileRef#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.
+ *
+ * <p> The {@link StandardOpenOption} enumeration type defines the
+ * <i>standard</i> options.
+ *
+ * @since 1.7
+ */
+
+public interface OpenOption {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Path.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1573 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.channels.*;
+import java.io.*;
+import java.net.URI;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+
+/**
+ * A file reference that locates a file using a system dependent path. The file
+ * is not required to exist.
+ *
+ * <p> On many platforms a <em>path</em> is the means to locate and access files
+ * in a file system. A path is hierarchical and composed of a sequence of
+ * directory names separated by a special separator or delimiter.
+ *
+ * <h4>Path operations</h4>
+ *
+ * <p> A system dependent path represented by this class is conceptually a
+ * sequence of name elements and optionally a <em>root component</em>. The name
+ * that is <em>farthest</em> from the root of the directory hierarchy is the
+ * name of a file or directory. The other elements are directory names. The root
+ * component typically identifies a file system hierarchy. A {@code Path} can
+ * represent a root, a root and a sequence of names, or simply one or more name
+ * elements. It defines the {@link #getName() getName}, {@link #getParent
+ * getParent}, {@link #getRoot getRoot}, and {@link #subpath subpath} methods
+ * to access the components or a subsequence of its name elements.
+ *
+ * <p> In addition to accessing the components of a path, a {@code Path} also
+ * defines {@link #resolve(Path) resolve} and {@link #relativize relativize}
+ * operations. Paths can also be {@link #compareTo compared}, and tested
+ * against each using using the {@link #startsWith startsWith} and {@link
+ * #endsWith endWith} methods.
+ *
+ * <h4>File operations</h4>
+ *
+ * <p> A {@code Path} is either <em>absolute</em> or <em>relative</em>. An
+ * absolute path is complete in that does not need to be combined with another
+ * path in order to locate a file. All operations on relative paths are first
+ * resolved against a file system's default directory as if by invoking the
+ * {@link #toAbsolutePath toAbsolutePath} method.
+ *
+ * <p> In addition to the operations defined by the {@link FileRef} interface,
+ * this class defines the following operations:
+ *
+ * <ul>
+ *   <li><p> Files may be {@link #createFile(FileAttribute[]) created}, or
+ *     directories may be {@link #createDirectory(FileAttribute[]) created}.
+ *     </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>
+ *
+ * <p> This class implements {@link Watchable} interface so that a directory
+ * located by a path can be {@link #register registered} with a {@link WatchService}.
+ * and entries in the directory watched.
+ *
+ * <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 is obtained, in bulk, by
+ * invoking the {@link Attributes#readBasicFileAttributes
+ * Attributes.readBasicFileAttributes} method:
+ * <pre>
+ *     Path file = ...
+ *     BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
+ * </pre>
+ *
+ * <a name="interop"><h4>Interoperability</h4></a>
+ *
+ * <p> Paths created by file systems associated with the default {@link
+ * java.nio.file.spi.FileSystemProvider provider} are generally interoperable
+ * with the {@link java.io.File java.io.File} class. Paths created by other
+ * providers are unlikely to be interoperable with the abstract path names
+ * represented by {@code java.io.File}. The {@link java.io.File#toPath
+ * File.toPath} method may be used to obtain a {@code Path} from the abstract
+ * path name represented by a {@code java.io.File java.io.File} object. The
+ * resulting {@code Path} can be used to operate on the same file as the {@code
+ * java.io.File} object.
+ *
+ * <p> Path objects created by file system's associated with the default
+ * provider are interoperable with objects created by other file systems created
+ * by the same provider. Path objects created by file systems associated with
+ * other providers may not be interoperable with other file systems created by
+ * the same provider. The reasons for this are provider specific.
+ *
+ * <h4>Concurrency</h4></a>
+ *
+ * <p> Instances of this class are immutable and safe for use by multiple concurrent
+ * threads.
+ *
+ * @since 1.7
+ */
+
+public abstract class Path
+    implements FileRef, Comparable<Path>, Iterable<Path>, Watchable
+{
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected Path() { }
+
+    /**
+     * Returns the file system that created this object.
+     *
+     * @return  The file system that created this object
+     */
+    public abstract FileSystem getFileSystem();
+
+    /**
+     * Tells whether or not this path is absolute.
+     *
+     * <p> An absolute path is complete in that it doesn't need to be
+     * combined with other path information in order to locate a file.
+     *
+     * @return  {@code true} if, and only if, this path is absolute
+     */
+    public abstract boolean isAbsolute();
+
+    /**
+     * Returns the root component of this path as a {@code Path} object,
+     * or {@code null} if this path does not have a root component.
+     *
+     * @return  A path representing the root component of this path,
+     *          or {@code null}
+     */
+    public abstract Path getRoot();
+
+    /**
+     * Returns the name of the file or directory denoted by this path. The
+     * file name is the <em>farthest</em> element from the root in the directory
+     * hierarchy.
+     *
+     * @return  A path representing the name of the file or directory, or
+     *          {@code null} if this path has zero elements
+     */
+    public abstract Path getName();
+
+    /**
+     * Returns the <em>parent path</em>, or {@code null} if this path does not
+     * have a parent.
+     *
+     * <p> The parent of this path object consists of this path's root
+     * component, if any, and each element in the path except for the
+     * <em>farthest</em> from the root in the directory hierarchy. This method
+     * does not access the file system; the path or its parent may not exist.
+     * Furthermore, this method does not eliminate special names such as "."
+     * and ".." that may be used in some implementations. On UNIX for example,
+     * the parent of "{@code /a/b/c}" is "{@code /a/b}", and the parent of
+     * {@code "x/y/.}" is "{@code x/y}". This method may be used with the {@link
+     * #normalize normalize} method, to eliminate redundant names, for cases where
+     * <em>shell-like</em> navigation is required.
+     *
+     * <p> If this path has one or more elements, and no root component, then
+     * this method is equivalent to evaluating the expression:
+     * <blockquote><pre>
+     * subpath(0,&nbsp;getNameCount()-1);
+     * </pre></blockquote>
+     *
+     * @return  A path representing the path's parent
+     */
+    public abstract Path getParent();
+
+    /**
+     * Returns the number of name elements in the path.
+     *
+     * @return  The number of elements in the path, or {@code 0} if this path
+     *          only represents a root component
+     */
+    public abstract int getNameCount();
+
+   /**
+     * Returns a name element of this path.
+     *
+     * <p> The {@code index} parameter is the index of the name element to return.
+     * The element that is <em>closest</em> to the root in the directory hierarchy
+     * has index {@code 0}. The element that is <em>farthest</em> from the root
+     * has index {@link #getNameCount count}{@code -1}.
+     *
+     * @param   index
+     *          The index of the element
+     *
+     * @return  The name element
+     *
+     * @throws  IllegalArgumentException
+     *          If {@code index} is negative, {@code index} is greater than or
+     *          equal to the number of elements, or this path has zero name
+     *          elements.
+     */
+    public abstract Path getName(int index);
+
+    /**
+     * Returns a relative {@code Path} that is a subsequence of the name
+     * elements of this path.
+     *
+     * <p> The {@code beginIndex} and {@code endIndex} parameters specify the
+     * subsequence of name elements. The name that is <em>closest</em> to the root
+     * in the directory hierarchy has index {@code 0}. The name that is
+     * <em>farthest</em> from the root has index {@link #getNameCount
+     * count}{@code -1}. The returned {@code Path} object has the name elements
+     * that begin at {@code beginIndex} and extend to the element at index {@code
+     * endIndex-1}.
+     *
+     * @param   beginIndex
+     *          The index of the first element, inclusive
+     * @param   endIndex
+     *          The index of the last element, exclusive
+     *
+     * @return  A new {@code Path} object that is a subsequence of the name
+     *          elements in this {@code Path}
+     *
+     * @throws  IllegalArgumentException
+     *          If {@code beginIndex} is negative, or greater than or equal to
+     *          the number of elements. If {@code endIndex} is less than or
+     *          equal to {@code beginIndex}, or larger than the number of elements.
+     */
+    public abstract Path subpath(int beginIndex, int endIndex);
+
+    /**
+     * Tests if this path starts with the given path.
+     *
+     * <p> This path <em>starts</em> with the given path if this path's root
+     * component <em>starts</em> with the root component of the given path,
+     * and this path starts with the same name elements as the given path.
+     * If the given path has more name elements than this path then {@code false}
+     * is returned.
+     *
+     * <p> Whether or not the root component of this path starts with the root
+     * component of the given path is file system specific. If this path does
+     * not have a root component and the given path has a root component then
+     * this path does not start with the given path.
+     *
+     * @param   other
+     *          The given path
+     *
+     * @return  {@code true} if this path starts with the given path; otherwise
+     *          {@code false}
+     */
+    public abstract boolean startsWith(Path other);
+
+    /**
+     * Tests if this path ends with the given path.
+     *
+     * <p> If the given path has <em>N</em> elements, and no root component,
+     * and this path has <em>N</em> or more elements, then this path ends with
+     * the given path if the last <em>N</em> elements of each path, starting at
+     * the element farthest from the root, are equal.
+     *
+     * <p> If the given path has a root component then this path ends with the
+     * given path if the root component of this path <em>ends with</em> the root
+     * component of the given path, and the corresponding elements of both paths
+     * are equal. Whether or not the root component of this path ends with the
+     * root component of the given path is file system specific. If this path
+     * does not have a root component and the given path has a root component
+     * then this path does not end with the given path.
+     *
+     * @param   other
+     *          The given path
+     *
+     * @return  {@code true} if this path ends with the given path; otherwise
+     *          {@code false}
+     */
+    public abstract boolean endsWith(Path other);
+
+    /**
+     * Returns a path that is this path with redundant name elements eliminated.
+     *
+     * <p> The precise definition of this method is implementation dependent but
+     * in general it derives from this path, a path that does not contain
+     * <em>redundant</em> name elements. In many file systems, the "{@code .}"
+     * and "{@code ..}" are special names used to indicate the current directory
+     * and parent directory. In such file systems all occurrences of "{@code .}"
+     * are considered redundant. If a "{@code ..}" is preceded by a
+     * non-"{@code ..}" name then both names are considered redundant (the
+     * process to identify such names is repeated until is it no longer
+     * applicable).
+     *
+     * <p> This method does not access the file system; the path may not locate
+     * a file that exists. Eliminating "{@code ..}" and a preceding name from a
+     * path may result in the path that locates a different file than the original
+     * path. This can arise when the preceding name is a symbolic link.
+     *
+     * @return  The resulting path, or this path if it does not contain
+     *          redundant name elements, or {@code null} if this path does not
+     *          have a root component and all name elements are redundant.
+     *
+     * @see #getParent
+     * @see #toRealPath
+     */
+    public abstract Path normalize();
+
+    // -- resolution and relativization --
+
+    /**
+     * Resolve the given path against this path.
+     *
+     * <p> If the {@code other} parameter is an {@link #isAbsolute() absolute}
+     * path then this method trivially returns {@code other}. If {@code other}
+     * is {@code null} then this path is returned. Otherwise this method
+     * considers this path to be a directory and resolves the given path
+     * against this path. In the simplest case, the given path does not have
+     * a {@link #getRoot root} component, in which case this method <em>joins</em>
+     * the given path to this path and returns a resulting path that {@link
+     * #endsWith ends} with the given path. Where the given path has a root
+     * component then resolution is highly implementation dependent and therefore
+     * unspecified.
+     *
+     * @param   other
+     *          The path to resolve against this path; can be {@code null}
+     *
+     * @return  The resulting path
+     *
+     * @see #relativize
+     */
+    public abstract Path resolve(Path other);
+
+    /**
+     * Converts a given path string to a {@code Path} and resolves it against
+     * this {@code Path} in exactly the manner specified by the {@link
+     * #resolve(Path) resolve} method.
+     *
+     * @param   other
+     *          The path string to resolve against this path
+     *
+     * @return  The resulting path
+     *
+     * @throws  InvalidPathException
+     *          If the path string cannot be converted to a Path.
+     *
+     * @see FileSystem#getPath
+     */
+    public abstract Path resolve(String other);
+
+    /**
+     * Constructs a relative path between this path and a given path.
+     *
+     * <p> Relativization is the inverse of {@link #resolve(Path) resolution}.
+     * This method attempts to construct a {@link #isAbsolute relative} path
+     * that when {@link #resolve(Path) resolved} against this path, yields a
+     * path that locates the same file as the given path. For example, on UNIX,
+     * if this path is {@code "/a/b"} and the given path is {@code "/a/b/c/d"}
+     * then the resulting relative path would be {@code "c/d"}. Where this
+     * path and the given path do not have a {@link #getRoot root} component,
+     * then a relative path can be constructed. A relative path cannot be
+     * constructed if only one of the paths have a root component. Where both
+     * paths have a root component then it is implementation dependent if a
+     * relative path can be constructed. If this path and the given path are
+     * {@link #equals equal} then {@code null} is returned.
+     *
+     * <p> For any two paths <i>p</i> and <i>q</i>, where <i>q</i> does not have
+     * a root component,
+     * <blockquote>
+     *   <i>p</i><tt>.relativize(</tt><i>p</i><tt>.resolve(</tt><i>q</i><tt>)).equals(</tt><i>q</i><tt>)</tt>
+     * </blockquote>
+     *
+     * <p> When symbolic-links are supported, then whether the resulting path,
+     * when resolved against this path, yields a path that can be used to locate
+     * the {@link #isSameFile same} file as {@code other} is implementation
+     * dependent. For example, if this path is  {@code "/a/b"} and the given
+     * path is {@code "/a/x"} then the resulting relative path may be {@code
+     * "../x"}. If {@code "b"} is a symbolic-link then is implementation
+     * dependent if {@code "a/b/../x"} would locate the same file as {@code "/a/x"}.
+     *
+     * @param   other
+     *          The resulting path
+     *
+     * @return  The resulting relative path, or {@code null} if both paths are
+     *          equal
+     *
+     * @throws  IllegalArgumentException
+     *          If {@code other} is not a {@code Path} that can be relativized
+     *          against this path
+     */
+    public abstract Path relativize(Path other);
+
+    // -- file operations --
+
+    /**
+     * 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> As with the {@link FileRef#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
+     * 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.
+     *
+     * @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
+     *          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(boolean failIfNotExists) throws IOException;
+
+    /**
+     * Creates a symbolic link to a target <i>(optional operation)</i>.
+     *
+     * <p> The {@code target} parameter is the target of the link. It may be an
+     * {@link Path#isAbsolute absolute} or relative path and may not exist. When
+     * the target is a relative path then file system operations on the resulting
+     * link are relative to the path of the link.
+     *
+     * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
+     * attributes} to set atomically when creating the link. Each 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> Where symbolic links are supported, but the underlying {@link FileStore}
+     * does not support symbolic links, then this may fail with an {@link
+     * IOException}. Additionally, some operating systems may require that the
+     * Java virtual machine be started with implementation specific privileges to
+     * create symbolic links, in which case this method may throw {@code IOException}.
+     *
+     * @param   target
+     *          The target of the link
+     * @param   attrs
+     *          The array of attributes to set atomically when creating the
+     *          symbolic link
+     *
+     * @return  this path
+     *
+     * @throws  UnsupportedOperationException
+     *          If the implementation does not support symbolic links or the
+     *          array contains an attribute that cannot be set atomically when
+     *          creating the symbolic link
+     * @throws  FileAlreadyExistsException
+     *          If a file with the name already exists <i>(optional specific
+     *          exception)</i>
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the the default provider, and a security manager
+     *          is installed, it denies {@link LinkPermission}<tt>("symbolic")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the path of the symbolic link.
+     */
+    public abstract Path createSymbolicLink(Path target, FileAttribute<?>... attrs)
+        throws IOException;
+
+    /**
+     * Creates a new link (directory entry) for an existing file <i>(optional
+     * operation)</i>.
+     *
+     * <p> This path locates the directory entry to create. The {@code existing}
+     * parameter is the path to an existing file. This method creates a new
+     * directory entry for the file so that it can be accessed using this path.
+     * On some file systems this is known as creating a "hard link". Whether the
+     * file attributes are maintained for the file or for each directory entry
+     * is file system specific and therefore not specified. Typically, a file
+     * system requires that all links (directory entries) for a file be on the
+     * same file system. Furthermore, on some platforms, the Java virtual machine
+     * may require to be started with implementation specific privileges to
+     * create hard links or to create links to directories.
+     *
+     * @param   existing
+     *          A reference to an existing file
+     *
+     * @return  this path
+     *
+     * @throws  UnsupportedOperationException
+     *          If the implementation does not support adding an existing file
+     *          to a directory
+     * @throws  FileAlreadyExistsException
+     *          If the entry could not otherwise be created because a file of
+     *          that name already exists <i>(optional specific exception)</i>
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the the default provider, and a security manager
+     *          is installed, it denies {@link LinkPermission}<tt>("hard")</tt>
+     *          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;
+
+    /**
+     * Reads the target of a symbolic link <i>(optional operation)</i>.
+     *
+     * <p> If the file system supports <a href="package-summary.html#links">symbolic
+     * links</a> then this method is used read the target of the link, failing
+     * if the file is not a link. The target of the link need not exist. The
+     * returned {@code Path} object will be associated with the same file
+     * system as this {@code Path}.
+     *
+     * @return  A {@code Path} object representing the target of the link
+     *
+     * @throws  UnsupportedOperationException
+     *          If the implementation does not support symbolic links
+     * @throws  NotLinkException
+     *          If the target could otherwise not be read because the file
+     *          is not a link <i>(optional specific exception)</i>
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the the default provider, and a security manager
+     *          is installed, it checks that {@code FilePermission} has been
+     *          granted with the "{@code readlink}" action to read the link.
+     */
+    public abstract Path readSymbolicLink() throws IOException;
+
+    /**
+     * Returns a URI to represent this path.
+     *
+     * <p> This method constructs a hierarchical {@link URI} that is absolute
+     * with a non-empty path component. Its {@link URI#getScheme() scheme} is
+     * equal to the URI scheme that identifies the provider. The exact form of
+     * the other URI components is highly provider dependent. In particular, it
+     * is implementation dependent if its query, fragment, and authority
+     * components are defined or undefined.
+     *
+     * <p> For the default provider the {@link URI#getPath() path} component
+     * will represent the {@link #toAbsolutePath absolute} path; the query,
+     * fragment components are undefined. Whether the authority component is
+     * defined or not is implementation dependent. There is no guarantee that
+     * the {@code URI} may be used to construct a {@link java.io.File java.io.File}.
+     * In particular, if this path represents a Universal Naming Convention (UNC)
+     * path, then the UNC server name may be encoded in the authority component
+     * of the resulting URI. In the case of the default provider, and the file
+     * exists, and it can be determined that the file is a directory, then the
+     * resulting {@code URI} will end with a slash.
+     *
+     * <p> The default provider provides a similar <em>round-trip</em> guarantee
+     * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
+     * is guaranteed that
+     * <blockquote><tt>
+     * {@link Paths#get(URI) Paths.get}(</tt><i>p</i><tt>.toUri()).equals(</tt><i>p</i>
+     * <tt>.{@link #toAbsolutePath() toAbsolutePath}())</tt>
+     * </blockquote>
+     * so long as the original {@code Path}, the {@code URI}, and the new {@code
+     * Path} are all created in (possibly different invocations of) the same
+     * Java virtual machine. Whether other providers make any guarantees is
+     * provider specific and therefore unspecified.
+     *
+     * <p> When a file system is constructed to access the contents of a file
+     * as a file system then it is highly implementation specific if the returned
+     * URI represents the given path in the file system or it represents a
+     * <em>compound</em> URI that encodes the URI of the enclosing file system.
+     * A format for compound URIs is not defined in this release; such a scheme
+     * may be added in a future release.
+     *
+     * @return  An absolute, hierarchical URI with a non-empty path component
+     *
+     * @throws  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, the URI of the enclosing file system cannot be
+     *          obtained.
+     *
+     * @throws  SecurityException
+     *          In the case of the the default provider, and a security manager
+     *          is installed, the {@link #toAbsolutePath toAbsolutePath} method
+     *          throws a security exception.
+     */
+    public abstract URI toUri();
+
+    /**
+     * Returns a {@code Path} object representing the absolute path of this
+     * path.
+     *
+     * <p> If this path is already {@link Path#isAbsolute absolute} then this
+     * method simply returns this path. Otherwise, this method resolves the path
+     * in an implementation dependent manner, typically by resolving the path
+     * against a file system default directory. Depending on the implementation,
+     * this method may throw an I/O error if the file system is not accessible.
+     *
+     * @return  A {@code Path} object representing the absolute path
+     *
+     * @throws  IOError
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the the default provider, and a security manager
+     *          is installed, its {@link SecurityManager#checkPropertyAccess(String)
+     *          checkPropertyAccess} method is invoked to check access to the
+     *          system property {@code user.dir}
+     */
+    public abstract Path toAbsolutePath();
+
+    /**
+     * Returns the <em>real</em> path of an existing file.
+     *
+     * <p> The precise definition of this method is implementation dependent but
+     * in general it derives from this path, an {@link #isAbsolute absolute}
+     * path that locates the {@link #isSameFile same} file as this path, but
+     * with name elements that represent the actual name of the directories
+     * and the file. For example, where filename comparisons on a file system
+     * are case insensitive then the name elements represent the names in their
+     * actual case. Additionally, the resulting path has redundant name
+     * elements removed.
+     *
+     * <p> If this path is relative then its absolute path is first obtained,
+     * as if by invoking the {@link #toAbsolutePath toAbsolutePath} method.
+     *
+     * <p> The {@code resolveLinks} parameter specifies if symbolic links
+     * should be resolved. This parameter is ignored when symbolic links are
+     * not supported. Where supported, and the parameter has the value {@code
+     * true} then symbolic links are resolved to their final target. Where the
+     * parameter has the value {@code false} then this method does not resolve
+     * symbolic links. Some implementations allow special names such as
+     * "{@code ..}" to refer to the parent directory. When deriving the <em>real
+     * path</em>, and a "{@code ..}" (or equivalent) is preceded by a
+     * non-"{@code ..}" name then an implementation will typically causes both
+     * names to be removed. When not resolving symbolic links and the preceding
+     * name is a symbolic link then the names are only removed if it guaranteed
+     * that the resulting path will locate the same file as this path.
+     *
+     * @return  An absolute path represent the <em>real</em> path of the file
+     *          located by this object
+     *
+     * @throws  IOException
+     *          If the file does not exist or an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the the default provider, and a security manager
+     *          is installed, its {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file, and where
+     *          this path is not absolute, its {@link SecurityManager#checkPropertyAccess(String)
+     *          checkPropertyAccess} method is invoked to check access to the
+     *          system property {@code user.dir}
+     */
+    public abstract Path toRealPath(boolean resolveLinks) throws IOException;
+
+    /**
+     * Copy the file located by this path to a target location.
+     *
+     * <p> This method copies the file located by this {@code Path} to the
+     * target location with the {@code options} parameter specifying how the
+     * copy is performed. By default, the copy fails if the target file already
+     * exists, except if the source and target are the {@link #isSameFile same}
+     * file, in which case this method has no effect. File attributes are not
+     * required to be copied to the target file. If symbolic links are supported,
+     * and the file is a link, then the final target of the link is copied. If
+     * the file is a directory then it creates an empty directory in the target
+     * location (entries in the directory are not copied). This method can be
+     * used with the {@link Files#walkFileTree Files.walkFileTree} utility
+     * method to copy a directory and all entries in the directory, or an entire
+     * <i>file-tree</i> where required.
+     *
+     * <p> The {@code options} parameter is an array of options and may contain
+     * any of the following:
+     *
+     * <table border=1 cellpadding=5 summary="">
+     * <tr> <th>Option</th> <th>Description</th> </tr>
+     * <tr>
+     *   <td> {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} </td>
+     *   <td> If the target file exists, then the target file is replaced if it
+     *     is not a non-empty directory. If the target file exists and is a
+     *     symbolic-link then the symbolic-link is replaced (not the target of
+     *     the link. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@link StandardCopyOption#COPY_ATTRIBUTES COPY_ATTRIBUTES} </td>
+     *   <td> Attempts to copy the file attributes associated with this file to
+     *     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>
+     * </tr>
+     * <tr>
+     *   <td> {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} </td>
+     *   <td> Symbolic-links are not followed. If the file, located by this path,
+     *     is a symbolic-link then the link is copied rather than the target of
+     *     the link. It is implementation specific if file attributes can be
+     *     copied to the new link. In other words, the {@code COPY_ATTRIBUTES}
+     *     option may be ignored when copying a link. </td>
+     * </tr>
+     * </table>
+     *
+     * <p> An implementation of this interface may support additional
+     * implementation specific options.
+     *
+     * <p> Copying a file is not an atomic operation. If an {@link IOException}
+     * is thrown then it possible that the target file is incomplete or some of
+     * its file attributes have not been copied from the source file. When the
+     * {@code REPLACE_EXISTING} option is specified and the target file exists,
+     * then the target file is replaced. The check for the existence of the file
+     * and the creation of the new file may not be atomic with respect to other
+     * file system activities.
+     *
+     * @param   target
+     *          The target location
+     * @param   options
+     *          Options specifying how the copy should be done
+     *
+     * @return  The target
+     *
+     * @throws  UnsupportedOperationException
+     *          If the array contains a copy option that is not supported
+     * @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")}.
+     */
+    public abstract Path copyTo(Path target, CopyOption... options)
+        throws IOException;
+
+    /**
+     * Move or rename the file located by this path to a target location.
+     *
+     * <p> By default, this method attempts to move the file to the target
+     * location, failing if the target file exists except if the source and
+     * target are the {@link #isSameFile same} file, in which case this method
+     * has no effect. If the file is a symbolic link then the link is moved and
+     * not the target of the link. This method may be invoked to move an empty
+     * directory. 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. When invoked to move a directory that is not empty then the
+     * directory is moved if it does not require moving the entries in the directory.
+     * For example, renaming a directory on the same {@link FileStore} will usually
+     * not require moving the entries in the directory. When moving a directory
+     * requires that its entries be moved then this method fails (by throwing
+     * an {@code IOException}). To move a <i>file tree</i> may involve copying
+     * rather than moving directories and this can be done using the {@link
+     * #copyTo copyTo} method in conjunction with the {@link
+     * Files#walkFileTree Files.walkFileTree} utility method.
+     *
+     * <p> The {@code options} parameter is an array of options and may contain
+     * any of the following:
+     *
+     * <table border=1 cellpadding=5 summary="">
+     * <tr> <th>Option</th> <th>Description</th> </tr>
+     * <tr>
+     *   <td> {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} </td>
+     *   <td> If the target file exists, then the target file is replaced if it
+     *     is not a non-empty directory. If the target file exists and is a
+     *     symbolic-link then the symbolic-link is replaced and not the target of
+     *     the link. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} </td>
+     *   <td> The move is performed as an atomic file system operation and all
+     *     other options are ignored. If the target file exists then it is
+     *     implementation specific if the existing file is replaced or this method
+     *     fails by throwing an {@link IOException}. If the move cannot be
+     *     performed as an atomic file system operation then {@link
+     *     AtomicMoveNotSupportedException} is thrown. This can arise, for
+     *     example, when the target location is on a different {@code FileStore}
+     *     and would require that the file be copied, or target location is
+     *     associated with a different provider to this object. </td>
+     * </table>
+     *
+     * <p> An implementation of this interface may support additional
+     * implementation specific options.
+     *
+     * <p> Where the move requires that the file be copied then the {@link
+     * BasicFileAttributes#lastModifiedTime last-modified-time} is copied to the
+     * new file. An implementation may also attempt to copy other file
+     * attributes but is not required to fail if the file attributes cannot be
+     * copied. When the move is performed as a non-atomic operation, and a {@code
+     * IOException} is thrown, then the state of the files is not defined. The
+     * original file and the target file may both exist, the target file may be
+     * incomplete or some of its file attributes may not been copied from the
+     * original file.
+     *
+     * @param   target
+     *          The target location
+     * @param   options
+     *          Options specifying how the move should be done
+     *
+     * @return  The target
+     *
+     * @throws  UnsupportedOperationException
+     *          If the array contains a copy option that is not supported
+     * @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.
+     */
+    public abstract Path moveTo(Path target, CopyOption... options)
+        throws IOException;
+
+    /**
+     * Opens the directory referenced by this object, returning a {@code
+     * DirectoryStream} to iterate over all entries in the directory. The
+     * elements returned by the directory stream's {@link DirectoryStream#iterator
+     * iterator} are of type {@code Path}, each one representing an entry in the
+     * directory. The {@code Path} objects are obtained as if by {@link
+     * #resolve(Path) resolving} the name of the directory entry against this
+     * path.
+     *
+     * <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).
+     *
+     * <p> When an implementation supports operations on entries in the
+     * directory that execute in a race-free manner then the returned directory
+     * stream is a {@link SecureDirectoryStream}.
+     *
+     * @return  A new and open {@code DirectoryStream} object
+     *
+     * @throws  NotDirectoryException
+     *          If the file could not otherwise be opened because it 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#checkRead(String) checkRead}
+     *          method is invoked to check read access to the directory.
+     */
+    public abstract DirectoryStream<Path> newDirectoryStream()
+        throws IOException;
+
+    /**
+     * Opens the directory referenced by this object, returning a {@code
+     * DirectoryStream} to iterate over the entries in the directory. The
+     * elements returned by the directory stream's {@link DirectoryStream#iterator
+     * iterator} are of type {@code Path}, each one representing an entry in the
+     * 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 matching the
+     * {@code String} representation of their file names against the given
+     * <em>globbing</em> pattern.
+     *
+     * <p> For example, suppose we want to iterate over the files ending with
+     * ".java" in a directory:
+     * <pre>
+     *     Path dir = ...
+     *     DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream("*.java");
+     * </pre>
+     *
+     * <p> The globbing pattern is specified by the {@link
+     * FileSystem#getNameMatcher getNameMatcher} method.
+     *
+     * <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.
+     *
+     * <p> When an implementation supports operations on entries in the
+     * directory that execute in a race-free manner then the returned directory
+     * stream is a {@link SecureDirectoryStream}.
+     *
+     * @param   glob
+     *          The glob pattern
+     *
+     * @return  A new and open {@code DirectoryStream} object
+     *
+     * @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>
+     * @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 directory.
+     */
+    public abstract DirectoryStream<Path> newDirectoryStream(String glob)
+        throws IOException;
+
+    /**
+     * Opens the directory referenced by this object, returning a {@code
+     * DirectoryStream} to iterate over the entries in the directory. The
+     * elements returned by the directory stream's {@link DirectoryStream#iterator
+     * iterator} are of type {@code Path}, each one representing an entry in the
+     * 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.
+     *
+     * <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).
+     *
+     * <p> When an implementation supports operations on entries in the
+     * directory that execute in a race-free manner then the returned directory
+     * stream is a {@link SecureDirectoryStream}.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we want to iterate over the files in a directory that are
+     * 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;
+     *             }
+     *         }
+     *     };
+     *     Path dir = ...
+     *     DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream(filter);
+     * </pre>
+     * @param   filter
+     *          The directory stream filter
+     *
+     * @return  A new and open {@code DirectoryStream} object
+     *
+     * @throws  NotDirectoryException
+     *          If the file could not otherwise be opened because it 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#checkRead(String) checkRead}
+     *          method is invoked to check read access to the directory.
+     */
+    public abstract DirectoryStream<Path> newDirectoryStream(DirectoryStream.Filter<? super Path> filter)
+        throws IOException;
+
+    /**
+     * Creates a new and empty file, failing if the file already exists.
+     *
+     * <p> This {@code Path} locates the file to create. The check for the
+     * existence of the file and the creation of the new file if it does not
+     * exist are a single operation that is atomic with respect to all other
+     * filesystem activities that might affect the directory.
+     *
+     * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
+     * file-attributes} to set atomically when creating the file. Each 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.
+     *
+     * @param   attrs
+     *          An optional list of file attributes to set atomically when
+     *          creating the file
+     *
+     * @return  This path
+     *
+     * @throws  UnsupportedOperationException
+     *          If the array contains an attribute that cannot be set atomically
+     *          when creating the file
+     * @throws  FileAlreadyExistsException
+     *          If a file of that name already exists
+     *          <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 to check write access to the new file.
+     */
+    public abstract Path createFile(FileAttribute<?>... attrs) throws IOException;
+
+    /**
+     * Creates a new directory.
+     *
+     * <p> This {@code Path} locates the directory to create. The check for the
+     * existence of the file and the creation of the directory if it does not
+     * exist are a single operation that is atomic with respect to all other
+     * filesystem activities that might affect the directory.
+     *
+     * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute
+     * file-attributes} to set atomically when creating the directory. 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.
+     *
+     * @param   attrs
+     *          An optional list of file attributes to set atomically when
+     *          creating the directory
+     *
+     * @return  This path
+     *
+     * @throws  UnsupportedOperationException
+     *          If the array contains an attribute that cannot be set atomically
+     *          when creating the directory
+     * @throws  FileAlreadyExistsException
+     *          If a directory could not otherwise be created because a file of
+     *          that name already exists <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 to check write access to the new directory.
+     */
+    public abstract Path createDirectory(FileAttribute<?>... attrs)
+        throws IOException;
+
+    /**
+     * Opens or creates a file, returning a seekable byte channel to access 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:
+     *
+     * <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#CREATE_NEW CREATE_NEW} </td>
+     *   <td> If this option is present then a new file is created, failing if
+     *   the file already exists or is a symbolic link. When creating a file the
+     *   check for the existence of the file and the creation of the file if it
+     *   does not exist is atomic with respect to other file system operations.
+     *   This option is ignored when the file is opened only for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td > {@link StandardOpenOption#CREATE CREATE} </td>
+     *   <td> If this option is present then an existing file is opened if it
+     *   exists, otherwise a new file is created. This option is ignored if the
+     *   {@code CREATE_NEW} option is also present or the file is opened only
+     *   for reading. </td>
+     * </tr>
+     * <tr>
+     *   <td > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </td>
+     *   <td> When this option is present then the implementation makes a
+     *   <em>best effort</em> attempt to delete the file when closed by the
+     *   {@link SeekableByteChannel#close close} method. If the {@code close}
+     *   method is not invoked then a <em>best effort</em> attempt is made to
+     *   delete the file when the Java virtual machine terminates. </td>
+     * </tr>
+     * <tr>
+     *   <td>{@link StandardOpenOption#SPARSE SPARSE} </td>
+     *   <td> When creating a new file this option is a <em>hint</em> that the
+     *   new file will be sparse. This option is ignored when not creating
+     *   a new file. </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 may also support additional implementation specific
+     * options.
+     *
+     * <p> The {@code attrs} parameter is an optional array of file {@link
+     * 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}.
+     *
+     * <p> <b>Usage Examples:</b>
+     * <pre>
+     *     Path file = ...
+     *
+     *     // open file for reading
+     *     ReadableByteChannel rbc = file.newByteChannel(EnumSet.of(READ)));
+     *
+     *     // open file for writing to the end of an existing file, creating
+     *     // the file if it doesn't already exist
+     *     WritableByteChannel wbc = file.newByteChannel(EnumSet.of(CREATE,APPEND));
+     *
+     *     // create file with initial permissions, opening it for both reading and writing
+     *     FileAttribute&lt;Set&lt;PosixFilePermission&gt;&gt; perms = ...
+     *     SeekableByteChannel sbc = file.newByteChannel(EnumSet.of(CREATE_NEW,READ,WRITE), perms);
+     * </pre>
+     *
+     * @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 seekable byte channel
+     *
+     * @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  FileAlreadyExistsException
+     *          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
+     *          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.
+     */
+    public abstract SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+                                                       FileAttribute<?>... attrs)
+        throws IOException;
+
+    /**
+     * 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}.
+     *
+     * @param   options
+     *          Options specifying how the file is opened
+     *
+     * @return  a new seekable byte channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If an unsupported open option is specified
+     * @throws  FileAlreadyExistsException
+     *          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}
+     */
+
+    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.
+     */
+    public abstract InputStream newInputStream() 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 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>
+     *
+     * @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.
+     */
+    public abstract OutputStream newOutputStream(Set<? extends OpenOption> options,
+                                                 FileAttribute<?>... attrs)
+        throws IOException;
+
+    /**
+     * Tells whether or not the file located by this object is considered
+     * <em>hidden</em>. The exact definition of hidden is platform or provider
+     * dependent. On UNIX for example a file is considered to be hidden if its
+     * name begins with a period character ('.'). On Windows a file is
+     * considered hidden if it isn't a directory and the DOS {@link
+     * DosFileAttributes#isHidden hidden} attribute is set.
+     *
+     * <p> Depending on the implementation this method may require to access
+     * the file system to determine if the file is considered hidden.
+     *
+     * @return  {@code true} if the file is considered hidden
+     *
+     * @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.
+     */
+    public abstract boolean isHidden() throws IOException;
+
+    /**
+     * Tests whether the file located by this path exists.
+     *
+     * <p> This convenience method is intended for cases where it is required to
+     * take action when it can be confirmed that a file exists. This method simply
+     * invokes the {@link #checkAccess checkAccess} method to check if the file
+     * exists. If the {@code checkAccess} method succeeds then this method returns
+     * {@code true}, otherwise if an {@code IOException} is thrown (because the
+     * file doesn't exist or cannot be accessed by this Java virtual machine)
+     * then {@code false} is returned.
+     *
+     * <p> Note that the result of this method is immediately outdated. If this
+     * method indicates the file exists then there is no guarantee that a
+     * subsequence access will succeed. Care should be taken when using this
+     * method in security sensitive applications.
+     *
+     * @return  {@code true} if the file exists; {@code false} if the file does
+     *          not exist or its existence cannot be determined.
+     *
+     * @throws  SecurityException
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String)} is invoked to check
+     *          read access to the file.
+     *
+     * @see #notExists
+     */
+    public abstract boolean exists();
+
+    /**
+     * Tests whether the file located by this path does not exist.
+     *
+     * <p> This convenience method is intended for cases where it is required to
+     * take action when it can be confirmed that a file does not exist. This
+     * method invokes the {@link #checkAccess checkAccess} method to check if the
+     * file exists. If the file does not exist then {@code true} is returned,
+     * otherwise the file exists or cannot be accessed by this Java virtual
+     * machine and {@code false} is returned.
+     *
+     * <p> Note that this method is not the complement of the {@link #exists
+     * exists} method. Where it is not possible to determine if a file exists
+     * or not then both methods return {@code false}. As with the {@code exists}
+     * method, the result of this method is immediately outdated. If this
+     * method indicates the file does exist then there is no guarantee that a
+     * subsequence attempt to create the file will succeed. Care should be taken
+     * when using this method in security sensitive applications.
+     *
+     * @return  {@code true} if the file does not exist; {@code false} if the
+     *          file exists or its existence cannot be determined.
+     *
+     * @throws  SecurityException
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String)} is invoked to check
+     *          read access to the file.
+     */
+    public abstract boolean notExists();
+
+    // -- watchable --
+
+    /**
+     * Registers the file located by this path with a watch service.
+     *
+     * <p> In this release, this path locates a directory that exists. The
+     * directory is registered with the watch service so that entries in the
+     * directory can be watched. The {@code events} parameter is an array of
+     * events to register and may contain the following events:
+     * <ul>
+     *   <li>{@link StandardWatchEventKind#ENTRY_CREATE ENTRY_CREATE} -
+     *       entry created or moved into the directory</li>
+     *   <li>{@link StandardWatchEventKind#ENTRY_DELETE ENTRY_DELETE} -
+     *        entry deleted or moved out of the directory</li>
+     *   <li>{@link StandardWatchEventKind#ENTRY_MODIFY ENTRY_MODIFY} -
+     *        entry in directory was modified</li>
+     * </ul>
+     *
+     * <p> The {@link WatchEvent#context context} for these events is the
+     * relative path between the directory located by this path, and the path
+     * that locates the directory entry that is created, deleted, or modified.
+     *
+     * <p> The set of events may include additional implementation specific
+     * event that are not defined by the enum {@link StandardWatchEventKind}
+     *
+     * <p> The {@code modifiers} parameter is an array of <em>modifiers</em>
+     * that qualify how the directory is registered. This release does not
+     * define any <em>standard</em> modifiers. The array may contain
+     * implementation specific modifiers.
+     *
+     * <p> Where a file is registered with a watch service by means of a symbolic
+     * link then it is implementation specific if the watch continues to depend
+     * on the existence of the link after it is registered.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we wish register a directory for entry create, delete, and modify
+     * events:
+     * <pre>
+     *     Path dir = ...
+     *     WatchService watcher = ...
+     *
+     *     WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+     * </pre>
+     *
+     * @param   watcher
+     *          The watch service to which this object is to be registered
+     * @param   events
+     *          The events for which this object should be registered
+     * @param   modifiers
+     *          The modifiers, if any, that modify how the object is registered
+     *
+     * @return  A key representing the registration of this object with the
+     *          given watch service
+     *
+     * @throws  UnsupportedOperationException
+     *          If unsupported events or modifiers are specified
+     * @throws  IllegalArgumentException
+     *          If an invalid combination of events or modifiers is specified
+     * @throws  ClosedWatchServiceException
+     *          If the watch service is closed
+     * @throws  NotDirectoryException
+     *          If the file is registered to watch the entries in a directory
+     *          and the file 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#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file.
+     */
+
+    public abstract WatchKey register(WatchService watcher,
+                                      WatchEvent.Kind<?>[] events,
+                                      WatchEvent.Modifier... modifiers)
+        throws IOException;
+
+    // -- Iterable --
+
+    /**
+     * Returns an iterator over the name elements of this path.
+     *
+     * <p> The first element returned by the iterator represents the name
+     * element that is closest to the root in the directory hierarchy, the
+     * second element is the next closest, and so on. The last element returned
+     * is the name of the file or directory denoted by this path. The {@link
+     * #getRoot root} component, if present, is not returned by the iterator.
+     *
+     * @return  An iterator over the name elements of this path.
+     */
+
+    public abstract Iterator<Path> iterator();
+
+    // -- compareTo/equals/hashCode --
+
+    /**
+     * Compares two abstract paths lexicographically. The ordering defined by
+     * this method is provider specific, and in the case of the default
+     * provider, platform specific. This method does not access the file system
+     * and neither file is required to exist.
+     *
+     * @param   other  The path compared to this path.
+     *
+     * @return  Zero if the argument is {@link #equals equal} to this path, a
+     *          value less than zero if this path is lexicographically less than
+     *          the argument, or a value greater than zero if this path is
+     *          lexicographically greater than the argument
+     */
+
+    public abstract int compareTo(Path other);
+
+    /**
+     * 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
+     * different provider, then this method immediately returns {@code false}.
+     *
+     * <p> Whether or not two path are equal depends on the file system
+     * implementation. In some cases the paths are compared without regard
+     * to case, and others are case sensitive. This method does not access the
+     * file system and the file is not required to 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 Path}
+     *          that is identical to this {@code Path}
+     */
+
+    public abstract boolean equals(Object ob);
+
+    /**
+     * Computes a hash code for this path.
+     *
+     * <p> The hash code is based upon the components of the path, and
+     * satisfies the general contract of the {@link Object#hashCode
+     * Object.hashCode} method.
+     *
+     * @return  The hash-code value for this Path
+     */
+
+    public abstract int hashCode();
+
+    /**
+     * Returns the string representation of this path.
+     *
+     * <p> If this path was created by converting a path string using the
+     * {@link FileSystem#getPath getPath} method then the path string returned
+     * by this method may differ from the original String used to create the path.
+     *
+     * <p> The returned path string uses the default name {@link
+     * FileSystem#getSeparator separator} to separate names in the path.
+     *
+     * @return  The string representation of this path
+     */
+
+    public abstract String toString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/PathMatcher.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * An interface that is implemented by objects that perform match operations on
+ * paths.
+ *
+ * @since 1.7
+ *
+ * @see FileSystem#getNameMatcher
+ * @see Path#newDirectoryStream(String)
+ */
+
+public interface PathMatcher {
+    /**
+     * Tells if given path matches this matcher's pattern.
+     *
+     * @param   path
+     *          The path to match
+     *
+     * @return  {@code true} if, and only if, the path matches this
+     *          matcher's pattern
+     */
+    boolean matches(Path path);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Paths.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.spi.FileSystemProvider;
+import java.net.URI;
+import java.util.Iterator;
+
+/**
+ * This class consists exclusively of static methods that return a {@link Path}
+ * by converting a path string or {@link URI}.
+ *
+ * @since 1.7
+ */
+
+public class Paths {
+    private Paths() { }
+
+    /**
+     * Constructs a {@code Path} by converting the given path string.
+     *
+     * <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
+     * getPath} method of the {@link FileSystems#getDefault default} {@link
+     * FileSystem}.
+     *
+     * @param   path
+     *          The path string to convert
+     *
+     * @return  The resulting {@code Path}
+     *
+     * @throws  InvalidPathException
+     *          If the path string cannot be converted to a {@code Path}
+     *
+     * @see FileSystem#getPath
+     */
+    public static Path get(String path) {
+        return FileSystems.getDefault().getPath(path);
+    }
+
+    /**
+     * Converts the given URI to a {@link Path} object.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers to locate the provider that is identified by the
+     * URI {@link URI#getScheme scheme} of the given URI. URI schemes are
+     * compared without regard to case. If the provider is found then its {@link
+     * FileSystemProvider#getPath getPath} method is invoked to convert the
+     * URI.
+     *
+     * <p> In the case of the default provider, identified by the URI scheme
+     * "file", the given URI has a non-empty path component, and undefined query
+     * and fragment components. Whether the authority component may be present
+     * is platform specific. The returned {@code Path} is associated with the
+     * {@link FileSystems#getDefault default} file system.
+     *
+     * <p> The default provider provides a similar <em>round-trip</em> guarantee
+     * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
+     * is guaranteed that
+     * <blockquote><tt>
+     * Paths.get(</tt><i>p</i><tt>.{@link Path#toUri() toUri}()).equals(</tt>
+     * <i>p</i><tt>.{@link Path#toAbsolutePath() toAbsolutePath}())</tt>
+     * </blockquote>
+     * so long as the original {@code Path}, the {@code URI}, and the new {@code
+     * Path} are all created in (possibly different invocations of) the same
+     * Java virtual machine. Whether other providers make any guarantees is
+     * provider specific and therefore unspecified.
+     *
+     * @param   uri
+     *          The URI to convert
+     *
+     * @return  The resulting {@code Path}
+     *
+     * @throws  IllegalArgumentException
+     *          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
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission to access the file system
+     */
+    public static Path get(URI uri) {
+        String scheme =  uri.getScheme();
+        if (scheme == null)
+            throw new IllegalArgumentException("Missing scheme");
+
+        // check for default provider to avoid loading of installed providers
+        if (scheme.equalsIgnoreCase("file"))
+            return FileSystems.getDefault().provider().getPath(uri);
+
+        // try to find provider
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (provider.getScheme().equalsIgnoreCase(scheme)) {
+                return provider.getPath(uri);
+            }
+        }
+
+        throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderMismatchException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Unchecked exception thrown when an attempt is made to invoke a method on an
+ * object created by one file system provider with a parameter created by a
+ * different file system provider.
+ */
+public class ProviderMismatchException
+    extends java.lang.IllegalArgumentException
+{
+    static final long serialVersionUID = 4990847485741612530L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ProviderMismatchException() {
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   msg
+     *          The detail message
+     */
+    public ProviderMismatchException(String msg) {
+        super(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ProviderNotFoundException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Runtime exception thrown a provider of the required type cannot be found.
+ */
+
+public class ProviderNotFoundException
+    extends RuntimeException
+{
+    static final long serialVersionUID = -1880012509822920354L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ProviderNotFoundException() {
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   msg
+     *          The detail message
+     */
+    public ProviderNotFoundException(String msg) {
+        super(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/ReadOnlyFileSystemException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Unchecked exception thrown when an attempt is made to update an object in a
+ * file system that is accessed through a read-only {@code FileSystem}.
+ */
+
+public class ReadOnlyFileSystemException
+    extends UnsupportedOperationException
+{
+    static final long serialVersionUID = -6822409595617487197L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ReadOnlyFileSystemException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SecureDirectoryStream.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 "Classname" 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.attribute.*;
+import java.nio.channels.SeekableByteChannel;
+import java.util.Set;
+import java.io.IOException;
+
+/**
+ * A {@code DirectoryStream} that defines operations on files that are located
+ * relative to an open directory. A {@code SecureDirectoryStream} is intended
+ * for use by sophisticated or security sensitive applications requiring to
+ * 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
+ * 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>.
+ *
+ * <p> A {@code SecureDirectoryStream} requires corresponding support from the
+ * underlying operating system. Where an implementation supports this features
+ * then the {@code DirectoryStream} returned by the {@link Path#newDirectoryStream
+ * newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
+ * be cast to that type in order to invoke the methods defined by this interface.
+ *
+ * <p> As specified by {@code DirectoryStream}, the iterator's {@link
+ * java.util.Iterator#remove() remove} method removes the directory entry for
+ * the last element returned by the iterator. In the case of a {@code
+ * SecureDirectoryStream} the {@code remove} method behaves as if by invoking
+ * the {@link #deleteFile deleteFile} or {@link #deleteDirectory deleteDirectory}
+ * methods defined by this interface. The {@code remove} may require to examine
+ * the file to determine if the file is a directory, and consequently, it may
+ * not be atomic with respect to other file system operations.
+ *
+ * <p> In the case of the default {@link java.nio.file.spi.FileSystemProvider
+ * provider}, and a security manager is set, then the permission checks are
+ * performed using the path obtained by resolving the given relative path
+ * against the <i>original path</i> of the directory (irrespective of if the
+ * directory is moved since it was opened).
+ *
+ * @since   1.7
+ */
+
+public abstract class SecureDirectoryStream
+    implements DirectoryStream<Path>
+{
+    /**
+     * Initialize a new instance of this class.
+     */
+    protected SecureDirectoryStream() { }
+
+    /**
+     * Opens the directory identified by the given path, returning a {@code
+     * 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
+     * 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).
+     *
+     * <p> The new directory stream, once created, is not dependent upon the
+     * directory stream used to create it. Closing this directory stream has no
+     * effect upon newly created directory stream.
+     *
+     * @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}.
+     *
+     * @return  A new and open {@code SecureDirectoryStream} object
+     *
+     * @throws  ClosedDirectoryStreamException
+     *          If the directory stream is closed
+     * @throws  NotDirectoryException
+     *          If the file could not otherwise be opened because it 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#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)
+        throws IOException;
+
+    /**
+     * Opens or creates a file in this directory, returning a seekable byte
+     * channel to access the file.
+     *
+     * <p> This method works in exactly the manner specified by the {@link
+     * Path#newByteChannel Path.newByteChannel} 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 file to open or
+     * create is relative to this open directory. In addition to the options
+     * defined by the {@code Path.newByteChannel} method, 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 channel, once created, is not dependent upon the directory stream
+     * used to create it. Closing this directory stream has no effect upon the
+     * channel.
+     *
+     * @param   path
+     *          The path of the file to open open or create
+     * @param   options
+     *          Options specifying how the file is opened
+     * @param   attrs
+     *          An optional list of attributes to set atomically when creating
+     *          the file
+     *
+     * @throws  ClosedDirectoryStreamException
+     *          If the directory stream is closed
+     * @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  FileAlreadyExistsException
+     *          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
+     *          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.
+     */
+    public abstract SeekableByteChannel newByteChannel(Path path,
+                                                       Set<? extends OpenOption> options,
+                                                       FileAttribute<?>... attrs)
+        throws IOException;
+
+    /**
+     * Deletes a file.
+     *
+     * <p> Unlike the {@link FileRef#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
+     * deleted (not the final target of the link). When the parameter is a
+     * relative path then the file to delete is relative to this open directory.
+     *
+     * @param   path
+     *          The path of the file to delete
+     *
+     * @throws  ClosedDirectoryStreamException
+     *          If the directory stream is closed
+     * @throws  NoSuchFileException
+     *          If the the file does not exist <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) checkDelete}
+     *          method is invoked to check delete access to the file
+     */
+    public abstract void deleteFile(Path path) throws IOException;
+
+    /**
+     * Deletes a directory.
+     *
+     * <p> Unlike the {@link FileRef#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
+     * directory to delete is relative to this open directory.
+     *
+     * @param   path
+     *          The path of the directory to delete
+     *
+     * @throws  ClosedDirectoryStreamException
+     *          If the directory stream is closed
+     * @throws  NoSuchFileException
+     *          If the the directory does not exist <i>(optional specific exception)</i>
+     * @throws  DirectoryNotEmptyException
+     *          If the directory could not otherwise be deleted because it 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) checkDelete}
+     *          method is invoked to check delete access to the directory
+     */
+    public abstract void deleteDirectory(Path path) throws IOException;
+
+    /**
+     * Move a file from this directory to another directory.
+     *
+     * <p> This method works in a similar manner to {@link Path#moveTo moveTo}
+     * method when the {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} option
+     * is specified. That is, this method moves a file as an atomic file system
+     * operation. If the {@code srcpath} parameter is an {@link Path#isAbsolute
+     * absolute} path then it locates the source file. If the parameter is a
+     * relative path then it is located relative to this open directory. If
+     * the {@code targetpath} parameter is absolute then it locates the target
+     * file (the {@code targetdir} parameter is ignored). If the parameter is
+     * a relative path it is located relative to the open directory identified
+     * by the {@code targetdir} parameter. In all cases, if the target file
+     * exists then it is implementation specific if it is replaced or this
+     * method fails.
+     *
+     * @param   srcpath
+     *          The name of the file to move
+     * @param   targetdir
+     *          The destination directory
+     * @param   targetpath
+     *          The name to give the file in the destination directory
+     *
+     * @throws  ClosedDirectoryStreamException
+     *          If this or the target directory stream is closed
+     * @throws  FileAlreadyExistsException
+     *          The file already exists in the target directory and cannot
+     *          be replaced <i>(optional specific exception)</i>
+     * @throws  AtomicMoveNotSupportedException
+     *          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.
+     */
+    public abstract void move(Path srcpath, SecureDirectoryStream targetdir, Path targetpath)
+        throws IOException;
+
+    /**
+     * Returns a new file attribute view to access the file attributes of this
+     * directory.
+     *
+     * <p> The resulting file attribute view can be used to read or update the
+     * attributes of this (open) directory. The {@code type} parameter specifies
+     * the type of the attribute view and the method returns an instance of that
+     * type if supported. Invoking this method to obtain a {@link
+     * BasicFileAttributeView} always returns an instance of that class that is
+     * bound to this open directory.
+     *
+     * <p> The state of resulting file attribute view is intimately connected
+     * to this directory stream. Once the directory stream is {@link #close closed},
+     * then all methods to read or update attributes will throw {@link
+     * ClosedDirectoryStreamException ClosedDirectoryStreamException}.
+     *
+     * @param   type
+     *          The {@code Class} object corresponding to the file attribute view
+     *
+     * @return  A new file attribute view of the specified type bound to
+     *          this directory stream, or {@code null} if the attribute view
+     *          type is not available
+     */
+    public abstract <V extends FileAttributeView> V getFileAttributeView(Class<V> type);
+
+    /**
+     * Returns a new file attribute view to access the file attributes of a file
+     * in this directory.
+     *
+     * <p> The resulting file attribute view can be used to read or update the
+     * attributes of file in this directory. The {@code type} parameter specifies
+     * the type of the attribute view and the method returns an instance of that
+     * type if supported. Invoking this method to obtain a {@link
+     * BasicFileAttributeView} always returns an instance of that class that is
+     * bound to the file in the directory.
+     *
+     * <p> The state of resulting file attribute view is intimately connected
+     * to this directory stream. Once the directory stream {@link #close closed},
+     * then all methods to read or update attributes will throw {@link
+     * ClosedDirectoryStreamException ClosedDirectoryStreamException}. The
+     * file is not required to exist at the time that the file attribute view
+     * is created but methods to read or update attributes of the file will
+     * fail when invoked and the file does not exist.
+     *
+     * @param   path
+     *          The path of the file
+     * @param   type
+     *          The {@code Class} object corresponding to the file attribute view
+     * @param   options
+     *          Options indicating how symbolic links are handled
+     *
+     * @return  A new file attribute view of the specified type bound to a
+     *          this directory stream, or {@code null} if the attribute view
+     *          type is not available
+     *
+     */
+    public abstract <V extends FileAttributeView> V getFileAttributeView(Path path,
+                                                                         Class<V> type,
+                                                                         LinkOption... options);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/SimpleFileVisitor.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.io.IOException;
+import java.io.IOError;
+
+/**
+ * A simple visitor of files with default behavior to visit all files and to
+ * re-throw I/O errors.
+ *
+ * <p> Methods in this class may be overridden subject to their general contract.
+ *
+ * @param   <T>     The type of reference to the files
+ *
+ * @since 1.7
+ */
+
+public class SimpleFileVisitor<T extends FileRef> implements FileVisitor<T> {
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected SimpleFileVisitor() {
+    }
+
+    /**
+     * Invoked for a directory before entries in the directory are visited.
+     *
+     * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
+     * CONTINUE}.
+     */
+
+    public FileVisitResult preVisitDirectory(T dir) {
+        return FileVisitResult.CONTINUE;
+    }
+
+    /**
+     * Invoked for a directory that could not be opened.
+     *
+     * <p> Unless overridden, this method throws {@link IOError} with the I/O
+     * exception as cause.
+     *
+     * @throws  IOError
+     *          With the I/O exception thrown when the attempt to open the
+     *          directory failed
+     */
+
+    public FileVisitResult preVisitDirectoryFailed(T dir, IOException exc) {
+        throw new IOError(exc);
+    }
+
+    /**
+     * Invoked for a file in a directory.
+     *
+     * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
+     * CONTINUE}.
+     */
+
+    public FileVisitResult visitFile(T file, BasicFileAttributes attrs) {
+        return FileVisitResult.CONTINUE;
+    }
+
+    /**
+     * Invoked for a file when its basic file attributes could not be read.
+     *
+     * <p> Unless overridden, this method throws {@link IOError} with the I/O
+     * exception as cause.
+     *
+     * @throws  IOError
+     *          With the I/O exception thrown when the attempt to read the file
+     *          attributes failed
+     */
+
+    public FileVisitResult visitFileFailed(T file, IOException exc) {
+        throw new IOError(exc);
+    }
+
+    /**
+     * Invoked for a directory after entries in the directory, and all of their
+     * descendants, have been visited.
+     *
+     * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
+     * CONTINUE} if the directory iteration completes without an I/O exception;
+     * otherwise this method throws {@link IOError} with the I/O exception as
+     * cause.
+     *
+     * @throws  IOError
+     *          If iteration of the directory completed prematurely due to an
+     *          I/O error
+     */
+
+    public FileVisitResult postVisitDirectory(T dir, IOException exc) {
+        if (exc != null)
+            throw new IOError(exc);
+        return FileVisitResult.CONTINUE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardCopyOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Defines the standard copy options.
+ *
+ * @since 1.7
+ */
+
+public enum StandardCopyOption implements CopyOption {
+    /**
+     * Replace an existing file if it exists.
+     */
+    REPLACE_EXISTING,
+    /**
+     * Copy attributes to the new file.
+     */
+    COPY_ATTRIBUTES,
+    /**
+     * Move the file as an atomic file system operation.
+     */
+    ATOMIC_MOVE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardOpenOption.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Defines the standard open options.
+ *
+ * @since 1.7
+ */
+
+public enum StandardOpenOption implements OpenOption {
+    /**
+     * Open for read access.
+     */
+    READ,
+
+    /**
+     * Open for write access.
+     */
+    WRITE,
+
+    /**
+     * If the file is opened for {@link #WRITE} access then bytes will be written
+     * to the end of the file rather than the beginning.
+     *
+     * <p> If the file is opened for write access by other programs, then it
+     * is file system specific if writing to the end of the file is atomic.
+     */
+    APPEND,
+
+    /**
+     * If the file already exists and it is opened for {@link #WRITE}
+     * access, then its length is truncated to 0. This option is ignored
+     * if the file is opened only for {@link #READ} access.
+     */
+    TRUNCATE_EXISTING,
+
+    /**
+     * Create a new file if it does not exist.
+     * This option is ignored if the {@link #CREATE_NEW} option is also set.
+     * The check for the existence of the file and the creation of the file
+     * if it does not exist is atomic with respect to other file system
+     * operations.
+     */
+    CREATE,
+
+    /**
+     * Create a new file, failing if the file already exists.
+     * The check for the existence of the file and the creation of the file
+     * if it does not exist is atomic with respect to other file system
+     * operations.
+     */
+    CREATE_NEW,
+
+    /**
+     * Delete on close. When this option is present then the implementation
+     * makes a <em>best effort</em> attempt to delete the file when the closed
+     * by the appropriate {@code close} method. If the {@code close} method is
+     * not invoked then a <em>best effort</em> attempt is made to delete the
+     * file when the Java virtual machine terminates (either normally, as
+     * defined by the Java Language Specification, or where possible, abnormally).
+     * This option is primarily intended for use with <em>work files</em> that
+     * are used solely by a single instance of the Java virtual machine. This
+     * option is not recommended for use when opening files that are open
+     * concurrently by other entities. Many of the details as to when and how
+     * the file is deleted are implementation specific and therefore not
+     * specified. In particular, an implementation may be unable to guarantee
+     * that it deletes the expected file when replaced by an attacker while the
+     * file is open. Consequently, security sensitive applications should take
+     * care when using this option.
+     *
+     * <p> For security reasons, this option may imply the {@link
+     * LinkOption#NOFOLLOW_LINKS} option. In other words, if the option is present
+     * when opening an existing file that is a symbolic link then it may fail
+     * (by throwing {@link java.io.IOException}).
+     */
+    DELETE_ON_CLOSE,
+
+    /**
+     * Sparse file. When used with the {@link #CREATE_NEW} option then this
+     * option provides a <em>hint</em> that the new file will be sparse. The
+     * option is ignored when the file system does not support the creation of
+     * sparse files.
+     */
+    SPARSE,
+
+    /**
+     * 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>
+     */
+    SYNC,
+
+    /**
+     * 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>
+     */
+    DSYNC;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/StandardWatchEventKind.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * Defines the <em>standard</em> event kinds.
+ *
+ * @since 1.7
+ */
+
+public class StandardWatchEventKind {
+    private StandardWatchEventKind() { }
+
+    /**
+     * A special event to indicate that events may have been lost or
+     * discarded.
+     *
+     * <p> The {@link WatchEvent#context context} for this event is
+     * implementation specific and may be {@code null}. The event {@link
+     * WatchEvent#count count} may be greater than {@code 1}.
+     *
+     * @see WatchService
+     */
+    public static final WatchEvent.Kind<Void> OVERFLOW =
+        new StdWatchEventKind<Void>("OVERFLOW", Void.class);
+
+    /**
+     * Directory entry created.
+     *
+     * <p> When a directory is registered for this event then the {@link WatchKey}
+     * is queued when it is observed that an entry is created in the directory
+     * or renamed into the directory. The event {@link WatchEvent#count count}
+     * for this event is always {@code 1}.
+     */
+    public static final WatchEvent.Kind<Path> ENTRY_CREATE =
+        new StdWatchEventKind<Path>("ENTRY_CREATE", Path.class);
+
+    /**
+     * Directory entry deleted.
+     *
+     * <p> When a directory is registered for this event then the {@link WatchKey}
+     * is queued when it is observed that an entry is deleted or renamed out of
+     * the directory. The event {@link WatchEvent#count count} for this event
+     * is always {@code 1}.
+     */
+    public static final WatchEvent.Kind<Path> ENTRY_DELETE =
+        new StdWatchEventKind<Path>("ENTRY_DELETE", Path.class);
+
+    /**
+     * Directory entry modified.
+     *
+     * <p> When a directory is registered for this event then the {@link WatchKey}
+     * is queued when it is observed that an entry in the directory has been
+     * modified. The event {@link WatchEvent#count count} for this event is
+     * {@code 1} or greater.
+     */
+    public static final WatchEvent.Kind<Path> ENTRY_MODIFY =
+        new StdWatchEventKind<Path>("ENTRY_MODIFY", Path.class);
+
+    private static class StdWatchEventKind<T> implements WatchEvent.Kind<T> {
+        private final String name;
+        private final Class<T> type;
+        StdWatchEventKind(String name, Class<T> type) {
+            this.name = name;
+            this.type = type;
+        }
+ public String name() { return name; }
+ public Class<T> type() { return type; }
+ public String toString() { return name; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchEvent.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+/**
+ * An event or a repeated event for an object that is registered with a {@link
+ * WatchService}.
+ *
+ * <p> An event is classified by its {@link #kind() kind} and has a {@link
+ * #count() count} to indicate the number of times that the event has been
+ * observed. This allows for efficient representation of repeated events. The
+ * {@link #context() context} method returns any context associated with
+ * the event. In the case of a repeated event then the context is the same for
+ * all events.
+ *
+ * <p> Watch events are immutable and safe for use by multiple concurrent
+ * threads.
+ *
+ * @param   <T>     The type of the context object associated with the event
+ *
+ * @since 1.7
+ */
+
+public abstract class WatchEvent<T> {
+
+    /**
+     * An event kind, for the purposes of identification.
+     *
+     * @since 1.7
+     * @see StandardWatchEventKind
+     */
+    public static interface Kind<T> {
+        /**
+         * Returns the name of the event kind.
+         */
+        String name();
+
+        /**
+         * Returns the type of the {@link WatchEvent#context context} value.
+         */
+        Class<T> type();
+    }
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected WatchEvent() { }
+
+    /**
+     * An event modifier that qualifies how a {@link Watchable} is registered
+     * with a {@link WatchService}.
+     *
+     * <p> This release does not define any <em>standard</em> modifiers.
+     *
+     * @since 1.7
+     * @see Watchable#register
+     */
+    public static interface Modifier {
+        /**
+         * Returns the name of the modifier.
+         */
+        String name();
+    }
+
+    /**
+     * Returns the event kind.
+     *
+     * @return  The event kind
+     */
+    public abstract Kind<T> kind();
+
+    /**
+     * Returns the event count. If the event count is greater than {@code 1}
+     * then this is a repeated event.
+     *
+     * @return  The event count
+     */
+    public abstract int count();
+
+    /**
+     * Returns the context for the event.
+     *
+     * <p> In the case of {@link StandardWatchEventKind#ENTRY_CREATE ENTRY_CREATE},
+     * {@link StandardWatchEventKind#ENTRY_DELETE ENTRY_DELETE}, and {@link
+     * StandardWatchEventKind#ENTRY_MODIFY ENTRY_MODIFY} events the context is
+     * a {@code Path} that is the {@link Path#relativize relative} path between
+     * the directory registered with the watch service, and the entry that is
+     * created, deleted, or modified.
+     *
+     * @return  The event context; may be {@code null}
+     */
+    public abstract T context();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchKey.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.util.List;
+
+/**
+ * A key representing the registration of an object with a {@link WatchService}.
+ *
+ * <p> A watch key is created when a {@link Watchable Watchable} object is
+ * registered with a watch service. The key remains {@link #isValid valid} until:
+ * <ol>
+ *   <li> It is cancelled, explicitly, by invoking its {@link #cancel cancel}
+ *     method, or</li>
+ *   <li> Cancelled implicitly, because the object is no longer accessible,
+ *     or </li>
+ *   <li> By {@link WatchService#close closing} the watch service. </li>
+ * </ol>
+ *
+ * <p> A watch key has a state. When initially created the key is said to be
+ * <em>ready</em>. When an event is detected then the key is <em>signalled</em>
+ * and queued so that it can be retrieved by invoking the watch service's {@link
+ * WatchService#poll() poll} or {@link WatchService#take() take} methods. Once
+ * signalled, a key remains in this state until its {@link #reset reset} method
+ * is invoked to return the key to the ready state. Events detected while the
+ * key is in the signalled state are queued but do not cause the key to be
+ * re-queued for retrieval from the watch service. Events are retrieved by
+ * invoking the key's {@link #pollEvents pollEvents} method. This method
+ * retrieves and removes all events accumulated for the object. When initially
+ * created, a watch key has no pending events. Typically events are retrieved
+ * when the key is in the signalled state leading to the following idiom:
+ *
+ * <pre>
+ *     for (;;) {
+ *         // retrieve key
+ *         WatchKey key = watcher.take();
+ *
+ *         // process events
+ *         for (WatchEvent&lt;?&gt; event: key.pollEvents()) {
+ *             :
+ *         }
+ *
+ *         // reset the key
+ *         boolean valid = key.reset();
+ *         if (!valid) {
+ *             // object no longer registered
+ *         }
+ *     }
+ * </pre>
+ *
+ * <p> Watch keys are safe for use by multiple concurrent threads. Where there
+ * are several threads retrieving signalled keys from a watch service then care
+ * should be taken to ensure that the {@code reset} method is only invoked after
+ * the events for the object have been processed. This ensures that one thread
+ * is processing the events for an object at any time.
+ *
+ * @since 1.7
+ */
+
+public abstract class WatchKey {
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected WatchKey() { }
+
+    /**
+     * Tells whether or not this watch key is valid.
+     *
+     * <p> A watch key is valid upon creation and remains until it is cancelled,
+     * or its watch service is closed.
+     *
+     * @return  {@code true} if, and only if, this watch key is valid
+     */
+    public abstract boolean isValid();
+
+    /**
+     * Retrieves and removes all pending events for this watch key, returning
+     * a {@code List} of the events that were retrieved.
+     *
+     * <p> Note that this method does not wait if there are no events pending.
+     *
+     * @return  The list of the events retrieved
+     */
+    public abstract List<WatchEvent<?>> pollEvents();
+
+    /**
+     * Resets this watch key.
+     *
+     * <p> If this watch key has been cancelled or this watch key is already in
+     * the ready state then invoking this method has no effect. Otherwise
+     * if there are pending events for the object then this watch key is
+     * immediately re-queued to the watch service. If there are no pending
+     * events then the watch key is put into the ready state and will remain in
+     * that state until an event is detected or the watch key is cancelled.
+     *
+     * @return  {@code true} if the watch key is valid and has been reset;
+     *          {@code false} if the watch key could not be reset because it is
+     *          no longer {@link #isValid valid}
+     */
+    public abstract boolean reset();
+
+    /**
+     * Cancels the registration with the watch service. Upon return the watch key
+     * 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
+     * cancelled.
+     *
+     * <p> If this watch key has already been cancelled then invoking this
+     * method has no effect.  Once cancelled, a watch key remains forever invalid.
+     */
+    public abstract void cancel();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/WatchService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A watch service that <em>watches</em> registered objects for changes and
+ * events. For example a file manager may use a watch service to monitor a
+ * directory for changes so that it can update its display of the list of files
+ * when files are created or deleted.
+ *
+ * <p> A {@link Watchable} object is registered with a watch service by invoking
+ * its {@link Watchable#register register} method, returning a {@link WatchKey}
+ * to represent the registration. When an event for an object is detected the
+ * key is <em>signalled</em>, and if not currently signalled, it is queued to
+ * the watch service so that it can be retrieved by consumers that invoke the
+ * {@link #poll() poll} or {@link #take() take} methods to retrieve keys
+ * and process events. Once the events have been processed the consumer
+ * invokes the key's {@link WatchKey#reset reset} method to reset the key which
+ * allows the key to be signalled and re-queued with further events.
+ *
+ * <p> Registration with a watch service is cancelled by invoking the key's
+ * {@link WatchKey#cancel cancel} method. A key that is queued at the time that
+ * it is cancelled remains in the queue until it is retrieved. Depending on the
+ * object, a key may be cancelled automatically. For example, suppose a
+ * directory is watched and the watch service detects that it has been deleted
+ * or its file system is no longer accessible. When a key is cancelled in this
+ * manner it is signalled and queued, if not currently signalled. To ensure
+ * that the consumer is notified the return value from the {@code reset}
+ * method indicates if the key is valid.
+ *
+ * <p> A watch service is safe for use by multiple concurrent consumers. To
+ * ensure that only one consumer processes the events for a particular object at
+ * any time then care should be taken to ensure that the key's {@code reset}
+ * method is only invoked after its events have been processed. The {@link
+ * #close close} method may be invoked at any time to close the service causing
+ * any threads waiting to retrieve keys, to throw {@code
+ * ClosedWatchServiceException}.
+ *
+ * <p> File systems may report events faster than they can be retrieved or
+ * processed and an implementation may impose an unspecified limit on the number
+ * of events that it may accumulate. Where an implementation <em>knowingly</em>
+ * discards events then it arranges for the key's {@link WatchKey#pollEvents
+ * pollEvents} method to return an element with an event type of {@link
+ * StandardWatchEventKind#OVERFLOW OVERFLOW}. This event can be used by the
+ * consumer as a trigger to re-examine the state of the object.
+ *
+ * <p> When an event is reported to indicate that a file in a watched directory
+ * has been modified then there is no guarantee that the program (or programs)
+ * that have modified the file have completed. Care should be taken to coordinate
+ * access with other programs that may be updating the file.
+ * The {@link java.nio.channels.FileChannel FileChannel} class defines methods
+ * to lock regions of a file against access by other programs.
+ *
+ * <h4>Platform dependencies</h4>
+ *
+ * <p> The implementation that observes events from the file system is intended
+ * to map directly on to the native file event notification facility where
+ * available, or to use a primitive mechanism, such as polling, when a native
+ * facility is not available. Consequently, many of the details on how events
+ * are detected, their timeliness, and whether their ordering is preserved are
+ * highly implementation specific. For example, when a file in a watched
+ * directory is modified then it may result in a single {@link
+ * StandardWatchEventKind#ENTRY_MODIFY ENTRY_MODIFY} event in some
+ * implementations but several events in other implementations. Short-lived
+ * files (meaning files that are deleted very quickly after they are created)
+ * may not be detected by primitive implementations that periodically poll the
+ * file system to detect changes.
+ *
+ * <p> If a watched file is not located on a local storage device then it is
+ * implementation specific if changes to the file can be detected. In particular,
+ * it is not required that changes to files carried out on remote systems be
+ * detected.
+ *
+ * @since 1.7
+ *
+ * @see FileSystem#newWatchService
+ */
+
+public abstract class WatchService
+    implements Closeable
+{
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected WatchService() { }
+
+    /**
+     * Closes this watch service.
+     *
+     * <p> If a thread is currently blocked in the {@link #take take} or {@link
+     * #poll(long,TimeUnit) poll} methods waiting for a key to be queued then
+     * it immediately receives a {@link ClosedWatchServiceException}. Any
+     * valid keys associated with this watch service are {@link WatchKey#isValid
+     * invalidated}.
+     *
+     * <p> After a watch service is closed, any further attempt to invoke
+     * operations upon it will throw {@link ClosedWatchServiceException}.
+     * If this watch service is already closed then invoking this method
+     * has no effect.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+
+    public abstract void close() throws IOException;
+
+    /**
+     * Retrieves and removes the next watch key, or {@code null} if none are
+     * present.
+     *
+     * @return  The next watch key, or {@code null}
+     *
+     * @throws  ClosedWatchServiceException
+     *          If this watch service is closed
+     */
+    public abstract WatchKey poll();
+
+    /**
+     * Retrieves and removes the next watch key, waiting if necessary up to the
+     * specified wait time if none are yet present.
+     *
+     * @param   timeout
+     *          how to wait before giving up, in units of unit
+     * @param   unit
+     *          a {@code TimeUnit} determining how to interpret the timeout
+     *          parameter
+     *
+     * @return  The next watch key, or {@code null}
+     *
+     * @throws  ClosedWatchServiceException
+     *          If this watch service is closed, or it is closed while waiting
+     *          for the next key
+     * @throws  InterruptedException
+     *          If interrupted while waiting
+     */
+    public abstract WatchKey poll(long timeout, TimeUnit unit)
+        throws InterruptedException;
+
+    /**
+     * Retrieves and removes next watch key waiting if none are yet present.
+     *
+     * @return  The next watch key
+     *
+     * @throws  ClosedWatchServiceException
+     *          If this watch service is closed, or it is closed while waiting
+     *          for the next key
+     * @throws  InterruptedException
+     *          If interrupted while waiting
+     */
+    public abstract WatchKey take() throws InterruptedException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/Watchable.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file;
+
+import java.io.IOException;
+
+/**
+ * An object that may be registered with a watch service so that it can be
+ * <em>watched</em> for changes and events.
+ *
+ * <p> This interface defines the {@link #register register} method to register
+ * the object with a {@link WatchService} returning a {@link WatchKey} to
+ * represent the registration. An object may be registered with more than one
+ * watch service. Registration with a watch service is cancelled by invoking the
+ * key's {@link WatchKey#cancel cancel} method.
+ *
+ * @since 1.7
+ *
+ * @see Path#register
+ */
+
+public interface Watchable {
+
+    /**
+     * Registers an object with a watch service.
+     *
+     * <p> If the file system object identified by this object is currently
+     * registered with the watch service then the watch key, representing that
+     * registration, is returned after changing the event set or modifiers to
+     * those specified by the {@code events} and {@code modifiers} parameters.
+     * Changing the event set does not cause pending events for the object to be
+     * discarded. Objects are automatically registered for the {@link
+     * StandardWatchEventKind#OVERFLOW OVERFLOW} event. This event is not
+     * required to be present in the array of events.
+     *
+     * <p> Otherwise the file system object has not yet been registered with the
+     * given watch service, so it is registered and the resulting new key is
+     * returned.
+     *
+     * <p> Implementations of this interface should specify the events they
+     * support.
+     *
+     * @param   watcher
+     *          The watch service to which this object is to be registered
+     * @param   events
+     *          The events for which this object should be registered
+     * @param   modifiers
+     *          The modifiers, if any, that modify how the object is registered
+     *
+     * @return  A key representing the registration of this object with the
+     *          given watch service
+     *
+     * @throws  UnsupportedOperationException
+     *          If unsupported events or modifiers are specified
+     * @throws  IllegalArgumentException
+     *          If an invalid of combination of events are modifiers are specified
+     * @throws  ClosedWatchServiceException
+     *          If the watch service is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission required to monitor this object. Implementations of
+     *          this interface should specify the permission checks.
+     */
+    WatchKey register(WatchService watcher,
+                      WatchEvent.Kind<?>[] events,
+                      WatchEvent.Modifier... modifiers)
+        throws IOException;
+
+
+    /**
+     * Registers an object with a watch service.
+     *
+     * <p> An invocation of this method behaves in exactly the same way as the
+     * invocation
+     * <pre>
+     *     watchable.{@link #register(WatchService,WatchEvent.Kind[],WatchEvent.Modifier[]) register}(watcher, events, new WatchEvent.Modifier[0]);
+     * </pre>
+     *
+     * @param   watcher
+     *          The watch service to which this object is to be registered
+     * @param   events
+     *          The events for which this object should be registered
+     *
+     * @return  A key representing the registration of this object with the
+     *          given watch service
+     *
+     * @throws  UnsupportedOperationException
+     *          If unsupported events are specified
+     * @throws  IllegalArgumentException
+     *          If an invalid of combination of events are specified
+     * @throws  ClosedWatchServiceException
+     *          If the watch service is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission required to monitor this object. Implementations of
+     *          this interface should specify the permission checks.
+     */
+    WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events)
+        throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntry.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.util.*;
+
+/**
+ * An entry in an access control list (ACL).
+ *
+ * <p> The ACL entry represented by this class is based on the ACL model
+ * specified in <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC&nbsp;3530:
+ * Network File System (NFS) version 4 Protocol</i></a>. Each entry has four
+ * components as follows:
+ *
+ * <ol>
+ *    <li><p> The {@link #type() type} component determines if the entry
+ *    grants or denies access. </p></li>
+ *
+ *    <li><p> The {@link #principal() principal} component, sometimes called the
+ *    "who" component, is a {@link UserPrincipal} corresponding to the identity
+ *    that the entry grants or denies access
+ *    </p></li>
+ *
+ *    <li><p> The {@link #permissions permissions} component is a set of
+ *    {@link AclEntryPermission permissions}
+ *    </p></li>
+ *
+ *    <li><p> The {@link #flags flags} component is a set of {@link AclEntryFlag
+ *    flags} to indicate how entries are inherited and propagated </p></li>
+ * </ol>
+ *
+ * <p> ACL entries are created using an associated {@link Builder} object by
+ * invoking its {@link Builder#build build} method.
+ *
+ * <p> ACL entries are immutable and are safe for use by multiple concurrent
+ * threads.
+ *
+ * @since 1.7
+ */
+
+public final class AclEntry {
+
+    private final AclEntryType type;
+    private final UserPrincipal who;
+    private final Set<AclEntryPermission> perms;
+    private final Set<AclEntryFlag> flags;
+
+    // cached hash code
+    private volatile int hash;
+
+    // private constructor
+    private AclEntry(AclEntryType type,
+                     UserPrincipal who,
+                     Set<AclEntryPermission> perms,
+                     Set<AclEntryFlag> flags)
+    {
+        this.type = type;
+        this.who = who;
+        this.perms = perms;
+        this.flags = flags;
+    }
+
+    /**
+     * A builder of {@link AclEntry} objects.
+     *
+     * <p> A {@code Builder} object is obtained by invoking one of the {@link
+     * AclEntry#newBuilder newBuilder} methods defined by the {@code AclEntry}
+     * class.
+     *
+     * <p> Builder objects are mutable and are not safe for use by multiple
+     * concurrent threads without appropriate synchronization.
+     *
+     * @since 1.7
+     */
+    public static final class Builder {
+        private AclEntryType type;
+        private UserPrincipal who;
+        private Set<AclEntryPermission> perms;
+        private Set<AclEntryFlag> flags;
+
+        private Builder(AclEntryType type,
+                        UserPrincipal who,
+                        Set<AclEntryPermission> perms,
+                        Set<AclEntryFlag> flags)
+        {
+            assert perms != null && flags != null;
+            this.type = type;
+            this.who = who;
+            this.perms = perms;
+            this.flags = flags;
+        }
+
+        /**
+         * Constructs an {@link AclEntry} from the components of this builder.
+         * The type and who components are required to have been set in order
+         * to construct an {@code AclEntry}.
+         *
+         * @return  A new ACL entry
+         *
+         * @throws  IllegalStateException
+         *          If the type or who component have not been set.
+         */
+        public AclEntry build() {
+            if (type == null)
+                throw new IllegalStateException("Missing type component");
+            if (who == null)
+                throw new IllegalStateException("Missing who component");
+            return new AclEntry(type, who, perms, flags);
+        }
+
+        /**
+         * Sets the type component of this builder.
+         *
+         * @return  This builder
+         */
+        public Builder setType(AclEntryType type) {
+            if (type == null)
+                throw new NullPointerException();
+            this.type = type;
+            return this;
+        }
+
+        /**
+         * Sets the principal component of this builder.
+         *
+         * @return  This builder
+         */
+        public Builder setPrincipal(UserPrincipal who) {
+            if (who == null)
+                throw new NullPointerException();
+            this.who = who;
+            return this;
+        }
+
+        // check set only contains elements of the given type
+        private static void checkSet(Set<?> set, Class<?> type) {
+            for (Object e: set) {
+                if (e == null)
+                    throw new NullPointerException();
+                type.cast(e);
+            }
+        }
+
+        /**
+         * Sets the permissions component of this builder. On return, the
+         * permissions component of this builder is a copy of the given set.
+         *
+         * @return  This builder
+         *
+         * @throws  ClassCastException
+         *          If the sets contains elements that are not of type {@code
+         *          AclEntryPermission}
+         */
+        public Builder setPermissions(Set<AclEntryPermission> perms) {
+            // copy and check for erroneous elements
+            perms = new HashSet<AclEntryPermission>(perms);
+            checkSet(perms, AclEntryPermission.class);
+            this.perms = perms;
+            return this;
+        }
+
+        /**
+         * Sets the permissions component of this builder. On return, the
+         * permissions component of this builder is a copy of the permissions in
+         * the given array.
+         *
+         * @return  This builder
+         */
+        public Builder setPermissions(AclEntryPermission... perms) {
+            Set<AclEntryPermission> set =
+                new HashSet<AclEntryPermission>(perms.length);
+            // copy and check for null elements
+            for (AclEntryPermission p: perms) {
+                if (p == null)
+                    throw new NullPointerException();
+                set.add(p);
+            }
+            this.perms = set;
+            return this;
+        }
+
+        /**
+         * Sets the flags component of this builder. On return, the flags
+         * component of this builder is a copy of the given set.
+         *
+         * @return  This builder
+         *
+         * @throws  ClassCastException
+         *          If the sets contains elements that are not of type {@code
+         *          AclEntryFlag}
+         */
+        public Builder setFlags(Set<AclEntryFlag> flags) {
+            // copy and check for erroneous elements
+            flags = new HashSet<AclEntryFlag>(flags);
+            checkSet(flags, AclEntryFlag.class);
+            this.flags = flags;
+            return this;
+        }
+
+        /**
+         * Sets the flags component of this builder. On return, the flags
+         * component of this builder is a copy of the flags in the given
+         * array.
+         *
+         * @return  This builder
+         */
+        public Builder setFlags(AclEntryFlag... flags) {
+            Set<AclEntryFlag> set = new HashSet<AclEntryFlag>(flags.length);
+            // copy and check for null elements
+            for (AclEntryFlag f: flags) {
+                if (f == null)
+                    throw new NullPointerException();
+                set.add(f);
+            }
+            this.flags = set;
+            return this;
+        }
+    }
+
+    /**
+     * Constructs a new builder. The initial value of the type and who
+     * components is {@code null}. The initial value of the permissions and
+     * flags components is the empty set.
+     *
+     * @return  A new builder
+     */
+    public static Builder newBuilder() {
+        Set<AclEntryPermission> perms = Collections.emptySet();
+        Set<AclEntryFlag> flags = Collections.emptySet();
+        return new Builder(null, null, perms, flags);
+    }
+
+    /**
+     * Constructs a new builder with the components of an existing ACL entry.
+     *
+     * @param   entry
+     *          An ACL entry
+     *
+     * @return  A new builder
+     */
+    public static Builder newBuilder(AclEntry entry) {
+        return new Builder(entry.type, entry.who, entry.perms, entry.flags);
+    }
+
+    /**
+     * Returns the ACL entry type.
+     */
+    public AclEntryType type() {
+        return type;
+    }
+
+    /**
+     * Returns the principal component.
+     */
+    public UserPrincipal principal() {
+        return who;
+    }
+
+    /**
+     * Returns a copy of the permissions component.
+     *
+     * <p> The returned set is a modifiable copy of the permissions.
+     */
+    public Set<AclEntryPermission> permissions() {
+        return new HashSet<AclEntryPermission>(perms);
+    }
+
+    /**
+     * Returns a copy of the flags component.
+     *
+     * <p> The returned set is a modifiable copy of the flags.
+     */
+    public Set<AclEntryFlag> flags() {
+        return new HashSet<AclEntryFlag>(flags);
+    }
+
+    /**
+     * Compares the specified object with this ACL entry for equality.
+     *
+     * <p> If the given object is not an {@code AclEntry} then this method
+     * immediately returns {@code false}.
+     *
+     * <p> For two ACL entries to be considered equals requires that they are
+     * both the same type, their who components are equal, their permissions
+     * components are equal, and their flags components are equal.
+     *
+     * <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 an AclEntry that
+     *          is identical to this AclEntry
+     */
+
+    public boolean equals(Object ob) {
+        if (ob == this)
+            return true;
+        if (ob == null || !(ob instanceof AclEntry))
+            return false;
+        AclEntry other = (AclEntry)ob;
+        if (this.type != other.type)
+            return false;
+        if (!this.who.equals(other.who))
+            return false;
+        if (!this.perms.equals(other.perms))
+            return false;
+        if (!this.flags.equals(other.flags))
+            return false;
+        return true;
+    }
+
+    private static int hash(int h, Object o) {
+        return h * 127 + o.hashCode();
+    }
+
+    /**
+     * Returns the hash-code value for this ACL entry.
+     *
+     * <p> This method satisfies the general contract of the {@link
+     * Object#hashCode method}.
+     */
+
+    public int hashCode() {
+        // return cached hash if available
+        if (hash != 0)
+            return hash;
+        int h = type.hashCode();
+        h = hash(h, who);
+        h = hash(h, perms);
+        h = hash(h, flags);
+        hash = h;
+        return hash;
+    }
+
+    /**
+     * Returns the string representation of this ACL entry.
+     *
+     * @return  The string representation of this entry
+     */
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        // who
+        sb.append(who.getName());
+        sb.append(':');
+
+        // permissions
+        for (AclEntryPermission perm: perms) {
+            sb.append(perm.name());
+            sb.append('/');
+        }
+        sb.setLength(sb.length()-1); // drop final slash
+        sb.append(':');
+
+        // flags
+        if (!flags.isEmpty()) {
+            for (AclEntryFlag flag: flags) {
+                sb.append(flag.name());
+                sb.append('/');
+            }
+            sb.setLength(sb.length()-1);  // drop final slash
+            sb.append(':');
+        }
+
+        // type
+        sb.append(type.name());
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryFlag.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * Defines the flags for used by the flags component of an ACL {@link AclEntry
+ * entry}.
+ *
+ * <p> In this release, this class does not define flags related to {@link
+ * AclEntryType#AUDIT} and {@link AclEntryType#ALARM} entry types.
+ *
+ * @since 1.7
+ */
+
+public enum AclEntryFlag {
+
+    /**
+     * Can be placed on a directory and indicates that the ACL entry should be
+     * added to each new non-directory file created.
+     */
+    FILE_INHERIT,
+
+    /**
+     * Can be placed on a directory and indicates that the ACL entry should be
+     * added to each new directory created.
+     */
+    DIRECTORY_INHERIT,
+
+    /**
+     * Can be placed on a directory to indicate that the ACL entry should not
+     * be placed on the newly created directory which is inheritable by
+     * subdirectories of the created directory.
+     */
+    NO_PROPAGATE_INHERIT,
+
+    /**
+     * Can be placed on a directory but does not apply to the directory,
+     * only to newly created files/directories as specified by the
+     * {@link #FILE_INHERIT} and {@link #DIRECTORY_INHERIT} flags.
+     */
+    INHERIT_ONLY;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryPermission.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * Defines the permissions for use with the permissions component of an ACL
+ * {@link AclEntry entry}.
+ *
+ * @since 1.7
+ */
+
+public enum AclEntryPermission {
+
+    /**
+     * Permission to read the data of the file.
+     */
+    READ_DATA,
+
+    /**
+     * Permission to modify the file's data.
+     */
+    WRITE_DATA,
+
+    /**
+     * Permission to append data to a file.
+     */
+    APPEND_DATA,
+
+    /**
+     * Permission to read the named attributes of a file.
+     *
+     * <p> <a href="http://www.ietf.org/rfc/rfc3530.txt">RFC&nbsp;3530: Network
+     * File System (NFS) version 4 Protocol</a> defines <em>named attributes</em>
+     * as opaque files associated with a file in the file system.
+     */
+    READ_NAMED_ATTRS,
+
+    /**
+     * Permission to write the named attributes of a file.
+     *
+     * <p> <a href="http://www.ietf.org/rfc/rfc3530.txt">RFC&nbsp;3530: Network
+     * File System (NFS) version 4 Protocol</a> defines <em>named attributes</em>
+     * as opaque files associated with a file in the file system.
+     */
+    WRITE_NAMED_ATTRS,
+
+    /**
+     * Permission to execute a file.
+     */
+    EXECUTE,
+
+    /**
+     * Permission to delete a file or directory within a directory.
+     */
+    DELETE_CHILD,
+
+    /**
+     * The ability to read (non-acl) file attributes.
+     */
+    READ_ATTRIBUTES,
+
+    /**
+     * The ability to write (non-acl) file attributes.
+     */
+    WRITE_ATTRIBUTES,
+
+    /**
+     * Permission to delete the file.
+     */
+    DELETE,
+
+    /**
+     * Permission to read the ACL attribute.
+     */
+    READ_ACL,
+
+    /**
+     * Permission to write the ACL attribute.
+     */
+    WRITE_ACL,
+
+    /**
+     * Permission to change the owner.
+     */
+    WRITE_OWNER,
+
+    /**
+     * Permission to access file locally at the server with synchronous reads
+     * and writes.
+     */
+    SYNCHRONIZE;
+
+    /**
+     * Permission to list the entries of a directory (equal to {@link #READ_DATA})
+     */
+    public static final AclEntryPermission LIST_DIRECTORY = READ_DATA;
+
+    /**
+     * Permission to add a new file to a directory (equal to {@link #WRITE_DATA})
+     */
+    public static final AclEntryPermission ADD_FILE = WRITE_DATA;
+
+    /**
+     * Permission to create a subdirectory to a directory (equal to {@link #APPEND_DATA})
+     */
+    public static final AclEntryPermission ADD_SUBDIRECTORY = APPEND_DATA;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclEntryType.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * A typesafe enumeration of the access control entry types.
+ *
+ * @since 1.7
+ */
+
+public enum AclEntryType {
+    /**
+     * Explicitly grants access to a file or directory.
+     */
+    ALLOW,
+
+    /**
+     * Explicitly denies access to a file or directory.
+     */
+    DENY,
+
+    /**
+     * Log, in a system dependent way, the access specified in the
+     * permissions component of the ACL entry.
+     */
+    AUDIT,
+
+    /**
+     * Generate an alarm, in a system dependent way, the access specified in the
+     * permissions component of the ACL entry.
+     */
+    ALARM
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.nio.file.*;
+import java.util.List;
+import java.io.IOException;
+
+/**
+ * A file attribute view that supports reading or updating a file's Access
+ * Control Lists (ACL) or file owner attributes.
+ *
+ * <p> ACLs are used to specify access rights to file system objects. An ACL is
+ * an ordered list of {@link AclEntry access-control-entries}, each specifying a
+ * {@link UserPrincipal} and the level of access for that user principal. This
+ * file attribute view defines the {@link #getAcl() getAcl}, and {@link
+ * #setAcl(List) setAcl} methods to read and write ACLs based on the ACL
+ * model specified in <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC&nbsp;3530:
+ * Network File System (NFS) version 4 Protocol</i></a>. This file attribute view
+ * is intended for file system implementations that support the NFSv4 ACL model
+ * or have a <em>well-defined</em> mapping between the NFSv4 ACL model and the ACL
+ * model used by the file system. The details of such mapping are implementation
+ * dependent and are therefore unspecified.
+ *
+ * <p> This class also extends {@code FileOwnerAttributeView} so as to define
+ * methods to get and set the file owner.
+ *
+ * <p> When a file system provides access to a set of {@link FileStore
+ * file-systems} that are not homogeneous then only some of the file systems may
+ * support ACLs. The {@link FileStore#supportsFileAttributeView
+ * supportsFileAttributeView} method can be used to test if a file system
+ * supports ACLs.
+ *
+ * <a name="interop"><h4>Interoperability</h4></a>
+ *
+ * RFC&nbsp;3530 allows for special user identities to be used on platforms that
+ * support the POSIX defined access permissions. The special user identities
+ * are "{@code OWNER@}", "{@code GROUP@}", and "{@code EVERYONE@}". When both
+ * the {@code AclFileAttributeView} and the {@link PosixFileAttributeView}
+ * are supported then these special user identities may be included in ACL {@link
+ * AclEntry entries} that are read or written. The file system's {@link
+ * UserPrincipalLookupService} may be used to obtain a {@link UserPrincipal}
+ * to represent these special identities by invoking the {@link
+ * UserPrincipalLookupService#lookupPrincipalByName lookupPrincipalByName}
+ * method.
+ *
+ * <p> <b>Usage Example:</b>
+ * Suppose we wish to add an entry to an existing ACL to grant "joe" access:
+ * <pre>
+ *     // lookup "joe"
+ *     UserPrincipal joe = file.getFileSystem().getUserPrincipalLookupService()
+ *         .lookupPrincipalByName("joe");
+ *
+ *     // get view
+ *     AclFileAttributeView view = file.newFileAttributeView(AclFileAttributeView.class);
+ *
+ *     // create ACE to give "joe" read access
+ *     AclEntry entry = AclEntry.newBuilder()
+ *         .setType(AclEntryType.ALLOW)
+ *         .setPrincipal(joe)
+ *         .setPermissions(AclEntryPermission.READ_DATA, AclEntryPermission.READ_ATTRIBUTES)
+ *         .build();
+ *
+ *     // read ACL, insert ACE, re-write ACL
+ *     List&lt;AclEntry&gt acl = view.getAcl();
+ *     acl.add(0, entry);   // insert before any DENY entries
+ *     view.setAcl(acl);
+ * </pre>
+ *
+ * <h4> Dynamic Access </h4>
+ * <p> Where dynamic access to file attributes is required, the attributes
+ * supported by this attribute view are as follows:
+ * <blockquote>
+ * <table border="1" cellpadding="8">
+ *   <tr>
+ *     <th> Name </th>
+ *     <th> Type </th>
+ *   </tr>
+ *   <tr>
+ *     <td> "acl" </td>
+ *     <td> {@link List}&lt;{@link AclEntry}&gt; </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "owner" </td>
+ *     <td> {@link UserPrincipal} </td>
+ *   </tr>
+ * </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 #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>
+ *
+ * <p> Implementations supporting this attribute view may also support setting
+ * the initial ACL when creating a file or directory. The initial ACL
+ * may be provided to methods such as {@link Path#createFile createFile} or {@link
+ * Path#createDirectory createDirectory} as an {@link FileAttribute} with {@link
+ * FileAttribute#name name} {@code "acl:acl"} and a {@link FileAttribute#value
+ * value} that is the list of {@code AclEntry} objects.
+ *
+ * <p> Where an implementation supports an ACL model that differs from the NFSv4
+ * defined ACL model then setting the initial ACL when creating the file must
+ * translate the ACL to the model supported by the file system. Methods that
+ * create a file should reject (by throwing {@link IOException IOException})
+ * any attempt to create a file that would be less secure as a result of the
+ * translation.
+ *
+ * @since 1.7
+ * @see Attributes#getAcl
+ * @see Attributes#setAcl
+ */
+
+public interface AclFileAttributeView
+    extends FileOwnerAttributeView
+{
+    /**
+     * Returns the name of the attribute view. Attribute views of this type
+     * have the name {@code "acl"}.
+     */
+
+    String name();
+
+    /**
+     * Reads the access control list.
+     *
+     * <p> When the file system uses an ACL model that differs from the NFSv4
+     * defined ACL model, then this method returns an ACL that is the translation
+     * of the ACL to the NFSv4 ACL model.
+     *
+     * <p> The returned list is modifiable so as to facilitate changes to the
+     * existing ACL. The {@link #setAcl setAcl} method is used to update
+     * the file's ACL attribute.
+     *
+     * @return  An ordered list of {@link AclEntry entries} representing the
+     *          ACL
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     */
+    List<AclEntry> getAcl() throws IOException;
+
+    /**
+     * Updates (replace) the access control list.
+     *
+     * <p> Where the file system supports Access Control Lists, and it uses an
+     * ACL model that differs from the NFSv4 defined ACL model, then this method
+     * must translate the ACL to the model supported by the file system. This
+     * method should reject (by throwing {@link IOException IOException}) any
+     * attempt to write an ACL that would appear to make the file more secure
+     * than would be the case if the ACL were updated. Where an implementation
+     * does not support a mapping of {@link AclEntryType#AUDIT} or {@link
+     * AclEntryType#ALARM} entries, then this method ignores these entries when
+     * writing the ACL.
+     *
+     * <p> If an ACL entry contains a {@link AclEntry#principal user-principal}
+     * that is not associated with the same provider as this attribute view then
+     * {@link ProviderMismatchException} is thrown. Additional validation, if
+     * any, is implementation dependent.
+     *
+     * <p> If the file system supports other security related file attributes
+     * (such as a file {@link PosixFileAttributes#permissions
+     * access-permissions} for example), the updating the access control list
+     * may also cause these security related attributes to be updated.
+     *
+     * @param   acl
+     *          The new access control list
+     *
+     * @throws  IOException
+     *          If an I/O error occurs or the ACL is invalid
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     */
+    void setAcl(List<AclEntry> acl) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/AttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.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.
+ *
+ * @since 1.7
+ */
+
+public interface AttributeView {
+    /**
+     * Returns the name of the attribute view.
+     */
+    String name();
+
+    /**
+     * Reads the value of an attribute.
+     *
+     * @param   attribute
+     *          The attribute name (case sensitive)
+     *
+     * @return  The value of the attribute, or {@code null} if the attribute is
+     *          not supported
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is set and it denies access
+     */
+    Object getAttribute(String attribute) throws IOException;
+
+    /**
+     * Sets/updates the value of an attribute.
+     *
+     * @param   attribute
+     *          The attribute name (case sensitive)
+     * @param   value
+     *          The attribute value
+     *
+     * @throws  UnsupportedOperationException
+     *          If the attribute is not supported or this attribute view does
+     *          not support updating the value of the attribute
+     * @throws  IllegalArgumentException
+     *          If the attribute value is of the correct type but has an
+     *          inappropriate value
+     * @throws  ClassCastException
+     *          If the attribute value is not of the expected type or is a
+     *          collection containing elements that are not of the expected
+     *          type
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is set and it denies access
+     */
+    void setAttribute(String attribute, Object value) throws IOException;
+
+    /**
+     * Reads all, or a subset, of the attributes supported by this file attribute
+     * view.
+     *
+     * <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 others 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/Attributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,713 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+
+/**
+ * This class consists exclusively of static methods that operate on or return
+ * the attributes of files or file stores. These methods provide for convenient
+ * use of the {@link AttributeView attribute-views} defined in this package.
+ *
+ * @since 1.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();
+    }
+
+    /**
+     * Reads the basic file attributes of a file.
+     *
+     * <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. This option
+     * should be used where there is a need to determine if a file is a
+     * symbolic link:
+     * <pre>
+     *    boolean isSymbolicLink = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS).isSymbolicLink();
+     * </pre>
+     *
+     * <p> It is implementation specific if all file attributes are read as an
+     * atomic operation with respect to other file system operations.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     * @param   options
+     *          Options indicating how symbolic links are handled
+     *
+     * @return  The basic file attributes
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, the security manager's {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to file
+     *
+     * @see BasicFileAttributeView#readAttributes
+     */
+    public static BasicFileAttributes readBasicFileAttributes(FileRef file,
+                                                              LinkOption... options)
+        throws IOException
+    {
+        return file.getFileAttributeView(BasicFileAttributeView.class, options)
+            .readAttributes();
+    }
+
+    /**
+     * Reads the POSIX file attributes of a file.
+     *
+     * <p> The {@code file} parameter locates a file that supports the {@link
+     * PosixFileAttributeView}. This file attribute view provides access to a
+     * subset of the file attributes commonly associated with files on file
+     * systems used by operating systems that implement the Portable Operating
+     * System Interface (POSIX) family of standards. It is implementation
+     * specific if all file attributes are read as an atomic operation with
+     * respect to other file system operations.
+     *
+     * <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   options
+     *          Options indicating how symbolic links are handled
+     *
+     * @return  The POSIX file attributes
+     *
+     * @throws  UnsupportedOperationException
+     *          If the {@code PosixFileAttributeView} is not available
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     *
+     * @see PosixFileAttributeView#readAttributes
+     */
+    public static PosixFileAttributes readPosixFileAttributes(FileRef file,
+                                                              LinkOption... options)
+        throws IOException
+    {
+        PosixFileAttributeView view =
+            file.getFileAttributeView(PosixFileAttributeView.class, options);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        return view.readAttributes();
+    }
+
+    /**
+     * Reads the DOS file attributes of a file.
+     *
+     * <p> The {@code file} parameter locates a file that supports the {@link
+     * DosFileAttributeView}. This file attribute view provides access to
+     * legacy "DOS" attributes supported by the file systems such as File
+     * Allocation Table (FAT), commonly used in <em>consumer devices</em>. It is
+     * implementation specific if all file attributes are read as an atomic
+     * operation with respect to other file system operations.
+     *
+     * <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   options
+     *          Options indicating how symbolic links are handled
+     *
+     * @return  The DOS file attributes
+     *
+     * @throws  UnsupportedOperationException
+     *          If the {@code DosFileAttributeView} is not available
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, the security manager's {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to file
+     *
+     * @see DosFileAttributeView#readAttributes
+     */
+    public static DosFileAttributes readDosFileAttributes(FileRef file,
+                                                          LinkOption... options)
+        throws IOException
+    {
+        DosFileAttributeView view =
+            file.getFileAttributeView(DosFileAttributeView.class, options);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        return view.readAttributes();
+    }
+
+    /**
+     * Returns the owner of a file.
+     *
+     * <p> The {@code file} parameter locates a file that supports the {@link
+     * FileOwnerAttributeView}. This file attribute view provides access to
+     * a file attribute that is the owner of the file.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     *
+     * @return  A user principal representing the owner of the file
+     *
+     * @throws  UnsupportedOperationException
+     *          If the {@code FileOwnerAttributeView} is not available
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     *
+     * @see FileOwnerAttributeView#getOwner
+     */
+    public static UserPrincipal getOwner(FileRef file) throws IOException {
+        FileOwnerAttributeView view =
+            file.getFileAttributeView(FileOwnerAttributeView.class);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        return view.getOwner();
+    }
+
+    /**
+     * Updates the file owner.
+     *
+     * <p> The {@code file} parameter locates a file that supports the {@link
+     * FileOwnerAttributeView}. This file attribute view provides access to
+     * a file attribute that is the owner of the file.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     * @param   owner
+     *          The new file owner
+     *
+     * @throws  UnsupportedOperationException
+     *          If the {@code FileOwnerAttributeView} is not available
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     *
+     * @see FileOwnerAttributeView#setOwner
+     */
+    public static void setOwner(FileRef file, UserPrincipal owner)
+            throws IOException
+    {
+        FileOwnerAttributeView view =
+            file.getFileAttributeView(FileOwnerAttributeView.class);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        view.setOwner(owner);
+    }
+
+    /**
+     * Reads a file's Access Control List (ACL).
+     *
+     * <p> The {@code file} parameter locates a file that supports the {@link
+     * AclFileAttributeView}. This file attribute view provides access to ACLs
+     * based on the ACL model specified in
+     *  <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC&nbsp;3530</i></a>.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     *
+     * @return  An ordered list of {@link AclEntry entries} representing the
+     *          ACL. The returned list is modifiable.
+     *
+     * @throws  UnsupportedOperationException
+     *          If the {@code AclAttributeView} is not available
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     *
+     * @see AclFileAttributeView#getAcl
+     */
+    public static List<AclEntry> getAcl(FileRef file) throws IOException {
+        AclFileAttributeView view =
+            file.getFileAttributeView(AclFileAttributeView.class);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        return view.getAcl();
+    }
+
+    /**
+     * Updates a file's Access Control List (ACL).
+     *
+     * <p> The {@code file} parameter locates a file that supports the {@link
+     * AclFileAttributeView}. This file attribute view provides access to ACLs
+     * based on the ACL model specified in
+     *  <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC&nbsp;3530</i></a>.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     * @param   acl
+     *          The new file ACL
+     *
+     * @throws  UnsupportedOperationException
+     *          If the {@code AclFileAttributeView} is not available
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     *
+     * @see AclFileAttributeView#setAcl
+     */
+    public static void setAcl(FileRef file, List<AclEntry> acl)
+        throws IOException
+    {
+        AclFileAttributeView view =
+            file.getFileAttributeView(AclFileAttributeView.class);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        view.setAcl(acl);
+    }
+
+    /**
+     * Updates the value of a file's last modified 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.
+     *
+     * <p> If the file system does not support a last modified time attribute then
+     * this method has no effect.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     *
+     * @param   lastModifiedTime
+     *          The new last modified time, or {@code -1L} to update it to
+     *          the current time
+     * @param   unit
+     *          A {@code TimeUnit} determining how to interpret the
+     *          {@code lastModifiedTime} parameter
+     *
+     * @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
+     *          In the case of the default provider, the security manager's {@link
+     *          SecurityManager#checkWrite(String) checkWrite} method is invoked
+     *          to check write access to file
+     *
+     * @see BasicFileAttributeView#setTimes
+     */
+    public static void setLastModifiedTime(FileRef file,
+                                           long lastModifiedTime,
+                                           TimeUnit unit)
+        throws IOException
+    {
+        file.getFileAttributeView(BasicFileAttributeView.class)
+            .setTimes(lastModifiedTime, null, null, unit);
+    }
+
+    /**
+     * 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.
+     *
+     * <p> If the file system does not support a last access time attribute then
+     * this method has no effect.
+     *
+     * @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
+     *
+     * @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
+     *          In the case of the default provider, the security manager's {@link
+     *          SecurityManager#checkWrite(String) checkWrite} method is invoked
+     *          to check write access to file
+     *
+     * @see BasicFileAttributeView#setTimes
+     */
+    public static void setLastAccessTime(FileRef file,
+                                         long lastAccessTime,
+                                         TimeUnit unit)
+        throws IOException
+    {
+        file.getFileAttributeView(BasicFileAttributeView.class)
+            .setTimes(null, lastAccessTime, null, unit);
+    }
+
+    /**
+     * Sets a file's POSIX permissions.
+     *
+     * <p> The {@code file} parameter is a reference to an existing file. It
+     * supports the {@link PosixFileAttributeView} that provides access to file
+     * attributes commonly associated with files on file systems used by
+     * operating systems that implement the Portable Operating System Interface
+     * (POSIX) family of standards.
+     *
+     * @param   file
+     *          A file reference that locates the file
+     * @param   perms
+     *          The new set of permissions
+     *
+     * @throws  UnsupportedOperationException
+     *          If {@code PosixFileAttributeView} is not available
+     * @throws  ClassCastException
+     *          If the sets contains elements that are not of type {@code
+     *          PosixFilePermission}
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     *
+     * @see PosixFileAttributeView#setPermissions
+     */
+    public static void setPosixFilePermissions(FileRef file,
+                                               Set<PosixFilePermission> perms)
+        throws IOException
+    {
+        PosixFileAttributeView view =
+            file.getFileAttributeView(PosixFileAttributeView.class);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        view.setPermissions(perms);
+    }
+
+    /**
+     * Reads the space attributes of a file store.
+     *
+     * <p> The {@code store} parameter is a file store that supports the
+     * {@link FileStoreSpaceAttributeView} providing access to the space related
+     * attributes of the file store. It is implementation specific if all attributes
+     * are read as an atomic operation with respect to other file system operations.
+     *
+     * @param   store
+     *          The file store
+     *
+     * @return  The file store space attributes
+     *
+     * @throws  UnsupportedOperationException
+     *          If the file store space attribute view is not supported
+     * @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 is invoked to check read access to the file used to {@link
+     *          FileRef#getFileStore obtain} access to the file
+     *          store, and in addition it checks {@link RuntimePermission}<tt>
+     *          ("getFileStoreAttributes")</tt>
+     *
+     * @see FileStoreSpaceAttributeView#readAttributes()
+     */
+    public static FileStoreSpaceAttributes readFileStoreSpaceAttributes(FileStore store)
+        throws IOException
+    {
+        FileStoreSpaceAttributeView view =
+            store.getFileStoreAttributeView(FileStoreSpaceAttributeView.class);
+        if (view == null)
+            throw new UnsupportedOperationException();
+        return view.readAttributes();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.util.concurrent.TimeUnit;
+import java.io.IOException;
+
+/**
+ * A file attribute view that provides a view of a <em>basic set</em> of file
+ * attributes common to many file systems. The basic set of file attributes
+ * consist of <em>mandatory</em> and <em>optional</em> file attributes as
+ * defined by the {@link BasicFileAttributes} interface.
+
+ * <p> The file attributes are retrieved from the file system as a <em>bulk
+ * operation</em> by invoking the {@link #readAttributes() readAttributes} method.
+ * This class also defines the {@link #setTimes setTimes} method to update the
+ * file's time attributes.
+ *
+ * <p> Where dynamic access to file attributes is required, the attributes
+ * supported by this attribute view have the following names and types:
+ * <blockquote>
+ *  <table border="1" cellpadding="8">
+ *   <tr>
+ *     <th> Name </th>
+ *     <th> Type </th>
+ *   </tr>
+ *  <tr>
+ *     <td> "lastModifiedTime" </td>
+ *     <td> {@link Long} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "lastAccessTime" </td>
+ *     <td> {@link Long} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "creationTime" </td>
+ *     <td> {@link Long} </td>
+ *   </tr>
+ *  <tr>
+ *     <td> "resolution" </td>
+ *     <td> {@link java.util.concurrent.TimeUnit} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "size" </td>
+ *     <td> {@link Long} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "isRegularFile" </td>
+ *     <td> {@link Boolean} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "isDirectory" </td>
+ *     <td> {@link Boolean} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "isSymbolicLink" </td>
+ *     <td> {@link Boolean} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "isOther" </td>
+ *     <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
+ * #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.
+ *
+ * @since 1.7
+ * @see Attributes
+ */
+
+public interface BasicFileAttributeView
+    extends FileAttributeView
+{
+    /**
+     * Returns the name of the attribute view. Attribute views of this type
+     * have the name {@code "basic"}.
+     */
+
+    String name();
+
+    /**
+     * Reads the basic file attributes as a bulk operation.
+     *
+     * <p> It is implementation specific if all file attributes are read as an
+     * atomic operation with respect to other file system operations.
+     *
+     * @return  The file attributes
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, its {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file
+     */
+    BasicFileAttributes readAttributes() throws IOException;
+
+    /**
+     * Updates any or all of the file's last modified time, last access time,
+     * 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.
+     *
+     * <p> If any of the {@code lastModifiedTime}, {@code lastAccessTime},
+     * or {@code createTime} parameters has the value {@code null} then the
+     * corresponding timestamp is not changed. An implementation may require to
+     * 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
+     * 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
+     * @param   lastAccessTime
+     *          The last access time, or {@code -1L} to update it to
+     *          the current time, or {@code null} to not change the attribute.
+     * @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
+     *
+     * @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
+     *          In the case of the default provider, a security manager is
+     *          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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Basic attributes associated with a file in a file system.
+ *
+ * <p> Basic file attributes are attributes that are common to many file systems
+ * and consist of mandatory and optional file attributes as defined by this
+ * interface.
+ *
+ * <p> <b>Usage Example:</b>
+ * <pre>
+ *    FileRef file = ...
+ *    BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
+ * </pre>
+ *
+ * @since 1.7
+ *
+ * @see BasicFileAttributeView
+ */
+
+public interface BasicFileAttributes {
+
+    /**
+     * 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.
+     */
+    long 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.
+     */
+    long 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.
+     */
+    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();
+
+    /**
+     * Tells whether the file is a regular file with opaque content.
+     */
+    boolean isRegularFile();
+
+    /**
+     * Tells whether the file is a directory.
+     */
+    boolean isDirectory();
+
+    /**
+     * Tells whether the file is a symbolic-link.
+     */
+    boolean isSymbolicLink();
+
+    /**
+     * Tells whether the file is something other than a regular file, directory,
+     * or link.
+     */
+    boolean isOther();
+
+    /**
+     * Returns the size of the file (in bytes). The size may differ from the
+     * actual size on the file system due to compression, support for sparse
+     * files, or other reasons. The size of files that are not {@link
+     * #isRegularFile regular} files is implementation specific and
+     * therefore unspecified.
+     *
+     * @return  The file size, in bytes
+     */
+    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
+     * uniquely identify a file. Such identifiers are important for operations
+     * such as file tree traversal in file systems that support <a
+     * href="../package-summary.html#links">symbolic links</a> or file systems
+     * that allow a file to be an entry in more than one directory. On UNIX file
+     * systems, for example, the <em>device ID</em> and <em>inode</em> are
+     * commonly used for such purposes.
+     *
+     * <p> The file key returned by this method can only be guaranteed to be
+     * unique if the file system and files remain static. Whether a file system
+     * re-use identifiers after a file is deleted is implementation dependent and
+     * therefore unspecified.
+     *
+     * <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
+     * non-{@code null} file keys, then their file keys are equal.
+     *
+     * @see java.nio.file.Files#walkFileTree
+     */
+    Object fileKey();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.io.IOException;
+
+/**
+ * A file attribute view that provides a view of the legacy "DOS" file attributes.
+ * These attributes are supported by file systems such as the File Allocation
+ * Table (FAT) format commonly used in <em>consumer devices</em>.
+ *
+ * <p> A {@code DosFileAttributeView} is a {@link BasicFileAttributeView} that
+ * additionally supports access to the set of DOS attribute flags that are used
+ * to indicate if the file is read-only, hidden, a system file, or archived.
+ *
+ * <p> Where dynamic access to file attributes is required, the attributes
+ * supported by this attribute view are as defined by {@code
+ * BasicFileAttributeView}, and in addition, the following attributes are
+ * supported:
+ * <blockquote>
+ * <table border="1" cellpadding="8">
+ *   <tr>
+ *     <th> Name </th>
+ *     <th> Type </th>
+ *   </tr>
+ *   <tr>
+ *     <td> readonly </td>
+ *     <td> {@link Boolean} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> hidden </td>
+ *     <td> {@link Boolean} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> system </td>
+ *     <td> {@link Boolean} </td>
+ *   </tr>
+ *   <tr>
+ *     <td> archive </td>
+ *     <td> {@link Boolean} </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, 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.
+ *
+ * @since 1.7
+ */
+
+public interface DosFileAttributeView
+    extends BasicFileAttributeView
+{
+    /**
+     * Returns the name of the attribute view. Attribute views of this type
+     * have the name {@code "dos"}.
+     */
+
+    String name();
+
+    /**
+     * @throws  IOException                             {@inheritDoc}
+     * @throws  SecurityException                       {@inheritDoc}
+     */
+
+    DosFileAttributes readAttributes() throws IOException;
+
+    /**
+     * Updates the value of the read-only attribute.
+     *
+     * <p> It is implementation specific if the attribute can be updated as an
+     * atomic operation with respect to other file system operations. An
+     * implementation may, for example, require to read the existing value of
+     * the DOS attribute in order to update this attribute.
+     *
+     * @param   value
+     *          The new value of the attribute
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default, and a security manager is installed,
+     *          its  {@link SecurityManager#checkWrite(String) checkWrite} method
+     *          is invoked to check write access to the file
+     */
+    void setReadOnly(boolean value) throws IOException;
+
+    /**
+     * Updates the value of the hidden attribute.
+     *
+     * <p> It is implementation specific if the attribute can be updated as an
+     * atomic operation with respect to other file system operations. An
+     * implementation may, for example, require to read the existing value of
+     * the DOS attribute in order to update this attribute.
+     *
+     * @param   value
+     *          The new value of the attribute
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default, and a security manager is installed,
+     *          its  {@link SecurityManager#checkWrite(String) checkWrite} method
+     *          is invoked to check write access to the file
+     */
+    void setHidden(boolean value) throws IOException;
+
+    /**
+     * Updates the value of the system attribute.
+     *
+     * <p> It is implementation specific if the attribute can be updated as an
+     * atomic operation with respect to other file system operations. An
+     * implementation may, for example, require to read the existing value of
+     * the DOS attribute in order to update this attribute.
+     *
+     * @param   value
+     *          The new value of the attribute
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default, and a security manager is installed,
+     *          its  {@link SecurityManager#checkWrite(String) checkWrite} method
+     *          is invoked to check write access to the file
+     */
+    void setSystem(boolean value) throws IOException;
+
+    /**
+     * Updates the value of the archive attribute.
+     *
+     * <p> It is implementation specific if the attribute can be updated as an
+     * atomic operation with respect to other file system operations. An
+     * implementation may, for example, require to read the existing value of
+     * the DOS attribute in order to update this attribute.
+     *
+     * @param   value
+     *          The new value of the attribute
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default, and a security manager is installed,
+     *          its  {@link SecurityManager#checkWrite(String) checkWrite} method
+     *          is invoked to check write access to the file
+     */
+    void setArchive(boolean value) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * File attributes associated with a file in a file system that supports
+ * legacy "DOS" attributes.
+ *
+ * <p> The DOS attributes of a file are retrieved using a {@link
+ * DosFileAttributeView} by invoking its {@link DosFileAttributeView#readAttributes
+ * readAttributes} method.
+ *
+ * @since 1.7
+ *
+ * @see Attributes#readDosFileAttributes
+ */
+
+public interface DosFileAttributes
+    extends BasicFileAttributes
+{
+    /**
+     * Returns the value of the read-only attribute.
+     *
+     * <p> This attribute is often used as a simple access control mechanism
+     * to prevent files from being deleted or updated. Whether the file system
+     * or platform does any enforcement to prevent <em>read-only</em> files
+     * from being updated is implementation specific.
+     *
+     * @return  The value of the read-only attribute.
+     */
+    boolean isReadOnly();
+
+    /**
+     * Returns the value of the hidden attribute.
+     *
+     * <p> This attribute is often used to indicate if the file is visible to
+     * users.
+     *
+     * @return  The value of the hidden attribute.
+     */
+    boolean isHidden();
+
+    /**
+     * Returns the value of the archive attribute.
+     *
+     * <p> This attribute is typically used by backup programs.
+     *
+     * @return  The value of the archive attribute.
+     */
+    boolean isArchive();
+
+    /**
+     * Returns the value of the system attribute.
+     *
+     * <p> This attribute is often used to indicate that the file is a component
+     * of the operating system.
+     *
+     * @return  The value of the system attribute.
+     */
+    boolean isSystem();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttribute.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * An object that encapsulates the value of a file attribute that can be set
+ * atomically when creating a new file or directory by invoking the {@link
+ * java.nio.file.Path#createFile createFile} or {@link
+ * java.nio.file.Path#createDirectory createDirectory} methods.
+ *
+ * @param <T> The type of the file attribute value
+ *
+ * @since 1.7
+ * @see PosixFilePermissions#asFileAttribute
+ */
+
+public interface FileAttribute<T> {
+    /**
+     * Returns the attribute name.
+     */
+    String name();
+
+    /**
+     * Returns the attribute value.
+     */
+    T value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * An attribute view that is a read-only or updatable view of non-opaque
+ * values associated with a file in a filesystem. This interface is extended or
+ * implemented by specific file attribute views that define methods to read
+ * and/or update the attributes of a file.
+ *
+ * @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
+    extends AttributeView
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileOwnerAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.io.IOException;
+
+/**
+ * A file attribute view that supports reading or updating the owner of a file.
+ * This file attribute view is intended for file system implementations that
+ * support a file attribute that represents an identity that is the owner of
+ * the file. Often the owner of a file is the identity of the entity that
+ * created the file.
+ *
+ * <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.
+ *
+ * @since 1.7
+ */
+
+public interface FileOwnerAttributeView
+    extends FileAttributeView
+{
+    /**
+     * Returns the name of the attribute view. Attribute views of this type
+     * have the name {@code "owner"}.
+     */
+
+    String name();
+
+    /**
+     * Read the file owner.
+     *
+     * <p> It it implementation specific if the file owner can be a {@link
+     * GroupPrincipal group}.
+     *
+     * @return  the file owner
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessUserInformation")</tt> or its
+     *          {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     */
+    UserPrincipal getOwner() throws IOException;
+
+    /**
+     * Updates the file owner.
+     *
+     * <p> It it implementation specific if the file owner can be a {@link
+     * GroupPrincipal group}. To ensure consistent and correct behavior
+     * across platforms it is recommended that this method should only be used
+     * to set the file owner to a user principal that is not a group.
+     *
+     * @param   owner
+     *          The new file owner
+     *
+     * @throws  IOException
+     *          If an I/O error occurs, or the {@code owner} parameter is a
+     *          group and this implementation does not support setting the owner
+     *          to a group
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessUserInformation")</tt> or its
+     *          {@link SecurityManager#checkWrite(String) checkWrite} method
+     *          denies write access to the file.
+     */
+    void setOwner(UserPrincipal owner) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * An attribute view that is a read-only or updatable view of the attributes of
+ * a {@link java.nio.file.FileStore}.
+ *
+ * @since 1.7
+ */
+
+public interface FileStoreAttributeView
+    extends AttributeView
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.nio.file.*;
+import java.util.Map;
+import java.io.IOException;
+
+/**
+ * A file store attribute view that supports reading of space attributes.
+ *
+ * <p> Where dynamic access to file attributes is required, the attributes
+ * supported by this attribute view have the following names and types:
+ * <blockquote>
+ * <table border="1" cellpadding="8">
+ *   <tr>
+ *     <th> Name </th>
+ *     <th> Type </th>
+ *   </tr>
+ *  <tr>
+ *     <td> "totalSpace" </td>
+ *     <td> {@link Long} </td>
+ *   </tr>
+ *  <tr>
+ *     <td> "usableSpace" </td>
+ *     <td> {@link Long} </td>
+ *   </tr>
+ *  <tr>
+ *     <td> "unallocatedSpace" </td>
+ *     <td> {@link Long} </td>
+ *   </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.
+ *
+ * @since 1.7
+ */
+
+public interface FileStoreSpaceAttributeView
+    extends FileStoreAttributeView
+{
+    /**
+     * Returns the name of the attribute view. Attribute views of this type
+     * have the name {@code "space"}.
+     */
+
+    String name();
+
+    /**
+     * Reads the disk space attributes as a bulk operation.
+     *
+     * <p> It is file system specific if all attributes are read as an
+     * atomic operation with respect to other file system operations.
+     *
+     * @return  The disk space attributes
+     *
+     * @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 is invoked to check read access to the file used to {@link
+     *          FileRef#getFileStore obtain} access to the file
+     *          system, and in addition it checks {@link RuntimePermission}<tt>
+     *          ("getFileStoreAttributes")</tt>
+     */
+    FileStoreSpaceAttributes readAttributes() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * Space related attributes of a file store.
+ *
+ * @since 1.7
+ *
+ * @see Attributes#readFileStoreSpaceAttributes
+ */
+
+public interface FileStoreSpaceAttributes {
+    /**
+     * Returns the size, in bytes, of the file store.
+     */
+    long totalSpace();
+
+    /**
+     * Returns the number of bytes available to this Java virtual machine on the
+     * file store.
+     *
+     * <p> The returned number of available bytes is a hint, but not a
+     * guarantee, that it is possible to use most or any of these bytes.  The
+     * number of usable bytes is most likely to be accurate immediately
+     * after the space attributes are obtained. It is likely to be made inaccurate
+     * by any external I/O operations including those made on the system outside
+     * of this Java virtual machine.
+     */
+    long usableSpace();
+
+    /**
+     * Returns the number of unallocated bytes in the file store.
+     *
+     * <p> The returned number of unallocated bytes is a hint, but not a
+     * guarantee, that it is possible to use most or any of these bytes.  The
+     * number of unallocated bytes is most likely to be accurate immediately
+     * after the space attributes are obtained. It is likely to be
+     * made inaccurate by any external I/O operations including those made on
+     * the system outside of this virtual machine.
+     */
+    long unallocatedSpace();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/GroupPrincipal.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+/**
+ * A {@code UserPrincipal} representing a <em>group identity</em>, used to
+ * determine access rights to objects in a file system. The exact definition of
+ * a group is implementation specific, but typically, it represents an identity
+ * created for administrative purposes so as to determine the access rights for
+ * the members of the group. Whether an entity can be a member of multiple
+ * groups, and whether groups can be nested, are implementation specified and
+ * therefore not specified.
+ *
+ * @since 1.7
+ *
+ * @see UserPrincipalLookupService#lookupPrincipalByGroupName
+ */
+
+public interface GroupPrincipal extends UserPrincipal { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.io.IOException;
+
+/**
+ * A file attribute view that provides a view of a file's user-defined
+ * attributes, sometimes known as <em>extended attributes</em>. Named attributes
+ * are used to store metadata with a file that is not meaningful to the file
+ * system. It is primarily intended for file system implementations that support
+ * such a capability directly but may be emulated. The details of such emulation
+ * are highly implementation specific and therefore not specified.
+ *
+ * <p> This {@code FileAttributeView} provides a view of a file's named
+ * attributes as a set of name/value pairs, where the attribute name is
+ * represented by a {@code String}. An implementation may require to encode and
+ * decode from the platform or file system representation when accessing the
+ * attribute. The value has opaque content. This attribute view defines the
+ * {@link #read read} and {@link #write write} methods to read the value into
+ * or write from a {@link ByteBuffer}. This {@code FileAttributeView} is not
+ * intended for use where the size of an attribute value is larger than {@link
+ * Integer#MAX_VALUE}.
+ *
+ * <p> {@note There has been feedback that the read/write methods should use byte
+ * arrays instead of ByteBuffers.}
+ *
+ * <p> Named attributes may be used in some implementations to store security
+ * related attributes so consequently, in the case of the default provider at
+ * least, all methods that access named attributes require the
+ * {@code RuntimePermission("accessNamedAttributes")} permission when a
+ * security manager is installed.
+ *
+ * <p> The {@link java.nio.file.FileStore#supportsFileAttributeView
+ * supportsFileAttributeView} method may be used to test if a specific {@link
+ * java.nio.file.FileStore FileStore} supports the storage of named 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 as if by invoking the {@link #read read} method. Upon return, the
+ * buffer's {@link ByteBuffer#position position} is the index of the first
+ * byte of the attribute value, and its {@link ByteBuffer#limit limit} is
+ * the index of the first byte that should not be read. The {@link
+ * #setAttribute setAttribute} method may be used to write the value of a
+ * user-defined/named attribute from a buffer as if by invoking the {@link
+ * #write write} method.
+ *
+ * @since 1.7
+ */
+
+public interface NamedAttributeView
+    extends FileAttributeView
+{
+    /**
+     * Returns the name of this attribute view. Attribute views of this type
+     * have the name {@code "xattr"}.
+     */
+
+    String name();
+
+    /**
+     * Returns a list containing the names of the user-defined/named
+     * attributes.
+     *
+     * @return  An unmodifiable list continaing the names of the file's
+     *          user-defined/named attributes
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessNamedAttributes")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     */
+    List<String> list() throws IOException;
+
+    /**
+     * Returns the size of the value of a user-defined/named attribute.
+     *
+     * @param   name
+     *          The attribute name
+     *
+     * @return  The size of the attribute value, in bytes.
+     *
+     * @throws  ArithmeticException
+     *          If the size of the attribute is larger than {@link Integer#MAX_VALUE}
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessNamedAttributes")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     */
+    int size(String name) throws IOException;
+
+    /**
+     * Read the value of a user-defined/named attribute into a buffer.
+     *
+     * <p> This method reads the value of the attribute into the given buffer
+     * as a sequence of bytes, failing if the number of bytes remaining in
+     * the buffer is insufficient to read the complete attribute value. The
+     * number of bytes transferred into the buffer is {@code n}, where {@code n}
+     * is the size of the attribute value. The first byte in the sequence is at
+     * index {@code p} and the last byte is at index {@code p + n - 1}, where
+     * {@code p} is the buffer's position. Upon return the buffer's position
+     * will be equal to {@code p + n}; its limit will not have changed.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we want to read a file's MIME type that is stored as a named
+     * attribute:
+     * <pre>
+     *    NamedAttributeView view = file.getFileAttributeView(NamedAttributeView.class);
+     *    String name = "user.mimetype";
+     *    ByteBuffer buf = ByteBuffer.allocate(view.size(name));
+     *    view.read(name, buf);
+     *    buf.flip();
+     *    String value = Charset.defaultCharset().decode(buf).toString();
+     * </pre>
+     *
+     * @param   name
+     *          The attribute name
+     * @param   dst
+     *          The destination buffer
+     *
+     * @return  The number of bytes read, possibly zero
+     *
+     * @throws  IllegalArgumentException
+     *          If the destination buffer is read-only
+     * @throws  IOException
+     *          If an I/O error occurs or there is insufficient space in the
+     *          destination buffer for the attribute value
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessNamedAttributes")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     *
+     * @see #size
+     */
+    int read(String name, ByteBuffer dst) throws IOException;
+
+    /**
+     * Writes the value of a user-defined/named attribute from a buffer.
+     *
+     * <p> This method writes the value of the attribute from a given buffer as
+     * a sequence of bytes. The size of the value to transfer is {@code r},
+     * where {@code r} is the number of bytes remaining in the buffer, that is
+     * {@code src.remaining()}. The sequence of bytes is transferred from the
+     * buffer starting at index {@code p}, where {@code p} is the buffer's
+     * position. Upon return, the buffer's position will be equal to {@code
+     * p + n}, where {@code n} is the number of bytes transferred; its limit
+     * will not have changed.
+     *
+     * <p> If an attribute of the given name already exists then its value is
+     * replaced. If the attribute does not exist then it is created. If it
+     * implementation specific if a test to check for the existence of the
+     * attribute and the creation of attribute are atomic with repect to other
+     * file system activities.
+     *
+     * <p> Where there is insufficient space to store the attribute, or the
+     * attribute name or value exceed an implementation specific maximum size
+     * then an {@code IOException} is thrown.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we want to write a file's MIME type as a named attribute:
+     * <pre>
+     *    NamedAttributeView view = file.getFileAttributeView(NamedAttributeView.class);
+     *    view.write("user.mimetype", Charset.defaultCharset().encode("text/html"));
+     * </pre>
+     *
+     * @param   name
+     *          The attribute name
+     * @param   src
+     *          The buffer containing the attribute value
+     *
+     * @return  The number of bytes written, possibly zero
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessNamedAttributes")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     */
+    int write(String name, ByteBuffer src) throws IOException;
+
+    /**
+     * Deletes a user-defined/named attribute.
+     *
+     * @param   name
+     *          The attribute name
+     *
+     * @throws  IOException
+     *          If an I/O error occurs or the attribute does not exist
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link
+     *          RuntimePermission}<tt>("accessNamedAttributes")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     */
+    void delete(String name) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.nio.file.*;
+import java.util.Set;
+import java.io.IOException;
+
+/**
+ * A file attribute view that provides a view of the file attributes commonly
+ * associated with files on file systems used by operating systems that implement
+ * the Portable Operating System Interface (POSIX) family of standards.
+ *
+ * <p> Operating systems that implement the <a href="http://www.opengroup.org">
+ * POSIX</a> family of standards commonly use file systems that have a
+ * file <em>owner</em>, <em>group-owner</em>, and related <em>access
+ * permissions</em>. This file attribute view provides read and write access
+ * to these attributes.
+ *
+ * <p> The {@link #readAttributes() readAttributes} method is used to read the
+ * file's attributes. The file {@link PosixFileAttributes#owner() owner} is
+ * represented by a {@link UserPrincipal} that is the identity of the file owner
+ * for the purposes of access control. The {@link PosixFileAttributes#group()
+ * group-owner}, represented by a {@link GroupPrincipal}, is the identity of the
+ * group owner, where a group is an identity created for administrative purposes
+ * so as to determine the access rights for the members of the group.
+ *
+ * <p> The {@link PosixFileAttributes#permissions() permissions} attribute is a
+ * set of access permissions. This file attribute view provides access to the nine
+ * permission defined by the {@link PosixFilePermission} class.
+ * These nine permission bits determine the <em>read</em>, <em>write</em>, and
+ * <em>execute</em> access for the file owner, group, and others (others
+ * meaning identities other than the owner and members of the group). Some
+ * operating systems and file systems may provide additional permission bits
+ * but access to these other bits is not defined by this class in this release.
+ *
+ * <p> <b>Usage Example:</b>
+ * Suppose we need to print out the owner and access permissions of a file:
+ * <pre>
+ *     FileRef file = ...
+ *     PosixFileAttributes attrs = file.newFileAttributeView(PosixFileAttributeView.class)
+ *         .readAttributes();
+ *     System.out.format("%s %s%n",
+ *         atts.owner().getName(),
+ *         PosixFilePermissions.toString(attrs.permissions()));
+ * </pre>
+ *
+ * <h4> Dynamic Access </h4>
+ * <p> Where dynamic access to file attributes is required, the attributes
+ * supported by this attribute view are as defined by {@link
+ * BasicFileAttributeView} and {@link FileOwnerAttributeView}, and in addition,
+ * the following attributes are supported:
+ * <blockquote>
+ * <table border="1" cellpadding="8">
+ *   <tr>
+ *     <th> Name </th>
+ *     <th> Type </th>
+ *   </tr>
+ *  <tr>
+ *     <td> "permissions" </td>
+ *     <td> {@link Set}&lt;{@link PosixFilePermission}&gt; </td>
+ *   </tr>
+ *   <tr>
+ *     <td> "group" </td>
+ *     <td> {@link GroupPrincipal} </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, 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 permissions, owner, or group-owner as if by invoking the {@link
+ * #setPermissions setPermissions}, {@link #setOwner setOwner}, and {@link
+ * #setGroup setGroup} methods respectively.
+ *
+ * <h4> Setting Initial Permissions </h4>
+ * <p> Implementations supporting this attribute view may also support setting
+ * the initial permissions when creating a file or directory. The
+ * initial permissions are provided to the  {@link Path#createFile createFile}
+ * or {@link Path#createDirectory createDirectory} methods as a {@link
+ * FileAttribute} with {@link FileAttribute#name name} {@code "posix:permissions"}
+ * and a {@link FileAttribute#value value} that is the set of permissions. The
+ * following example uses the {@link PosixFilePermissions#asFileAttribute
+ * asFileAttribute} method to construct a {@code FileAttribute} when creating a
+ * file:
+ *
+ * <pre>
+ *     Path path = ...
+ *     Set&lt;PosixFilePermission&gt; perms =
+ *         EnumSet.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ);
+ *     path.createFile(PosixFilePermissions.asFileAttribute(perms));
+ * </pre>
+ *
+ * <p> When the access permissions are set at file creation time then the actual
+ * value of the permissions may differ that the value of the attribute object.
+ * The reasons for this are implementation specific. On UNIX systems, for
+ * example, a process has a <em>umask</em> that impacts the permission bits
+ * of newly created files. Where an implementation supports the setting of
+ * the access permissions, and the underlying file system supports access
+ * permissions, then it is required that the value of the actual access
+ * permissions will be equal or less than the value of the attribute
+ * provided to the {@link java.nio.file.Path#createFile createFile} or
+ * {@link java.nio.file.Path#createDirectory createDirectory} methods. In
+ * other words, the file may be more secure than requested.
+ *
+ * @since 1.7
+ *
+ * @see Attributes#readPosixFileAttributes
+ */
+
+public interface PosixFileAttributeView
+    extends BasicFileAttributeView, FileOwnerAttributeView
+{
+    /**
+     * Returns the name of the attribute view. Attribute views of this type
+     * have the name {@code "posix"}.
+     */
+
+    String name();
+
+    /**
+     * @throws  IOException                {@inheritDoc}
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkRead(String) checkRead} method
+     *          denies read access to the file.
+     */
+
+    PosixFileAttributes readAttributes() throws IOException;
+
+    /**
+     * Updates the file permissions.
+     *
+     * @param   perms
+     *          The new set of permissions
+     *
+     * @throws  ClassCastException
+     *          If the sets contains elements that are not of type {@code
+     *          PosixFilePermission}
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, a security manager is
+     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     */
+    void setPermissions(Set<PosixFilePermission> perms) throws IOException;
+
+    /**
+     * Updates the file group-owner.
+     *
+     * @param   group
+     *          The new file group-owner
+
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method denies write access to the file.
+     */
+    void setGroup(GroupPrincipal group) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.util.Set;
+
+/**
+ * File attributes associated with files on file systems used by operating systems
+ * that implement the Portable Operating System Interface (POSIX) family of
+ * standards.
+ *
+ * <p> The POSIX attributes of a file are retrieved using a {@link
+ * PosixFileAttributeView} by invoking its {@link
+ * PosixFileAttributeView#readAttributes readAttributes} method.
+ *
+ * @since 1.7
+ *
+ * @see Attributes#readPosixFileAttributes
+ */
+
+public interface PosixFileAttributes
+    extends BasicFileAttributes
+{
+    /**
+     * Returns the owner of the file.
+     *
+     * @return  The file owner
+     *
+     * @see PosixFileAttributeView#setOwner
+     */
+    UserPrincipal owner();
+
+    /**
+     * Returns the group owner of the file.
+     *
+     * @return  The file group owner
+     *
+     * @see PosixFileAttributeView#setGroup
+     */
+    GroupPrincipal group();
+
+    /**
+     * Returns the permissions of the file. The file permissions are returned
+     * as a set of {@link PosixFilePermission} elements. The returned set is a
+     * copy of the file permissions and is modifiable. This allows the result
+     * to be modified and passed to the {@link PosixFileAttributeView#setPermissions
+     * setPermissions} method to update the file's permissions.
+     *
+     * @return  The file permissions
+     *
+     * @see PosixFileAttributeView#setPermissions
+     */
+    Set<PosixFilePermission> permissions();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermission.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.util.*;
+
+/**
+ * Defines the bits for use with the {@link PosixFileAttributes#permissions()
+ * permissions} attribute.
+ *
+ * <p> The {@link PosixFileAttributes} class defines method methods for
+ * manipulating {@link Set sets} of permissions.
+ *
+ * @since 1.7
+ */
+
+public enum PosixFilePermission {
+
+    /**
+     * Read permission, owner.
+     */
+    OWNER_READ,
+
+    /**
+     * Write permission, owner.
+     */
+    OWNER_WRITE,
+
+    /**
+     * Execute/search permission, owner.
+     */
+    OWNER_EXECUTE,
+
+    /**
+     * Read permission, group.
+     */
+    GROUP_READ,
+
+    /**
+     * Write permission, group.
+     */
+    GROUP_WRITE,
+
+    /**
+     * Execute/search permission, group.
+     */
+    GROUP_EXECUTE,
+
+    /**
+     * Read permission, others.
+     */
+    OTHERS_READ,
+
+    /**
+     * Write permission, others.
+     */
+    OTHERS_WRITE,
+
+    /**
+     * Execute/search permission, others.
+     */
+    OTHERS_EXECUTE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/PosixFilePermissions.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import static java.nio.file.attribute.PosixFilePermission.*;
+import java.util.*;
+
+/**
+ * This class consists exclusively of static methods that operate on sets of
+ * {@link PosixFilePermission} objects.
+ *
+ * @since 1.7
+ */
+
+public class PosixFilePermissions {
+    private PosixFilePermissions() { }
+
+    // Write string representation of permission bits to {@code sb}.
+    private static void writeBits(StringBuilder sb, boolean r, boolean w, boolean x) {
+        if (r) {
+            sb.append('r');
+        } else {
+            sb.append('-');
+        }
+        if (w) {
+            sb.append('w');
+        } else {
+            sb.append('-');
+        }
+        if (x) {
+            sb.append('x');
+        } else {
+            sb.append('-');
+        }
+    }
+
+    /**
+     * Returns the {@code String} representation of a set of permissions.
+     *
+     * <p> If the set contains {@code null} or elements that are not of type
+     * {@code PosixFilePermission} then these elements are ignored.
+     *
+     * @param   perms
+     *          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);
+        writeBits(sb, perms.contains(OWNER_READ), perms.contains(OWNER_WRITE),
+          perms.contains(OWNER_EXECUTE));
+        writeBits(sb, perms.contains(GROUP_READ), perms.contains(GROUP_WRITE),
+          perms.contains(GROUP_EXECUTE));
+        writeBits(sb, perms.contains(OTHERS_READ), perms.contains(OTHERS_WRITE),
+          perms.contains(OTHERS_EXECUTE));
+        return sb.toString();
+    }
+
+    private static boolean isSet(char c, char setValue) {
+        if (c == setValue)
+            return true;
+        if (c == '-')
+            return false;
+        throw new IllegalArgumentException("Invalid mode");
+    }
+    private static boolean isR(char c) { return isSet(c, 'r'); }
+    private static boolean isW(char c) { return isSet(c, 'w'); }
+    private static boolean isX(char c) { return isSet(c, 'x'); }
+
+    /**
+     * Returns the set of permissions corresponding to a given {@code String}
+     * representation.
+     *
+     * <p> The {@code perms} parameter is a {@code String} representing the
+     * permissions. It has 9 characters that are interpreted as three sets of
+     * three. The first set refers to the owner's permissions; the next to the
+     * group permissions and the last to others. Within each set, the first
+     * character is {@code 'r'} to indicate permission to read, the second
+     * character is {@code 'w'} to indicate permission to write, and the third
+     * character is {@code 'x'} for execute permission. Where a permission is
+     * not set then the corresponding character is set to {@code '-'}.
+     *
+     * <p> <b>Usage Example:</b>
+     * Suppose we require the set of permissions that indicate the owner has read,
+     * write, and execute permissions, the group has read and execute permissions
+     * and others have none.
+     * <pre>
+     *   Set&lt;PosixFilePermission&gt; perms = PosixFilePermissions.fromString("rwxr-x---");
+     * </pre>
+     *
+     * @param   perms
+     *          String representing a set of permissions
+     *
+     * @return  The resulting set of permissions
+     *
+     * @throws  IllegalArgumentException
+     *          If the string cannot be converted to a set of permissions
+     *
+     * @see #toString(Set)
+     */
+    public static Set<PosixFilePermission> fromString(String perms) {
+        if (perms.length() != 9)
+            throw new IllegalArgumentException("Invalid mode");
+        Set<PosixFilePermission> result = new HashSet<PosixFilePermission>();
+        if (isR(perms.charAt(0))) result.add(OWNER_READ);
+        if (isW(perms.charAt(1))) result.add(OWNER_WRITE);
+        if (isX(perms.charAt(2))) result.add(OWNER_EXECUTE);
+        if (isR(perms.charAt(3))) result.add(GROUP_READ);
+        if (isW(perms.charAt(4))) result.add(GROUP_WRITE);
+        if (isX(perms.charAt(5))) result.add(GROUP_EXECUTE);
+        if (isR(perms.charAt(6))) result.add(OTHERS_READ);
+        if (isW(perms.charAt(7))) result.add(OTHERS_WRITE);
+        if (isX(perms.charAt(8))) result.add(OTHERS_EXECUTE);
+        return result;
+    }
+
+    /**
+     * Creates a {@link FileAttribute}, encapsulating a copy of the given file
+     * permissions, suitable for passing to the {@link java.nio.file.Path#createFile
+     * createFile} or {@link java.nio.file.Path#createDirectory createDirectory}
+     * methods.
+     *
+     * @param   perms
+     *          The set of permissions
+     *
+     * @return  An attribute encapsulating the given file permissions with
+     *          {@link FileAttribute#name name} {@code "posix:permissions"}
+     *
+     * @throws  ClassCastException
+     *          If the sets contains elements that are not of type {@code
+     *          PosixFilePermission}
+     */
+    public static FileAttribute<Set<PosixFilePermission>>
+        asFileAttribute(Set<PosixFilePermission> perms)
+    {
+        // copy set and check for nulls (CCE will be thrown if an element is not
+        // a PosixFilePermission)
+        perms = new HashSet<PosixFilePermission>(perms);
+        for (PosixFilePermission p: perms) {
+            if (p == null)
+                throw new NullPointerException();
+        }
+        final Set<PosixFilePermission> value = perms;
+        return new FileAttribute<Set<PosixFilePermission>>() {
+
+            public String name() {
+                return "posix:permissions";
+            }
+
+            public Set<PosixFilePermission> value() {
+                return Collections.unmodifiableSet(value);
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipal.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.security.Principal;
+
+/**
+ * A {@code Principal} representing an identity used to determine access rights
+ * to objects in a file system.
+ *
+ * <p> On many platforms and file systems an entity requires appropriate access
+ * rights or permissions in order to access objects in a file system. The
+ * access rights are generally performed by checking the identity of the entity.
+ * For example, on implementations that use Access Control Lists (ACLs) to
+ * enforce privilege separation then a file in the file system may have an
+ * associated ACL that determine the access rights of identities specified in the
+ * ACL.
+ *
+ * <p> A {@code UserPrincipal} object is an abstract representation of an
+ * identity. It has a {@link #getName() name} that is typically the username or
+ * account name that it represents. User principal objects may be obtained using
+ * a {@link UserPrincipalLookupService}, or returned by {@link
+ * FileAttributeView} implementations that provide access to identity related
+ * attributes. For example, the {@link AclFileAttributeView} and {@link
+ * PosixFileAttributeView} provide access to a file's {@link
+ * PosixFileAttributes#owner owner}.
+ *
+ * @since 1.7
+ */
+
+public interface UserPrincipal extends Principal { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalLookupService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.io.IOException;
+
+/**
+ * An object to lookup user and group principals by name. A {@link UserPrincipal}
+ * represents an identity that may be used to determine access rights to objects
+ * in a file system. A {@link GroupPrincipal} represents a <em>group identity</em>.
+ * A {@code UserPrincipalLookupService} defines methods to lookup identities by
+ * name or group name (which are typically user or account names). Whether names
+ * and group names are case sensitive or not depends on the implementation.
+ * The exact definition of a group is implementation specific but typically a
+ * group represents an identity created for administrative purposes so as to
+ * determine the access rights for the members of the group. In particular it is
+ * implementation specific if the <em>namespace</em> for names and groups is the
+ * same or is distinct. To ensure consistent and correct behavior across
+ * platforms it is recommended that this API be used as if the namespaces are
+ * distinct. In other words, the {@link #lookupPrincipalByName
+ * lookupPrincipalByName} should be used to lookup users, and {@link
+ * #lookupPrincipalByGroupName lookupPrincipalByGroupName} should be used to
+ * lookup groups.
+ *
+ * @since 1.7
+ *
+ * @see java.nio.file.FileSystem#getUserPrincipalLookupService
+ */
+
+public abstract class UserPrincipalLookupService {
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected UserPrincipalLookupService() {
+    }
+
+    /**
+     * Lookup a user principal by name.
+     *
+     * @param   name
+     *          The string representation of the user principal to lookup
+     *
+     * @return  A user principal
+     *
+     * @throws  UserPrincipalNotFoundException
+     *          The principal does not exist
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it checks {@link RuntimePermission}<tt>("lookupUserInformation")</tt>
+     */
+    public abstract UserPrincipal lookupPrincipalByName(String name)
+        throws IOException;
+
+    /**
+     * Lookup a group principal by group name.
+     *
+     * <p> Where an implementation does not support any notion of group then
+     * this method always throws {@link UserPrincipalNotFoundException}. Where
+     * the namespace for user accounts and groups is the same, then this method
+     * is identical to invoking {@link #lookupPrincipalByName
+     * lookupPrincipalByName}.
+     *
+     * @param   group
+     *          The string representation of the group to lookup
+     *
+     * @return  A user principal.
+     *
+     * @throws  UserPrincipalNotFoundException
+     *          The principal does not exist or is not a group
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, it checks {@link RuntimePermission}<tt>("lookupUserInformation")</tt>
+     */
+    public abstract GroupPrincipal lookupPrincipalByGroupName(String group)
+        throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/UserPrincipalNotFoundException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.attribute;
+
+import java.io.IOException;
+
+/**
+ * Checked exception thrown when a lookup of {@link UserPrincipal} fails because
+ * the principal does not exist.
+ *
+ * @since 1.7
+ */
+
+public class UserPrincipalNotFoundException
+    extends IOException
+{
+    static final long serialVersionUID = -5369283889045833024L;
+
+    private final String name;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   name
+     *          The principal name; may be {@code null}
+     */
+    public UserPrincipalNotFoundException(String name) {
+        super();
+        this.name = name;
+    }
+
+    /**
+     * Returns the user principal name if this exception was created with the
+     * user principal name that was not found, otherwise <tt>null</tt>.
+     *
+     * @return  The user principal name or {@code null}
+     */
+    public String getName() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/package-info.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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.
+ */
+
+/**
+ * Interfaces and classes providing access to file and file system attributes.
+ *
+ * <blockquote><table cellspacing=1 cellpadding=0 summary="Attribute views">
+ * <tr><th><p align="left">Attribute views</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><td valign=top><tt><i>{@link org.classpath.icedtea.java.nio.file.attribute.AttributeView}</i></tt></td>
+ *     <td>Can read or update non-opaque values associated with objects in a file system</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.FileAttributeView}</i></tt></td>
+ *     <td>Can read or update file attributes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read or update a basic set of file attributes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read or update POSIX defined file attributes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.DosFileAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read or update FAT file attributes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp<i>{@link org.classpath.icedtea.java.nio.file.attribute.FileOwnerAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read or update the owner of a file</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.AclFileAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read or update Access Control Lists</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.NamedAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read or update Named Attributes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.FileStoreAttributeView}</i></tt></td>
+ *     <td>Can read or update file system attributes</td></tr>
+ * <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributeView}&nbsp;&nbsp;</i></tt></td>
+ *     <td>Can read file system <em>space usage</em> related attributes</td></tr>
+ * </table></blockquote>
+ *
+ * <p> An attribute view provides a read-only or updatable view of the non-opaque
+ * values, or <em>metadata</em>, associated with objects in a file system.
+ * The {@link org.classpath.icedtea.java.nio.file.attribute.FileAttributeView} interface is
+ * extended by several other interfaces that that views to specific sets of file
+ * attributes. {@code FileAttributeViews} are selected by invoking the {@link
+ * org.classpath.icedtea.java.nio.file.FileRef#getFileAttributeView} method with a
+ * <em>type-token</em> to identify the required view. Views can also be identified
+ * by name. The {@link org.classpath.icedtea.java.nio.file.attribute.FileStoreAttributeView} interface
+ * provides access to file store attributes. A {@code FileStoreAttributeView} of
+ * a given type is obtained by invoking the {@link
+ * org.classpath.icedtea.java.nio.file.FileStore#getFileStoreAttributeView} method.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView}
+ * class defines methods to read and update a <em>basic</em> set of file
+ * attributes that are common to many file systems.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView}
+ * interface extends {@code BasicFileAttributeView} by defining methods
+ * to access the file attributes commonly used by file systems and operating systems
+ * that implement the Portable Operating System Interface (POSIX) family of
+ * standards.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.file.attribute.DosFileAttributeView}
+ * class extends {@code BasicFileAttributeView} by defining methods to
+ * access the legacy "DOS" file attributes supported on file systems such as File
+ * Allocation Tabl (FAT), commonly used in consumer devices.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.file.attribute.AclFileAttributeView}
+ * class defines methods to read and write the Access Control List (ACL)
+ * file attribute. The ACL model used by this file attribute view is based
+ * on the model defined by <a href="http://www.ietf.org/rfc/rfc3530.txt">
+ * <i>RFC&nbsp;3530: Network File System (NFS) version 4 Protocol</i></a>.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributeView} class
+ * defines methods to read file system space usage related attributes of a file system.
+ *
+ * <p> The {@link org.classpath.icedtea.java.nio.file.attribute.Attributes} utility class defines
+ * static methods to access file or file system attribute using the above
+ * attribute views.
+ *
+ * <p> In addition to attribute views, this package also defines classes and
+ * interfaces that are used when accessing attributes:
+ *
+ * <ul>
+ *
+ *   <p><li> The {@link org.classpath.icedtea.java.nio.file.attribute.UserPrincipal} and
+ *   {@link org.classpath.icedtea.java.nio.file.attribute.GroupPrincipal} interfaces represent an
+ *   identity or group identity. </li>
+ *
+ *   <p><li> The {@link org.classpath.icedtea.java.nio.file.attribute.UserPrincipalLookupService}
+ *   interface defines methods to lookup user or group principals. </li>
+ *
+ *   <p><li> The {@link org.classpath.icedtea.java.nio.file.attribute.Attribute} interface
+ *   represents the value of an attribute for cases where the attribute value is
+ *   require to be set atomically when creating an object in the file system. </li>
+ *
+ * </ul>
+ *
+ *
+ * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
+ * or method in any class or interface in this package will cause a {@link
+ * java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * @since 1.7
+ */
+
+package org.classpath.icedtea.java.nio.file.attribute;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/package-info.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+/**
+ * Define interfaces and classes for the Java virtual machine to access files,
+ * file attributes, and file systems.
+ *
+ * <p> The org.classpath.icedtea.java.nio.file package defines classes to access files and file
+ * systems. The API to access file and file system attributes is defined in the
+ * {@link org.classpath.icedtea.java.nio.file.attribute} package. The {@link org.classpath.icedtea.java.nio.file.spi}
+ * package is used by service provider implementors wishing to extend the
+ * platform default provider, or to construct other provider implementations.
+ *
+ * <a name="links"><h3>Symbolic Links</h3></a>
+ * Many operating systems and file systems support <em>symbolic links</em>.
+ * A symbolic link is a special file that serves as a reference to another file.
+ * For the most part, symbolic links are transparent to applications and
+ * operations on symbolic links are automatically redirected to the <em>target</em>
+ * of the link. Exceptions to this are when a symbolic link is deleted or
+ * renamed/moved in which case the link is deleted or removed rather than the
+ * target of the link. This package includes support for symbolic links where
+ * implementations provide these semantics. File systems may support other types
+ * that are semantically close but support for these other types of links is
+ * not included in this package.
+ *
+ * <a name="interop"><h3>Interoperability</h3></a>
+ * The {@link org.classpath.icedtea.java.io.File} class defines the {@link org.classpath.icedtea.java.io.File#toPath
+ * toPath} method to construct a {@link org.classpath.icedtea.java.nio.file.Path} by converting
+ * the abstract path represented by the {@code org.classpath.icedtea.java.io.File} object. The resulting
+ * {@code Path} can be used to operate on the same file as the {@code File}
+ * object. The {@code Path} specification provides further information
+ * on the <a href="Path.html#interop">interoperability</a> between {@code Path}
+ * and {@code org.classpath.icedtea.java.io.File} objects.
+ *
+ * <h3>Visibility</h3>
+ * The view of the files and file system provided by classes in this package are
+ * guaranteed to be consistent with other views provided by other instances in the
+ * same Java virtual machine.  The view may or may not, however, be consistent with
+ * the view of the file system as seen by other concurrently running programs due
+ * to caching performed by the underlying operating system and delays induced by
+ * network-filesystem protocols. This is true regardless of the language in which
+ * these other programs are written, and whether they are running on the same machine
+ * or on some other machine.  The exact nature of any such inconsistencies are
+ * system-dependent and are therefore unspecified.
+ *
+ * <a name="integrity"><h3>Synchronized I/O File Integrity</h3></a>
+ * The {@link org.classpath.icedtea.java.nio.file.StandardOpenOption#SYNC SYNC} and {@link
+ * org.classpath.icedtea.java.nio.file.StandardOpenOption#DSYNC DSYNC} options are used when opening a file
+ * to require that updates to the file are written synchronously to the underlying
+ * storage device. In the case of the default provider, and the file resides on
+ * a local storage device, and the {@link java.nio.channels.SeekableByteChannel
+ * seekable} channel is connected to a file that was opened with one of these
+ * options, then an invocation of the {@link
+ * java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) write}
+ * method is only guaranteed to return when all changes made to the file
+ * by that invocation have been written to the device. These options are useful
+ * for ensuring that critical information is not lost in the event of a system
+ * crash. If the file does not reside on a local device then no such guarantee
+ * is made. Whether this guarantee is possible with other {@link
+ * org.classpath.icedtea.java.nio.file.spi.FileSystemProvider provider} implementations is provider
+ * specific.
+ *
+ * <h3>General Exceptions</h3>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method of any class or interface in this package will cause a {@link
+ * java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
+ * invoking a method with a collection containing a {@code null} element will
+ * cause a {@code NullPointerException}, unless otherwise specified.
+ *
+ * <p> Unless otherwise noted, methods that attempt to access the file system
+ * will throw {@link org.classpath.icedtea.java.nio.file.ClosedFileSystemException} when invoked on
+ * objects associated with a {@link org.classpath.icedtea.java.nio.file.FileSystem} that has been
+ * {@link org.classpath.icedtea.java.nio.file.FileSystem#close closed}. Additionally, any methods
+ * that attempt write access to a file system will throw {@link
+ * org.classpath.icedtea.java.nio.file.ReadOnlyFileSystemException} when invoked on an object associated
+ * with a {@link org.classpath.icedtea.java.nio.file.FileSystem} that only provides read-only access.
+ *
+ * <p> Unless otherwise noted, invoking a method of any class or interface in
+ * this package created by one {@link org.classpath.icedtea.java.nio.file.spi.FileSystemProvider
+ * provider} with a parameter that is an object created by another provider,
+ * will throw {@link org.classpath.icedtea.java.nio.file.ProviderMismatchException}.
+ *
+ * <h3>Optional Specific Exceptions</h3>
+ * Most of the methods defined by classes in this package that access the
+ * file system specify that {@link java.io.IOException} be thrown when an I/O
+ * error occurs. In some cases, these methods define specific I/O exceptions
+ * for common cases. These exceptions, noted as <i>optional specific exceptions</i>,
+ * are thrown by the implementation where it can detect the specific error.
+ * Where the specific error cannot be detected then the more general {@code
+ * IOException} is thrown.
+ *
+ * @since 1.7
+ */
+package org.classpath.icedtea.java.nio.file;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/AbstractPath.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.spi;
+
+import java.nio.file.*;
+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() { }
+
+    /**
+     * @throws  NoSuchFileException             {@inheritDoc}
+     * @throws  DirectoryNotEmptyException      {@inheritDoc}
+     * @throws  IOException                     {@inheritDoc}
+     * @throws  SecurityException               {@inheritDoc}
+     */
+
+    public final void delete() throws IOException {
+        delete(true);
+    }
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  FileAlreadyExistsException      {@inheritDoc}
+     * @throws  IOException                     {@inheritDoc}
+     * @throws  SecurityException               {@inheritDoc}
+     */
+
+    public final Path createFile(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        EnumSet<StandardOpenOption> options =
+            EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
+        SeekableByteChannel sbc = newByteChannel(options, attrs);
+        try {
+            sbc.close();
+        } catch (IOException x) {
+            // ignore
+        }
+        return this;
+    }
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  FileAlreadyExistsException      {@inheritDoc}
+     * @throws  IOException                     {@inheritDoc}
+     * @throws  SecurityException               {@inheritDoc}
+     */
+
+    public final 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}
+     */
+
+    public InputStream newInputStream() throws IOException {
+        return Channels.newInputStream(newByteChannel(StandardOpenOption.READ));
+    }
+
+    /**
+     * 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}
+     */
+
+    public OutputStream newOutputStream(OpenOption... options) throws IOException {
+
+        int len = options.length;
+        Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
+        if (len == 0) {
+            opts.add(StandardOpenOption.CREATE);
+            opts.add(StandardOpenOption.TRUNCATE_EXISTING);
+        } else {
+            for (OpenOption opt: options) {
+                if (opt == StandardOpenOption.READ)
+                    throw new IllegalArgumentException("READ not allowed");
+                opts.add(opt);
+            }
+        }
+        opts.add(StandardOpenOption.WRITE);
+        return Channels.newOutputStream(newByteChannel(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}
+     */
+
+    public OutputStream newOutputStream(Set<? extends OpenOption> options,
+                                        FileAttribute<?>... attrs)
+        throws IOException
+    {
+        Set<OpenOption> opts = new HashSet<OpenOption>(options);
+        if (opts.isEmpty()) {
+            opts.add(StandardOpenOption.CREATE);
+            opts.add(StandardOpenOption.TRUNCATE_EXISTING);
+        } else {
+            if (opts.contains(StandardOpenOption.READ))
+                throw new IllegalArgumentException("READ not allowed");
+        }
+        opts.add(StandardOpenOption.WRITE);
+        return Channels.newOutputStream(newByteChannel(opts, attrs));
+    }
+
+    /**
+     * @throws  NotDirectoryException           {@inheritDoc}
+     * @throws  IOException                     {@inheritDoc}
+     * @throws  SecurityException               {@inheritDoc}
+     */
+
+    public final DirectoryStream<Path> newDirectoryStream() throws IOException {
+        return newDirectoryStream(acceptAllFilter);
+    }
+    private static final DirectoryStream.Filter<Path> acceptAllFilter =
+        new DirectoryStream.Filter<Path>() {
+ 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#getNameMatcher
+     * getNameMatcher} 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}
+     */
+
+    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().getNameMatcher("glob", glob);
+        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
+
+            public boolean accept(Path entry)  {
+                return matcher.matches(entry.getName());
+            }
+        };
+        return newDirectoryStream(filter);
+    }
+
+
+    public final boolean exists() {
+        try {
+            checkAccess();
+            return true;
+        } catch (IOException x) {
+            // unable to determine if file exists
+        }
+        return false;
+    }
+
+
+    public final boolean notExists() {
+        try {
+            checkAccess();
+            return false;
+        } catch (NoSuchFileException x) {
+            // file confirmed not to exist
+            return true;
+        } catch (IOException x) {
+            return false;
+        }
+    }
+
+
+    public final 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}
+     */
+
+    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}
+     */
+
+    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 {
+            target.createFile();
+            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(StandardOpenOption.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();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.spi;
+
+import java.nio.file.*;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.channels.*;
+import java.net.URI;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.IOException;
+
+/**
+ * Service-provider class for file systems.
+ *
+ * <p> A file system provider is a concrete implementation of this class that
+ * implements the abstract methods defined by this class. A provider is
+ * identified by a {@code URI} {@link #getScheme() scheme}. The default provider
+ * is identified by the URI scheme "file". It creates the {@link FileSystem} that
+ * provides access to the file systems accessible to the Java virtual machine.
+ * The {@link FileSystems} class defines how file system providers are located
+ * and loaded. The default provider is typically a system-default provider but
+ * may be overridden if the system property {@code
+ * java.nio.file.spi.DefaultFileSystemProvider} is set. In that case, the
+ * provider has a one argument constructor whose formal parameter type is {@code
+ * FileSystemProvider}. All other providers have a zero argument constructor
+ * that initializes the provider.
+ *
+ * <p> A provider is a factory for one or more {@link FileSystem} instances. Each
+ * file system is identified by a {@code URI} where the URI's scheme matches
+ * the provider's {@link #getScheme scheme}. The default file system, for example,
+ * is identified by the URI {@code "file:///"}. A memory-based file system,
+ * for example, may be identified by a URI such as {@code "memory:///?name=logfs"}.
+ * The {@link #newFileSystem newFileSystem} method may be used to create a file
+ * system, and the {@link #getFileSystem getFileSystem} method may be used to
+ * obtain a reference to an existing file system created by the provider. Where
+ * a provider is the factory for a single file system then it is provider dependent
+ * if the file system is created when the provider is initialized, or later when
+ * the {@code newFileSystem} method is invoked. In the case of the default
+ * provider, the {@code FileSystem} is created when the provider is initialized.
+ *
+ * <p> In addition to file systems, a provider is also a factory for {@link
+ * FileChannel} and {@link AsynchronousFileChannel} channels. The {@link
+ * #newFileChannel newFileChannel} and {@link #newAsynchronousFileChannel
+ * AsynchronousFileChannel} methods are defined to open or create files, returning
+ * a channel to access the file. These methods are invoked by static factory
+ * methods defined in the {@link java.nio.channels} package.
+ *
+ * <p> All of the methods in this class are safe for use by multiple concurrent
+ * threads.
+ *
+ * @since 1.7
+ */
+
+public abstract class FileSystemProvider {
+    // lock using when loading providers
+    private static final Object lock = new Object();
+
+    // installed providers
+    private static volatile List<FileSystemProvider> installedProviders;
+
+    // used to avoid recursive loading of instaled providers
+    private static boolean loadingProviders  = false;
+
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(new RuntimePermission("fileSystemProvider"));
+        return null;
+    }
+    private FileSystemProvider(Void ignore) { }
+
+    /**
+     * Initializes a new instance of this class.
+     *
+     * <p> During construction a provider may safely access files associated
+     * with the default provider but care needs to be taken to avoid circular
+     * loading of other installed providers. If circular loading of installed
+     * providers is detected then an unspecified error is thrown.
+     *
+     * @throws  SecurityException
+     *          If a security manager has been installed and it denies
+     *          {@link RuntimePermission}<tt>("fileSystemProvider")</tt>
+     */
+    protected FileSystemProvider() {
+        this(checkPermission());
+    }
+
+    // loads all installed providers
+    private static List<FileSystemProvider> loadInstalledProviders() {
+        List<FileSystemProvider> list = new ArrayList<FileSystemProvider>();
+
+        ServiceLoader<FileSystemProvider> sl = ServiceLoader
+            .load(FileSystemProvider.class, ClassLoader.getSystemClassLoader());
+
+        // ServiceConfigurationError may be throw here
+        for (FileSystemProvider provider: sl) {
+            String scheme = provider.getScheme();
+
+            // add to list if the provider is not "file" and isn't a duplicate
+            if (!scheme.equalsIgnoreCase("file")) {
+                boolean found = false;
+                for (FileSystemProvider p: list) {
+                    if (p.getScheme().equalsIgnoreCase(scheme)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    list.add(provider);
+                }
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Returns a list of the installed file system providers.
+     *
+     * <p> The first invocation of this method causes the default provider to be
+     * initialized (if not already initialized) and loads any other installed
+     * providers as described by the {@link FileSystems} class.
+     *
+     * @return  An unmodifiable list of the installed file system providers. The
+     *          list contains at least one element, that is the default file
+     *          system provider
+     *
+     * @throws  ServiceConfigurationError
+     *          When an error occurs while loading a service provider
+     */
+    public static List<FileSystemProvider> installedProviders() {
+        if (installedProviders == null) {
+            // ensure default provider is initialized
+            FileSystemProvider defaultProvider = FileSystems.getDefault().provider();
+
+            synchronized (lock) {
+                if (installedProviders == null) {
+                    if (loadingProviders) {
+                        throw new Error("Circular loading of installed providers detected");
+                    }
+                    loadingProviders = true;
+
+                    List<FileSystemProvider> list = AccessController
+                        .doPrivileged(new PrivilegedAction<List<FileSystemProvider>>() {
+
+                            public List<FileSystemProvider> run() {
+                                return loadInstalledProviders();
+                        }});
+
+                    // insert the default provider at the start of the list
+                    list.add(0, defaultProvider);
+
+                    installedProviders = Collections.unmodifiableList(list);
+                }
+            }
+        }
+        return installedProviders;
+    }
+
+    /**
+     * Returns the URI scheme that identifies this provider.
+     *
+     * @return  The URI scheme
+     */
+    public abstract String getScheme();
+
+    /**
+     * Constructs a new {@code FileSystem} object identified by a URI. This
+     * method is invoked by the {@link FileSystems#newFileSystem(URI,Map)}
+     * method to open a new file system identified by a URI.
+     *
+     * <p> The {@code uri} parameter is an absolute, hierarchical URI, with a
+     * scheme equal (without regard to case) to the scheme supported by this
+     * provider. The exact form of the URI is highly provider dependent. The
+     * {@code env} parameter is a map of provider specific properties to configure
+     * the file system.
+     *
+     * <p> This method throws {@link FileSystemAlreadyExistsException} if the
+     * file system already exists because it was previously created by an
+     * invocation of this method. Once a file system is {@link FileSystem#close
+     * closed} it is provider-dependent if the provider allows a new file system
+     * to be created with the same URI as a file system it previously created.
+     *
+     * @param   uri
+     *          URI reference
+     * @param   env
+     *          A map of provider specific properties to configure the file system;
+     *          may be empty
+     *
+     * @return  A new file system
+     *
+     * @throws  IllegalArgumentException
+     *          If the pre-conditions for the {@code uri} parameter aren't met,
+     *          or the {@code env} parameter does not contain properties required
+     *          by the provider, or a property value is invalid
+     * @throws  IOException
+     *          An I/O error occurs creating the file system
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission required by the file system provider implementation
+     * @throws  FileSystemAlreadyExistsException
+     *          If the file system has already been created
+     */
+    public abstract FileSystem newFileSystem(URI uri, Map<String,?> env)
+        throws IOException;
+
+    /**
+     * Returns an existing {@code FileSystem} created by this provider.
+     *
+     * <p> This method returns a reference to a {@code FileSystem} that was
+     * created by invoking the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)}
+     * method. File systems created the {@link #newFileSystem(FileRef,Map)
+     * newFileSystem(FileRef,Map)} method are not returned by this method.
+     * The file system is identified by its {@code URI}. Its exact form
+     * is highly provider dependent. In the case of the default provider the URI's
+     * path component is {@code "/"} and the authority, query and fragment components
+     * are undefined (Undefined components are represented by {@code null}).
+     *
+     * <p> Once a file system created by this provider is {@link FileSystem#close
+     * closed} it is provider-dependent if this method returns a reference to
+     * the closed file system or throws {@link FileSystemNotFoundException}.
+     * If the provider allows a new file system to be created with the same URI
+     * as a file system it previously created then this method throws the
+     * exception if invoked after the file system is closed (and before a new
+     * instance is created by the {@link #newFileSystem newFileSystem} method).
+     *
+     * <p> If a security manager is installed then a provider implementation
+     * may require to check a permission before returning a reference to an
+     * existing file system. In the case of the {@link FileSystems#getDefault
+     * default} file system, no permission check is required.
+     *
+     * @param   uri
+     *          URI reference
+     *
+     * @return  The file system
+     *
+     * @throws  IllegalArgumentException
+     *          If the pre-conditions for the {@code uri} parameter aren't met
+     * @throws  FileSystemNotFoundException
+     *          If the file system does not exist
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission.
+     */
+    public abstract FileSystem getFileSystem(URI uri);
+
+    /**
+     * Return a {@code Path} object by converting the given {@link URI}.
+     *
+     * <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
+     * given URI has a non-empty path component, and undefined query, and
+     * fragment components. The resulting {@code Path} is associated with the
+     * default {@link FileSystems#getDefault default} {@code FileSystem}.
+     *
+     * <p> If a security manager is installed then a provider implementation
+     * may require to check a permission. In the case of the {@link
+     * FileSystems#getDefault default} file system, no permission check is
+     * required.
+     *
+     * @param   uri
+     *          The URI to convert
+     *
+     * @throws  IllegalArgumentException
+     *          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
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission.
+     */
+    public abstract Path getPath(URI uri);
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method is intended for specialized providers of pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system. The {@code file} parameter is a reference to an existing file
+     * and the {@code env} parameter is a map of provider specific properties to
+     * configure the file system.
+     *
+     * <p> If this provider does not support the creation of such file systems
+     * or if the provider does not recognize the file type of the given file then
+     * it throws {@code UnsupportedOperationException}. The default implementation
+     * of this method throws {@code UnsupportedOperationException}.
+     *
+     * @param   file
+     *          The file
+     * @param   env
+     *          A map of provider specific properties to configure the file system;
+     *          may be empty
+     *
+     * @return  A new file system
+     *
+     * @throws  UnsupportedOperationException
+     *          If this provider does not support access to the contents as a
+     *          file system or it does not recognize the file type of the
+     *          given file
+     * @throws  IllegalArgumentException
+     *          If the {@code env} parameter does not contain properties required
+     *          by the provider, or a property value is invalid
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission.
+     */
+    public FileSystem newFileSystem(FileRef file, Map<String,?> env)
+        throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Opens or creates a file for reading and/or writing, returning a file
+     * channel to access the file.
+     *
+     * <p> This method is invoked by the {@link FileChannel#open(Path,Set,FileAttribute[])
+     * FileChannel.open} method to open a file channel. A provider that does not
+     * support all the features required to construct a file channel throws
+     * {@code UnsupportedOperationException}. The default provider is required
+     * to support the creation of file channels. When not overridden, the
+     * default implementation throws {@code UnsupportedOperationException}.
+     *
+     * @param   path
+     *          The path of the file to open or create
+     * @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 file channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If this provider that does not support creating file channels,
+     *          or an unsupported open option or file attribute is specified
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default file system, the {@link
+     *          SecurityManager#checkRead(String)} method is invoked to check
+     *          read access if the file is opened for reading. The {@link
+     *          SecurityManager#checkWrite(String)} method is invoked to check
+     *          write access if the file is opened for writing
+     */
+    public FileChannel newFileChannel(Path path,
+                                      Set<? extends OpenOption> options,
+                                      FileAttribute<?>... attrs)
+        throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Opens or creates a file for reading and/or writing, returning an
+     * asynchronous file channel to access the file.
+     *
+     * <p> This method is invoked by the {@link
+     * AsynchronousFileChannel#open(Path,Set,ExecutorService,FileAttribute[])
+     * AsynchronousFileChannel.open} method to open an asynchronous file channel.
+     * A provider that does not support all the features required to construct
+     * an asynchronous file channel throws {@code UnsupportedOperationException}.
+     * The default provider is required to support the creation of asynchronous
+     * file channels. When not overridden, the default implementation of this
+     * method throws {@code UnsupportedOperationException}.
+     *
+     * @param   path
+     *          The path of the file to open or create
+     * @param   options
+     *          Options specifying how the file is opened
+     * @param   executor
+     *          The thread pool or {@code null} to associate the channel with
+     *          the default thread pool
+     * @param   attrs
+     *          An optional list of file attributes to set atomically when
+     *          creating the file
+     *
+     * @return  A new asynchronous file channel
+     *
+     * @throws  IllegalArgumentException
+     *          If the set contains an invalid combination of options
+     * @throws  UnsupportedOperationException
+     *          If this provider that does not support creating asynchronous file
+     *          channels, or an unsupported open option or file attribute is
+     *          specified
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default file system, the {@link
+     *          SecurityManager#checkRead(String)} method is invoked to check
+     *          read access if the file is opened for reading. The {@link
+     *          SecurityManager#checkWrite(String)} method is invoked to check
+     *          write access if the file is opened for writing
+     */
+    public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
+                                                              Set<? extends OpenOption> options,
+                                                              ExecutorService executor,
+                                                              FileAttribute<?>... attrs)
+        throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.nio.file.spi;
+
+import java.nio.file.FileRef;
+import java.io.IOException;
+
+/**
+ * A file type detector for probing a file to guess its file type.
+ *
+ * <p> A file type detector is a concrete implementation of this class, has a
+ * zero-argument constructor, and implements the abstract methods specified
+ * below.
+ *
+ * <p> The means by which a file type detector determines the file type is
+ * highly implementation specific. A simple implementation might examine the
+ * <em>file extension</em> (a convention used in some platforms) and map it to
+ * a file type. In other cases, the file type may be stored as a file <a
+ * href="../attribute/package-summary.html"> attribute</a> or the bytes in a
+ * file may be examined to guess its file type.
+ *
+ * @see java.nio.file.Files#probeContentType(FileRef)
+ *
+ * @since 1.7
+ */
+
+public abstract class FileTypeDetector {
+
+    /**
+     * Initializes a new instance of this class.
+     *
+     * @throws  SecurityException
+     *          If a security manager has been installed and it denies
+     *          {@link RuntimePermission}<tt>("fileTypeDetector")</tt>
+     */
+    protected FileTypeDetector() {
+        SecurityManager sm = System.getSecurityManager();
+         if (sm != null)
+             sm.checkPermission(new RuntimePermission("fileTypeDetector"));
+    }
+
+    /**
+     * Probes the given file to guess its content type.
+     *
+     * <p> The means by which this method determines the file type is highly
+     * implementation specific. It may simply examine the file name, it may use
+     * a file <a href="../attribute/package-summary.html">attribute</a>,
+     * or it may examines bytes in the file.
+     *
+     * <p> The probe result is the string form of 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>. The string must be parsable according to the
+     * grammar in the RFC 2045.
+     *
+     * @param   file
+     *          The file to probe
+     *
+     * @return  The content type or {@code null} if the file type is not
+     *          recognized
+     *
+     * @throws  IOException
+     *          An I/O error occurs
+     * @throws  SecurityException
+     *          If the implementation requires to access the file, and a
+     *          security manager is installed, and it denies an unspecified
+     *          permission required by a file system provider implementation.
+     *          If the file reference is associated with the default file system
+     *          provider then the {@link SecurityManager#checkRead(String)} method
+     *          is invoked to check read access to the file.
+     *
+     * @see java.nio.file.Files#probeContentType
+     */
+    public abstract String probeContentType(FileRef file)
+        throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/package-info.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+/**
+ * Service-provider classes for the <tt>{@link org.classpath.icedtea.java.nio.file}</tt> package.
+ *
+ * <p> Only developers who are defining new file system providers or file type
+ * detectors should need to make direct use of this package.  </p>
+ *
+ * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
+ * or method in any class or interface in this package will cause a {@link
+ * java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * @since 1.7
+ */
+
+package org.classpath.icedtea.java.nio.file.spi;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/util/Scanner.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,2657 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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 org.classpath.icedtea.java.util;
+
+import java.util.regex.*;
+import java.io.*;
+import java.math.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.charset.*;
+import java.text.*;
+import java.util.InputMismatchException;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import sun.misc.LRUCache;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+/**
+ * A simple text scanner which can parse primitive types and strings using
+ * regular expressions.
+ *
+ * <p>A <code>Scanner</code> breaks its input into tokens using a
+ * delimiter pattern, which by default matches whitespace. The resulting
+ * tokens may then be converted into values of different types using the
+ * various <tt>next</tt> methods.
+ *
+ * <p>For example, this code allows a user to read a number from
+ * <tt>System.in</tt>:
+ * <blockquote><pre>
+ *     Scanner sc = new Scanner(System.in);
+ *     int i = sc.nextInt();
+ * </pre></blockquote>
+ *
+ * <p>As another example, this code allows <code>long</code> types to be
+ * assigned from entries in a file <code>myNumbers</code>:
+ * <blockquote><pre>
+ *      Scanner sc = new Scanner(new File("myNumbers"));
+ *      while (sc.hasNextLong()) {
+ *          long aLong = sc.nextLong();
+ *      }</pre></blockquote>
+ *
+ * <p>The scanner can also use delimiters other than whitespace. This
+ * example reads several items in from a string:
+ *<blockquote><pre>
+ *     String input = "1 fish 2 fish red fish blue fish";
+ *     Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
+ *     System.out.println(s.nextInt());
+ *     System.out.println(s.nextInt());
+ *     System.out.println(s.next());
+ *     System.out.println(s.next());
+ *     s.close(); </pre></blockquote>
+ * <p>
+ * prints the following output:
+ * <blockquote><pre>
+ *     1
+ *     2
+ *     red
+ *     blue </pre></blockquote>
+ *
+ * <p>The same output can be generated with this code, which uses a regular
+ * expression to parse all four tokens at once:
+ *<blockquote><pre>
+ *     String input = "1 fish 2 fish red fish blue fish";
+ *     Scanner s = new Scanner(input);
+ *     s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
+ *     MatchResult result = s.match();
+ *     for (int i=1; i<=result.groupCount(); i++)
+ *         System.out.println(result.group(i));
+ *     s.close(); </pre></blockquote>
+ *
+ * <p>The <a name="default-delimiter">default whitespace delimiter</a> used
+ * by a scanner is as recognized by {@link java.lang.Character}.{@link
+ * java.lang.Character#isWhitespace(char) isWhitespace}. The {@link #reset}
+ * method will reset the value of the scanner's delimiter to the default
+ * whitespace delimiter regardless of whether it was previously changed.
+ *
+ * <p>A scanning operation may block waiting for input.
+ *
+ * <p>The {@link #next} and {@link #hasNext} methods and their
+ * primitive-type companion methods (such as {@link #nextInt} and
+ * {@link #hasNextInt}) first skip any input that matches the delimiter
+ * pattern, and then attempt to return the next token. Both <tt>hasNext</tt>
+ * and <tt>next</tt> methods may block waiting for further input.  Whether a
+ * <tt>hasNext</tt> method blocks has no connection to whether or not its
+ * associated <tt>next</tt> method will block.
+ *
+ * <p> The {@link #findInLine}, {@link #findWithinHorizon}, and {@link #skip}
+ * methods operate independently of the delimiter pattern. These methods will
+ * attempt to match the specified pattern with no regard to delimiters in the
+ * input and thus can be used in special circumstances where delimiters are
+ * not relevant. These methods may block waiting for more input.
+ *
+ * <p>When a scanner throws an {@link InputMismatchException}, the scanner
+ * will not pass the token that caused the exception, so that it may be
+ * retrieved or skipped via some other method.
+ *
+ * <p>Depending upon the type of delimiting pattern, empty tokens may be
+ * returned. For example, the pattern <tt>"\\s+"</tt> will return no empty
+ * tokens since it matches multiple instances of the delimiter. The delimiting
+ * pattern <tt>"\\s"</tt> could return empty tokens since it only passes one
+ * space at a time.
+ *
+ * <p> A scanner can read text from any object which implements the {@link
+ * java.lang.Readable} interface.  If an invocation of the underlying
+ * readable's {@link java.lang.Readable#read} method throws an {@link
+ * java.io.IOException} then the scanner assumes that the end of the input
+ * has been reached.  The most recent <tt>IOException</tt> thrown by the
+ * underlying readable can be retrieved via the {@link #ioException} method.
+ *
+ * <p>When a <code>Scanner</code> is closed, it will close its input source
+ * if the source implements the {@link java.io.Closeable} interface.
+ *
+ * <p>A <code>Scanner</code> is not safe for multithreaded use without
+ * external synchronization.
+ *
+ * <p>Unless otherwise mentioned, passing a <code>null</code> parameter into
+ * any method of a <code>Scanner</code> will cause a
+ * <code>NullPointerException</code> to be thrown.
+ *
+ * <p>A scanner will default to interpreting numbers as decimal unless a
+ * different radix has been set by using the {@link #useRadix} method. The
+ * {@link #reset} method will reset the value of the scanner's radix to
+ * <code>10</code> regardless of whether it was previously changed.
+ *
+ * <a name="localized-numbers">
+ * <h4> Localized numbers </h4>
+ *
+ * <p> An instance of this class is capable of scanning numbers in the standard
+ * formats as well as in the formats of the scanner's locale. A scanner's
+ * <a name="initial-locale">initial locale </a>is the value returned by the {@link
+ * java.util.Locale#getDefault} method; it may be changed via the {@link
+ * #useLocale} method. The {@link #reset} method will reset the value of the
+ * scanner's locale to the initial locale regardless of whether it was
+ * previously changed.
+ *
+ * <p>The localized formats are defined in terms of the following parameters,
+ * which for a particular locale are taken from that locale's {@link
+ * java.text.DecimalFormat DecimalFormat} object, <tt>df</tt>, and its and
+ * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object,
+ * <tt>dfs</tt>.
+ *
+ * <blockquote><table>
+ * <tr><td valign="top"><i>LocalGroupSeparator&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The character used to separate thousands groups,
+ *                      <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
+ *                      java.text.DecimalFormatSymbols#getGroupingSeparator
+ *                      getGroupingSeparator()}</td></tr>
+ * <tr><td valign="top"><i>LocalDecimalSeparator&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The character used for the decimal point,
+ *                      <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
+ *                      java.text.DecimalFormatSymbols#getDecimalSeparator
+ *                      getDecimalSeparator()}</td></tr>
+ * <tr><td valign="top"><i>LocalPositivePrefix&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The string that appears before a positive number (may
+ *                      be empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
+ *                      java.text.DecimalFormat#getPositivePrefix
+ *                      getPositivePrefix()}</td></tr>
+ * <tr><td valign="top"><i>LocalPositiveSuffix&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The string that appears after a positive number (may be
+ *                      empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
+ *                      java.text.DecimalFormat#getPositiveSuffix
+ *                      getPositiveSuffix()}</td></tr>
+ * <tr><td valign="top"><i>LocalNegativePrefix&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The string that appears before a negative number (may
+ *                      be empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
+ *                      java.text.DecimalFormat#getNegativePrefix
+ *                      getNegativePrefix()}</td></tr>
+ * <tr><td valign="top"><i>LocalNegativeSuffix&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The string that appears after a negative number (may be
+ *                      empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
+ *                      java.text.DecimalFormat#getNegativeSuffix
+ *                      getNegativeSuffix()}</td></tr>
+ * <tr><td valign="top"><i>LocalNaN&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The string that represents not-a-number for
+ *                      floating-point values,
+ *                      <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
+ *                      java.text.DecimalFormatSymbols#getNaN
+ *                      getNaN()}</td></tr>
+ * <tr><td valign="top"><i>LocalInfinity&nbsp;&nbsp;</i></td>
+ *     <td valign="top">The string that represents infinity for floating-point
+ *                      values, <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
+ *                      java.text.DecimalFormatSymbols#getInfinity
+ *                      getInfinity()}</td></tr>
+ * </table></blockquote>
+ *
+ * <a name="number-syntax">
+ * <h4> Number syntax </h4>
+ *
+ * <p> The strings that can be parsed as numbers by an instance of this class
+ * are specified in terms of the following regular-expression grammar, where
+ * Rmax is the highest digit in the radix being used (for example, Rmax is 9
+ * in base 10).
+ *
+ * <p>
+ * <table cellspacing=0 cellpadding=0 align=center>
+ *
+ *   <tr><td valign=top align=right><i>NonASCIIDigit</i>&nbsp;&nbsp;::</td>
+ *       <td valign=top>= A non-ASCII character c for which
+ *            {@link java.lang.Character#isDigit Character.isDigit}<tt>(c)</tt>
+ *                        returns&nbsp;true</td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>Non0Digit</i>&nbsp;&nbsp;::</td>
+ *   <td><tt>= [1-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>Digit</i>&nbsp;&nbsp;::</td>
+ *   <td><tt>= [0-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td valign=top align=right><i>GroupedNumeral</i>&nbsp;&nbsp;::</td>
+ *       <td valign=top>
+ *         <table cellpadding=0 cellspacing=0>
+ *           <tr><td><tt>= (&nbsp;</tt></td>
+ *               <td><i>Non0Digit</i><tt>
+ *                   </tt><i>Digit</i><tt>?
+ *                   </tt><i>Digit</i><tt>?</tt></td></tr>
+ *           <tr><td></td>
+ *               <td><tt>(&nbsp;</tt><i>LocalGroupSeparator</i><tt>
+ *                         </tt><i>Digit</i><tt>
+ *                         </tt><i>Digit</i><tt>
+ *                         </tt><i>Digit</i><tt> )+ )</tt></td></tr>
+ *         </table></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>Numeral</i>&nbsp;&nbsp;::</td>
+ *       <td><tt>= ( ( </tt><i>Digit</i><tt>+ )
+ *               | </tt><i>GroupedNumeral</i><tt> )</tt></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td valign=top align=right>
+ *         <a name="Integer-regex"><i>Integer</i>&nbsp;&nbsp;::</td>
+ *       <td valign=top><tt>= ( [-+]? ( </tt><i>Numeral</i><tt>
+ *                               ) )</tt></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalPositivePrefix</i><tt> </tt><i>Numeral</i><tt>
+ *                      </tt><i>LocalPositiveSuffix</i></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalNegativePrefix</i><tt> </tt><i>Numeral</i><tt>
+ *                 </tt><i>LocalNegativeSuffix</i></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>DecimalNumeral</i>&nbsp;&nbsp;::</td>
+ *       <td><tt>= </tt><i>Numeral</i></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>Numeral</i><tt>
+ *                 </tt><i>LocalDecimalSeparator</i><tt>
+ *                 </tt><i>Digit</i><tt>*</tt></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalDecimalSeparator</i><tt>
+ *                 </tt><i>Digit</i><tt>+</tt></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>Exponent</i>&nbsp;&nbsp;::</td>
+ *       <td><tt>= ( [eE] [+-]? </tt><i>Digit</i><tt>+ )</tt></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right>
+ *         <a name="Decimal-regex"><i>Decimal</i>&nbsp;&nbsp;::</td>
+ *       <td><tt>= ( [-+]? </tt><i>DecimalNumeral</i><tt>
+ *                         </tt><i>Exponent</i><tt>? )</tt></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalPositivePrefix</i><tt>
+ *                 </tt><i>DecimalNumeral</i><tt>
+ *                 </tt><i>LocalPositiveSuffix</i>
+ *                 </tt><i>Exponent</i><tt>?</td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalNegativePrefix</i><tt>
+ *                 </tt><i>DecimalNumeral</i><tt>
+ *                 </tt><i>LocalNegativeSuffix</i>
+ *                 </tt><i>Exponent</i><tt>?</td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>HexFloat</i>&nbsp;&nbsp;::</td>
+ *       <td><tt>= [-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+
+ *                 ([pP][-+]?[0-9]+)?</tt></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>NonNumber</i>&nbsp;&nbsp;::</td>
+ *       <td valign=top><tt>= NaN
+ *                          | </tt><i>LocalNan</i><tt>
+ *                          | Infinity
+ *                          | </tt><i>LocalInfinity</i></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td align=right><i>SignedNonNumber</i>&nbsp;&nbsp;::</td>
+ *       <td><tt>= ( [-+]? </tt><i>NonNumber</i><tt> )</tt></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalPositivePrefix</i><tt>
+ *                 </tt><i>NonNumber</i><tt>
+ *                 </tt><i>LocalPositiveSuffix</i></td></tr>
+ *   <tr><td></td>
+ *       <td><tt>| </tt><i>LocalNegativePrefix</i><tt>
+ *                 </tt><i>NonNumber</i><tt>
+ *                 </tt><i>LocalNegativeSuffix</i></td></tr>
+ *
+ *   <tr><td>&nbsp;</td></tr>
+ *
+ *   <tr><td valign=top align=right>
+ *         <a name="Float-regex"><i>Float</i>&nbsp;&nbsp;::</td>
+ *       <td valign=top><tt>= </tt><i>Decimal</i><tt></td></tr>
+ *       <tr><td></td>
+ *           <td><tt>| </tt><i>HexFloat</i><tt></td></tr>
+ *       <tr><td></td>
+ *           <td><tt>| </tt><i>SignedNonNumber</i><tt></td></tr>
+ *
+ * </table>
+ * </center>
+ *
+ * <p> Whitespace is not significant in the above regular expressions.
+ *
+ * @since   1.5
+ */
+public final class Scanner implements Iterator<String> {
+
+    // Internal buffer used to hold input
+    private CharBuffer buf;
+
+    // Size of internal character buffer
+    private static final int BUFFER_SIZE = 1024; // change to 1024;
+
+    // The index into the buffer currently held by the Scanner
+    private int position;
+
+    // Internal matcher used for finding delimiters
+    private Matcher matcher;
+
+    // Pattern used to delimit tokens
+    private Pattern delimPattern;
+
+    // Pattern found in last hasNext operation
+    private Pattern hasNextPattern;
+
+    // Position after last hasNext operation
+    private int hasNextPosition;
+
+    // Result after last hasNext operation
+    private String hasNextResult;
+
+    // The input source
+    private Readable source;
+
+    // Boolean is true if source is done
+    private boolean sourceClosed = false;
+
+    // Boolean indicating more input is required
+    private boolean needInput = false;
+
+    // Boolean indicating if a delim has been skipped this operation
+    private boolean skipped = false;
+
+    // A store of a position that the scanner may fall back to
+    private int savedScannerPosition = -1;
+
+    // A cache of the last primitive type scanned
+    private Object typeCache = null;
+
+    // Boolean indicating if a match result is available
+    private boolean matchValid = false;
+
+    // Boolean indicating if this scanner has been closed
+    private boolean closed = false;
+
+    // The current radix used by this scanner
+    private int radix = 10;
+
+    // The default radix for this scanner
+    private int defaultRadix = 10;
+
+    // The locale used by this scanner
+    private Locale locale = null;
+
+    // A cache of the last few recently used Patterns
+    private LRUCache<String,Pattern> patternCache =
+    new LRUCache<String,Pattern>(7) {
+        protected Pattern create(String s) {
+            return Pattern.compile(s);
+        }
+        protected boolean hasName(Pattern p, String s) {
+            return p.pattern().equals(s);
+        }
+    };
+
+    // A holder of the last IOException encountered
+    private IOException lastException;
+
+    // A pattern for java whitespace
+    private static Pattern WHITESPACE_PATTERN = Pattern.compile(
+                                                "\\p{javaWhitespace}+");
+
+    // A pattern for any token
+    private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
+
+    // A pattern for non-ASCII digits
+    private static Pattern NON_ASCII_DIGIT = Pattern.compile(
+        "[\\p{javaDigit}&&[^0-9]]");
+
+    // Fields and methods to support scanning primitive types
+
+    /**
+     * Locale dependent values used to scan numbers
+     */
+    private String groupSeparator = "\\,";
+    private String decimalSeparator = "\\.";
+    private String nanString = "NaN";
+    private String infinityString = "Infinity";
+    private String positivePrefix = "";
+    private String negativePrefix = "\\-";
+    private String positiveSuffix = "";
+    private String negativeSuffix = "";
+
+    /**
+     * Fields and an accessor method to match booleans
+     */
+    private static volatile Pattern boolPattern;
+    private static final String BOOLEAN_PATTERN = "true|false";
+    private static Pattern boolPattern() {
+        Pattern bp = boolPattern;
+        if (bp == null)
+            boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN,
+                                          Pattern.CASE_INSENSITIVE);
+        return bp;
+    }
+
+    /**
+     * Fields and methods to match bytes, shorts, ints, and longs
+     */
+    private Pattern integerPattern;
+    private String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+    private String non0Digit = "[\\p{javaDigit}&&[^0]]";
+    private int SIMPLE_GROUP_INDEX = 5;
+    private String buildIntegerPatternString() {
+        String radixDigits = digits.substring(0, radix);
+        // \\p{javaDigit} is not guaranteed to be appropriate
+        // here but what can we do? The final authority will be
+        // whatever parse method is invoked, so ultimately the
+        // Scanner will do the right thing
+        String digit = "((?i)["+radixDigits+"]|\\p{javaDigit})";
+        String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
+                                groupSeparator+digit+digit+digit+")+)";
+        // digit++ is the possessive form which is necessary for reducing
+        // backtracking that would otherwise cause unacceptable performance
+        String numeral = "(("+ digit+"++)|"+groupedNumeral+")";
+        String javaStyleInteger = "([-+]?(" + numeral + "))";
+        String negativeInteger = negativePrefix + numeral + negativeSuffix;
+        String positiveInteger = positivePrefix + numeral + positiveSuffix;
+        return "("+ javaStyleInteger + ")|(" +
+            positiveInteger + ")|(" +
+            negativeInteger + ")";
+    }
+    private Pattern integerPattern() {
+        if (integerPattern == null) {
+            integerPattern = patternCache.forName(buildIntegerPatternString());
+        }
+        return integerPattern;
+    }
+
+    /**
+     * Fields and an accessor method to match line separators
+     */
+    private static volatile Pattern separatorPattern;
+    private static volatile Pattern linePattern;
+    private static final String LINE_SEPARATOR_PATTERN =
+                                           "\r\n|[\n\r\u2028\u2029\u0085]";
+    private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$";
+
+    private static Pattern separatorPattern() {
+        Pattern sp = separatorPattern;
+        if (sp == null)
+            separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
+        return sp;
+    }
+
+    private static Pattern linePattern() {
+        Pattern lp = linePattern;
+        if (lp == null)
+            linePattern = lp = Pattern.compile(LINE_PATTERN);
+        return lp;
+    }
+
+    /**
+     * Fields and methods to match floats and doubles
+     */
+    private Pattern floatPattern;
+    private Pattern decimalPattern;
+    private void buildFloatAndDecimalPattern() {
+        // \\p{javaDigit} may not be perfect, see above
+        String digit = "([0-9]|(\\p{javaDigit}))";
+        String exponent = "([eE][+-]?"+digit+"+)?";
+        String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
+                                groupSeparator+digit+digit+digit+")+)";
+        // Once again digit++ is used for performance, as above
+        String numeral = "(("+digit+"++)|"+groupedNumeral+")";
+        String decimalNumeral = "("+numeral+"|"+numeral +
+            decimalSeparator + digit + "*+|"+ decimalSeparator +
+            digit + "++)";
+        String nonNumber = "(NaN|"+nanString+"|Infinity|"+
+                               infinityString+")";
+        String positiveFloat = "(" + positivePrefix + decimalNumeral +
+                            positiveSuffix + exponent + ")";
+        String negativeFloat = "(" + negativePrefix + decimalNumeral +
+                            negativeSuffix + exponent + ")";
+        String decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+
+            positiveFloat + "|" + negativeFloat + ")";
+        String hexFloat =
+            "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?";
+        String positiveNonNumber = "(" + positivePrefix + nonNumber +
+                            positiveSuffix + ")";
+        String negativeNonNumber = "(" + negativePrefix + nonNumber +
+                            negativeSuffix + ")";
+        String signedNonNumber = "(([-+]?"+nonNumber+")|" +
+                                 positiveNonNumber + "|" +
+                                 negativeNonNumber + ")";
+        floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" +
+                                       signedNonNumber);
+        decimalPattern = Pattern.compile(decimal);
+    }
+    private Pattern floatPattern() {
+        if (floatPattern == null) {
+            buildFloatAndDecimalPattern();
+        }
+        return floatPattern;
+    }
+    private Pattern decimalPattern() {
+        if (decimalPattern == null) {
+            buildFloatAndDecimalPattern();
+        }
+        return decimalPattern;
+    }
+
+    // Constructors
+
+    /**
+     * Constructs a <code>Scanner</code> that returns values scanned
+     * from the specified source delimited by the specified pattern.
+     *
+     * @param  source A character source implementing the Readable interface
+     * @param pattern A delimiting pattern
+     * @return A scanner with the specified source and pattern
+     */
+    private Scanner(Readable source, Pattern pattern) {
+        if (source == null)
+            throw new NullPointerException("source");
+        if (pattern == null)
+            throw new NullPointerException("pattern");
+        this.source = source;
+        delimPattern = pattern;
+        buf = CharBuffer.allocate(BUFFER_SIZE);
+        buf.limit(0);
+        matcher = delimPattern.matcher(buf);
+        matcher.useTransparentBounds(true);
+        matcher.useAnchoringBounds(false);
+        useLocale(Locale.getDefault());
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified source.
+     *
+     * @param  source A character source implementing the {@link Readable}
+     *         interface
+     */
+    public Scanner(Readable source) {
+        this(source, WHITESPACE_PATTERN);
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified input stream. Bytes from the stream are converted
+     * into characters using the underlying platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
+     *
+     * @param  source An input stream to be scanned
+     */
+    public Scanner(InputStream source) {
+        this(new InputStreamReader(source), WHITESPACE_PATTERN);
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified input stream. Bytes from the stream are converted
+     * into characters using the specified charset.
+     *
+     * @param  source An input stream to be scanned
+     * @param charsetName The encoding type used to convert bytes from the
+     *        stream into characters to be scanned
+     * @throws IllegalArgumentException if the specified character set
+     *         does not exist
+     */
+    public Scanner(InputStream source, String charsetName) {
+        this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
+    }
+
+    private static Readable makeReadable(InputStream source,
+                                         String charsetName)
+    {
+        if (source == null)
+            throw new NullPointerException("source");
+        InputStreamReader isr = null;
+        try {
+            isr = new InputStreamReader(source, charsetName);
+        } catch (UnsupportedEncodingException uee) {
+            IllegalArgumentException iae = new IllegalArgumentException();
+            iae.initCause(uee);
+            throw iae;
+        }
+        return isr;
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified file. Bytes from the file are converted into
+     * characters using the underlying platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
+     *
+     * @param  source A file to be scanned
+     * @throws FileNotFoundException if source is not found
+     */
+    public Scanner(File source)
+        throws FileNotFoundException
+    {
+        this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified file. Bytes from the file are converted into
+     * characters using the specified charset.
+     *
+     * @param  source A file to be scanned
+     * @param charsetName The encoding type used to convert bytes from the file
+     *        into characters to be scanned
+     * @throws FileNotFoundException if source is not found
+     * @throws IllegalArgumentException if the specified encoding is
+     *         not found
+     */
+    public Scanner(File source, String charsetName)
+        throws FileNotFoundException
+    {
+        this((ReadableByteChannel)(new FileInputStream(source).getChannel()),
+             charsetName);
+    }
+
+    /**
+     * {@note new}
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified file. Bytes from the file are converted into
+     * characters using the underlying platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
+     *
+     * @param   source
+     *          A file to be scanned
+     * @throws  IOException
+     *          if an I/O error occurs opening source
+     *
+     * @since   1.7
+     */
+    public Scanner(FileRef source)
+        throws IOException
+    {
+        this(source.newByteChannel());
+    }
+
+    /**
+     * {@note new}
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified file. Bytes from the file are converted into
+     * characters using the specified charset.
+     *
+     * @param   source
+     *          A file to be scanned
+     * @param   charsetName
+     *          The encoding type used to convert bytes from the file
+     *          into characters to be scanned
+     * @throws  IOException
+     *          if an I/O error occurs opening source
+     * @throws  IllegalArgumentException
+     *          if the specified encoding is not found
+     * @since   1.7
+     */
+    public Scanner(FileRef source, String charsetName)
+        throws IOException
+    {
+        this(source.newByteChannel(), charsetName);
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified string.
+     *
+     * @param  source A string to scan
+     */
+    public Scanner(String source) {
+        this(new StringReader(source), WHITESPACE_PATTERN);
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified channel. Bytes from the source are converted into
+     * characters using the underlying platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
+     *
+     * @param  source A channel to scan
+     */
+    public Scanner(ReadableByteChannel source) {
+        this(makeReadable(source), WHITESPACE_PATTERN);
+    }
+
+    private static Readable makeReadable(ReadableByteChannel source) {
+        if (source == null)
+            throw new NullPointerException("source");
+        String defaultCharsetName =
+            java.nio.charset.Charset.defaultCharset().name();
+        return Channels.newReader(source,
+                           java.nio.charset.Charset.defaultCharset().name());
+    }
+
+    /**
+     * Constructs a new <code>Scanner</code> that produces values scanned
+     * from the specified channel. Bytes from the source are converted into
+     * characters using the specified charset.
+     *
+     * @param  source A channel to scan
+     * @param charsetName The encoding type used to convert bytes from the
+     *        channel into characters to be scanned
+     * @throws IllegalArgumentException if the specified character set
+     *         does not exist
+     */
+    public Scanner(ReadableByteChannel source, String charsetName) {
+        this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
+    }
+
+    private static Readable makeReadable(ReadableByteChannel source,
+                                  String charsetName)
+    {
+        if (source == null)
+            throw new NullPointerException("source");
+        if (!Charset.isSupported(charsetName))
+            throw new IllegalArgumentException(charsetName);
+        return Channels.newReader(source, charsetName);
+    }
+
+    // Private primitives used to support scanning
+
+    private void saveState() {
+        savedScannerPosition = position;
+    }
+
+    private void revertState() {
+        this.position = savedScannerPosition;
+        savedScannerPosition = -1;
+        skipped = false;
+    }
+
+    private boolean revertState(boolean b) {
+        this.position = savedScannerPosition;
+        savedScannerPosition = -1;
+        skipped = false;
+        return b;
+    }
+
+    private void cacheResult() {
+        hasNextResult = matcher.group();
+        hasNextPosition = matcher.end();
+        hasNextPattern = matcher.pattern();
+    }
+
+    private void cacheResult(String result) {
+        hasNextResult = result;
+        hasNextPosition = matcher.end();
+        hasNextPattern = matcher.pattern();
+    }
+
+    // Clears both regular cache and type cache
+    private void clearCaches() {
+        hasNextPattern = null;
+        typeCache = null;
+    }
+
+    // Also clears both the regular cache and the type cache
+    private String getCachedResult() {
+        position = hasNextPosition;
+        hasNextPattern = null;
+        typeCache = null;
+        return hasNextResult;
+    }
+
+    // Also clears both the regular cache and the type cache
+    private void useTypeCache() {
+        if (closed)
+            throw new IllegalStateException("Scanner closed");
+        position = hasNextPosition;
+        hasNextPattern = null;
+        typeCache = null;
+    }
+
+    // Tries to read more input. May block.
+    private void readInput() {
+        if (buf.limit() == buf.capacity())
+            makeSpace();
+
+        // Prepare to receive data
+        int p = buf.position();
+        buf.position(buf.limit());
+        buf.limit(buf.capacity());
+
+        int n = 0;
+        try {
+            n = source.read(buf);
+        } catch (IOException ioe) {
+            lastException = ioe;
+            n = -1;
+        }
+
+        if (n == -1) {
+            sourceClosed = true;
+            needInput = false;
+        }
+
+        if (n > 0)
+            needInput = false;
+
+        // Restore current position and limit for reading
+        buf.limit(buf.position());
+        buf.position(p);
+    }
+
+    // After this method is called there will either be an exception
+    // or else there will be space in the buffer
+    private boolean makeSpace() {
+        clearCaches();
+        int offset = savedScannerPosition == -1 ?
+            position : savedScannerPosition;
+        buf.position(offset);
+        // Gain space by compacting buffer
+        if (offset > 0) {
+            buf.compact();
+            translateSavedIndexes(offset);
+            position -= offset;
+            buf.flip();
+            return true;
+        }
+        // Gain space by growing buffer
+        int newSize = buf.capacity() * 2;
+        CharBuffer newBuf = CharBuffer.allocate(newSize);
+        newBuf.put(buf);
+        newBuf.flip();
+        translateSavedIndexes(offset);
+        position -= offset;
+        buf = newBuf;
+        matcher.reset(buf);
+        return true;
+    }
+
+    // When a buffer compaction/reallocation occurs the saved indexes must
+    // be modified appropriately
+    private void translateSavedIndexes(int offset) {
+        if (savedScannerPosition != -1)
+            savedScannerPosition -= offset;
+    }
+
+    // If we are at the end of input then NoSuchElement;
+    // If there is still input left then InputMismatch
+    private void throwFor() {
+        skipped = false;
+        if ((sourceClosed) && (position == buf.limit()))
+            throw new NoSuchElementException();
+        else
+            throw new InputMismatchException();
+    }
+
+    // Returns true if a complete token or partial token is in the buffer.
+    // It is not necessary to find a complete token since a partial token
+    // means that there will be another token with or without more input.
+    private boolean hasTokenInBuffer() {
+        matchValid = false;
+        matcher.usePattern(delimPattern);
+        matcher.region(position, buf.limit());
+
+        // Skip delims first
+        if (matcher.lookingAt())
+            position = matcher.end();
+
+        // If we are sitting at the end, no more tokens in buffer
+        if (position == buf.limit())
+            return false;
+
+        return true;
+    }
+
+    /*
+     * Returns a "complete token" that matches the specified pattern
+     *
+     * A token is complete if surrounded by delims; a partial token
+     * is prefixed by delims but not postfixed by them
+     *
+     * The position is advanced to the end of that complete token
+     *
+     * Pattern == null means accept any token at all
+     *
+     * Triple return:
+     * 1. valid string means it was found
+     * 2. null with needInput=false means we won't ever find it
+     * 3. null with needInput=true means try again after readInput
+     */
+    private String getCompleteTokenInBuffer(Pattern pattern) {
+        matchValid = false;
+
+        // Skip delims first
+        matcher.usePattern(delimPattern);
+        if (!skipped) { // Enforcing only one skip of leading delims
+            matcher.region(position, buf.limit());
+            if (matcher.lookingAt()) {
+                // If more input could extend the delimiters then we must wait
+                // for more input
+                if (matcher.hitEnd() && !sourceClosed) {
+                    needInput = true;
+                    return null;
+                }
+                // The delims were whole and the matcher should skip them
+                skipped = true;
+                position = matcher.end();
+            }
+        }
+
+        // If we are sitting at the end, no more tokens in buffer
+        if (position == buf.limit()) {
+            if (sourceClosed)
+                return null;
+            needInput = true;
+            return null;
+        }
+
+        // Must look for next delims. Simply attempting to match the
+        // pattern at this point may find a match but it might not be
+        // the first longest match because of missing input, or it might
+        // match a partial token instead of the whole thing.
+
+        // Then look for next delims
+        matcher.region(position, buf.limit());
+        boolean foundNextDelim = matcher.find();
+        if (foundNextDelim && (matcher.end() == position)) {
+            // Zero length delimiter match; we should find the next one
+            // using the automatic advance past a zero length match;
+            // Otherwise we have just found the same one we just skipped
+            foundNextDelim = matcher.find();
+        }
+        if (foundNextDelim) {
+            // In the rare case that more input could cause the match
+            // to be lost and there is more input coming we must wait
+            // for more input. Note that hitting the end is okay as long
+            // as the match cannot go away. It is the beginning of the
+            // next delims we want to be sure about, we don't care if
+            // they potentially extend further.
+            if (matcher.requireEnd() && !sourceClosed) {
+                needInput = true;
+                return null;
+            }
+            int tokenEnd = matcher.start();
+            // There is a complete token.
+            if (pattern == null) {
+                // Must continue with match to provide valid MatchResult
+                pattern = FIND_ANY_PATTERN;
+            }
+            //  Attempt to match against the desired pattern
+            matcher.usePattern(pattern);
+            matcher.region(position, tokenEnd);
+            if (matcher.matches()) {
+                String s = matcher.group();
+                position = matcher.end();
+                return s;
+            } else { // Complete token but it does not match
+                return null;
+            }
+        }
+
+        // If we can't find the next delims but no more input is coming,
+        // then we can treat the remainder as a whole token
+        if (sourceClosed) {
+            if (pattern == null) {
+                // Must continue with match to provide valid MatchResult
+                pattern = FIND_ANY_PATTERN;
+            }
+            // Last token; Match the pattern here or throw
+            matcher.usePattern(pattern);
+            matcher.region(position, buf.limit());
+            if (matcher.matches()) {
+                String s = matcher.group();
+                position = matcher.end();
+                return s;
+            }
+            // Last piece does not match
+            return null;
+        }
+
+        // There is a partial token in the buffer; must read more
+        // to complete it
+        needInput = true;
+        return null;
+    }
+
+    // Finds the specified pattern in the buffer up to horizon.
+    // Returns a match for the specified input pattern.
+    private String findPatternInBuffer(Pattern pattern, int horizon) {
+        matchValid = false;
+        matcher.usePattern(pattern);
+        int bufferLimit = buf.limit();
+        int horizonLimit = -1;
+        int searchLimit = bufferLimit;
+        if (horizon > 0) {
+            horizonLimit = position + horizon;
+            if (horizonLimit < bufferLimit)
+                searchLimit = horizonLimit;
+        }
+        matcher.region(position, searchLimit);
+        if (matcher.find()) {
+            if (matcher.hitEnd() && (!sourceClosed)) {
+                // The match may be longer if didn't hit horizon or real end
+                if (searchLimit != horizonLimit) {
+                     // Hit an artificial end; try to extend the match
+                    needInput = true;
+                    return null;
+                }
+                // The match could go away depending on what is next
+                if ((searchLimit == horizonLimit) && matcher.requireEnd()) {
+                    // Rare case: we hit the end of input and it happens
+                    // that it is at the horizon and the end of input is
+                    // required for the match.
+                    needInput = true;
+                    return null;
+                }
+            }
+            // Did not hit end, or hit real end, or hit horizon
+            position = matcher.end();
+            return matcher.group();
+        }
+
+        if (sourceClosed)
+            return null;
+
+        // If there is no specified horizon, or if we have not searched
+        // to the specified horizon yet, get more input
+        if ((horizon == 0) || (searchLimit != horizonLimit))
+            needInput = true;
+        return null;
+    }
+
+    // Returns a match for the specified input pattern anchored at
+    // the current position
+    private String matchPatternInBuffer(Pattern pattern) {
+        matchValid = false;
+        matcher.usePattern(pattern);
+        matcher.region(position, buf.limit());
+        if (matcher.lookingAt()) {
+            if (matcher.hitEnd() && (!sourceClosed)) {
+                // Get more input and try again
+                needInput = true;
+                return null;
+            }
+            position = matcher.end();
+            return matcher.group();
+        }
+
+        if (sourceClosed)
+            return null;
+
+        // Read more to find pattern
+        needInput = true;
+        return null;
+    }
+
+    // Throws if the scanner is closed
+    private void ensureOpen() {
+        if (closed)
+            throw new IllegalStateException("Scanner closed");
+    }
+
+    // Public methods
+
+    /**
+     * Closes this scanner.
+     *
+     * <p> If this scanner has not yet been closed then if its underlying
+     * {@linkplain java.lang.Readable readable} also implements the {@link
+     * java.io.Closeable} interface then the readable's <tt>close</tt> method
+     * will be invoked.  If this scanner is already closed then invoking this
+     * method will have no effect.
+     *
+     * <p>Attempting to perform search operations after a scanner has
+     * been closed will result in an {@link IllegalStateException}.
+     *
+     */
+    public void close() {
+        if (closed)
+            return;
+        if (source instanceof Closeable) {
+            try {
+                ((Closeable)source).close();
+            } catch (IOException ioe) {
+                lastException = ioe;
+            }
+        }
+        sourceClosed = true;
+        source = null;
+        closed = true;
+    }
+
+    /**
+     * Returns the <code>IOException</code> last thrown by this
+     * <code>Scanner</code>'s underlying <code>Readable</code>. This method
+     * returns <code>null</code> if no such exception exists.
+     *
+     * @return the last exception thrown by this scanner's readable
+     */
+    public IOException ioException() {
+        return lastException;
+    }
+
+    /**
+     * Returns the <code>Pattern</code> this <code>Scanner</code> is currently
+     * using to match delimiters.
+     *
+     * @return this scanner's delimiting pattern.
+     */
+    public Pattern delimiter() {
+        return delimPattern;
+    }
+
+    /**
+     * Sets this scanner's delimiting pattern to the specified pattern.
+     *
+     * @param pattern A delimiting pattern
+     * @return this scanner
+     */
+    public Scanner useDelimiter(Pattern pattern) {
+        delimPattern = pattern;
+        return this;
+    }
+
+    /**
+     * Sets this scanner's delimiting pattern to a pattern constructed from
+     * the specified <code>String</code>.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>useDelimiter(pattern)</tt> behaves in exactly the same way as the
+     * invocation <tt>useDelimiter(Pattern.compile(pattern))</tt>.
+     *
+     * <p> Invoking the {@link #reset} method will set the scanner's delimiter
+     * to the <a href= "#default-delimiter">default</a>.
+     *
+     * @param pattern A string specifying a delimiting pattern
+     * @return this scanner
+     */
+    public Scanner useDelimiter(String pattern) {
+        delimPattern = patternCache.forName(pattern);
+        return this;
+    }
+
+    /**
+     * Returns this scanner's locale.
+     *
+     * <p>A scanner's locale affects many elements of its default
+     * primitive matching regular expressions; see
+     * <a href= "#localized-numbers">localized numbers</a> above.
+     *
+     * @return this scanner's locale
+     */
+    public Locale locale() {
+        return this.locale;
+    }
+
+    /**
+     * Sets this scanner's locale to the specified locale.
+     *
+     * <p>A scanner's locale affects many elements of its default
+     * primitive matching regular expressions; see
+     * <a href= "#localized-numbers">localized numbers</a> above.
+     *
+     * <p>Invoking the {@link #reset} method will set the scanner's locale to
+     * the <a href= "#initial-locale">initial locale</a>.
+     *
+     * @param locale A string specifying the locale to use
+     * @return this scanner
+     */
+    public Scanner useLocale(Locale locale) {
+        if (locale.equals(this.locale))
+            return this;
+
+        this.locale = locale;
+        DecimalFormat df =
+            (DecimalFormat)NumberFormat.getNumberInstance(locale);
+        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
+
+        // These must be literalized to avoid collision with regex
+        // metacharacters such as dot or parenthesis
+        groupSeparator =   "\\" + dfs.getGroupingSeparator();
+        decimalSeparator = "\\" + dfs.getDecimalSeparator();
+
+        // Quoting the nonzero length locale-specific things
+        // to avoid potential conflict with metacharacters
+        nanString = "\\Q" + dfs.getNaN() + "\\E";
+        infinityString = "\\Q" + dfs.getInfinity() + "\\E";
+        positivePrefix = df.getPositivePrefix();
+        if (positivePrefix.length() > 0)
+            positivePrefix = "\\Q" + positivePrefix + "\\E";
+        negativePrefix = df.getNegativePrefix();
+        if (negativePrefix.length() > 0)
+            negativePrefix = "\\Q" + negativePrefix + "\\E";
+        positiveSuffix = df.getPositiveSuffix();
+        if (positiveSuffix.length() > 0)
+            positiveSuffix = "\\Q" + positiveSuffix + "\\E";
+        negativeSuffix = df.getNegativeSuffix();
+        if (negativeSuffix.length() > 0)
+            negativeSuffix = "\\Q" + negativeSuffix + "\\E";
+
+        // Force rebuilding and recompilation of locale dependent
+        // primitive patterns
+        integerPattern = null;
+        floatPattern = null;
+
+        return this;
+    }
+
+    /**
+     * Returns this scanner's default radix.
+     *
+     * <p>A scanner's radix affects elements of its default
+     * number matching regular expressions; see
+     * <a href= "#localized-numbers">localized numbers</a> above.
+     *
+     * @return the default radix of this scanner
+     */
+    public int radix() {
+        return this.defaultRadix;
+    }
+
+    /**
+     * Sets this scanner's default radix to the specified radix.
+     *
+     * <p>A scanner's radix affects elements of its default
+     * number matching regular expressions; see
+     * <a href= "#localized-numbers">localized numbers</a> above.
+     *
+     * <p>If the radix is less than <code>Character.MIN_RADIX</code>
+     * or greater than <code>Character.MAX_RADIX</code>, then an
+     * <code>IllegalArgumentException</code> is thrown.
+     *
+     * <p>Invoking the {@link #reset} method will set the scanner's radix to
+     * <code>10</code>.
+     *
+     * @param radix The radix to use when scanning numbers
+     * @return this scanner
+     * @throws IllegalArgumentException if radix is out of range
+     */
+    public Scanner useRadix(int radix) {
+        if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
+            throw new IllegalArgumentException("radix:"+radix);
+
+        if (this.defaultRadix == radix)
+            return this;
+        this.defaultRadix = radix;
+        // Force rebuilding and recompilation of radix dependent patterns
+        integerPattern = null;
+        return this;
+    }
+
+    // The next operation should occur in the specified radix but
+    // the default is left untouched.
+    private void setRadix(int radix) {
+        if (this.radix != radix) {
+            // Force rebuilding and recompilation of radix dependent patterns
+            integerPattern = null;
+            this.radix = radix;
+        }
+    }
+
+    /**
+     * Returns the match result of the last scanning operation performed
+     * by this scanner. This method throws <code>IllegalStateException</code>
+     * if no match has been performed, or if the last match was
+     * not successful.
+     *
+     * <p>The various <code>next</code>methods of <code>Scanner</code>
+     * make a match result available if they complete without throwing an
+     * exception. For instance, after an invocation of the {@link #nextInt}
+     * method that returned an int, this method returns a
+     * <code>MatchResult</code> for the search of the
+     * <a href="#Integer-regex"><i>Integer</i></a> regular expression
+     * defined above. Similarly the {@link #findInLine},
+     * {@link #findWithinHorizon}, and {@link #skip} methods will make a
+     * match available if they succeed.
+     *
+     * @return a match result for the last match operation
+     * @throws IllegalStateException  If no match result is available
+     */
+    public MatchResult match() {
+        if (!matchValid)
+            throw new IllegalStateException("No match result available");
+        return matcher.toMatchResult();
+    }
+
+    /**
+     * <p>Returns the string representation of this <code>Scanner</code>. The
+     * string representation of a <code>Scanner</code> contains information
+     * that may be useful for debugging. The exact format is unspecified.
+     *
+     * @return  The string representation of this scanner
+     */
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("java.util.Scanner");
+        sb.append("[delimiters=" + delimPattern + "]");
+        sb.append("[position=" + position + "]");
+        sb.append("[match valid=" + matchValid + "]");
+        sb.append("[need input=" + needInput + "]");
+        sb.append("[source closed=" + sourceClosed + "]");
+        sb.append("[skipped=" + skipped + "]");
+        sb.append("[group separator=" + groupSeparator + "]");
+        sb.append("[decimal separator=" + decimalSeparator + "]");
+        sb.append("[positive prefix=" + positivePrefix + "]");
+        sb.append("[negative prefix=" + negativePrefix + "]");
+        sb.append("[positive suffix=" + positiveSuffix + "]");
+        sb.append("[negative suffix=" + negativeSuffix + "]");
+        sb.append("[NaN string=" + nanString + "]");
+        sb.append("[infinity string=" + infinityString + "]");
+        return sb.toString();
+    }
+
+    /**
+     * Returns true if this scanner has another token in its input.
+     * This method may block while waiting for input to scan.
+     * The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner has another token
+     * @throws IllegalStateException if this scanner is closed
+     * @see java.util.Iterator
+     */
+    public boolean hasNext() {
+        ensureOpen();
+        saveState();
+        while (!sourceClosed) {
+            if (hasTokenInBuffer())
+                return revertState(true);
+            readInput();
+        }
+        boolean result = hasTokenInBuffer();
+        return revertState(result);
+    }
+
+    /**
+     * Finds and returns the next complete token from this scanner.
+     * A complete token is preceded and followed by input that matches
+     * the delimiter pattern. This method may block while waiting for input
+     * to scan, even if a previous invocation of {@link #hasNext} returned
+     * <code>true</code>.
+     *
+     * @return the next token
+     * @throws NoSuchElementException if no more tokens are available
+     * @throws IllegalStateException if this scanner is closed
+     * @see java.util.Iterator
+     */
+    public String next() {
+        ensureOpen();
+        clearCaches();
+
+        while (true) {
+            String token = getCompleteTokenInBuffer(null);
+            if (token != null) {
+                matchValid = true;
+                skipped = false;
+                return token;
+            }
+            if (needInput)
+                readInput();
+            else
+                throwFor();
+        }
+    }
+
+    /**
+     * The remove operation is not supported by this implementation of
+     * <code>Iterator</code>.
+     *
+     * @throws UnsupportedOperationException if this method is invoked.
+     * @see java.util.Iterator
+     */
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns true if the next token matches the pattern constructed from the
+     * specified string. The scanner does not advance past any input.
+     *
+     * <p> An invocation of this method of the form <tt>hasNext(pattern)</tt>
+     * behaves in exactly the same way as the invocation
+     * <tt>hasNext(Pattern.compile(pattern))</tt>.
+     *
+     * @param pattern a string specifying the pattern to scan
+     * @return true if and only if this scanner has another token matching
+     *         the specified pattern
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNext(String pattern)  {
+        return hasNext(patternCache.forName(pattern));
+    }
+
+    /**
+     * Returns the next token if it matches the pattern constructed from the
+     * specified string.  If the match is successful, the scanner advances
+     * past the input that matched the pattern.
+     *
+     * <p> An invocation of this method of the form <tt>next(pattern)</tt>
+     * behaves in exactly the same way as the invocation
+     * <tt>next(Pattern.compile(pattern))</tt>.
+     *
+     * @param pattern a string specifying the pattern to scan
+     * @return the next token
+     * @throws NoSuchElementException if no such tokens are available
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public String next(String pattern)  {
+        return next(patternCache.forName(pattern));
+    }
+
+    /**
+     * Returns true if the next complete token matches the specified pattern.
+     * A complete token is prefixed and postfixed by input that matches
+     * the delimiter pattern. This method may block while waiting for input.
+     * The scanner does not advance past any input.
+     *
+     * @param pattern the pattern to scan for
+     * @return true if and only if this scanner has another token matching
+     *         the specified pattern
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNext(Pattern pattern) {
+        ensureOpen();
+        if (pattern == null)
+            throw new NullPointerException();
+        hasNextPattern = null;
+        saveState();
+
+        while (true) {
+            if (getCompleteTokenInBuffer(pattern) != null) {
+                matchValid = true;
+                cacheResult();
+                return revertState(true);
+            }
+            if (needInput)
+                readInput();
+            else
+                return revertState(false);
+        }
+    }
+
+    /**
+     * Returns the next token if it matches the specified pattern. This
+     * method may block while waiting for input to scan, even if a previous
+     * invocation of {@link #hasNext(Pattern)} returned <code>true</code>.
+     * If the match is successful, the scanner advances past the input that
+     * matched the pattern.
+     *
+     * @param pattern the pattern to scan for
+     * @return the next token
+     * @throws NoSuchElementException if no more tokens are available
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public String next(Pattern pattern) {
+        ensureOpen();
+        if (pattern == null)
+            throw new NullPointerException();
+
+        // Did we already find this pattern?
+        if (hasNextPattern == pattern)
+            return getCachedResult();
+        clearCaches();
+
+        // Search for the pattern
+        while (true) {
+            String token = getCompleteTokenInBuffer(pattern);
+            if (token != null) {
+                matchValid = true;
+                skipped = false;
+                return token;
+            }
+            if (needInput)
+                readInput();
+            else
+                throwFor();
+        }
+    }
+
+    /**
+     * Returns true if there is another line in the input of this scanner.
+     * This method may block while waiting for input. The scanner does not
+     * advance past any input.
+     *
+     * @return true if and only if this scanner has another line of input
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextLine() {
+        saveState();
+
+        String result = findWithinHorizon(linePattern(), 0);
+        if (result != null) {
+            MatchResult mr = this.match();
+            String lineSep = mr.group(1);
+            if (lineSep != null) {
+                result = result.substring(0, result.length() -
+                                          lineSep.length());
+                cacheResult(result);
+
+            } else {
+                cacheResult();
+            }
+        }
+        revertState();
+        return (result != null);
+    }
+
+    /**
+     * Advances this scanner past the current line and returns the input
+     * that was skipped.
+     *
+     * This method returns the rest of the current line, excluding any line
+     * separator at the end. The position is set to the beginning of the next
+     * line.
+     *
+     * <p>Since this method continues to search through the input looking
+     * for a line separator, it may buffer all of the input searching for
+     * the line to skip if no line separators are present.
+     *
+     * @return the line that was skipped
+     * @throws NoSuchElementException if no line was found
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public String nextLine() {
+        if (hasNextPattern == linePattern())
+            return getCachedResult();
+        clearCaches();
+
+        String result = findWithinHorizon(linePattern, 0);
+        if (result == null)
+            throw new NoSuchElementException("No line found");
+        MatchResult mr = this.match();
+        String lineSep = mr.group(1);
+        if (lineSep != null)
+            result = result.substring(0, result.length() - lineSep.length());
+        if (result == null)
+            throw new NoSuchElementException();
+        else
+            return result;
+    }
+
+    // Public methods that ignore delimiters
+
+    /**
+     * Attempts to find the next occurrence of a pattern constructed from the
+     * specified string, ignoring delimiters.
+     *
+     * <p>An invocation of this method of the form <tt>findInLine(pattern)</tt>
+     * behaves in exactly the same way as the invocation
+     * <tt>findInLine(Pattern.compile(pattern))</tt>.
+     *
+     * @param pattern a string specifying the pattern to search for
+     * @return the text that matched the specified pattern
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public String findInLine(String pattern) {
+        return findInLine(patternCache.forName(pattern));
+    }
+
+    /**
+     * Attempts to find the next occurrence of the specified pattern ignoring
+     * delimiters. If the pattern is found before the next line separator, the
+     * scanner advances past the input that matched and returns the string that
+     * matched the pattern.
+     * If no such pattern is detected in the input up to the next line
+     * separator, then <code>null</code> is returned and the scanner's
+     * position is unchanged. This method may block waiting for input that
+     * matches the pattern.
+     *
+     * <p>Since this method continues to search through the input looking
+     * for the specified pattern, it may buffer all of the input searching for
+     * the desired token if no line separators are present.
+     *
+     * @param pattern the pattern to scan for
+     * @return the text that matched the specified pattern
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public String findInLine(Pattern pattern) {
+        ensureOpen();
+        if (pattern == null)
+            throw new NullPointerException();
+        clearCaches();
+        // Expand buffer to include the next newline or end of input
+        int endPosition = 0;
+        saveState();
+        while (true) {
+            String token = findPatternInBuffer(separatorPattern(), 0);
+            if (token != null) {
+                endPosition = matcher.start();
+                break; // up to next newline
+            }
+            if (needInput) {
+                readInput();
+            } else {
+                endPosition = buf.limit();
+                break; // up to end of input
+            }
+        }
+        revertState();
+        int horizonForLine = endPosition - position;
+        // If there is nothing between the current pos and the next
+        // newline simply return null, invoking findWithinHorizon
+        // with "horizon=0" will scan beyond the line bound.
+        if (horizonForLine == 0)
+            return null;
+        // Search for the pattern
+        return findWithinHorizon(pattern, horizonForLine);
+    }
+
+    /**
+     * Attempts to find the next occurrence of a pattern constructed from the
+     * specified string, ignoring delimiters.
+     *
+     * <p>An invocation of this method of the form
+     * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as
+     * the invocation
+     * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>.
+     *
+     * @param pattern a string specifying the pattern to search for
+     * @return the text that matched the specified pattern
+     * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if horizon is negative
+     */
+    public String findWithinHorizon(String pattern, int horizon) {
+        return findWithinHorizon(patternCache.forName(pattern), horizon);
+    }
+
+    /**
+     * Attempts to find the next occurrence of the specified pattern.
+     *
+     * <p>This method searches through the input up to the specified
+     * search horizon, ignoring delimiters. If the pattern is found the
+     * scanner advances past the input that matched and returns the string
+     * that matched the pattern. If no such pattern is detected then the
+     * null is returned and the scanner's position remains unchanged. This
+     * method may block waiting for input that matches the pattern.
+     *
+     * <p>A scanner will never search more than <code>horizon</code> code
+     * points beyond its current position. Note that a match may be clipped
+     * by the horizon; that is, an arbitrary match result may have been
+     * different if the horizon had been larger. The scanner treats the
+     * horizon as a transparent, non-anchoring bound (see {@link
+     * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}).
+     *
+     * <p>If horizon is <code>0</code>, then the horizon is ignored and
+     * this method continues to search through the input looking for the
+     * specified pattern without bound. In this case it may buffer all of
+     * the input searching for the pattern.
+     *
+     * <p>If horizon is negative, then an IllegalArgumentException is
+     * thrown.
+     *
+     * @param pattern the pattern to scan for
+     * @return the text that matched the specified pattern
+     * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if horizon is negative
+     */
+    public String findWithinHorizon(Pattern pattern, int horizon) {
+        ensureOpen();
+        if (pattern == null)
+            throw new NullPointerException();
+        if (horizon < 0)
+            throw new IllegalArgumentException("horizon < 0");
+        clearCaches();
+
+        // Search for the pattern
+        while (true) {
+            String token = findPatternInBuffer(pattern, horizon);
+            if (token != null) {
+                matchValid = true;
+                return token;
+            }
+            if (needInput)
+                readInput();
+            else
+                break; // up to end of input
+        }
+        return null;
+    }
+
+    /**
+     * Skips input that matches the specified pattern, ignoring delimiters.
+     * This method will skip input if an anchored match of the specified
+     * pattern succeeds.
+     *
+     * <p>If a match to the specified pattern is not found at the
+     * current position, then no input is skipped and a
+     * <tt>NoSuchElementException</tt> is thrown.
+     *
+     * <p>Since this method seeks to match the specified pattern starting at
+     * the scanner's current position, patterns that can match a lot of
+     * input (".*", for example) may cause the scanner to buffer a large
+     * amount of input.
+     *
+     * <p>Note that it is possible to skip something without risking a
+     * <code>NoSuchElementException</code> by using a pattern that can
+     * match nothing, e.g., <code>sc.skip("[ \t]*")</code>.
+     *
+     * @param pattern a string specifying the pattern to skip over
+     * @return this scanner
+     * @throws NoSuchElementException if the specified pattern is not found
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public Scanner skip(Pattern pattern) {
+        ensureOpen();
+        if (pattern == null)
+            throw new NullPointerException();
+        clearCaches();
+
+        // Search for the pattern
+        while (true) {
+            String token = matchPatternInBuffer(pattern);
+            if (token != null) {
+                matchValid = true;
+                position = matcher.end();
+                return this;
+            }
+            if (needInput)
+                readInput();
+            else
+                throw new NoSuchElementException();
+        }
+    }
+
+    /**
+     * Skips input that matches a pattern constructed from the specified
+     * string.
+     *
+     * <p> An invocation of this method of the form <tt>skip(pattern)</tt>
+     * behaves in exactly the same way as the invocation
+     * <tt>skip(Pattern.compile(pattern))</tt>.
+     *
+     * @param pattern a string specifying the pattern to skip over
+     * @return this scanner
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public Scanner skip(String pattern) {
+        return skip(patternCache.forName(pattern));
+    }
+
+    // Convenience methods for scanning primitives
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a boolean value using a case insensitive pattern
+     * created from the string "true|false".  The scanner does not
+     * advance past the input that matched.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         boolean value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextBoolean()  {
+        return hasNext(boolPattern());
+    }
+
+    /**
+     * Scans the next token of the input into a boolean value and returns
+     * that value. This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid boolean value.
+     * If the match is successful, the scanner advances past the input that
+     * matched.
+     *
+     * @return the boolean scanned from the input
+     * @throws InputMismatchException if the next token is not a valid boolean
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean nextBoolean()  {
+        clearCaches();
+        return Boolean.parseBoolean(next(boolPattern()));
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a byte value in the default radix using the
+     * {@link #nextByte} method. The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         byte value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextByte() {
+        return hasNextByte(defaultRadix);
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a byte value in the specified radix using the
+     * {@link #nextByte} method. The scanner does not advance past any input.
+     *
+     * @param radix the radix used to interpret the token as a byte value
+     * @return true if and only if this scanner's next token is a valid
+     *         byte value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextByte(int radix) {
+        setRadix(radix);
+        boolean result = hasNext(integerPattern());
+        if (result) { // Cache it
+            try {
+                String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
+                    processIntegerToken(hasNextResult) :
+                    hasNextResult;
+                typeCache = Byte.parseByte(s, radix);
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>byte</tt>.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>nextByte()</tt> behaves in exactly the same way as the
+     * invocation <tt>nextByte(radix)</tt>, where <code>radix</code>
+     * is the default radix of this scanner.
+     *
+     * @return the <tt>byte</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public byte nextByte() {
+         return nextByte(defaultRadix);
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>byte</tt>.
+     * This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid byte value as
+     * described below. If the translation is successful, the scanner advances
+     * past the input that matched.
+     *
+     * <p> If the next token matches the <a
+     * href="#Integer-regex"><i>Integer</i></a> regular expression defined
+     * above then the token is converted into a <tt>byte</tt> value as if by
+     * removing all locale specific prefixes, group separators, and locale
+     * specific suffixes, then mapping non-ASCII digits into ASCII
+     * digits via {@link Character#digit Character.digit}, prepending a
+     * negative sign (-) if the locale specific negative prefixes and suffixes
+     * were present, and passing the resulting string to
+     * {@link Byte#parseByte(String, int) Byte.parseByte} with the
+     * specified radix.
+     *
+     * @param radix the radix used to interpret the token as a byte value
+     * @return the <tt>byte</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public byte nextByte(int radix) {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof Byte)
+            && this.radix == radix) {
+            byte val = ((Byte)typeCache).byteValue();
+            useTypeCache();
+            return val;
+        }
+        setRadix(radix);
+        clearCaches();
+        // Search for next byte
+        try {
+            String s = next(integerPattern());
+            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
+                s = processIntegerToken(s);
+            return Byte.parseByte(s, radix);
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a short value in the default radix using the
+     * {@link #nextShort} method. The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         short value in the default radix
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextShort() {
+        return hasNextShort(defaultRadix);
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a short value in the specified radix using the
+     * {@link #nextShort} method. The scanner does not advance past any input.
+     *
+     * @param radix the radix used to interpret the token as a short value
+     * @return true if and only if this scanner's next token is a valid
+     *         short value in the specified radix
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextShort(int radix) {
+        setRadix(radix);
+        boolean result = hasNext(integerPattern());
+        if (result) { // Cache it
+            try {
+                String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
+                    processIntegerToken(hasNextResult) :
+                    hasNextResult;
+                typeCache = Short.parseShort(s, radix);
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>short</tt>.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>nextShort()</tt> behaves in exactly the same way as the
+     * invocation <tt>nextShort(radix)</tt>, where <code>radix</code>
+     * is the default radix of this scanner.
+     *
+     * @return the <tt>short</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public short nextShort() {
+        return nextShort(defaultRadix);
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>short</tt>.
+     * This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid short value as
+     * described below. If the translation is successful, the scanner advances
+     * past the input that matched.
+     *
+     * <p> If the next token matches the <a
+     * href="#Integer-regex"><i>Integer</i></a> regular expression defined
+     * above then the token is converted into a <tt>short</tt> value as if by
+     * removing all locale specific prefixes, group separators, and locale
+     * specific suffixes, then mapping non-ASCII digits into ASCII
+     * digits via {@link Character#digit Character.digit}, prepending a
+     * negative sign (-) if the locale specific negative prefixes and suffixes
+     * were present, and passing the resulting string to
+     * {@link Short#parseShort(String, int) Short.parseShort} with the
+     * specified radix.
+     *
+     * @param radix the radix used to interpret the token as a short value
+     * @return the <tt>short</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public short nextShort(int radix) {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof Short)
+            && this.radix == radix) {
+            short val = ((Short)typeCache).shortValue();
+            useTypeCache();
+            return val;
+        }
+        setRadix(radix);
+        clearCaches();
+        // Search for next short
+        try {
+            String s = next(integerPattern());
+            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
+                s = processIntegerToken(s);
+            return Short.parseShort(s, radix);
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as an int value in the default radix using the
+     * {@link #nextInt} method. The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         int value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextInt() {
+        return hasNextInt(defaultRadix);
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as an int value in the specified radix using the
+     * {@link #nextInt} method. The scanner does not advance past any input.
+     *
+     * @param radix the radix used to interpret the token as an int value
+     * @return true if and only if this scanner's next token is a valid
+     *         int value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextInt(int radix) {
+        setRadix(radix);
+        boolean result = hasNext(integerPattern());
+        if (result) { // Cache it
+            try {
+                String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
+                    processIntegerToken(hasNextResult) :
+                    hasNextResult;
+                typeCache = Integer.parseInt(s, radix);
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * The integer token must be stripped of prefixes, group separators,
+     * and suffixes, non ascii digits must be converted into ascii digits
+     * before parse will accept it.
+     */
+    private String processIntegerToken(String token) {
+        String result = token.replaceAll(""+groupSeparator, "");
+        boolean isNegative = false;
+        int preLen = negativePrefix.length();
+        if ((preLen > 0) && result.startsWith(negativePrefix)) {
+            isNegative = true;
+            result = result.substring(preLen);
+        }
+        int sufLen = negativeSuffix.length();
+        if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
+            isNegative = true;
+            result = result.substring(result.length() - sufLen,
+                                      result.length());
+        }
+        if (isNegative)
+            result = "-" + result;
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as an <tt>int</tt>.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>nextInt()</tt> behaves in exactly the same way as the
+     * invocation <tt>nextInt(radix)</tt>, where <code>radix</code>
+     * is the default radix of this scanner.
+     *
+     * @return the <tt>int</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public int nextInt() {
+        return nextInt(defaultRadix);
+    }
+
+    /**
+     * Scans the next token of the input as an <tt>int</tt>.
+     * This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid int value as
+     * described below. If the translation is successful, the scanner advances
+     * past the input that matched.
+     *
+     * <p> If the next token matches the <a
+     * href="#Integer-regex"><i>Integer</i></a> regular expression defined
+     * above then the token is converted into an <tt>int</tt> value as if by
+     * removing all locale specific prefixes, group separators, and locale
+     * specific suffixes, then mapping non-ASCII digits into ASCII
+     * digits via {@link Character#digit Character.digit}, prepending a
+     * negative sign (-) if the locale specific negative prefixes and suffixes
+     * were present, and passing the resulting string to
+     * {@link Integer#parseInt(String, int) Integer.parseInt} with the
+     * specified radix.
+     *
+     * @param radix the radix used to interpret the token as an int value
+     * @return the <tt>int</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public int nextInt(int radix) {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof Integer)
+            && this.radix == radix) {
+            int val = ((Integer)typeCache).intValue();
+            useTypeCache();
+            return val;
+        }
+        setRadix(radix);
+        clearCaches();
+        // Search for next int
+        try {
+            String s = next(integerPattern());
+            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
+                s = processIntegerToken(s);
+            return Integer.parseInt(s, radix);
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a long value in the default radix using the
+     * {@link #nextLong} method. The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         long value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextLong() {
+        return hasNextLong(defaultRadix);
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a long value in the specified radix using the
+     * {@link #nextLong} method. The scanner does not advance past any input.
+     *
+     * @param radix the radix used to interpret the token as a long value
+     * @return true if and only if this scanner's next token is a valid
+     *         long value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextLong(int radix) {
+        setRadix(radix);
+        boolean result = hasNext(integerPattern());
+        if (result) { // Cache it
+            try {
+                String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
+                    processIntegerToken(hasNextResult) :
+                    hasNextResult;
+                typeCache = Long.parseLong(s, radix);
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>long</tt>.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>nextLong()</tt> behaves in exactly the same way as the
+     * invocation <tt>nextLong(radix)</tt>, where <code>radix</code>
+     * is the default radix of this scanner.
+     *
+     * @return the <tt>long</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public long nextLong() {
+        return nextLong(defaultRadix);
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>long</tt>.
+     * This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid long value as
+     * described below. If the translation is successful, the scanner advances
+     * past the input that matched.
+     *
+     * <p> If the next token matches the <a
+     * href="#Integer-regex"><i>Integer</i></a> regular expression defined
+     * above then the token is converted into a <tt>long</tt> value as if by
+     * removing all locale specific prefixes, group separators, and locale
+     * specific suffixes, then mapping non-ASCII digits into ASCII
+     * digits via {@link Character#digit Character.digit}, prepending a
+     * negative sign (-) if the locale specific negative prefixes and suffixes
+     * were present, and passing the resulting string to
+     * {@link Long#parseLong(String, int) Long.parseLong} with the
+     * specified radix.
+     *
+     * @param radix the radix used to interpret the token as an int value
+     * @return the <tt>long</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public long nextLong(int radix) {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof Long)
+            && this.radix == radix) {
+            long val = ((Long)typeCache).longValue();
+            useTypeCache();
+            return val;
+        }
+        setRadix(radix);
+        clearCaches();
+        try {
+            String s = next(integerPattern());
+            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
+                s = processIntegerToken(s);
+            return Long.parseLong(s, radix);
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * The float token must be stripped of prefixes, group separators,
+     * and suffixes, non ascii digits must be converted into ascii digits
+     * before parseFloat will accept it.
+     *
+     * If there are non-ascii digits in the token these digits must
+     * be processed before the token is passed to parseFloat.
+     */
+    private String processFloatToken(String token) {
+        String result = token.replaceAll(groupSeparator, "");
+        if (!decimalSeparator.equals("\\."))
+            result = result.replaceAll(decimalSeparator, ".");
+        boolean isNegative = false;
+        int preLen = negativePrefix.length();
+        if ((preLen > 0) && result.startsWith(negativePrefix)) {
+            isNegative = true;
+            result = result.substring(preLen);
+        }
+        int sufLen = negativeSuffix.length();
+        if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
+            isNegative = true;
+            result = result.substring(result.length() - sufLen,
+                                      result.length());
+        }
+        if (result.equals(nanString))
+            result = "NaN";
+        if (result.equals(infinityString))
+            result = "Infinity";
+        if (isNegative)
+            result = "-" + result;
+
+        // Translate non-ASCII digits
+        Matcher m = NON_ASCII_DIGIT.matcher(result);
+        if (m.find()) {
+            StringBuilder inASCII = new StringBuilder();
+            for (int i=0; i<result.length(); i++) {
+                char nextChar = result.charAt(i);
+                if (Character.isDigit(nextChar)) {
+                    int d = Character.digit(nextChar, 10);
+                    if (d != -1)
+                        inASCII.append(d);
+                    else
+                        inASCII.append(nextChar);
+                } else {
+                    inASCII.append(nextChar);
+                }
+            }
+            result = inASCII.toString();
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a float value using the {@link #nextFloat}
+     * method. The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         float value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextFloat() {
+        setRadix(10);
+        boolean result = hasNext(floatPattern());
+        if (result) { // Cache it
+            try {
+                String s = processFloatToken(hasNextResult);
+                typeCache = Float.valueOf(Float.parseFloat(s));
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>float</tt>.
+     * This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid float value as
+     * described below. If the translation is successful, the scanner advances
+     * past the input that matched.
+     *
+     * <p> If the next token matches the <a
+     * href="#Float-regex"><i>Float</i></a> regular expression defined above
+     * then the token is converted into a <tt>float</tt> value as if by
+     * removing all locale specific prefixes, group separators, and locale
+     * specific suffixes, then mapping non-ASCII digits into ASCII
+     * digits via {@link Character#digit Character.digit}, prepending a
+     * negative sign (-) if the locale specific negative prefixes and suffixes
+     * were present, and passing the resulting string to
+     * {@link Float#parseFloat Float.parseFloat}. If the token matches
+     * the localized NaN or infinity strings, then either "Nan" or "Infinity"
+     * is passed to {@link Float#parseFloat(String) Float.parseFloat} as
+     * appropriate.
+     *
+     * @return the <tt>float</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Float</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public float nextFloat() {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof Float)) {
+            float val = ((Float)typeCache).floatValue();
+            useTypeCache();
+            return val;
+        }
+        setRadix(10);
+        clearCaches();
+        try {
+            return Float.parseFloat(processFloatToken(next(floatPattern())));
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a double value using the {@link #nextDouble}
+     * method. The scanner does not advance past any input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         double value
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextDouble() {
+        setRadix(10);
+        boolean result = hasNext(floatPattern());
+        if (result) { // Cache it
+            try {
+                String s = processFloatToken(hasNextResult);
+                typeCache = Double.valueOf(Double.parseDouble(s));
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a <tt>double</tt>.
+     * This method will throw <code>InputMismatchException</code>
+     * if the next token cannot be translated into a valid double value.
+     * If the translation is successful, the scanner advances past the input
+     * that matched.
+     *
+     * <p> If the next token matches the <a
+     * href="#Float-regex"><i>Float</i></a> regular expression defined above
+     * then the token is converted into a <tt>double</tt> value as if by
+     * removing all locale specific prefixes, group separators, and locale
+     * specific suffixes, then mapping non-ASCII digits into ASCII
+     * digits via {@link Character#digit Character.digit}, prepending a
+     * negative sign (-) if the locale specific negative prefixes and suffixes
+     * were present, and passing the resulting string to
+     * {@link Double#parseDouble Double.parseDouble}. If the token matches
+     * the localized NaN or infinity strings, then either "Nan" or "Infinity"
+     * is passed to {@link Double#parseDouble(String) Double.parseDouble} as
+     * appropriate.
+     *
+     * @return the <tt>double</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Float</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if the input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public double nextDouble() {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof Double)) {
+            double val = ((Double)typeCache).doubleValue();
+            useTypeCache();
+            return val;
+        }
+        setRadix(10);
+        clearCaches();
+        // Search for next float
+        try {
+            return Double.parseDouble(processFloatToken(next(floatPattern())));
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    // Convenience methods for scanning multi precision numbers
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a <code>BigInteger</code> in the default radix using the
+     * {@link #nextBigInteger} method. The scanner does not advance past any
+     * input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         <code>BigInteger</code>
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextBigInteger() {
+        return hasNextBigInteger(defaultRadix);
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a <code>BigInteger</code> in the specified radix using
+     * the {@link #nextBigInteger} method. The scanner does not advance past
+     * any input.
+     *
+     * @param radix the radix used to interpret the token as an integer
+     * @return true if and only if this scanner's next token is a valid
+     *         <code>BigInteger</code>
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextBigInteger(int radix) {
+        setRadix(radix);
+        boolean result = hasNext(integerPattern());
+        if (result) { // Cache it
+            try {
+                String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
+                    processIntegerToken(hasNextResult) :
+                    hasNextResult;
+                typeCache = new BigInteger(s, radix);
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a {@link java.math.BigInteger
+     * BigInteger}.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>nextBigInteger()</tt> behaves in exactly the same way as the
+     * invocation <tt>nextBigInteger(radix)</tt>, where <code>radix</code>
+     * is the default radix of this scanner.
+     *
+     * @return the <tt>BigInteger</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if the input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public BigInteger nextBigInteger() {
+        return nextBigInteger(defaultRadix);
+    }
+
+    /**
+     * Scans the next token of the input as a {@link java.math.BigInteger
+     * BigInteger}.
+     *
+     * <p> If the next token matches the <a
+     * href="#Integer-regex"><i>Integer</i></a> regular expression defined
+     * above then the token is converted into a <tt>BigInteger</tt> value as if
+     * by removing all group separators, mapping non-ASCII digits into ASCII
+     * digits via the {@link Character#digit Character.digit}, and passing the
+     * resulting string to the {@link
+     * java.math.BigInteger#BigInteger(java.lang.String)
+     * BigInteger(String, int)} constructor with the specified radix.
+     *
+     * @param radix the radix used to interpret the token
+     * @return the <tt>BigInteger</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Integer</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if the input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public BigInteger nextBigInteger(int radix) {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof BigInteger)
+            && this.radix == radix) {
+            BigInteger val = (BigInteger)typeCache;
+            useTypeCache();
+            return val;
+        }
+        setRadix(radix);
+        clearCaches();
+        // Search for next int
+        try {
+            String s = next(integerPattern());
+            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
+                s = processIntegerToken(s);
+            return new BigInteger(s, radix);
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if the next token in this scanner's input can be
+     * interpreted as a <code>BigDecimal</code> using the
+     * {@link #nextBigDecimal} method. The scanner does not advance past any
+     * input.
+     *
+     * @return true if and only if this scanner's next token is a valid
+     *         <code>BigDecimal</code>
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public boolean hasNextBigDecimal() {
+        setRadix(10);
+        boolean result = hasNext(decimalPattern());
+        if (result) { // Cache it
+            try {
+                String s = processFloatToken(hasNextResult);
+                typeCache = new BigDecimal(s);
+            } catch (NumberFormatException nfe) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Scans the next token of the input as a {@link java.math.BigDecimal
+     * BigDecimal}.
+     *
+     * <p> If the next token matches the <a
+     * href="#Decimal-regex"><i>Decimal</i></a> regular expression defined
+     * above then the token is converted into a <tt>BigDecimal</tt> value as if
+     * by removing all group separators, mapping non-ASCII digits into ASCII
+     * digits via the {@link Character#digit Character.digit}, and passing the
+     * resulting string to the {@link
+     * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)}
+     * constructor.
+     *
+     * @return the <tt>BigDecimal</tt> scanned from the input
+     * @throws InputMismatchException
+     *         if the next token does not match the <i>Decimal</i>
+     *         regular expression, or is out of range
+     * @throws NoSuchElementException if the input is exhausted
+     * @throws IllegalStateException if this scanner is closed
+     */
+    public BigDecimal nextBigDecimal() {
+        // Check cached result
+        if ((typeCache != null) && (typeCache instanceof BigDecimal)) {
+            BigDecimal val = (BigDecimal)typeCache;
+            useTypeCache();
+            return val;
+        }
+        setRadix(10);
+        clearCaches();
+        // Search for next float
+        try {
+            String s = processFloatToken(next(decimalPattern()));
+            return new BigDecimal(s);
+        } catch (NumberFormatException nfe) {
+            position = matcher.start(); // don't skip bad token
+            throw new InputMismatchException(nfe.getMessage());
+        }
+    }
+
+    /**
+     * Resets this scanner.
+     *
+     * <p> Resetting a scanner discards all of its explicit state
+     * information which may have been changed by invocations of {@link
+     * #useDelimiter}, {@link #useLocale}, or {@link #useRadix}.
+     *
+     * <p> An invocation of this method of the form
+     * <tt>scanner.reset()</tt> behaves in exactly the same way as the
+     * invocation
+     *
+     * <blockquote><pre>
+     *   scanner.useDelimiter("\\p{javaWhitespace}+")
+     *          .useLocale(Locale.getDefault())
+     *          .useRadix(10);
+     * </pre></blockquote>
+     *
+     * @return this scanner
+     *
+     * @since 1.6
+     */
+    public Scanner reset() {
+        delimPattern = WHITESPACE_PATTERN;
+        useLocale(Locale.getDefault());
+        useRadix(10);
+        clearCaches();
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.AsynchronousChannel;
+import java.util.concurrent.Future;
+
+/**
+ * Base implementation of Future used for asynchronous I/O
+ */
+
+abstract class AbstractFuture<V,A>
+    implements Future<V>
+{
+    private final AsynchronousChannel channel;
+    private final A attachment;
+
+    protected AbstractFuture(AsynchronousChannel channel, A attachment) {
+        this.channel = channel;
+        this.attachment = attachment;
+    }
+
+    final AsynchronousChannel channel() {
+        return channel;
+    }
+
+    final A attachment() {
+        return attachment;
+    }
+
+    /**
+     * Returns the result of the operation if it has completed successfully.
+     */
+    abstract V value();
+
+    /**
+     * Returns the exception if the operation has failed.
+     */
+    abstract Throwable exception();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.Channel;
+import java.nio.channels.AsynchronousChannelGroup;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.util.Queue;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Base implementation of AsynchronousChannelGroup
+ */
+
+abstract class AsynchronousChannelGroupImpl
+    extends AsynchronousChannelGroup implements Executor
+{
+    // number of internal threads handling I/O events when using an unbounded
+    // thread pool. Internal threads do not dispatch to completion handlers.
+    private static final int INTERNAL_THREAD_COUNT;
+    static {
+        String propValue = AccessController.doPrivileged(
+            new GetPropertyAction("sun.nio.ch.internalThreadPoolSize"));
+        int n = -1;
+        try {
+            n = Integer.parseInt(propValue);
+        } catch (NumberFormatException e) { }
+        INTERNAL_THREAD_COUNT = (n >= 0) ? n : 1;
+    }
+
+    // associated thread pool
+    private final ThreadPool pool;
+
+    // number of tasks running (including internal)
+    private final AtomicInteger threadCount = new AtomicInteger();
+
+    // associated Executor for timeouts
+    private ScheduledThreadPoolExecutor timeoutExecutor;
+
+    // task queue for when using a fixed thread pool. In that case, thread
+    // waiting on I/O events must be awokon to poll tasks from this queue.
+    private final Queue<Runnable> taskQueue;
+
+    // group shutdown
+    // shutdownLock is RW lock so as to allow for concurrent queuing of tasks
+    // when using a fixed thread pool.
+    private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock();
+    private final Object shutdownNowLock = new Object();
+    private volatile boolean shutdown;
+    private volatile boolean terminateInitiated;
+
+    AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
+                                 ThreadPool pool)
+    {
+        super(provider);
+        this.pool = pool;
+
+        if (pool.isFixedThreadPool()) {
+            taskQueue = new ConcurrentLinkedQueue<Runnable>();
+        } else {
+            taskQueue = null;   // not used
+        }
+
+        // use default thread factory as thread should not be visible to
+        // application (it doesn't execute completion handlers).
+        this.timeoutExecutor = (ScheduledThreadPoolExecutor)
+            Executors.newScheduledThreadPool(1, ThreadPool.defaultThreadFactory());
+        this.timeoutExecutor.setRemoveOnCancelPolicy(true);
+    }
+
+    final ExecutorService executor() {
+        return pool.executor();
+    }
+
+    final boolean isFixedThreadPool() {
+        return pool.isFixedThreadPool();
+    }
+
+    final int fixedThreadCount() {
+        if (isFixedThreadPool()) {
+            return pool.poolSize();
+        } else {
+            return pool.poolSize() + INTERNAL_THREAD_COUNT;
+        }
+    }
+
+    private Runnable bindToGroup(final Runnable task) {
+        final AsynchronousChannelGroupImpl thisGroup = this;
+        return new Runnable() {
+            public void run() {
+                Invoker.bindToGroup(thisGroup);
+                task.run();
+            }
+        };
+    }
+
+    private void startInternalThread(final Runnable task) {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+
+            public Void run() {
+                // internal threads should not be visible to application so
+                // cannot use user-supplied thread factory
+                ThreadPool.defaultThreadFactory().newThread(task).start();
+                return null;
+            }
+         });
+    }
+
+    protected final void startThreads(Runnable task) {
+        if (!isFixedThreadPool()) {
+            for (int i=0; i<INTERNAL_THREAD_COUNT; i++) {
+                startInternalThread(task);
+                threadCount.incrementAndGet();
+            }
+        }
+        if (pool.poolSize() > 0) {
+            task = bindToGroup(task);
+            try {
+                for (int i=0; i<pool.poolSize(); i++) {
+                    pool.executor().execute(task);
+                    threadCount.incrementAndGet();
+                }
+            } catch (RejectedExecutionException  x) {
+                // nothing we can do
+            }
+        }
+    }
+
+    final int threadCount() {
+        return threadCount.get();
+    }
+
+    /**
+     * Invoked by tasks as they terminate
+     */
+    final int threadExit(Runnable task, boolean replaceMe) {
+        if (replaceMe) {
+            try {
+                if (Invoker.isBoundToAnyGroup()) {
+                    // submit new task to replace this thread
+                    pool.executor().execute(bindToGroup(task));
+                } else {
+                    // replace internal thread
+                    startInternalThread(task);
+                }
+                return threadCount.get();
+            } catch (RejectedExecutionException x) {
+                // unable to replace
+            }
+        }
+        return threadCount.decrementAndGet();
+    }
+
+    /**
+     * Wakes up a thread waiting for I/O events to execute the given task.
+     */
+    abstract void executeOnHandlerTask(Runnable task);
+
+    /**
+     * For a fixed thread pool the task is queued to a thread waiting on I/O
+     * events. For other thread pools we simply submit the task to the thread
+     * pool.
+     */
+    final void executeOnPooledThread(Runnable task) {
+        if (isFixedThreadPool()) {
+            executeOnHandlerTask(task);
+        } else {
+            pool.executor().execute(bindToGroup(task));
+        }
+    }
+
+    final void offerTask(Runnable task) {
+        taskQueue.offer(task);
+    }
+
+    final Runnable pollTask() {
+        return (taskQueue == null) ? null : taskQueue.poll();
+    }
+
+    final Future<?> schedule(Runnable task, long timeout, TimeUnit unit) {
+        try {
+            return timeoutExecutor.schedule(task, timeout, unit);
+        } catch (RejectedExecutionException rej) {
+            if (terminateInitiated) {
+                // no timeout scheduled as group is terminating
+                return null;
+            }
+            throw new AssertionError(rej);
+        }
+    }
+
+
+    public final boolean isShutdown() {
+        return shutdown;
+    }
+
+
+    public final boolean isTerminated()  {
+        return pool.executor().isTerminated();
+    }
+
+    /**
+     * Returns true if there are no channels in the group
+     */
+    abstract boolean isEmpty();
+
+    /**
+     * Attaches a foreign channel to this group.
+     */
+    abstract Object attachForeignChannel(Channel channel, FileDescriptor fdo)
+        throws IOException;
+
+    /**
+     * Detaches a foreign channel from this group.
+     */
+    abstract void detachForeignChannel(Object key);
+
+    /**
+     * Closes all channels in the group
+     */
+    abstract void closeAllChannels() throws IOException;
+
+    /**
+     * Shutdown all tasks waiting for I/O events.
+     */
+    abstract void shutdownHandlerTasks();
+
+    private void shutdownExecutors() {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                pool.executor().shutdown();
+                timeoutExecutor.shutdown();
+                return null;
+            }
+        });
+    }
+
+
+    public final void shutdown() {
+        shutdownLock.writeLock().lock();
+        try {
+            if (shutdown) {
+                // already shutdown
+                return;
+            }
+            shutdown = true;
+        } finally {
+            shutdownLock.writeLock().unlock();
+        }
+
+        // if there are channels in the group then shutdown will continue
+        // when the last channel is closed
+        if (!isEmpty()) {
+            return;
+        }
+        // initiate termination (acquire shutdownNowLock to ensure that other
+        // threads invoking shutdownNow will block).
+        synchronized (shutdownNowLock) {
+            if (!terminateInitiated) {
+                terminateInitiated = true;
+                shutdownHandlerTasks();
+                shutdownExecutors();
+            }
+        }
+    }
+
+
+    public final void shutdownNow() throws IOException {
+        shutdownLock.writeLock().lock();
+        try {
+            shutdown = true;
+        } finally {
+            shutdownLock.writeLock().unlock();
+        }
+        synchronized (shutdownNowLock) {
+            if (!terminateInitiated) {
+                terminateInitiated = true;
+                closeAllChannels();
+                shutdownHandlerTasks();
+                shutdownExecutors();
+            }
+        }
+    }
+
+
+    public final boolean awaitTermination(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        return pool.executor().awaitTermination(timeout, unit);
+    }
+
+    /**
+     * Executes the given command on one of the channel group's pooled threads.
+     */
+
+    public final void execute(Runnable task) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            // when a security manager is installed then the user's task
+            // must be run with the current calling context
+            final AccessControlContext acc = AccessController.getContext();
+            final Runnable delegate = task;
+            task = new Runnable() {
+
+                public void run() {
+                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+
+                        public Void run() {
+                            delegate.run();
+                            return null;
+                        }
+                    }, acc);
+                }
+            };
+        }
+        executeOnPooledThread(task);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.locks.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * Base implementation of AsynchronousFileChannel.
+ */
+
+abstract class AsynchronousFileChannelImpl
+    extends AsynchronousFileChannel
+{
+    // close support
+    protected final ReadWriteLock closeLock = new ReentrantReadWriteLock();
+    protected volatile boolean closed;
+
+    // file descriptor
+    protected final FileDescriptor fdObj;
+
+    // indicates if open for reading/writing
+    protected final boolean reading;
+    protected final boolean writing;
+
+    // associated Executor
+    protected final ExecutorService executor;
+
+    protected AsynchronousFileChannelImpl(FileDescriptor fdObj,
+                                          boolean reading,
+                                          boolean writing,
+                                          ExecutorService executor)
+    {
+        this.fdObj = fdObj;
+        this.reading = reading;
+        this.writing = writing;
+        this.executor = executor;
+    }
+
+    final ExecutorService executor() {
+        return executor;
+    }
+
+
+    public final boolean isOpen() {
+        return !closed;
+    }
+
+    /**
+     * Marks the beginning of an I/O operation.
+     *
+     * @throws  ClosedChannelException  If channel is closed
+     */
+    protected final void begin() throws IOException {
+        closeLock.readLock().lock();
+        if (closed)
+            throw new ClosedChannelException();
+    }
+
+    /**
+     * Marks the end of an I/O operation.
+     */
+    protected final void end() {
+        closeLock.readLock().unlock();
+    }
+
+    /**
+     * Marks end of I/O operation
+     */
+    protected final void end(boolean completed) throws IOException {
+        end();
+        if (!completed && !isOpen())
+            throw new AsynchronousCloseException();
+    }
+
+    // -- file locking --
+
+    private volatile FileLockTable fileLockTable;
+
+    final void ensureFileLockTableInitialized() throws IOException {
+        if (fileLockTable == null) {
+            synchronized (this) {
+                if (fileLockTable == null) {
+                    fileLockTable = FileLockTable.newSharedFileLockTable(this, fdObj);
+                }
+            }
+        }
+    }
+
+    final void invalidateAllLocks() {
+        if (fileLockTable != null) {
+            try {
+                fileLockTable.removeAll( new FileLockTable.Releaser() {
+                    public void release(FileLock fl) {
+                        ((FileLockImpl)fl).invalidate();
+                    }
+                });
+            } catch (IOException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    /**
+     * Adds region to lock table
+     */
+    protected final FileLockImpl addToFileLockTable(long position, long size, boolean shared) {
+        final FileLockImpl fli;
+        try {
+            // like begin() but returns null instead of exception
+            closeLock.readLock().lock();
+            if (closed)
+                return null;
+
+            try {
+                ensureFileLockTableInitialized();
+            } catch (IOException x) {
+                // should not happen
+                throw new AssertionError(x);
+            }
+            fli = new FileLockImpl(this, position, size, shared);
+            // may throw OverlappedFileLockException
+            fileLockTable.add(fli);
+        } finally {
+            end();
+        }
+        return fli;
+    }
+
+    protected final void removeFromFileLockTable(FileLockImpl fli) {
+        fileLockTable.remove(fli);
+    }
+
+    /**
+     * Invoked by FileLockImpl to release lock acquired by this channel.
+     */
+    abstract void release(FileLockImpl fli) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileLockImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2001-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * 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.ch;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.FileLock;
+
+public class AsynchronousFileLockImpl
+    extends FileLock
+{
+    boolean valid;
+
+    FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared)
+    {
+        super(channel, position, size, shared);
+        this.valid = true;
+    }
+
+    public synchronized boolean isValid() {
+        return valid;
+    }
+
+    synchronized void invalidate() {
+        valid = false;
+    }
+
+    public synchronized void release() throws IOException {
+        Channel ch = acquiredBy();
+        if (!ch.isOpen())
+            throw new ClosedChannelException();
+        if (valid) {
+	  if (ch instanceof AsynchronousFileChannelImpl)
+	    ((AsynchronousFileChannelImpl)ch).release(this);
+	  else throw new AssertionError("Attempted to release unsupported channel " + ch);
+	  valid = false;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardSocketOption;
+import java.net.InetSocketAddress;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Base implementation of AsynchronousServerSocketChannel.
+ */
+
+abstract class AsynchronousServerSocketChannelImpl
+    extends AsynchronousServerSocketChannel
+    implements Cancellable, Groupable
+{
+    protected final FileDescriptor fd;
+
+    // the local address to which the channel's socket is bound
+    protected volatile SocketAddress localAddress = null;
+
+    // need this lock to set local address
+    private final Object stateLock = new Object();
+
+    // close support
+    private ReadWriteLock closeLock = new ReentrantReadWriteLock();
+    private volatile boolean open = true;
+
+    // set true when accept operation is cancelled
+    private volatile boolean acceptKilled;
+
+
+    AsynchronousServerSocketChannelImpl(AsynchronousChannelGroupImpl group) {
+        super(group.provider());
+        this.fd = Net.serverSocket(true);
+    }
+
+
+    public final boolean isOpen() {
+        return open;
+    }
+
+    /**
+     * Marks beginning of access to file descriptor/handle
+     */
+    final void begin() throws IOException {
+        closeLock.readLock().lock();
+        if (!isOpen())
+            throw new ClosedChannelException();
+    }
+
+    /**
+     * Marks end of access to file descriptor/handle
+     */
+    final void end() {
+        closeLock.readLock().unlock();
+    }
+
+    /**
+     * Invoked to close file descriptor/handle.
+     */
+    abstract void implClose() throws IOException;
+
+
+    public final void close() throws IOException {
+        // synchronize with any threads using file descriptor/handle
+        closeLock.writeLock().lock();
+        try {
+            if (!open)
+                return;     // already closed
+            open = false;
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+        implClose();
+    }
+
+    final boolean isAcceptKilled() {
+        return acceptKilled;
+    }
+
+
+    public final void onCancel(PendingFuture<?,?> task) {
+        acceptKilled = true;
+    }
+
+
+    public final AsynchronousServerSocketChannel bind(SocketAddress local, int backlog)
+        throws IOException
+    {
+        InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :
+            Net.checkAddress(local);
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkListen(isa.getPort());
+
+        try {
+            begin();
+            synchronized (stateLock) {
+                if (localAddress != null)
+                    throw new AlreadyBoundException();
+                Net.bind(fd, isa.getAddress(), isa.getPort());
+                Net.listen(fd, backlog < 1 ? 50 : backlog);
+                localAddress = Net.localAddress(fd);
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+
+    public final SocketAddress getLocalAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return localAddress;
+    }
+
+
+    public final <T> AsynchronousServerSocketChannel setOption(SocketOption<T> name,
+                                                               T value)
+        throws IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            Net.setSocketOption(fd, Net.UNSPEC, name, value);
+            return this;
+        } finally {
+            end();
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public final <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+        } finally {
+            end();
+        }
+    }
+
+    private static class LazyInitialization {
+        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SocketOption<?>> defaultOptions() {
+            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
+            set.add(StandardSocketOption.SO_RCVBUF);
+            set.add(StandardSocketOption.SO_REUSEADDR);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+
+    public final Set<SocketOption<?>> supportedOptions() {
+        return LazyInitialization.defaultOptions;
+    }
+
+
+    public final String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(this.getClass().getName());
+        sb.append('[');
+        if (!isOpen())
+            sb.append("closed");
+        else {
+            if (localAddress == null) {
+                sb.append("unbound");
+            } else {
+                sb.append(localAddress.toString());
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.SocketOption;
+import java.net.StandardSocketOption;
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+
+/**
+ * Base implementation of AsynchronousSocketChannel
+ */
+
+abstract class AsynchronousSocketChannelImpl
+    extends AsynchronousSocketChannel
+    implements Cancellable, Groupable
+{
+    protected final FileDescriptor fd;
+
+    // protects state, localAddress, and remoteAddress
+    protected final Object stateLock = new Object();
+
+    protected volatile SocketAddress localAddress = null;
+    protected volatile SocketAddress remoteAddress = null;
+
+    // State, increases monotonically
+    static final int ST_UNINITIALIZED = -1;
+    static final int ST_UNCONNECTED = 0;
+    static final int ST_PENDING = 1;
+    static final int ST_CONNECTED = 2;
+    protected volatile int state = ST_UNINITIALIZED;
+
+    // reading state
+    private final Object readLock = new Object();
+    private boolean reading;
+    private boolean readShutdown;
+    private boolean readKilled;     // further reading disallowed due to timeout
+
+    // writing state
+    private final Object writeLock = new Object();
+    private boolean writing;
+    private boolean writeShutdown;
+    private boolean writeKilled;    // further writing disallowed due to timeout
+
+    // close support
+    private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
+    private volatile boolean open = true;
+
+    AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group)
+        throws IOException
+    {
+        super(group.provider());
+        this.fd = Net.socket(true);
+        this.state = ST_UNCONNECTED;
+    }
+
+    // Constructor for sockets obtained from AsynchronousServerSocketChannelImpl
+    AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group,
+                                  FileDescriptor fd,
+                                  InetSocketAddress remote)
+        throws IOException
+    {
+        super(group.provider());
+        this.fd = fd;
+        this.state = ST_CONNECTED;
+        this.localAddress = Net.localAddress(fd);
+        this.remoteAddress = remote;
+    }
+
+
+    public final boolean isOpen() {
+        return open;
+    }
+
+    /**
+     * Marks beginning of access to file descriptor/handle
+     */
+    final void begin() throws IOException {
+        closeLock.readLock().lock();
+        if (!isOpen())
+            throw new ClosedChannelException();
+    }
+
+    /**
+     * Marks end of access to file descriptor/handle
+     */
+    final void end() {
+        closeLock.readLock().unlock();
+    }
+
+    /**
+     * Invoked to close socket and release other resources.
+     */
+    abstract void implClose() throws IOException;
+
+
+    public final void close() throws IOException {
+        // synchronize with any threads initiating asynchronous operations
+        closeLock.writeLock().lock();
+        try {
+            if (!open)
+                return;     // already closed
+            open = false;
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+        implClose();
+    }
+
+    final void enableReading(boolean killed) {
+        synchronized (readLock) {
+            reading = false;
+            if (killed)
+                readKilled = true;
+        }
+    }
+
+    final void enableReading() {
+        enableReading(false);
+    }
+
+    final void enableWriting(boolean killed) {
+        synchronized (writeLock) {
+            writing = false;
+            if (killed)
+                writeKilled = true;
+        }
+    }
+
+    final void enableWriting() {
+        enableWriting(false);
+    }
+
+    final void killReading() {
+        synchronized (readLock) {
+            readKilled = true;
+        }
+    }
+
+    final void killWriting() {
+        synchronized (writeLock) {
+            writeKilled = true;
+        }
+    }
+
+    final void killConnect() {
+        // when a connect is cancelled then the connection may have been
+        // established so prevent reading or writing.
+        killReading();
+        killWriting();
+    }
+
+    /**
+     * Invoked by read to initiate the I/O operation.
+     */
+    abstract <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
+                                                     boolean isScatteringRead,
+                                                     long timeout,
+                                                     TimeUnit unit,
+                                                     A attachment,
+                                                     CompletionHandler<V,? super A> handler);
+
+    @SuppressWarnings("unchecked")
+    private <V extends Number,A> Future<V> read(ByteBuffer[] dsts,
+                                                boolean isScatteringRead,
+                                                long timeout,
+                                                TimeUnit unit,
+                                                A attachment,
+                                                CompletionHandler<V,? super A> handler)
+    {
+        if (!isOpen()) {
+            CompletedFuture<V,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        if (remoteAddress == null)
+            throw new NotYetConnectedException();
+        if (timeout < 0L)
+            throw new IllegalArgumentException("Negative timeout");
+
+        boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining();
+        boolean shutdown = false;
+
+        // check and update state
+        synchronized (readLock) {
+            if (readKilled)
+                throw new RuntimeException("Reading not allowed due to timeout or cancellation");
+            if (reading)
+                throw new ReadPendingException();
+            if (readShutdown) {
+                shutdown = true;
+            } else {
+                if (hasSpaceToRead) {
+                    reading = true;
+                }
+            }
+        }
+
+        // immediately complete with -1 if shutdown for read
+        // immediately complete with 0 if no space remaining
+        if (shutdown || !hasSpaceToRead) {
+            CompletedFuture<V,A> result;
+            if (isScatteringRead) {
+                Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
+                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
+            } else {
+                int value = (shutdown) ? -1 : 0;
+                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
+            }
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        return readImpl(dsts, isScatteringRead, timeout, unit, attachment, handler);
+    }
+
+
+    public final <A> Future<Integer> read(ByteBuffer dst,
+                                          long timeout,
+                                          TimeUnit unit,
+                                          A attachment,
+                                          CompletionHandler<Integer,? super A> handler)
+    {
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        ByteBuffer[] bufs = new ByteBuffer[1];
+        bufs[0] = dst;
+        return read(bufs, false, timeout, unit, attachment, handler);
+    }
+
+
+    public final <A> Future<Long> read(ByteBuffer[] dsts,
+                                       int offset,
+                                       int length,
+                                       long timeout,
+                                       TimeUnit unit,
+                                       A attachment,
+                                       CompletionHandler<Long,? super A> handler)
+    {
+        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
+            throw new IndexOutOfBoundsException();
+        ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
+        for (int i=0; i<bufs.length; i++) {
+            if (bufs[i].isReadOnly())
+                throw new IllegalArgumentException("Read-only buffer");
+        }
+        return read(bufs, true, timeout, unit, attachment, handler);
+    }
+
+    /**
+     * Invoked by write to initiate the I/O operation.
+     */
+    abstract <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
+                                                      boolean isGatheringWrite,
+                                                      long timeout,
+                                                      TimeUnit unit,
+                                                      A attachment,
+                                                      CompletionHandler<V,? super A> handler);
+
+    @SuppressWarnings("unchecked")
+    private <V extends Number,A> Future<V> write(ByteBuffer[] srcs,
+                                                 boolean isGatheringWrite,
+                                                 long timeout,
+                                                 TimeUnit unit,
+                                                 A attachment,
+                                                 CompletionHandler<V,? super A> handler)
+    {
+        boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining();
+
+        boolean closed = false;
+        if (isOpen()) {
+            if (remoteAddress == null)
+                throw new NotYetConnectedException();
+            if (timeout < 0L)
+                throw new IllegalArgumentException("Negative timeout");
+            // check and update state
+            synchronized (writeLock) {
+                if (writeKilled)
+                    throw new RuntimeException("Writing not allowed due to timeout or cancellation");
+                if (writing)
+                    throw new WritePendingException();
+                if (writeShutdown) {
+                    closed = true;
+                } else {
+                    if (hasDataToWrite)
+                        writing = true;
+                }
+            }
+        } else {
+            closed = true;
+        }
+
+        // channel is closed or shutdown for write
+        if (closed) {
+            CompletedFuture<V,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        // nothing to write so complete immediately
+        if (!hasDataToWrite) {
+            CompletedFuture<V,A> result;
+            if (isGatheringWrite) {
+                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0L, attachment);
+            } else {
+                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0, attachment);
+            }
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler);
+    }
+
+
+    public final <A> Future<Integer> write(ByteBuffer src,
+                                           long timeout,
+                                           TimeUnit unit,
+                                           A attachment,
+                                           CompletionHandler<Integer,? super A> handler)
+    {
+        ByteBuffer[] bufs = new ByteBuffer[1];
+        bufs[0] = src;
+        return write(bufs, false, timeout, unit, attachment, handler);
+    }
+
+
+    public final <A> Future<Long> write(ByteBuffer[] srcs,
+                                        int offset,
+                                        int length,
+                                        long timeout,
+                                        TimeUnit unit,
+                                        A attachment,
+                                        CompletionHandler<Long,? super A> handler)
+    {
+        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
+            throw new IndexOutOfBoundsException();
+        srcs = Util.subsequence(srcs, offset, length);
+        return write(srcs, true, timeout, unit, attachment, handler);
+    }
+
+
+    public final AsynchronousSocketChannel bind(SocketAddress local)
+        throws IOException
+    {
+        try {
+            begin();
+            synchronized (stateLock) {
+                if (state == ST_PENDING)
+                    throw new ConnectionPendingException();
+                if (localAddress != null)
+                    throw new AlreadyBoundException();
+                InetSocketAddress isa = (local == null) ?
+                    new InetSocketAddress(0) : Net.checkAddress(local);
+                Net.bind(fd, isa.getAddress(), isa.getPort());
+                localAddress = Net.localAddress(fd);
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+
+    public final SocketAddress getLocalAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return localAddress;
+    }
+
+
+    public final <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            Net.setSocketOption(fd, Net.UNSPEC, name, value);
+            return this;
+        } finally {
+            end();
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public final <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+        } finally {
+            end();
+        }
+    }
+
+    private static class LazyInitialization {
+        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SocketOption<?>> defaultOptions() {
+            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(5);
+            set.add(StandardSocketOption.SO_SNDBUF);
+            set.add(StandardSocketOption.SO_RCVBUF);
+            set.add(StandardSocketOption.SO_KEEPALIVE);
+            set.add(StandardSocketOption.SO_REUSEADDR);
+            set.add(StandardSocketOption.TCP_NODELAY);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+
+    public final Set<SocketOption<?>> supportedOptions() {
+        return LazyInitialization.defaultOptions;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public final SocketAddress getRemoteAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return remoteAddress;
+    }
+
+
+    public final AsynchronousSocketChannel shutdownInput() throws IOException {
+        try {
+            begin();
+            if (remoteAddress == null)
+                throw new NotYetConnectedException();
+            synchronized (readLock) {
+                if (!readShutdown) {
+                    Net.shutdown(fd, Net.SHUT_RD);
+                    readShutdown = true;
+                }
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+
+    public final AsynchronousSocketChannel shutdownOutput() throws IOException {
+        try {
+            begin();
+            if (remoteAddress == null)
+                throw new NotYetConnectedException();
+            synchronized (writeLock) {
+                if (!writeShutdown) {
+                    Net.shutdown(fd, Net.SHUT_WR);
+                    writeShutdown = true;
+                }
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+
+    public final String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(this.getClass().getSuperclass().getName());
+        sb.append('[');
+        synchronized (stateLock) {
+            if (!isOpen()) {
+                sb.append("closed");
+            } else {
+                switch (state) {
+                case ST_UNCONNECTED:
+                    sb.append("unconnected");
+                    break;
+                case ST_PENDING:
+                    sb.append("connection-pending");
+                    break;
+                case ST_CONNECTED:
+                    sb.append("connected");
+                    if (readShutdown)
+                        sb.append(" ishut");
+                    if (writeShutdown)
+                        sb.append(" oshut");
+                    break;
+                }
+                if (localAddress != null) {
+                    sb.append(" local=");
+                    sb.append(localAddress.toString());
+                }
+                if (remoteAddress != null) {
+                    sb.append(" remote=");
+                    sb.append(remoteAddress.toString());
+                }
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Cancellable.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+/**
+ * Implemented by asynchronous channels that require notification when an I/O
+ * operation is cancelled.
+ */
+
+interface Cancellable {
+    /**
+     * Invoked to notify channel that cancel has been invoked while holding
+     * the Future's lock.
+     */
+    void onCancel(PendingFuture<?,?> task);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.AsynchronousChannel;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutionException;
+import java.io.IOException;
+
+/**
+ * A Future representing the result of an I/O operation that has already
+ * completed.
+ */
+
+final class CompletedFuture<V,A>
+    extends AbstractFuture<V,A>
+{
+    private final V result;
+    private final Throwable exc;
+
+    private CompletedFuture(AsynchronousChannel channel,
+                            V result,
+                            Throwable exc,
+                            A attachment)
+    {
+        super(channel, attachment);
+        this.result = result;
+        this.exc = exc;
+    }
+
+    @SuppressWarnings("unchecked")
+    static <V,A> CompletedFuture<V,A> withResult(AsynchronousChannel channel,
+                                                 V result,
+                                                 A attachment)
+    {
+        return new CompletedFuture<V,A>(channel, result, null, attachment);
+    }
+
+    @SuppressWarnings("unchecked")
+    static <V,A> CompletedFuture<V,A> withFailure(AsynchronousChannel channel,
+                                                  Throwable exc,
+                                                  A attachment)
+    {
+        // exception must be IOException or SecurityException
+        if (!(exc instanceof IOException) && !(exc instanceof SecurityException))
+            exc = new IOException(exc);
+        return new CompletedFuture(channel, null, exc, attachment);
+    }
+
+
+    public V get() throws ExecutionException {
+        if (exc != null)
+            throw new ExecutionException(exc);
+        return result;
+    }
+
+
+    public V get(long timeout, TimeUnit unit) throws ExecutionException {
+        if (unit == null)
+            throw new NullPointerException();
+        if (exc != null)
+            throw new ExecutionException(exc);
+        return result;
+    }
+
+
+    public boolean isCancelled() {
+        return false;
+    }
+
+
+    public boolean isDone() {
+        return true;
+    }
+
+
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        return false;
+    }
+
+
+    Throwable exception() {
+        return exc;
+    }
+
+
+    V value() {
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/FileLockTable.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.ref.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+abstract class FileLockTable {
+    protected FileLockTable() {
+    }
+
+    /**
+     * Creates and returns a file lock table for a channel that is connected to
+     * the a system-wide map of all file locks for the Java virtual machine.
+     */
+    public static FileLockTable newSharedFileLockTable(Channel channel,
+                                                       FileDescriptor fd)
+        throws IOException
+    {
+        return new SharedFileLockTable(channel, fd);
+    }
+
+    /**
+     * Adds a file lock to the table.
+     *
+     * @throws OverlappingFileLockException if the file lock overlaps
+     *         with an existing file lock in the table
+     */
+    public abstract void add(FileLock fl) throws OverlappingFileLockException;
+
+    /**
+     * Remove an existing file lock from the table.
+     */
+    public abstract void remove(FileLock fl);
+
+    /**
+     * An implementation of this interface releases a given file lock.
+     * Used with removeAll.
+     */
+    public abstract interface Releaser {
+        void release(FileLock fl) throws IOException;
+    }
+
+    /**
+     * Removes all file locks from the table.
+     * <p>
+     * The Releaser#release method is invoked for each file lock before
+     * it is removed.
+     *
+     * @throws IOException if the release method throws IOException
+     */
+    public abstract void removeAll(Releaser r) throws IOException;
+
+    /**
+     * Replaces an existing file lock in the table.
+     */
+    public abstract void replace(FileLock fl1, FileLock fl2);
+}
+
+
+
+/**
+ * A file lock table that is over a system-wide map of all file locks.
+ */
+class SharedFileLockTable extends FileLockTable {
+
+    /**
+     * A weak reference to a FileLock.
+     * <p>
+     * SharedFileLockTable uses a list of file lock references to avoid keeping the
+     * FileLock (and FileChannel) alive.
+     */
+    private static class FileLockReference extends WeakReference<FileLock> {
+        private FileKey fileKey;
+
+        FileLockReference(FileLock referent,
+                          ReferenceQueue<FileLock> queue,
+                          FileKey key) {
+            super(referent, queue);
+            this.fileKey = key;
+        }
+
+        FileKey fileKey() {
+            return fileKey;
+        }
+    }
+
+    // The system-wide map is a ConcurrentHashMap that is keyed on the FileKey.
+    // The map value is a list of file locks represented by FileLockReferences.
+    // All access to the list must be synchronized on the list.
+    private static ConcurrentHashMap<FileKey, ArrayList<FileLockReference>> lockMap =
+        new ConcurrentHashMap<FileKey, ArrayList<FileLockReference>>();
+
+    // reference queue for cleared refs
+    private static ReferenceQueue<FileLock> queue = new ReferenceQueue<FileLock>();
+
+    // The connection to which this table is connected
+    private final Channel channel;
+
+    // File key for the file that this channel is connected to
+    private final FileKey fileKey;
+
+    SharedFileLockTable(Channel channel, FileDescriptor fd) throws IOException {
+        this.channel = channel;
+        this.fileKey = FileKey.create(fd);
+    }
+
+
+    public void add(FileLock fl) throws OverlappingFileLockException {
+        ArrayList<FileLockReference> list = lockMap.get(fileKey);
+
+        for (;;) {
+
+            // The key isn't in the map so we try to create it atomically
+            if (list == null) {
+                list = new ArrayList<FileLockReference>(2);
+                ArrayList<FileLockReference> prev;
+                synchronized (list) {
+                    prev = lockMap.putIfAbsent(fileKey, list);
+                    if (prev == null) {
+                        // we successfully created the key so we add the file lock
+                        list.add(new FileLockReference(fl, queue, fileKey));
+                        break;
+                    }
+                }
+                // someone else got there first
+                list = prev;
+            }
+
+            // There is already a key. It is possible that some other thread
+            // is removing it so we re-fetch the value from the map. If it
+            // hasn't changed then we check the list for overlapping locks
+            // and add the new lock to the list.
+            synchronized (list) {
+                ArrayList<FileLockReference> current = lockMap.get(fileKey);
+                if (list == current) {
+                    checkList(list, fl.position(), fl.size());
+                    list.add(new FileLockReference(fl, queue, fileKey));
+                    break;
+                }
+                list = current;
+            }
+
+        }
+
+        // process any stale entries pending in the reference queue
+        removeStaleEntries();
+    }
+
+    private void removeKeyIfEmpty(FileKey fk, ArrayList<FileLockReference> list) {
+        assert Thread.holdsLock(list);
+        assert lockMap.get(fk) == list;
+        if (list.isEmpty()) {
+            lockMap.remove(fk);
+        }
+    }
+
+
+    public void remove(FileLock fl) {
+        assert fl != null;
+
+        // the lock must exist so the list of locks must be present
+        ArrayList<FileLockReference> list = lockMap.get(fileKey);
+        if (list == null) return;
+
+        synchronized (list) {
+            int index = 0;
+            while (index < list.size()) {
+                FileLockReference ref = list.get(index);
+                FileLock lock = ref.get();
+                if (lock == fl) {
+                    assert (lock != null) && (lock.channel() == channel);
+                    ref.clear();
+                    list.remove(index);
+                    break;
+                }
+                index++;
+            }
+        }
+    }
+
+
+    public void removeAll(Releaser releaser) throws IOException {
+        ArrayList<FileLockReference> list = lockMap.get(fileKey);
+        if (list != null) {
+            synchronized (list) {
+                int index = 0;
+                while (index < list.size()) {
+                    FileLockReference ref = list.get(index);
+                    FileLock lock = ref.get();
+
+                    // remove locks obtained by this channel
+                    if (lock != null && lock.channel() == channel) {
+                        // invoke the releaser to invalidate/release the lock
+                        releaser.release(lock);
+
+                        // remove the lock from the list
+                        ref.clear();
+                        list.remove(index);
+                    } else {
+                        index++;
+                    }
+                }
+
+                // once the lock list is empty we remove it from the map
+                removeKeyIfEmpty(fileKey, list);
+            }
+        }
+    }
+
+
+    public void replace(FileLock fromLock, FileLock toLock) {
+        // the lock must exist so there must be a list
+        ArrayList<FileLockReference> list = lockMap.get(fileKey);
+        assert list != null;
+
+        synchronized (list) {
+            for (int index=0; index<list.size(); index++) {
+                FileLockReference ref = list.get(index);
+                FileLock lock = ref.get();
+                if (lock == fromLock) {
+                    ref.clear();
+                    list.set(index, new FileLockReference(toLock, queue, fileKey));
+                    break;
+                }
+            }
+        }
+    }
+
+    // Check for overlapping file locks
+    private void checkList(List<FileLockReference> list, long position, long size)
+        throws OverlappingFileLockException
+    {
+        assert Thread.holdsLock(list);
+        for (FileLockReference ref: list) {
+            FileLock fl = ref.get();
+            if (fl != null && fl.overlaps(position, size))
+                throw new OverlappingFileLockException();
+        }
+    }
+
+    // Process the reference queue
+    private void removeStaleEntries() {
+        FileLockReference ref;
+        while ((ref = (FileLockReference)queue.poll()) != null) {
+            FileKey fk = ref.fileKey();
+            ArrayList<FileLockReference> list = lockMap.get(fk);
+            if (list != null) {
+                synchronized (list) {
+                    list.remove(ref);
+                    removeKeyIfEmpty(fk, list);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Groupable.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+/**
+ * Implemented by asynchronous channels that can be associated with an
+ * asynchronous channel group.
+ */
+
+interface Groupable {
+    AsynchronousChannelGroupImpl group();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Invoker.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Defines static methods to invoke a completion handler or arbitrary task.
+ */
+
+class Invoker {
+    private Invoker() { }
+
+    // maximum number of completion handlers that may be invoked on the current
+    // thread before it re-directs invocations to the thread pool. This helps
+    // avoid stack overflow and lessens the risk of starvation.
+    private static final int MAX_HANDLER_INVOKE_COUNT;
+    static {
+        String propValue = AccessController.doPrivileged(
+            new GetPropertyAction("sun.nio.ch.maxCompletionHandlersOnStack"));
+        int n = -1;
+        try {
+            n = Integer.parseInt(propValue);
+        } catch (NumberFormatException e) { }
+        MAX_HANDLER_INVOKE_COUNT = (n >= 1) ? n : 16;
+    }
+
+    // Per-thread object with reference to channel group and a counter for
+    // the number of completion handlers invoked. This should be reset to 0
+    // when all completion handlers have completed.
+    static class GroupAndInvokeCount {
+        private final AsynchronousChannelGroupImpl group;
+        private int handlerInvokeCount;
+        GroupAndInvokeCount(AsynchronousChannelGroupImpl group) {
+            this.group = group;
+        }
+        AsynchronousChannelGroupImpl group() {
+            return group;
+        }
+        int invokeCount() {
+            return handlerInvokeCount;
+        }
+        void setInvokeCount(int value) {
+            handlerInvokeCount = value;
+        }
+        void resetInvokeCount() {
+            handlerInvokeCount = 0;
+        }
+        void incrementInvokeCount() {
+            handlerInvokeCount++;
+        }
+    }
+    private static final ThreadLocal<GroupAndInvokeCount> myGroupAndInvokeCount =
+        new ThreadLocal<GroupAndInvokeCount>() {
+ protected GroupAndInvokeCount initialValue() {
+                return null;
+            }
+        };
+
+    /**
+     * Binds this thread to the given group
+     */
+    static void bindToGroup(AsynchronousChannelGroupImpl group) {
+        myGroupAndInvokeCount.set(new GroupAndInvokeCount(group));
+    }
+
+    /**
+     * Returns the GroupAndInvokeCount object for this thread.
+     */
+    static GroupAndInvokeCount getGroupAndInvokeCount() {
+        return myGroupAndInvokeCount.get();
+    }
+
+    /**
+     * Returns true if the current thread is in a channel group's thread pool
+     */
+    static boolean isBoundToAnyGroup() {
+        return myGroupAndInvokeCount.get() != null;
+    }
+
+
+    /**
+     * Returns true if the current thread is in the given channel's thread
+     * pool and we haven't exceeded the maximum number of handler frames on
+     * the stack.
+     */
+    static boolean mayInvokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
+                                   AsynchronousChannelGroupImpl group)
+    {
+        if ((myGroupAndInvokeCount != null) &&
+            (myGroupAndInvokeCount.group() == group) &&
+            (myGroupAndInvokeCount.invokeCount() < MAX_HANDLER_INVOKE_COUNT))
+        {
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * Invoke handler without checking the thread identity or number of handlers
+     * on the thread stack.
+     */
+    @SuppressWarnings("unchecked")
+    static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
+                                      AbstractFuture<V,A> result)
+    {
+        if (handler != null && !result.isCancelled()) {
+            Throwable exc = result.exception();
+            if (exc == null) {
+                handler.completed(result.value(), result.attachment());
+            } else {
+                handler.failed(exc, result.attachment());
+            }
+
+            // clear interrupt
+            Thread.interrupted();
+        }
+    }
+
+
+    /**
+     * Invoke handler after incrementing the invoke count.
+     */
+    static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
+                                   CompletionHandler<V,? super A> handler,
+                                   AbstractFuture<V,A> result)
+    {
+        myGroupAndInvokeCount.incrementInvokeCount();
+        invokeUnchecked(handler, result);
+    }
+
+    /**
+     * Invokes the handler. If the current thread is in the channel group's
+     * thread pool then the handler is invoked directly, otherwise it is
+     * invoked indirectly.
+     */
+    static <V,A> void invoke(CompletionHandler<V,? super A> handler,
+                             AbstractFuture<V,A> result)
+    {
+        if (handler != null) {
+            boolean invokeDirect = false;
+            boolean identityOkay = false;
+            GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+            if (thisGroupAndInvokeCount != null) {
+                AsynchronousChannel channel = result.channel();
+                if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
+                    identityOkay = true;
+                if (identityOkay &&
+                    (thisGroupAndInvokeCount.invokeCount() < MAX_HANDLER_INVOKE_COUNT))
+                {
+                    // group match
+                    invokeDirect = true;
+                }
+            }
+            if (invokeDirect) {
+                thisGroupAndInvokeCount.incrementInvokeCount();
+                invokeUnchecked(handler, result);
+            } else {
+                try {
+                    invokeIndirectly(handler, result);
+                } catch (RejectedExecutionException ree) {
+                    // channel group shutdown; fallback to invoking directly
+                    // if the current thread has the right identity.
+                    if (identityOkay) {
+                        invokeUnchecked(handler, result);
+                    } else {
+                        throw new ShutdownChannelGroupException();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Invokes the handler "indirectly" in the channel group's thread pool.
+     */
+    static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
+                                       final AbstractFuture<V,A> result)
+    {
+        if (handler != null) {
+            AsynchronousChannel channel = result.channel();
+            try {
+                ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
+                    public void run() {
+                        GroupAndInvokeCount thisGroupAndInvokeCount =
+                            myGroupAndInvokeCount.get();
+                        if (thisGroupAndInvokeCount != null)
+                            thisGroupAndInvokeCount.setInvokeCount(1);
+                        invokeUnchecked(handler, result);
+                    }
+                });
+            } catch (RejectedExecutionException ree) {
+                throw new ShutdownChannelGroupException();
+            }
+        }
+    }
+
+    /**
+     * Invokes the handler "indirectly" in the given Executor
+     */
+    static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
+                                       final AbstractFuture<V,A> result,
+                                       Executor executor)
+    {
+        if (handler != null) {
+            try {
+                executor.execute(new Runnable() {
+                    public void run() {
+                        invokeUnchecked(handler, result);
+                    }
+                });
+            } catch (RejectedExecutionException ree) {
+                throw new ShutdownChannelGroupException();
+            }
+        }
+    }
+
+    /**
+     * Invokes the given task on the thread pool associated with the given
+     * channel. If the current thread is in the thread pool then the task is
+     * invoked directly.
+     */
+    static void invokeOnThreadInThreadPool(Groupable channel,
+                                           Runnable task)
+    {
+        boolean invokeDirect;
+        GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+        AsynchronousChannelGroupImpl targetGroup = channel.group();
+        if (thisGroupAndInvokeCount == null) {
+            invokeDirect = false;
+        } else {
+            invokeDirect = (thisGroupAndInvokeCount.group == targetGroup);
+        }
+        try {
+            if (invokeDirect) {
+                task.run();
+            } else {
+                targetGroup.executeOnPooledThread(task);
+            }
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/PendingFuture.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+
+/**
+ * A Future for a pending I/O operation. A PendingFuture allows for the
+ * attachment of an additional arbitrary context object and a timer task.
+ */
+
+final class PendingFuture<V,A>
+    extends AbstractFuture<V,A>
+{
+    private static final CancellationException CANCELLED =
+        new CancellationException();
+
+    private final CompletionHandler<V,? super A> handler;
+
+    // true if result (or exception) is available
+    private volatile boolean haveResult;
+    private volatile V result;
+    private volatile Throwable exc;
+
+    // latch for waiting (created lazily if needed)
+    private CountDownLatch latch;
+
+    // optional timer task that is cancelled when result becomes available
+    private Future<?> timeoutTask;
+
+    // optional context object
+    private volatile Object context;
+
+
+    PendingFuture(AsynchronousChannel channel,
+                  CompletionHandler<V,? super A> handler,
+                  A attachment,
+                  Object context)
+    {
+        super(channel, attachment);
+        this.handler = handler;
+        this.context = context;
+    }
+
+    PendingFuture(AsynchronousChannel channel,
+                  CompletionHandler<V,? super A> handler,
+                  A attachment)
+    {
+        super(channel, attachment);
+        this.handler = handler;
+    }
+
+    CompletionHandler<V,? super A> handler() {
+        return handler;
+    }
+
+    void setContext(Object context) {
+        this.context = context;
+    }
+
+    Object getContext() {
+        return context;
+    }
+
+    void setTimeoutTask(Future<?> task) {
+        synchronized (this) {
+            if (haveResult) {
+                task.cancel(false);
+            } else {
+                this.timeoutTask = task;
+            }
+        }
+    }
+
+    // creates latch if required; return true if caller needs to wait
+    private boolean prepareForWait() {
+        synchronized (this) {
+            if (haveResult) {
+                return false;
+            } else {
+                if (latch == null)
+                    latch = new CountDownLatch(1);
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Sets the result, or a no-op if the result or exception is already set.
+     */
+    boolean setResult(V res) {
+        synchronized (this) {
+            if (haveResult)
+                return false;
+            result = res;
+            haveResult = true;
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+            if (latch != null)
+                latch.countDown();
+            return true;
+        }
+    }
+
+    /**
+     * Sets the result, or a no-op if the result or exception is already set.
+     */
+    boolean setFailure(Throwable x) {
+        if (!(x instanceof IOException) && !(x instanceof SecurityException))
+            x = new IOException(x);
+        synchronized (this) {
+            if (haveResult)
+                return false;
+            exc = x;
+            haveResult = true;
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+            if (latch != null)
+                latch.countDown();
+            return true;
+        }
+    }
+
+
+    public V get() throws ExecutionException, InterruptedException {
+        if (!haveResult) {
+            boolean needToWait = prepareForWait();
+            if (needToWait)
+                latch.await();
+        }
+        if (exc != null) {
+            if (exc == CANCELLED)
+                throw new CancellationException();
+            throw new ExecutionException(exc);
+        }
+        return result;
+    }
+
+
+    public V get(long timeout, TimeUnit unit)
+        throws ExecutionException, InterruptedException, TimeoutException
+    {
+        if (!haveResult) {
+            boolean needToWait = prepareForWait();
+            if (needToWait)
+                if (!latch.await(timeout, unit)) throw new TimeoutException();
+        }
+        if (exc != null) {
+            if (exc == CANCELLED)
+                throw new CancellationException();
+            throw new ExecutionException(exc);
+        }
+        return result;
+    }
+
+
+    Throwable exception() {
+        return (exc != CANCELLED) ? exc : null;
+    }
+
+
+    V value() {
+        return result;
+    }
+
+
+    public boolean isCancelled() {
+        return (exc == CANCELLED);
+    }
+
+
+    public boolean isDone() {
+        return haveResult;
+    }
+
+
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        synchronized (this) {
+            if (haveResult)
+                return false;    // already completed
+
+            // A shutdown of the channel group will close all channels and
+            // shutdown the executor. To ensure that the completion handler
+            // is executed we queue the task while holding the lock.
+            if (handler != null) {
+                prepareForWait();
+                Runnable cancelTask = new Runnable() {
+                    public void run() {
+                        while (!haveResult) {
+                            try {
+                                latch.await();
+                            } catch (InterruptedException ignore) { }
+                        }
+                        handler.cancelled(attachment());
+                    }
+                };
+                AsynchronousChannel ch = channel();
+                if (ch instanceof Groupable) {
+                    ((Groupable)ch).group().executeOnPooledThread(cancelTask);
+                } else {
+                    if (ch instanceof AsynchronousFileChannelImpl) {
+                        ((AsynchronousFileChannelImpl)ch).executor().execute(cancelTask);
+                    } else {
+                        throw new AssertionError("Should not get here");
+                    }
+                }
+            }
+
+            // notify channel
+            if (channel() instanceof Cancellable)
+                ((Cancellable)channel()).onCancel(this);
+
+            // set result and cancel timer
+            exc = CANCELLED;
+            haveResult = true;
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+        }
+
+        // close channel if forceful cancel
+        if (mayInterruptIfRunning) {
+            try {
+                channel().close();
+            } catch (IOException ignore) { }
+        }
+
+        // release waiters (this also releases the invoker)
+        if (latch != null)
+            latch.countDown();
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.*;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+
+/**
+ * A prototype implementation of AsynchronousDatagramChannel, used to aid
+ * test and spec development.
+ */
+
+class SimpleAsynchronousDatagramChannelImpl
+    extends AsynchronousDatagramChannel implements Groupable
+{
+    private final DatagramChannel dc;
+    private final AsynchronousChannelGroupImpl group;
+    private final Object attachKey;
+    private boolean closed;
+
+    SimpleAsynchronousDatagramChannelImpl(ProtocolFamily family,
+                                          AsynchronousChannelGroupImpl group)
+        throws IOException
+    {
+        super(group.provider());
+        this.dc = (family == null) ?
+            DatagramChannel.open() : DatagramChannel.open(family);
+        this.group = group;
+
+        boolean registered = false;
+        try {
+            if (!(dc instanceof DatagramChannelImpl))
+                throw new UnsupportedOperationException();
+            attachKey = group
+                .attachForeignChannel(this, ((DatagramChannelImpl)dc).getFD());
+            registered = true;
+        } finally {
+            if (!registered)
+                dc.close();
+        }
+    }
+
+
+    public AsynchronousChannelGroupImpl group() {
+        return group;
+    }
+
+
+    public boolean isOpen() {
+        return dc.isOpen();
+    }
+
+
+    public void close() throws IOException {
+        synchronized (dc) {
+            if (closed)
+                return;
+            closed = true;
+        }
+        group.detachForeignChannel(attachKey);
+        dc.close();
+    }
+
+
+    public AsynchronousDatagramChannel connect(SocketAddress remote)
+        throws IOException
+    {
+        dc.connect(remote);
+        return this;
+    }
+
+
+    public AsynchronousDatagramChannel disconnect() throws IOException {
+        dc.disconnect();
+        return this;
+    }
+
+    private static class WrappedMembershipKey extends MembershipKey {
+        private final MulticastChannel channel;
+        private final MembershipKey key;
+
+        WrappedMembershipKey(MulticastChannel channel, MembershipKey key) {
+            this.channel = channel;
+            this.key = key;
+        }
+
+
+        public boolean isValid() {
+            return key.isValid();
+        }
+
+
+        public void drop() throws IOException {
+            key.drop();
+        }
+
+
+        public MulticastChannel channel() {
+            return channel;
+        }
+
+
+        public InetAddress group() {
+            return key.group();
+        }
+
+
+        public NetworkInterface networkInterface() {
+            return key.networkInterface();
+        }
+
+
+        public InetAddress sourceAddress() {
+            return key.sourceAddress();
+        }
+
+
+        public MembershipKey block(InetAddress toBlock) throws IOException {
+            key.block(toBlock);
+            return this;
+        }
+
+
+        public MembershipKey unblock(InetAddress toUnblock) throws IOException {
+            key.unblock(toUnblock);
+            return this;
+        }
+
+
+        public String toString() {
+            return key.toString();
+        }
+    }
+
+
+    public MembershipKey join(InetAddress group,
+                              NetworkInterface interf)
+        throws IOException
+    {
+        MembershipKey key = ((MulticastChannel)dc).join(group, interf);
+        return new WrappedMembershipKey(this, key);
+    }
+
+
+    public MembershipKey join(InetAddress group,
+                              NetworkInterface interf,
+                              InetAddress source)
+        throws IOException
+    {
+        MembershipKey key = ((MulticastChannel)dc).join(group, interf, source);
+        return new WrappedMembershipKey(this, key);
+    }
+
+
+    public <A> Future<Integer> send(ByteBuffer src,
+                                    SocketAddress target,
+                                    long timeout,
+                                    TimeUnit unit,
+                                    A attachment,
+                                    CompletionHandler<Integer,? super A> handler)
+    {
+        if (timeout < 0L)
+            throw new IllegalArgumentException("Negative timeout");
+        if (unit == null)
+            throw new NullPointerException();
+
+        CompletedFuture<Integer,A> result;
+        try {
+            // assume it will not block
+            int n = dc.send(src, target);
+            result = CompletedFuture.withResult(this, n, attachment);
+        } catch (IOException ioe) {
+            result = CompletedFuture.withFailure(this, ioe, attachment);
+        }
+        Invoker.invoke(handler, result);
+        return result;
+    }
+
+
+    public <A> Future<Integer> write(ByteBuffer src,
+                                     long timeout,
+                                     TimeUnit unit,
+                                     A attachment,
+                                     CompletionHandler<Integer,? super A> handler)
+    {
+        if (timeout < 0L)
+            throw new IllegalArgumentException("Negative timeout");
+        if (unit == null)
+            throw new NullPointerException();
+
+        CompletedFuture<Integer,A> result;
+        try {
+            // assume it will not block
+            int n = dc.write(src);
+            result = CompletedFuture.withResult(this, n, attachment);
+        } catch (IOException ioe) {
+            result = CompletedFuture.withFailure(this, ioe, attachment);
+        }
+        Invoker.invoke(handler, result);
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <V,A> Future<?> scheduleTimeout(final PendingFuture<V,? super A> result,
+                                            long timeout, TimeUnit unit)
+    {
+        if (timeout > 0L) {
+            Runnable readTimeoutTask = new Runnable() {
+                public void run() {
+                    if (result.setFailure(new InterruptedByTimeoutException()))
+                        Invoker.invoke(result.handler(), (AbstractFuture<V,A>)result);
+                }
+            };
+            Future<?> timeoutTask = group.schedule(readTimeoutTask, timeout, unit);
+            result.setTimeoutTask(timeoutTask);
+            return timeoutTask;
+        } else {
+            return null;
+        }
+    }
+
+
+    public <A> Future<SocketAddress> receive(final ByteBuffer dst,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             final CompletionHandler<SocketAddress,? super A> handler)
+    {
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        if (timeout < 0L)
+            throw new IllegalArgumentException("Negative timeout");
+        if (unit == null)
+            throw new NullPointerException();
+
+        // complete immediately if channel closed
+        if (!isOpen()) {
+            CompletedFuture<SocketAddress,A> result = CompletedFuture.withFailure(this,
+                new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        final AccessControlContext acc = (System.getSecurityManager() == null) ?
+            null : AccessController.getContext();
+        final PendingFuture<SocketAddress,A> result =
+            new PendingFuture<SocketAddress,A>(this, handler, attachment);
+        Runnable task = new Runnable() {
+            public void run() {
+                boolean completedByMe = false;
+                try {
+                    SocketAddress remote;
+                    if (acc == null) {
+                        remote = dc.receive(dst);
+                    } else {
+                        // receive in caller context
+                        try {
+                            remote = AccessController.doPrivileged(
+                                new PrivilegedExceptionAction<SocketAddress>() {
+                                    public SocketAddress run() throws IOException {
+                                        return dc.receive(dst);
+                                    }}, acc);
+                        } catch (PrivilegedActionException pae) {
+                            Exception cause = pae.getException();
+                            if (cause instanceof SecurityException)
+                                throw (SecurityException)cause;
+                            throw (IOException)cause;
+                        }
+                    }
+                    completedByMe = result.setResult(remote);
+                } catch (Throwable x) {
+                    if (x instanceof ClosedChannelException)
+                        x = new AsynchronousCloseException();
+                    completedByMe = result.setFailure(x);
+                }
+                if (completedByMe)
+                    Invoker.invokeUnchecked(handler, result);
+            }
+        };
+        Future<?> timeoutTask = scheduleTimeout(result, timeout, unit);
+        try {
+            group.executeOnPooledThread(task);
+        } catch (RejectedExecutionException ree) {
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+            throw new ShutdownChannelGroupException();
+        }
+        return result;
+    }
+
+
+    public <A> Future<Integer> read(final ByteBuffer dst,
+                                    long timeout,
+                                    TimeUnit unit,
+                                    A attachment,
+                                    final CompletionHandler<Integer,? super A> handler)
+    {
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        if (timeout < 0L)
+            throw new IllegalArgumentException("Negative timeout");
+        if (unit == null)
+            throw new NullPointerException();
+        // another thread may disconnect before read is initiated
+        if (!dc.isConnected())
+            throw new NotYetConnectedException();
+
+        // complete immediately if channel closed
+        if (!isOpen()) {
+            CompletedFuture<Integer,A> result = CompletedFuture.withFailure(this,
+                new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        final PendingFuture<Integer,A> result =
+            new PendingFuture<Integer,A>(this, handler, attachment);
+        Runnable task = new Runnable() {
+            public void run() {
+                boolean completedByMe = false;
+                try {
+                    int n = dc.read(dst);
+                    completedByMe = result.setResult(n);
+                } catch (Throwable x) {
+                    if (x instanceof ClosedChannelException)
+                        x = new AsynchronousCloseException();
+                    completedByMe = result.setFailure(x);
+                }
+                if (completedByMe)
+                    Invoker.invokeUnchecked(handler, result);
+            }
+        };
+        Future<?> timeoutTask = scheduleTimeout(result, timeout, unit);
+        try {
+            group.executeOnPooledThread(task);
+        } catch (RejectedExecutionException ree) {
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+            throw new ShutdownChannelGroupException();
+        }
+        return result;
+    }
+
+
+    public  AsynchronousDatagramChannel bind(SocketAddress local)
+        throws IOException
+    {
+        dc.bind(local);
+        return this;
+    }
+
+
+    public SocketAddress getLocalAddress() throws IOException {
+        return dc.getLocalAddress();
+    }
+
+
+    public <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        dc.setOption(name, value);
+        return this;
+    }
+
+
+    public  <T> T getOption(SocketOption<T> name) throws IOException {
+        return dc.getOption(name);
+    }
+
+
+    public Set<SocketOption<?>> supportedOptions() {
+        return dc.supportedOptions();
+    }
+
+
+    public SocketAddress getRemoteAddress() throws IOException {
+        return dc.getRemoteAddress();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,429 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * "Portable" implementation of AsynchronousFileChannel for use on operating
+ * systems that don't support asynchronous file I/O.
+ */
+
+public class SimpleAsynchronousFileChannelImpl
+    extends AsynchronousFileChannelImpl
+{
+    // default (system-wide) thread pool
+    private static volatile ExecutorService defaultExecutor;
+
+    private static ExecutorService defaultExecutor() {
+        if (defaultExecutor == null) {
+            synchronized (SimpleAsynchronousFileChannelImpl.class) {
+                if (defaultExecutor == null) {
+                    /*
+                     * Create a thread pool for file I/O operations so as to
+                     * avoid sharing the thread pool with socket I/O.
+                     */
+                    defaultExecutor = ThreadPool.createDefault().executor();
+                }
+            }
+        }
+        return defaultExecutor;
+    }
+
+    // Used to make native read and write calls
+    private static final FileDispatcher nd = new FileDispatcherImpl();
+
+    // Thread-safe set of IDs of native threads, for signalling
+    private final NativeThreadSet threads = new NativeThreadSet(2);
+
+
+    SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
+                                      boolean reading,
+                                      boolean writing,
+                                      ExecutorService executor)
+    {
+        super(fdObj, reading, writing, executor);
+    }
+
+    public static AsynchronousFileChannel open(FileDescriptor fdo,
+                                               boolean reading,
+                                               boolean writing,
+                                               ThreadPool pool)
+    {
+        // Executor is either default or based on pool parameters
+        ExecutorService executor;
+        if (pool == null) {
+            executor = defaultExecutor();
+        } else {
+            executor = pool.executor();
+        }
+        return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
+    }
+
+
+    public void close() throws IOException {
+        // mark channel as closed
+        synchronized (fdObj) {
+            if (closed)
+                return;     // already closed
+            closed = true;
+            // from this point on, if another thread invokes the begin() method
+            // then it will throw ClosedChannelException
+        }
+
+        // signal any threads blocked on this channel
+        nd.preClose(fdObj);
+        threads.signal();
+
+        // wait until all I/O operations have completely gracefully
+        closeLock.writeLock().lock();
+        try {
+            // do nothing
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+
+        // Invalidate and release any locks that we still hold
+        invalidateAllLocks();
+
+        // close file
+        nd.close(fdObj);
+
+        // shutdown executor if specific to this channel
+        if (executor != defaultExecutor) {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    executor.shutdown();
+                    return null;
+                }
+            });
+        }
+    }
+
+
+    public long size() throws IOException {
+        int ti = threads.add();
+        try {
+            long n = 0L;
+            try {
+                begin();
+                do {
+                    n = nd.size(fdObj);
+                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                return n;
+            } finally {
+                end(n >= 0L);
+            }
+        } finally {
+            threads.remove(ti);
+        }
+    }
+
+
+    public AsynchronousFileChannel truncate(long size) throws IOException {
+        if (size < 0L)
+            throw new IllegalArgumentException("Negative size");
+        if (!writing)
+            throw new NonWritableChannelException();
+        int ti = threads.add();
+        try {
+            long n = 0L;
+            try {
+                begin();
+                do {
+                    n = nd.size(fdObj);
+                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+
+                // truncate file if 'size' less than current size
+                if (size < n && isOpen()) {
+                    do {
+                        n = nd.truncate(fdObj, size);
+                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                }
+                return this;
+            } finally {
+                end(n > 0);
+            }
+        } finally {
+            threads.remove(ti);
+        }
+    }
+
+
+    public void force(boolean metaData) throws IOException {
+        int ti = threads.add();
+        try {
+            int n = 0;
+            try {
+                begin();
+                do {
+                    n = nd.force(fdObj, metaData);
+                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+            } finally {
+                end(n >= 0);
+            }
+        } finally {
+            threads.remove(ti);
+        }
+    }
+
+
+    public <A> Future<FileLock> lock(final long position,
+                                     final long size,
+                                     final boolean shared,
+                                     A attachment,
+                                     final CompletionHandler<FileLock,? super A> handler)
+    {
+        if (shared && !reading)
+            throw new NonReadableChannelException();
+        if (!shared && !writing)
+            throw new NonWritableChannelException();
+
+        // add to lock table
+        final FileLockImpl fli = addToFileLockTable(position, size, shared);
+        if (fli == null) {
+            CompletedFuture<FileLock,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invokeIndirectly(handler, result, executor);
+            return result;
+        }
+
+        final PendingFuture<FileLock,A> result =
+            new PendingFuture<FileLock,A>(this, handler, attachment);
+        Runnable task = new Runnable() {
+            public void run() {
+                int ti = threads.add();
+                try {
+                    int n;
+                    try {
+                        begin();
+                        do {
+                            n = nd.lock(fdObj, true, position, size, shared);
+                        } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
+                        if (n == FileDispatcher.LOCKED) {
+                            result.setResult(fli);
+                        } else {
+                            if (n != FileDispatcher.INTERRUPTED)
+                                throw new AssertionError();
+                            throw new AsynchronousCloseException();
+                        }
+                    } catch (IOException x) {
+                        removeFromFileLockTable(fli);
+                        if (!isOpen())
+                            x = new AsynchronousCloseException();
+                        result.setFailure(x);
+                    } finally {
+                        end();
+                    }
+                } finally {
+                    threads.remove(ti);
+                }
+                Invoker.invokeUnchecked(handler, result);
+            }
+        };
+        try {
+            executor.execute(task);
+        } catch (RejectedExecutionException ree) {
+            // rollback
+            removeFromFileLockTable(fli);
+            throw new ShutdownChannelGroupException();
+        }
+        return result;
+    }
+
+
+    public FileLock tryLock(long position, long size, boolean shared)
+        throws IOException
+    {
+        if (shared && !reading)
+            throw new NonReadableChannelException();
+        if (!shared && !writing)
+            throw new NonWritableChannelException();
+
+        // add to lock table
+        FileLockImpl fli = addToFileLockTable(position, size, shared);
+        if (fli == null)
+            throw new ClosedChannelException();
+
+        int ti = threads.add();
+        boolean gotLock = false;
+        try {
+            begin();
+            int n;
+            do {
+                n = nd.lock(fdObj, false, position, size, shared);
+            } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
+            if (n != FileDispatcher.LOCKED) {
+                if (n == FileDispatcher.NO_LOCK)
+                    return null;    // locked by someone else
+                if (n == FileDispatcher.INTERRUPTED)
+                    throw new AsynchronousCloseException();
+                // should not get here
+                throw new AssertionError();
+            }
+            gotLock = true;
+            return fli;
+        } finally {
+            if (!gotLock)
+                removeFromFileLockTable(fli);
+            end();
+            threads.remove(ti);
+        }
+    }
+
+
+    void release(FileLockImpl fli) throws IOException {
+        try {
+            begin();
+            nd.release(fdObj, fli.position(), fli.size());
+            removeFromFileLockTable(fli);
+        } finally {
+            end();
+        }
+    }
+
+
+    public <A> Future<Integer> read(final ByteBuffer dst,
+                                    final long position,
+                                    A attachment,
+                                    final CompletionHandler<Integer,? super A> handler)
+    {
+        if (position < 0)
+            throw new IllegalArgumentException("Negative position");
+        if (!reading)
+            throw new NonReadableChannelException();
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+
+        // complete immediately if channel closed or no space remaining
+        if (!isOpen() || (dst.remaining() == 0)) {
+            CompletedFuture<Integer,A> result;
+            if (isOpen()) {
+                result = CompletedFuture.withResult(this, 0, attachment);
+            } else {
+                result = CompletedFuture.withFailure(this,
+                    new ClosedChannelException(), attachment);
+            }
+            Invoker.invokeIndirectly(handler, result, executor);
+            return result;
+        }
+
+        final PendingFuture<Integer,A> result =
+            new PendingFuture<Integer,A>(this, handler, attachment);
+        Runnable task = new Runnable() {
+            public void run() {
+                int ti = threads.add();
+                try {
+                    begin();
+                    int n;
+                    do {
+                        n = IOUtil.read(fdObj, dst, position, nd, null);
+                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                    if (n < 0 && !isOpen())
+                        throw new AsynchronousCloseException();
+                    result.setResult(n);
+                } catch (IOException x) {
+                    if (!isOpen())
+                        x = new AsynchronousCloseException();
+                    result.setFailure(x);
+                } finally {
+                    end();
+                    threads.remove(ti);
+                }
+                Invoker.invokeUnchecked(handler, result);
+            }
+        };
+        try {
+            executor.execute(task);
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
+        }
+        return result;
+    }
+
+
+    public <A> Future<Integer> write(final ByteBuffer src,
+                                     final long position,
+                                     A attachment,
+                                     final CompletionHandler<Integer,? super A> handler)
+    {
+        if (position < 0)
+            throw new IllegalArgumentException("Negative position");
+        if (!writing)
+            throw new NonWritableChannelException();
+
+        // complete immediately if channel is closed or no bytes remaining
+        if (!isOpen() || (src.remaining() == 0)) {
+            CompletedFuture<Integer,A> result;
+            if (isOpen()) {
+                result = CompletedFuture.withResult(this, 0, attachment);
+            } else {
+                result = CompletedFuture.withFailure(this,
+                    new ClosedChannelException(), attachment);
+            }
+            Invoker.invokeIndirectly(handler, result, executor);
+            return result;
+        }
+
+        final PendingFuture<Integer,A> result =
+            new PendingFuture<Integer,A>(this, handler, attachment);
+        Runnable task = new Runnable() {
+            public void run() {
+                int ti = threads.add();
+                try {
+                    begin();
+                    int n;
+                    do {
+                        n = IOUtil.write(fdObj, src, position, nd, null);
+                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                    if (n < 0 && !isOpen())
+                        throw new AsynchronousCloseException();
+                    result.setResult(n);
+                } catch (IOException x) {
+                    if (!isOpen())
+                        x = new AsynchronousCloseException();
+                    result.setFailure(x);
+                } finally {
+                    end();
+                    threads.remove(ti);
+                }
+                Invoker.invokeUnchecked(handler, result);
+            }
+        };
+        try {
+            executor.execute(task);
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/ThreadPool.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+import java.util.concurrent.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Defines static methods to create thread pools that are configured by
+ * system properties or a Map of parameters (or a combination of both).
+ */
+
+public class ThreadPool {
+    private static final String PROP_PREFIX = "java.nio.channels.DefaultThreadPool.";
+    private static final String INITIAL_SIZE = "initialSize";
+    private static final String THREAD_FACTORY = "threadFactory";
+
+    private static final ThreadFactory defaultThreadFactory = new ThreadFactory() {
+
+         public Thread newThread(Runnable r) {
+             Thread t = new Thread(r);
+             t.setDaemon(true);
+             return t;
+        }
+     };
+
+    private final ThreadPoolType poolType;
+    private final ExecutorService executor;
+    private final int poolSize;
+
+    private ThreadPool(ThreadPoolType poolType,
+                       ExecutorService executor,
+                       int poolSize)
+    {
+        this.poolType = poolType;
+        this.executor = executor;
+        this.poolSize = poolSize;
+    }
+
+    ExecutorService executor() {
+        return executor;
+    }
+
+    int poolSize() {
+        return poolSize;
+    }
+
+    boolean isFixedThreadPool() {
+        return poolType == ThreadPoolType.FIXED;
+    }
+
+    private static class LazyInitialization {
+        final static ThreadPool defaultThreadPool = createDefault();
+    }
+
+    // return the default (system-wide) thread pool
+    static ThreadPool getDefault() {
+        return LazyInitialization.defaultThreadPool;
+    }
+
+    // create using default settings (configured by system properties)
+    static ThreadPool createDefault() {
+        int initialSize = getDefaultThreadPoolInitialSize();
+        if (initialSize < 0)
+            initialSize = Runtime.getRuntime().availableProcessors();
+        ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory();
+        if (threadFactory == null)
+            threadFactory = defaultThreadFactory;
+        ExecutorService executor =
+            new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+                                   Long.MAX_VALUE, TimeUnit.MILLISECONDS,
+                                   new SynchronousQueue<Runnable>(),
+                                   threadFactory);
+        return new ThreadPool(ThreadPoolType.CACHED, executor, initialSize);
+    }
+
+    public static ThreadPool create(ThreadPoolType poolType,
+                                    ExecutorService executor,
+                                    int nThreads)
+    {
+        if (poolType == null || executor == null)
+            throw new NullPointerException();
+        if (poolType == ThreadPoolType.FIXED) {
+            if (nThreads <= 0)
+                throw new IllegalArgumentException("'nThreads' must be > 0");
+        } else if (poolType == ThreadPoolType.CACHED) {
+            // attempt to check if cached thread pool
+            if (executor instanceof ThreadPoolExecutor) {
+                int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize();
+                if (max == Integer.MAX_VALUE) {
+                    if (nThreads < 0)
+                        nThreads = Runtime.getRuntime().availableProcessors();
+                } else {
+                    // not a cached thread pool so ignore initial size
+                    nThreads = 0;
+                }
+            } else {
+                // some other type of thread pool
+                if (nThreads < 0) nThreads = 0;
+            }
+        } else {
+            throw new AssertionError();
+        }
+        return new ThreadPool(poolType, executor, nThreads);
+    }
+
+    static ThreadFactory defaultThreadFactory() {
+        return defaultThreadFactory;
+    }
+
+    private static int getDefaultThreadPoolInitialSize() {
+        String propName = PROP_PREFIX + INITIAL_SIZE;
+        String value = AccessController.doPrivileged(new GetPropertyAction(propName));
+        if (value != null) {
+            try {
+                return Integer.parseInt(value);
+            } catch (NumberFormatException x) {
+                throw new Error("Value of property '" + propName + "' is invalid: " + x);
+            }
+        }
+        return -1;
+    }
+
+    private static ThreadFactory getDefaultThreadPoolThreadFactory() {
+        String prop = AccessController.doPrivileged(new
+            GetPropertyAction(PROP_PREFIX + THREAD_FACTORY));
+        if (prop != null) {
+            try {
+                Class<?> c = Class
+                    .forName(prop, true, ClassLoader.getSystemClassLoader());
+                return ((ThreadFactory)c.newInstance());
+            } catch (ClassNotFoundException x) {
+                throw new Error(x);
+            } catch (InstantiationException x) {
+                throw new Error(x);
+            } catch (IllegalAccessException x) {
+                throw new Error(x);
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2007-2008 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 AclFileAttributeView
+ */
+
+abstract class AbstractAclFileAttributeView
+    implements AclFileAttributeView
+{
+    private static final String OWNER_NAME = "owner";
+    private static final String ACL_NAME = "acl";
+
+
+    public final String name() {
+        return "acl";
+    }
+
+
+    public final Object getAttribute(String attribute) throws IOException {
+        if (attribute.equals(OWNER_NAME))
+            return getOwner();
+        if (attribute.equals(ACL_NAME))
+            return getAcl();
+        return null;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public final void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        if (attribute.equals(OWNER_NAME)) {
+            setOwner((UserPrincipal)value);
+            return;
+        }
+        if (attribute.equals(ACL_NAME)) {
+            setAcl((List<AclEntry>)value);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
+
+
+    public final Map<String,?> readAttributes(String first, String[] rest)
+        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;
+                }
+            }
+        }
+        Map<String,Object> result = new HashMap<String,Object>(2);
+        if (acl)
+            result.put(ACL_NAME, getAcl());
+        if (owner)
+            result.put(OWNER_NAME, getOwner());
+        return Collections.unmodifiableMap(result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2007-2008 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.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base implementation of BasicFileAttributeView
+ */
+
+abstract class AbstractBasicFileAttributeView
+    implements BasicFileAttributeView
+{
+    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";
+    private static final String IS_OTHER_NAME = "isOther";
+
+    protected AbstractBasicFileAttributeView() { }
+
+
+    public String name() {
+        return "basic";
+    }
+
+
+    public Object getAttribute(String attribute) throws IOException {
+        BasicFileAttributes attrs = readAttributes();
+        if (attribute.equals(SIZE_NAME))
+            return attrs.size();
+        if (attribute.equals(CREATION_TIME_NAME))
+            return attrs.creationTime();
+        if (attribute.equals(LAST_ACCESS_TIME_NAME))
+            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))
+            return attrs.isRegularFile();
+        if (attribute.equals(IS_SYMBOLIC_LINK_NAME))
+            return attrs.isSymbolicLink();
+        if (attribute.equals(IS_OTHER_NAME))
+            return attrs.isOther();
+        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;
+    }
+
+
+    public void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        if (attribute.equals(LAST_MODIFIED_TIME_NAME)) {
+            setTimes(toTimeValue(value), null, null, TimeUnit.MILLISECONDS);
+            return;
+        }
+        if (attribute.equals(LAST_ACCESS_TIME_NAME)) {
+            setTimes(null, toTimeValue(value), null, TimeUnit.MILLISECONDS);
+            return;
+        }
+        if (attribute.equals(CREATION_TIME_NAME)) {
+            setTimes(null, null, toTimeValue(value), TimeUnit.MILLISECONDS);
+            return;
+        }
+        throw new UnsupportedOperationException("'" + attribute +
+            "' is unknown or read-only attribute");
+    }
+
+    /**
+     *
+     */
+    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;
+                    }
+                    set.add(attribute);
+                }
+            }
+        }
+
+        /**
+         * Creates builder to build up a map of the matching attributes
+         */
+        static AttributesBuilder create(String first, String[] rest) {
+            return new AttributesBuilder(first, rest);
+        }
+
+        /**
+         * Returns true if the attribute should be returned in the map
+         */
+        boolean match(String attribute) {
+            if (copyAll)
+                return true;
+            return set.contains(attribute);
+        }
+
+        void add(String attribute, Object value) {
+            map.put(attribute, value);
+        }
+
+        /**
+         * Returns the map. Discard all references to the AttributesBuilder
+         * after invoking this method.
+         */
+        Map<String,Object> unmodifiableMap() {
+            return Collections.unmodifiableMap(map);
+        }
+    }
+
+    /**
+     * Invoked by readAttributes or sub-classes to add all matching basic
+     * attributes to the builder
+     */
+    final void addBasicAttributesToBuilder(BasicFileAttributes attrs,
+                                           AttributesBuilder builder)
+    {
+        if (builder.match(SIZE_NAME))
+            builder.add(SIZE_NAME, attrs.size());
+        if (builder.match(CREATION_TIME_NAME))
+            builder.add(CREATION_TIME_NAME, attrs.creationTime());
+        if (builder.match(LAST_ACCESS_TIME_NAME))
+            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))
+            builder.add(IS_REGULAR_FILE_NAME, attrs.isRegularFile());
+        if (builder.match(IS_SYMBOLIC_LINK_NAME))
+            builder.add(IS_SYMBOLIC_LINK_NAME, attrs.isSymbolicLink());
+        if (builder.match(IS_OTHER_NAME))
+            builder.add(IS_OTHER_NAME, attrs.isOther());
+    }
+
+
+    public Map<String,?> readAttributes(String first, String[] rest)
+        throws IOException
+    {
+        AttributesBuilder builder = AttributesBuilder.create(first, rest);
+        addBasicAttributesToBuilder(readAttributes(), builder);
+        return builder.unmodifiableMap();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2007-2008 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";
+
+
+    public final String name() {
+        return "space";
+    }
+
+
+    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;
+    }
+
+
+    public final void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        if (attribute == null || value == null)
+            throw new NullPointerException();
+        throw new UnsupportedOperationException();
+    }
+
+
+    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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007-2008 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.FileRef;
+import java.nio.file.spi.FileTypeDetector;
+import java.io.IOException;
+import sun.nio.fs.MimeType;
+
+/**
+ * Base implementation of FileTypeDetector
+ */
+
+public abstract class AbstractFileTypeDetector
+    extends FileTypeDetector
+{
+    protected AbstractFileTypeDetector() {
+        super();
+    }
+
+    /**
+     * Invokes the implProbeContentType method to guess the file's content type,
+     * and this validates that the content type's syntax is valid.
+     */
+
+    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;
+    }
+
+    /**
+     * Probes the given file to guess its content type.
+     */
+    protected abstract String implProbeContentType(FileRef file)
+        throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-2008 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.ByteBuffer;
+import java.nio.file.attribute.NamedAttributeView;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Base implementation of NamedAttributeView
+ */
+
+abstract class AbstractNamedAttributeView
+    implements NamedAttributeView
+{
+    protected AbstractNamedAttributeView() { }
+
+    protected void checkAccess(String file,
+                               boolean checkRead,
+                               boolean checkWrite)
+    {
+        assert checkRead || checkWrite;
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (checkRead)
+                sm.checkRead(file);
+            if (checkWrite)
+                sm.checkWrite(file);
+            sm.checkPermission(new RuntimePermission("accessNamedAttributes"));
+        }
+    }
+
+
+    public final String name() {
+        return "xattr";
+    }
+
+
+    public final Object getAttribute(String attribute) throws IOException {
+        int size = size(attribute);
+        ByteBuffer buf = ByteBuffer.allocate(size);
+        read(attribute, buf);
+        buf.flip();
+        return buf;
+    }
+
+
+    public final void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        write(attribute, (ByteBuffer)value);
+    }
+
+
+    public final Map<String,?> readAttributes(String first, String... rest)
+        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) {
+                if (name.equals("*")) {
+                    readAll = true;
+                    break;
+                }
+                names.add(name);
+            }
+        }
+        if (readAll) {
+            names.clear();
+            for (String name: list()) {
+                names.add(name);
+            }
+        }
+
+        // allocate buffer for each value and return as map
+        Map<String,ByteBuffer> result = new HashMap<String,ByteBuffer>();
+        for (String name: names) {
+            int size = size(name);
+            ByteBuffer buf = ByteBuffer.allocate(size);
+            read(name, buf);
+            result.put(name, buf);
+            buf.flip();
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2007-2008 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 java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Base implementation of background poller thread used in watch service
+ * implementations. A poller thread waits on events from the file system and
+ * also services "requests" from clients to register for new events or cancel
+ * existing registrations.
+ */
+
+abstract class AbstractPoller implements Runnable {
+
+    // list of requests pending to the poller thread
+    private final LinkedList<Request> requestList;
+
+    // set to true when shutdown
+    private boolean shutdown;
+
+    protected AbstractPoller() {
+        this.requestList = new LinkedList<Request>();
+        this.shutdown = false;
+    }
+
+    /**
+     * Starts the poller thread
+     */
+    public void start() {
+        final Runnable thisRunnable = this;
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+
+            public Object run() {
+                Thread thr = new Thread(thisRunnable);
+                thr.setDaemon(true);
+                thr.start();
+                return null;
+            }
+         });
+    }
+
+    /**
+     * Wakeup poller thread so that it can service pending requests
+     */
+    abstract void wakeup() throws IOException;
+
+    /**
+     * Executed by poller thread to register directory for changes
+     */
+    abstract Object implRegister(Path path,
+                                 Set<? extends WatchEvent.Kind<?>> events,
+                                 WatchEvent.Modifier... modifiers);
+
+    /**
+     * Executed by poller thread to cancel key
+     */
+    abstract void implCancelKey(WatchKey key);
+
+    /**
+     * Executed by poller thread to shutdown and cancel all keys
+     */
+    abstract void implCloseAll();
+
+    /**
+     * Requests, and waits on, poller thread to register given file.
+     */
+    final WatchKey register(FileRef dir,
+                            WatchEvent.Kind<?>[] events,
+                            WatchEvent.Modifier... modifiers)
+        throws IOException
+    {
+        // validate arguments before request to poller
+        if (dir == null)
+            throw new NullPointerException();
+        if (events.length == 0)
+            throw new IllegalArgumentException("No events to register");
+        Set<WatchEvent.Kind<?>> eventSet = new HashSet<WatchEvent.Kind<?>>(events.length);
+        for (WatchEvent.Kind<?> event: events) {
+            // standard events
+            if (event == StandardWatchEventKind.ENTRY_CREATE ||
+                event == StandardWatchEventKind.ENTRY_MODIFY ||
+                event == StandardWatchEventKind.ENTRY_DELETE)
+            {
+                eventSet.add(event);
+                continue;
+            }
+
+            // OVERFLOW is ignored
+            if (event == StandardWatchEventKind.OVERFLOW) {
+                if (events.length == 1)
+                    throw new IllegalArgumentException("No events to register");
+                continue;
+            }
+
+            // null/unsupported
+            if (event == null)
+                throw new NullPointerException("An element in event set is 'null'");
+            throw new UnsupportedOperationException(event.name());
+        }
+        return (WatchKey)invoke(RequestType.REGISTER, dir, eventSet, modifiers);
+    }
+
+    /**
+     * Cancels, and waits on, poller thread to cancel given key.
+     */
+    final void cancel(WatchKey key) {
+        try {
+            invoke(RequestType.CANCEL, key);
+        } catch (IOException x) {
+            // should not happen
+            throw new AssertionError(x.getMessage());
+        }
+    }
+
+    /**
+     * Shutdown poller thread
+     */
+    final void close() throws IOException {
+        invoke(RequestType.CLOSE);
+    }
+
+    /**
+     * Types of request that the poller thread must handle
+     */
+    private static enum RequestType {
+        REGISTER,
+        CANCEL,
+        CLOSE;
+    }
+
+    /**
+     * Encapsulates a request (command) to the poller thread.
+     */
+    private static class Request {
+        private final RequestType type;
+        private final Object[] params;
+
+        private boolean completed = false;
+        private Object result = null;
+
+        Request(RequestType type, Object... params) {
+            this.type = type;
+            this.params = params;
+        }
+
+        RequestType type() {
+            return type;
+        }
+
+        Object[] parameters() {
+            return params;
+        }
+
+        void release(Object result) {
+            synchronized (this) {
+                this.completed = true;
+                this.result = result;
+                notifyAll();
+            }
+        }
+
+        /**
+         * Await completion of the request. The return value is the result of
+         * the request.
+         */
+        Object awaitResult() {
+            synchronized (this) {
+                while (!completed) {
+                    try {
+                        wait();
+                    } catch (InterruptedException x) {
+                        // ignore
+                    }
+                }
+                return result;
+            }
+        }
+    }
+
+    /**
+     * Enqueues request to poller thread and waits for result
+     */
+    private Object invoke(RequestType type, Object... params) throws IOException {
+        // submit request
+        Request req = new Request(type, params);
+        synchronized (requestList) {
+            if (shutdown) {
+                throw new ClosedWatchServiceException();
+            }
+            requestList.add(req);
+        }
+
+        // wakeup thread
+        wakeup();
+
+        // wait for result
+        Object result = req.awaitResult();
+
+        if (result instanceof RuntimeException)
+            throw (RuntimeException)result;
+        if (result instanceof IOException )
+            throw (IOException)result;
+        return result;
+    }
+
+    /**
+     * Invoked by poller thread to process all pending requests
+     *
+     * @return  true if poller thread should shutdown
+     */
+    @SuppressWarnings("unchecked")
+    boolean processRequests() {
+        synchronized (requestList) {
+            Request req;
+            while ((req = requestList.poll()) != null) {
+                // if in process of shutdown then reject request
+                if (shutdown) {
+                    req.release(new ClosedWatchServiceException());
+                }
+
+                switch (req.type()) {
+                    /**
+                     * Register directory
+                     */
+                    case REGISTER: {
+                        Object[] params = req.parameters();
+                        Path path = (Path)params[0];
+                        Set<? extends WatchEvent.Kind<?>> events =
+                            (Set<? extends WatchEvent.Kind<?>>)params[1];
+                        WatchEvent.Modifier[] modifiers =
+                            (WatchEvent.Modifier[])params[2];
+                        req.release(implRegister(path, events, modifiers));
+                        break;
+                    }
+                    /**
+                     * Cancel existing key
+                     */
+                    case CANCEL : {
+                        Object[] params = req.parameters();
+                        WatchKey key = (WatchKey)params[0];
+                        implCancelKey(key);
+                        req.release(null);
+                        break;
+                    }
+                    /**
+                     * Close watch service
+                     */
+                    case CLOSE: {
+                        implCloseAll();
+                        req.release(null);
+                        shutdown = true;
+                        break;
+                    }
+
+                    default:
+                        req.release(new IOException("request not recognized"));
+                }
+            }
+        }
+        return shutdown;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2007-2008 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 java.util.*;
+
+/**
+ * Base implementation class for watch keys.
+ */
+
+abstract class AbstractWatchKey extends WatchKey {
+
+    /**
+     * Maximum size of event list (in the future this may be tunable)
+     */
+    static final int MAX_EVENT_LIST_SIZE    = 512;
+
+    /**
+     * Special event to signal overflow
+     */
+    static final Event<Void> OVERFLOW_EVENT =
+        new Event<Void>(StandardWatchEventKind.OVERFLOW, null);
+
+    /**
+     * Possible key states
+     */
+    private static enum State { READY, SIGNALLED };
+
+    // reference to watcher
+    private final AbstractWatchService watcher;
+
+    // key state
+    private State state;
+
+    // pending events
+    private List<WatchEvent<?>> events;
+
+    protected AbstractWatchKey(AbstractWatchService watcher) {
+        this.watcher = watcher;
+        this.state = State.READY;
+        this.events = new ArrayList<WatchEvent<?>>();
+    }
+
+    /**
+     * Enqueues this key to the watch service
+     */
+    final void signal() {
+        synchronized (this) {
+            if (state == State.READY) {
+                state = State.SIGNALLED;
+                watcher.enqueueKey(this);
+            }
+        }
+    }
+
+    /**
+     * Adds the event to this key and signals it.
+     */
+    @SuppressWarnings("unchecked")
+    final void signalEvent(WatchEvent.Kind<?> kind, Object context) {
+        synchronized (this) {
+            int size = events.size();
+            if (size > 1) {
+                // don't let list get too big
+                if (size >= MAX_EVENT_LIST_SIZE) {
+                    kind = StandardWatchEventKind.OVERFLOW;
+                    context = null;
+                }
+
+                // repeated event
+                WatchEvent<?> prev = events.get(size-1);
+                if (kind == prev.kind()) {
+                    boolean isRepeat;
+                    if (context == null) {
+                        isRepeat = (prev.context() == null);
+                    } else {
+                        isRepeat = context.equals(prev.context());
+                    }
+                    if (isRepeat) {
+                        ((Event<?>)prev).increment();
+                        return;
+                    }
+                }
+            }
+
+            // non-repeated event
+            events.add(new Event<Object>((WatchEvent.Kind<Object>)kind, context));
+            signal();
+        }
+    }
+
+
+    public final List<WatchEvent<?>> pollEvents() {
+        synchronized (this) {
+            List<WatchEvent<?>> result = events;
+            events = new ArrayList<WatchEvent<?>>();
+            return result;
+        }
+    }
+
+
+    public final boolean reset() {
+        synchronized (this) {
+            if (state == State.SIGNALLED && isValid()) {
+                if (events.isEmpty()) {
+                    state = State.READY;
+                } else {
+                    // pending events so re-queue key
+                    watcher.enqueueKey(this);
+                }
+            }
+            return isValid();
+        }
+    }
+
+    /**
+     * WatchEvent implementation
+     */
+    private static class Event<T> extends WatchEvent<T> {
+        private final WatchEvent.Kind<T> kind;
+        private final T context;
+
+        // synchronize on watch key to access/increment count
+        private int count;
+
+        Event(WatchEvent.Kind<T> type, T context) {
+            this.kind = type;
+            this.context = context;
+            this.count = 1;
+        }
+
+
+        public WatchEvent.Kind<T> kind() {
+            return kind;
+        }
+
+
+        public T context() {
+            return context;
+        }
+
+
+        public int count() {
+            return count;
+        }
+
+        // for repeated events
+        void increment() {
+            count++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2007-2008 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 java.util.concurrent.*;
+import java.io.IOException;
+
+/**
+ * Base implementation class for watch services.
+ */
+
+abstract class AbstractWatchService extends WatchService {
+
+    // signaled keys waiting to be dequeued
+    private final LinkedBlockingDeque<WatchKey> pendingKeys =
+        new LinkedBlockingDeque<WatchKey>();
+
+    // special key to indicate that watch service is closed
+    private final WatchKey CLOSE_KEY =
+        new AbstractWatchKey(null) {
+
+            public boolean isValid() {
+                return true;
+            }
+
+
+            public void cancel() {
+            }
+        };
+
+    // used when closing watch service
+    private volatile boolean closed;
+    private Object closeLock = new Object();
+
+    protected AbstractWatchService() {
+    }
+
+    /**
+     * Register the given object with this watch service
+     */
+    abstract WatchKey register(Path path,
+                               WatchEvent.Kind<?>[] events,
+                               WatchEvent.Modifier... modifers)
+        throws IOException;
+
+    // used by AbstractWatchKey to enqueue key
+    final void enqueueKey(WatchKey key) {
+        pendingKeys.offer(key);
+    }
+
+    /**
+     * Throws ClosedWatchServiceException if watch service is closed
+     */
+    private void checkOpen() {
+        if (closed)
+            throw new ClosedWatchServiceException();
+    }
+
+    /**
+     * Checks the key isn't the special CLOSE_KEY used to unblock threads when
+     * the watch service is closed.
+     */
+    private void checkKey(WatchKey key) {
+        if (key == CLOSE_KEY) {
+            // re-queue in case there are other threads blocked in take/poll
+            enqueueKey(key);
+        }
+        checkOpen();
+    }
+
+
+    public final WatchKey  poll() {
+        checkOpen();
+        WatchKey key = pendingKeys.poll();
+        checkKey(key);
+        return key;
+    }
+
+
+    public final WatchKey poll(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        checkOpen();
+        WatchKey key = pendingKeys.poll(timeout, unit);
+        checkKey(key);
+        return key;
+    }
+
+
+    public final WatchKey take()
+        throws InterruptedException
+    {
+        checkOpen();
+        WatchKey key = pendingKeys.take();
+        checkKey(key);
+        return key;
+    }
+
+    /**
+     * Tells whether or not this watch service is open.
+     */
+    final boolean isOpen() {
+        return !closed;
+    }
+
+    /**
+     * Retrieves the object upon which the close method synchronizes.
+     */
+    final Object closeLock() {
+        return closeLock;
+    }
+
+    /**
+     * Closes this watch service. This method is invoked by the close
+     * method to perform the actual work of closing the watch service.
+     */
+    abstract void implClose() throws IOException;
+
+
+    public final void close()
+        throws IOException
+    {
+        synchronized (closeLock) {
+            // nothing to do if already closed
+            if (closed)
+                return;
+            closed = true;
+
+            implClose();
+
+            // clear pending keys and queue special key to ensure that any
+            // threads blocked in take/poll wakeup
+            pendingKeys.clear();
+            pendingKeys.offer(CLOSE_KEY);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2007-2008 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 sun.misc.Unsafe;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Base implementation of a task (typically native) that polls a memory location
+ * during execution so that it may be aborted/cancelled before completion. The
+ * task is executed by invoking the {@link runInterruptibly} method defined
+ * here and cancelled by invoking Thread.interrupt.
+ */
+
+abstract class Cancellable implements Runnable {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private final long pollingAddress;
+    private final Object lock = new Object();
+
+    // the following require lock when examining or changing
+    private boolean completed;
+    private Throwable exception;
+
+    protected Cancellable() {
+        pollingAddress = unsafe.allocateMemory(4);
+        unsafe.putIntVolatile(null, pollingAddress, 0);
+    }
+
+    /**
+     * Returns the memory address of a 4-byte int that should be polled to
+     * detect cancellation.
+     */
+    protected long addressToPollForCancel() {
+        return pollingAddress;
+    }
+
+    /**
+     * The value to write to the polled memory location to indicate that the
+     * task has been cancelled. If this method is not overridden then it
+     * defaults to MAX_VALUE.
+     */
+    protected int cancelValue() {
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * "cancels" the task by writing bits into memory location that it polled
+     * by the task.
+     */
+    final void cancel() {
+        synchronized (lock) {
+            if (!completed) {
+                unsafe.putIntVolatile(null, pollingAddress, cancelValue());
+            }
+        }
+    }
+
+    /**
+     * Returns the exception thrown by the task or null if the task completed
+     * successfully.
+     */
+    private Throwable exception() {
+        synchronized (lock) {
+            return exception;
+        }
+    }
+
+
+    public final void run() {
+        try {
+            implRun();
+        } catch (Throwable t) {
+            synchronized (lock) {
+                exception = t;
+            }
+        } finally {
+            synchronized (lock) {
+                completed = true;
+                unsafe.freeMemory(pollingAddress);
+            }
+        }
+    }
+
+    /**
+     * The task body. This should periodically poll the memory location
+     * to check for cancellation.
+     */
+    abstract void implRun() throws Throwable;
+
+    /**
+     * Invokes the task in its own thread. If this (meaning the current) thread
+     * is interrupted then an attempt is make to cancel the background task by
+     * writting bits into the memory location that it is polling. On return,
+     * the interrupt status for this thread has been cleared.
+     */
+    static void runInterruptibly(Cancellable task) throws ExecutionException {
+        Thread t = new Thread(task);
+        t.start();
+        while (t.isAlive()) {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+                task.cancel();
+            }
+        }
+        Throwable exc = task.exception();
+        if (exc != null)
+            throw new ExecutionException(exc);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2007-2008 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.util.*;
+import java.io.IOException;
+
+/**
+ * An implementation of FileOwnerAttributeView that delegates to a given
+ * PosixFileAttributeView or AclFileAttributeView object.
+ */
+
+final class FileOwnerAttributeViewImpl implements FileOwnerAttributeView {
+    private static final String OWNER_NAME = "owner";
+
+    private final FileAttributeView view;
+    private final boolean isPosixView;
+
+    FileOwnerAttributeViewImpl(PosixFileAttributeView view) {
+        this.view = view;
+        this.isPosixView = true;
+    }
+
+    FileOwnerAttributeViewImpl(AclFileAttributeView view) {
+        this.view = view;
+        this.isPosixView = false;
+    }
+
+
+    public String name() {
+        return "owner";
+    }
+
+
+    public Object getAttribute(String attribute) throws IOException {
+        if (attribute.equals(OWNER_NAME))
+            return getOwner();
+        return null;
+    }
+
+
+    public void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        if (attribute.equals(OWNER_NAME)) {
+            setOwner((UserPrincipal)value);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
+
+
+    public Map<String,?> readAttributes(String first, String[] rest) 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;
+                }
+            }
+        }
+        return result;
+    }
+
+
+    public UserPrincipal getOwner() throws IOException {
+        if (isPosixView) {
+            return ((PosixFileAttributeView)view).readAttributes().owner();
+        } else {
+            return ((AclFileAttributeView)view).getOwner();
+        }
+    }
+
+
+    public void setOwner(UserPrincipal owner)
+        throws IOException
+    {
+        if (isPosixView) {
+            ((PosixFileAttributeView)view).setOwner(owner);
+        } else {
+            ((AclFileAttributeView)view).setOwner(owner);
+        }
+    }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Globs.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2007-2008 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.regex.PatternSyntaxException;
+
+public class Globs {
+    private Globs() { }
+
+    /**
+     * Creates a regex pattern from the given glob expression.
+     *
+     * @throws  PatternSyntaxException
+     */
+    public static String toRegexPattern(String globPattern) {
+        String regexMetaChars = ".^$+{[]|()";
+        String globMetaChars = "\\*?[]{}";
+
+        boolean inNonCapturingGroup = false;
+
+        StringBuilder regex = new StringBuilder("^");
+
+        int i =0;
+        while (i< globPattern.length()) {
+            char c = globPattern.charAt(i++);
+            switch (c) {
+                case '\\' :
+                    // escape special characters
+                    if (i < globPattern.length()) {
+                        char next = globPattern.charAt(i);
+                        if (globMetaChars.indexOf(next) >= 0) {
+                            regex.append('\\');
+                            regex.append(next);
+                            i++;
+                        }
+                    } else {
+                        throw new PatternSyntaxException("No character to escape",
+                            globPattern, i-1);
+                    }
+                    break;
+
+                case '[' :
+                    regex.append('[');
+                    // negation
+                    if (i < globPattern.length() && globPattern.charAt(i) == '!') {
+                        regex.append('^');
+                        i++;
+                    }
+                    // hyphen allowed at start
+                    if (i < globPattern.length() && globPattern.charAt(i) == '-') {
+                        regex.append('-');
+                        i++;
+                    }
+                    boolean inRange = false;
+                    boolean seenRangeStart = false;
+                    while (i < globPattern.length()) {
+                        c = globPattern.charAt(i++);
+                        regex.append(c);
+                        if (c == ']')
+                            break;
+                        if (c == '-') {
+                            if (inRange || !seenRangeStart) {
+                                throw new PatternSyntaxException("Invalid range",
+                                    globPattern, i-1);
+                            }
+                            inRange = true;
+                        } else {
+                            if (inRange) {
+                                seenRangeStart = false;
+                                inRange = false;
+                            } else {
+                                seenRangeStart = true;
+                            }
+                        }
+                    }
+                    if (c != ']')
+                        throw new PatternSyntaxException("Missing ']", globPattern, i-1);
+                    break;
+
+                case '{' :
+                    if (inNonCapturingGroup) {
+                        throw new PatternSyntaxException("Cannot nest groups",
+                            globPattern, i-1);
+                    }
+                    regex.append("(?:(?:");
+                    inNonCapturingGroup = true;
+                    break;
+
+                case '}' :
+                    if (inNonCapturingGroup) {
+                        regex.append("))");
+                        inNonCapturingGroup = false;
+                    } else {
+                        regex.append('}');
+                    }
+                    break;
+
+                case ',' :
+                    if (inNonCapturingGroup) {
+                        regex.append(")|(?:");
+                        break;
+                    } else {
+                        regex.append(',');
+                    }
+                    break;
+
+                case '*':
+                    regex.append(".*");
+                    break;
+
+                case '?':
+                    regex.append('.');
+                    break;
+
+                default:
+                    // escape other meta characters
+                    for (int j=0; j<regexMetaChars.length(); j++) {
+                        if (c == regexMetaChars.charAt(j)) {
+                            regex.append('\\');
+                            break;
+                        }
+                    }
+                    regex.append(c);
+            }
+        }
+
+        if (inNonCapturingGroup)
+            throw new PatternSyntaxException("Missing '}", globPattern, i-1);
+
+        return regex.append('$').toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/MimeType.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2007-2008 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;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2007-2008 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 sun.misc.Unsafe;
+import sun.misc.Cleaner;
+
+/**
+ * A light-weight buffer in native memory.
+ */
+
+class NativeBuffer {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private final long address;
+    private final int size;
+    private final Cleaner cleaner;
+
+    // optional "owner" to avoid copying
+    // (only safe for use by thread-local caches)
+    private Object owner;
+
+    private static class Deallocator implements Runnable {
+        private final long address;
+        Deallocator(long address) {
+            this.address = address;
+        }
+        public void run() {
+            unsafe.freeMemory(address);
+        }
+    }
+
+    NativeBuffer(int size) {
+        this.address = unsafe.allocateMemory(size);
+        this.size = size;
+        this.cleaner = Cleaner.create(this, new Deallocator(address));
+    }
+
+    void release() {
+        NativeBuffers.releaseNativeBuffer(this);
+    }
+
+    long address() {
+        return address;
+    }
+
+    int size() {
+        return size;
+    }
+
+    Cleaner cleaner() {
+        return cleaner;
+    }
+
+    // not synchronized; only safe for use by thread-local caches
+    void setOwner(Object owner) {
+        this.owner = owner;
+    }
+
+    // not synchronized; only safe for use by thread-local caches
+    Object owner() {
+        return owner;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2007-2008 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 sun.misc.Unsafe;
+
+/**
+ * Factory for native buffers.
+ */
+
+class NativeBuffers {
+    private NativeBuffers() { }
+
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private static final int TEMP_BUF_POOL_SIZE = 3;
+    private static ThreadLocal<NativeBuffer[]> threadLocal =
+        new ThreadLocal<NativeBuffer[]>();
+
+    /**
+     * Allocates a native buffer, of at least the given size, from the heap.
+     */
+    static NativeBuffer allocNativeBuffer(int size) {
+        // Make a new one of at least 2k
+        if (size < 2048) size = 2048;
+        return new NativeBuffer(size);
+    }
+
+    /**
+     * Returns a native buffer, of at least the given size, from the thread
+     * local cache.
+     */
+    static NativeBuffer getNativeBufferFromCache(int size) {
+        // return from cache if possible
+        NativeBuffer[] buffers = threadLocal.get();
+        if (buffers != null) {
+            for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
+                NativeBuffer buffer = buffers[i];
+                if (buffer != null && buffer.size() >= size) {
+                    buffers[i] = null;
+                    return buffer;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a native buffer, of at least the given size. The native buffer
+     * is taken from the thread local cache if possible; otherwise it is
+     * allocated from the heap.
+     */
+    static NativeBuffer getNativeBuffer(int size) {
+        NativeBuffer buffer = getNativeBufferFromCache(size);
+        if (buffer != null) {
+            buffer.setOwner(null);
+            return buffer;
+        } else {
+            return allocNativeBuffer(size);
+        }
+    }
+
+    /**
+     * Releases the given buffer. If there is space in the thread local cache
+     * then the buffer goes into the cache; otherwise the memory is deallocated.
+     */
+    static void releaseNativeBuffer(NativeBuffer buffer) {
+        // create cache if it doesn't exist
+        NativeBuffer[] buffers = threadLocal.get();
+        if (buffers == null) {
+            buffers = new NativeBuffer[TEMP_BUF_POOL_SIZE];
+            buffers[0] = buffer;
+            threadLocal.set(buffers);
+            return;
+        }
+        // Put it in an empty slot if such exists
+        for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
+            if (buffers[i] == null) {
+                buffers[i] = buffer;
+                return;
+            }
+        }
+        // Otherwise replace a smaller one in the cache if such exists
+        for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
+            NativeBuffer existing = buffers[i];
+            if (existing.size() < buffer.size()) {
+                existing.cleaner().clean();
+                buffers[i] = buffer;
+                return;
+            }
+        }
+
+        // free it
+        buffer.cleaner().clean();
+    }
+
+    /**
+     * Copies a byte array and zero terminator into a given native buffer.
+     */
+    static void copyCStringToNativeBuffer(byte[] cstr, NativeBuffer buffer) {
+        long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET;
+        long len = cstr.length;
+        assert buffer.size() >= (len + 1);
+        unsafe.copyMemory(cstr, offset, null, buffer.address(), len);
+        unsafe.putByte(buffer.address() + len, (byte)0);
+    }
+
+    /**
+     * Copies a byte array and zero terminator into a native buffer, returning
+     * the buffer.
+     */
+    static NativeBuffer asNativeBuffer(byte[] cstr) {
+        NativeBuffer buffer = getNativeBuffer(cstr.length+1);
+        copyCStringToNativeBuffer(cstr, buffer);
+        return buffer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Simple WatchService implementation that uses background thread to poll
+ * registered directories for changes.  This implementation is for use
+ * on operating systems that do not have file change notification support.
+ */
+
+class PollingWatchService
+    extends AbstractWatchService
+{
+    // keys registered with the watch service
+    private final List<PollingWatchKey> keys;
+
+    private String sleepTimePropValue;
+    private final int sleepTime;
+
+    PollingWatchService() {
+        this.keys = new ArrayList<PollingWatchKey>();
+
+        // start background daemon thread to poll registered files
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+
+            public Void run() {
+                sleepTimePropValue = System.
+                    getProperty("sun.nio.fs.PollingWatchService.sleepTime");
+
+                Thread thr = new Thread(new Poller());
+                thr.setDaemon(true);
+                thr.start();
+                return null;
+            }
+         });
+
+         // use property value to configure sleep time if set
+         int t = 0;
+         if (sleepTimePropValue != null) {
+             try {
+                t = Integer.parseInt(sleepTimePropValue);
+             } catch (NumberFormatException x) {
+             }
+         }
+         if (t <= 0)
+             t = 2000;  // default to 2 seconds.
+         this.sleepTime = t;
+    }
+
+    /**
+     * Register the given file with this watch service
+     */
+
+    WatchKey register(final Path path,
+                      WatchEvent.Kind<?>[] events,
+                      WatchEvent.Modifier... modifiers)
+         throws IOException
+    {
+        // check events - CCE will be thrown if there are invalid elements
+        if (events.length == 0)
+            throw new IllegalArgumentException("No events to register");
+        final Set<WatchEvent.Kind<?>> eventSet =
+            new HashSet<WatchEvent.Kind<?>>(events.length);
+        for (WatchEvent.Kind<?> event: events) {
+            // standard events
+            if (event == StandardWatchEventKind.ENTRY_CREATE ||
+                event == StandardWatchEventKind.ENTRY_MODIFY ||
+                event == StandardWatchEventKind.ENTRY_DELETE)
+            {
+                eventSet.add(event);
+                continue;
+            }
+
+            // OVERFLOW is ignored
+            if (event == StandardWatchEventKind.OVERFLOW) {
+                if (events.length == 1)
+                    throw new IllegalArgumentException("No events to register");
+                continue;
+            }
+
+            // null/unsupported
+            if (event == null)
+                throw new NullPointerException("An element in event set is 'null'");
+            throw new UnsupportedOperationException(event.name());
+        }
+
+        // no modifiers supported at this time
+        if (modifiers.length > 0) {
+            if (modifiers[0] == null)
+                throw new NullPointerException();
+            throw new UnsupportedOperationException("Modifier not supported");
+        }
+
+        // check if watch service is closed
+        if (!isOpen())
+            throw new ClosedWatchServiceException();
+
+        // registration is done in privileged block as it requires the
+        // attributes of the entries in the directory.
+        try {
+            return AccessController.doPrivileged(
+                new PrivilegedExceptionAction<PollingWatchKey>() {
+
+                    public PollingWatchKey run() throws IOException {
+                        return doPrivilegedRegister(path, eventSet);
+                    }
+                });
+        } catch (PrivilegedActionException pae) {
+            Throwable cause = pae.getCause();
+            if (cause != null && cause instanceof IOException)
+                throw (IOException)cause;
+            throw new AssertionError(pae);
+        }
+    }
+
+    // registers directory returning a new key if not already registered or
+    // existing key if already registered
+    private PollingWatchKey doPrivilegedRegister(Path path,
+                                                 Set<? extends WatchEvent.Kind<?>> events)
+        throws IOException
+    {
+        // check file is a directory and get its file key if possible
+        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
+        if (!attrs.isDirectory()) {
+            throw new NotDirectoryException(path.toString());
+        }
+        Object fileKey = attrs.fileKey();
+
+        // Iterate over existing keys to check if file is already registered.
+        // Return existing key or create new key.
+        synchronized (keys) {
+            for (PollingWatchKey key: keys) {
+                Object otherFileKey = key.fileKey();
+
+                boolean isSame = false;
+                if (fileKey != null && otherFileKey != null) {
+                    isSame = fileKey.equals(otherFileKey);
+                } else {
+                    try {
+                        isSame = path.isSameFile(key.directory());
+                    } catch (IOException x) {
+                        // one of the files is not accessible
+                    }
+                }
+
+                // if key exists then update events and return it
+                if (isSame) {
+                    key.setEvents(events);
+                    return key;
+                }
+            }
+
+            // create new key
+            synchronized (closeLock()) {
+                if (!isOpen())
+                    throw new ClosedWatchServiceException();
+                PollingWatchKey newKey =
+                    new PollingWatchKey(this, path, events, fileKey);
+                keys.add(newKey);
+                return newKey;
+            }
+        }
+    }
+
+
+    void implClose() throws IOException {
+        synchronized (keys) {
+            Iterator<PollingWatchKey> i = keys.iterator();
+            while (i.hasNext()) {
+                i.next().invalidate();
+                i.remove();
+            }
+        }
+    }
+
+    /**
+     * Polling thread to poll each WatchKey registered with the WatchService
+     */
+    private class Poller implements Runnable {
+        public void run() {
+            for (;;) {
+                try {
+                    Thread.sleep(sleepTime);
+                } catch (InterruptedException x) { }
+
+                // watch service has been closed
+                if (!isOpen()) {
+                    return;
+                }
+
+                // take a snapshot of the keys to poll - this allows new registrations
+                // to be added at the same time as polling.
+                List<PollingWatchKey> shadowKeys;
+                synchronized (keys) {
+                    shadowKeys = new ArrayList<PollingWatchKey>(keys);
+                }
+
+                // poll each registered key
+                for (PollingWatchKey key: shadowKeys) {
+                    key.poll();
+                }
+            }
+        }
+    }
+
+    /**
+     * Entry in directory cache to record file last-modified-time and tick-count
+     */
+    private static class CacheEntry {
+        private long lastModified;
+        private int lastTickCount;
+
+        CacheEntry(long lastModified, int lastTickCount) {
+            this.lastModified = lastModified;
+            this.lastTickCount = lastTickCount;
+        }
+
+        int lastTickCount() {
+            return lastTickCount;
+        }
+
+        long lastModified() {
+            return lastModified;
+        }
+
+        void update(long lastModified, int tickCount) {
+            this.lastModified = lastModified;
+            this.lastTickCount = tickCount;
+        }
+    }
+
+    /**
+     * WatchKey implementation that encapsulates a map of the entries of the
+     * entries in the directory. Polling the key causes it to re-scan the
+     * directory and queue keys when entries are added, modified, or deleted.
+     */
+    private class PollingWatchKey extends AbstractWatchKey {
+        private final Path dir;
+        private final Object fileKey;
+        private Set<? extends WatchEvent.Kind<?>> events;
+        private volatile boolean valid;
+        private int tickCount;
+
+        // map of entries in directory
+        private Map<Path,CacheEntry> entries;
+
+        PollingWatchKey(PollingWatchService watcher,
+                        Path dir,
+                        Set<? extends WatchEvent.Kind<?>> events,
+                        Object fileKey)
+            throws IOException
+        {
+            super(watcher);
+            this.dir = dir;
+            this.fileKey = fileKey;
+            this.events = events;
+            this.valid = true;
+            this.tickCount = 0;
+            this.entries = new HashMap<Path,CacheEntry>();
+
+            // get the initial entries in the directory
+            DirectoryStream<Path> stream = dir.newDirectoryStream();
+            try {
+                for (Path entry: stream) {
+                    // don't follow links
+                    long lastModified = Attributes
+                        .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
+                        .lastModifiedTime();
+                    entries.put(entry.getName(),
+                                new CacheEntry(lastModified, tickCount));
+                }
+            } catch (ConcurrentModificationException cme) {
+                // thrown if directory iteration fails
+                Throwable cause = cme.getCause();
+                if (cause != null && cause instanceof IOException)
+                    throw (IOException)cause;
+                throw new AssertionError(cme);
+            } finally {
+                stream.close();
+            }
+        }
+
+        FileRef directory() {
+            return dir;
+        }
+
+        Object fileKey() {
+            return fileKey;
+        }
+
+        synchronized void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
+            this.events = events;
+        }
+
+
+        public boolean isValid() {
+            return valid;
+        }
+
+        void invalidate() {
+            valid = false;
+        }
+
+
+        public void cancel() {
+            valid = false;
+            synchronized (keys) {
+                keys.remove(this);
+            }
+        }
+
+        /**
+         * Polls the directory to detect for new files, modified files, or
+         * deleted files.
+         */
+        synchronized void poll() {
+            if (!valid) {
+                return;
+            }
+
+            // update tick
+            tickCount++;
+
+            // open directory
+            DirectoryStream<Path> stream = null;
+            try {
+                stream = dir.newDirectoryStream();
+            } catch (IOException x) {
+                // directory is no longer accessible so cancel key
+                cancel();
+                signal();
+                return;
+            }
+
+            // iterate over all entries in directory
+            try {
+                for (Path entry: stream) {
+                    long lastModified = 0L;
+                    try {
+                        lastModified = Attributes
+                            .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS)
+                            .lastModifiedTime();
+                    } catch (IOException x) {
+                        // unable to get attributes of entry. If file has just
+                        // been deleted then we'll report it as deleted on the
+                        // next poll
+                        continue;
+                    }
+
+                    // lookup cache
+                    CacheEntry e = entries.get(entry.getName());
+                    if (e == null) {
+                        // new file found
+                        entries.put(entry.getName(),
+                                     new CacheEntry(lastModified, tickCount));
+
+                        // queue ENTRY_CREATE if event enabled
+                        if (events.contains(StandardWatchEventKind.ENTRY_CREATE)) {
+                            signalEvent(StandardWatchEventKind.ENTRY_CREATE, entry.getName());
+                            continue;
+                        } else {
+                            // if ENTRY_CREATE is not enabled and ENTRY_MODIFY is
+                            // enabled then queue event to avoid missing out on
+                            // modifications to the file immediately after it is
+                            // created.
+                            if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) {
+                                signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName());
+                            }
+                        }
+                        continue;
+                    }
+
+                    // check if file has changed
+                    if (e.lastModified != lastModified) {
+                        if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) {
+                            signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName());
+                        }
+                    }
+                    // entry in cache so update poll time
+                    e.update(lastModified, tickCount);
+
+                }
+            } catch (ConcurrentModificationException x) {
+                // FIXME - should handle this
+            } finally {
+
+                // close directory stream
+                try {
+                    stream.close();
+                } catch (IOException x) {
+                    // ignore
+                }
+            }
+
+            // iterate over cache to detect entries that have been deleted
+            Iterator<Path> i = entries.keySet().iterator();
+            while (i.hasNext()) {
+                Path name = i.next();
+                CacheEntry entry = entries.get(name);
+
+                if (entry.lastTickCount() != tickCount) {
+                    // remove from map and queue delete event (if enabled)
+                    i.remove();
+                    if (events.contains(StandardWatchEventKind.ENTRY_DELETE)) {
+                        signalEvent(StandardWatchEventKind.ENTRY_DELETE, name);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Reflect.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 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.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Utility class for reflection.
+ */
+
+class Reflect {
+    private Reflect() {}
+
+    private static void setAccessible(final AccessibleObject ao) {
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+
+                public Object run() {
+                    ao.setAccessible(true);
+                    return null;
+                }});
+    }
+
+    /**
+     * Lookup the field of a given class.
+     */
+    static Field lookupField(String className, String fieldName) {
+        try {
+            Class<?> cl = Class.forName(className);
+            Field f = cl.getDeclaredField(fieldName);
+            setAccessible(f);
+            return f;
+        } catch (ClassNotFoundException x) {
+            throw new AssertionError(x);
+        } catch (NoSuchFieldException x) {
+            throw new AssertionError(x);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/aio/EchoServer.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistribution of source code must retain the above copyright notice, this
+ *  list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed, licensed or intended
+ * for use in the design, construction, operation or maintenance of any
+ * nuclear facility.
+ */
+
+import java.nio.ByteBuffer;
+import java.net.InetSocketAddress;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousServerSocketChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel;
+
+public class EchoServer {
+
+    // timeout for read and writes.
+    static final long READ_TIMEOUT_IN_SECONDS  = 30;
+    static final long WRITE_TIMEOUT_IN_SECONDS = 30;
+
+    // the connection count
+    static final AtomicInteger connectionCount = new AtomicInteger();
+
+    /**
+     * Encapsulates everything for a connection and is also the handler
+     * that is invoked when read/write operations complete.
+     */
+    static class Connection
+        implements CompletionHandler<Integer,Void>
+    {
+        private final AsynchronousSocketChannel channel;
+        private final ByteBuffer buf;
+
+        // true if reading; false if writing
+        private volatile boolean isReading;
+
+        private Connection(AsynchronousSocketChannel channel) {
+            this.channel = channel;
+            this.buf = ByteBuffer.allocateDirect(4096);
+            connectionCount.incrementAndGet();
+        }
+
+        static void handle(AsynchronousSocketChannel channel) {
+            new Connection(channel).startReading();
+        }
+
+        private void startReading() {
+            buf.rewind();
+            buf.limit(buf.capacity());
+            isReading = true;
+            channel.read(buf, READ_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS, null, this);
+        }
+
+        private void closeChannel() {
+            try {
+                channel.close();
+            } catch (IOException ignore) { }
+            connectionCount.decrementAndGet();
+        }
+
+        // invoked when a read or write completes
+
+        public void completed(Integer bytesTransferred, Void att) {
+            int n = bytesTransferred;
+            if (n < 0) {
+                // EOF
+                assert isReading;
+                closeChannel();
+                return;
+            }
+
+            // if read completed then flip buffer to write to client
+            if (isReading) {
+                buf.flip();
+                isReading = false;
+            }
+
+            // write any remaining bytes
+            if (!isReading && buf.hasRemaining()) {
+                channel.write(buf, WRITE_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS, null, this);
+            } else {
+                // nothing to write so switch back to reading
+                startReading();
+            }
+        }
+
+        // invoked if read or write fails
+
+        public void failed(Throwable exc, Void att) {
+            System.err.println(exc);
+            closeChannel();
+        }
+
+
+        public void cancelled(Void att) {
+            assert false;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // single argument that is the port number
+        int port = Integer.parseInt(args[0]);
+
+        // create the listener
+        final AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(port));
+
+        // accept connections
+        listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+
+            public void completed(AsynchronousSocketChannel channel, Void att) {
+                // start accepting the next connection
+                listener.accept(null, this);
+
+                // handle the new connection
+                Connection.handle(channel);
+            }
+
+
+            public void failed(Throwable exc, Void att) {
+                System.err.println(exc);
+                System.exit(-1);
+            }
+
+
+            public void cancelled(Void att) {
+            }
+        });
+
+        // keep the main thread busy reporting the connection count
+        for (;;) {
+            Thread.sleep(2000);
+            System.out.println(connectionCount.get());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/AclEdit.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+import org.classpath.icedtea.java.nio.file.AclEntryFlag;
+import org.classpath.icedtea.java.nio.file.AclEntryPermission;
+import org.classpath.icedtea.java.nio.file.AclEntryType;
+
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipalLookupService;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipalNotFoundException;
+
+/**
+ * Sample utility for editing a file's ACL.
+ */
+
+public class AclEdit {
+
+    // parse string as list of ACE permissions separated by /
+    static Set<AclEntryPermission> parsePermissions(String permsString) {
+        Set<AclEntryPermission> perms = new HashSet<AclEntryPermission>();
+        String[] result = permsString.split("/");
+        for (String s : result) {
+            if (s.equals(""))
+                continue;
+            try {
+                perms.add(AclEntryPermission.valueOf(s.toUpperCase()));
+            } catch (IllegalArgumentException x) {
+                System.err.format("Invalid permission '%s'\n", s);
+                System.exit(-1);
+            }
+        }
+        return perms;
+    }
+
+    // parse string as list of ACE flags separated by /
+    static Set<AclEntryFlag> parseFlags(String flagsString) {
+        Set<AclEntryFlag> flags = new HashSet<AclEntryFlag>();
+        String[] result = flagsString.split("/");
+        for (String s : result) {
+            if (s.equals(""))
+                continue;
+            try {
+                flags.add(AclEntryFlag.valueOf(s.toUpperCase()));
+            } catch (IllegalArgumentException x) {
+                System.err.format("Invalid flag '%s'\n", s);
+                System.exit(-1);
+            }
+        }
+        return flags;
+    }
+
+    // parse ACE type
+    static AclEntryType parseType(String typeString) {
+        // FIXME: support audit and alarm types in the future
+        if (typeString.equalsIgnoreCase("allow"))
+            return AclEntryType.ALLOW;
+        if (typeString.equalsIgnoreCase("deny"))
+            return AclEntryType.DENY;
+        System.err.format("Invalid type '%s'\n", typeString);
+        System.exit(-1);
+        return null;    // keep compiler happy
+    }
+
+    /**
+     * Parse string of the form:
+     *   [user|group:]<username|groupname>:<perms>[:flags]:<allow|deny>
+     */
+    static AclEntry parseAceString(String s,
+                                   UserPrincipalLookupService lookupService)
+    {
+        String[] result = s.split(":");
+
+        // must have at least 3 components (username:perms:type)
+        if (result.length < 3)
+            usage();
+
+        int index = 0;
+        int remaining = result.length;
+
+        // optional first component can indicate user or group type
+        boolean isGroup = false;
+        if (result[index].equalsIgnoreCase("user") ||
+            result[index].equalsIgnoreCase("group"))
+        {
+            if (--remaining < 3)
+                usage();
+            isGroup = result[index++].equalsIgnoreCase("group");
+        }
+
+        // user and permissions required
+        String userString = result[index++]; remaining--;
+        String permsString = result[index++]; remaining--;
+
+        // flags are optional
+        String flagsString = "";
+        String typeString = null;
+        if (remaining == 1) {
+            typeString = result[index++];
+        } else {
+            if (remaining == 2) {
+                flagsString = result[index++];
+                typeString = result[index++];
+            } else {
+                usage();
+            }
+        }
+
+        // lookup UserPrincipal
+        UserPrincipal user = null;
+        try {
+            user = (isGroup) ?
+                lookupService.lookupPrincipalByGroupName(userString) :
+                lookupService.lookupPrincipalByName(userString);
+        } catch (UserPrincipalNotFoundException x) {
+            System.err.format("Invalid %s '%s'\n",
+                ((isGroup) ? "group" : "user"),
+                userString);
+            System.exit(-1);
+        } catch (IOException x) {
+            System.err.format("Lookup of '%s' failed: %s\n", userString, x);
+            System.exit(-1);
+        }
+
+        // map string representation of permissions, flags, and type
+        Set<AclEntryPermission> perms = parsePermissions(permsString);
+        Set<AclEntryFlag> flags = parseFlags(flagsString);
+        AclEntryType type = parseType(typeString);
+
+        // build the ACL entry
+        return AclEntry.newBuilder()
+            .setType(type)
+            .setPrincipal(user)
+            .setPermissions(perms).setFlags(flags).build();
+    }
+
+    static void usage() {
+        System.err.println("usage: java AclEdit [ACL-operation] file");
+        System.err.println("");
+        System.err.println("Example 1: Prepends access control entry to the begining of the myfile's ACL");
+        System.err.println("       java AclEdit A+alice:read_data/read_attributes:allow myfile");
+        System.err.println("");
+        System.err.println("Example 2: Remove the entry at index 6 of myfile's ACL");
+        System.err.println("       java AclEdit A6- myfile");
+        System.err.println("");
+        System.err.println("Example 3: Replace the entry at index 2 of myfile's ACL");
+        System.err.println("       java AclEdit A2=bob:write_data/append_data:deny myfile");
+        System.exit(-1);
+    }
+
+    static enum Action {
+        PRINT,
+        ADD,
+        REMOVE,
+        REPLACE;
+    }
+
+    /**
+     * Main class: parses arguments and prints or edits ACL
+     */
+    public static void main(String[] args) throws IOException {
+        Action action = null;
+        int index = -1;
+        String entryString = null;
+
+        // parse arguments
+        if (args.length < 1 || args[0].equals("-help") || args[0].equals("-?"))
+            usage();
+
+        if (args.length == 1) {
+            action = Action.PRINT;
+        } else {
+            String s = args[0];
+
+            // A[index]+entry
+            if (Pattern.matches("^A[0-9]*\\+.*", s)) {
+                String[] result = s.split("\\+", 2);
+                if (result.length == 2) {
+                    if (result[0].length() < 2) {
+                        index = 0;
+                    } else {
+                        index = Integer.parseInt(result[0].substring(1));
+                    }
+                    entryString = result[1];
+                    action = Action.ADD;
+                }
+            }
+
+            // Aindex-
+            if (Pattern.matches("^A[0-9]+\\-", s)) {
+                String[] result = s.split("\\-", 2);
+                if (result.length == 2) {
+                    index = Integer.parseInt(result[0].substring(1));
+                    entryString = result[1];
+                    action = Action.REMOVE;
+                }
+            }
+
+            // Aindex=entry
+            if (Pattern.matches("^A[0-9]+=.*", s)) {
+                String[] result = s.split("=", 2);
+                if (result.length == 2) {
+                    index = Integer.parseInt(result[0].substring(1));
+                    entryString = result[1];
+                    action = Action.REPLACE;
+                }
+            }
+        }
+        if (action == null)
+            usage();
+
+        int fileArg = (action == Action.PRINT) ? 0 : 1;
+        Path file = Paths.get(args[fileArg]);
+
+        // read file's ACL
+        AclFileAttributeView view =
+            file.getFileAttributeView(AclFileAttributeView.class);
+        if (view == null) {
+            System.err.println("ACLs not supported on this platform");
+            System.exit(-1);
+        }
+        List<AclEntry> acl = view.getAcl();
+
+        switch (action) {
+            // print ACL
+            case PRINT : {
+                for (int i=0; i<acl.size(); i++) {
+                    System.out.format("%5d: %s\n", i, acl.get(i));
+                }
+                break;
+            }
+
+            // add ACE to existing ACL
+            case ADD: {
+                AclEntry entry = parseAceString(entryString, file
+                    .getFileSystem().getUserPrincipalLookupService());
+                if (index >= acl.size()) {
+                    acl.add(entry);
+                } else {
+                    acl.add(index, entry);
+                }
+                view.setAcl(acl);
+                break;
+            }
+
+            // remove ACE
+            case REMOVE: {
+                if (index >= acl.size()) {
+                    System.err.format("Index '%d' is invalid", index);
+                    System.exit(-1);
+                }
+                acl.remove(index);
+                view.setAcl(acl);
+                break;
+            }
+
+            // replace ACE
+            case REPLACE: {
+                if (index >= acl.size()) {
+                    System.err.format("Index '%d' is invalid", index);
+                    System.exit(-1);
+                }
+                AclEntry entry = parseAceString(entryString, file
+                    .getFileSystem().getUserPrincipalLookupService());
+                acl.set(index, entry);
+                view.setAcl(acl);
+                break;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Chmod.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileVisitor;
+import org.classpath.icedtea.java.nio.file.FileVisitOption;
+import org.classpath.icedtea.java.nio.file.FileVisitResult;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission;
+
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.OWNER_READ;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.GROUP_READ;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.GROUP_WRITE;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.OTHERS_READ;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.OTHERS_WRITE;
+import static org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission.OTHERS_EXECUTE;
+
+import static org.classpath.icedtea.java.nio.file.FileVisitResult.CONTINUE;
+
+/**
+ * Sample code that changes the permissions of files in a similar manner to the
+ * chmod(1) program.
+ */
+
+public class Chmod {
+
+    /**
+     * Compiles a list of one or more <em>symbolic mode expressions</em> that
+     * may be used to change a set of file permissions. This method is
+     * intended for use where file permissions are required to be changed in
+     * a manner similar to the UNIX <i>chmod</i> program.
+     *
+     * <p> The {@code exprs} parameter is a comma separated list of expressions
+     * where each takes the form:
+     * <blockquote>
+     * <i>who operator</i> [<i>permissions</i>]
+     * </blockquote>
+     * where <i>who</i> is one or more of the characters {@code 'u'}, {@code 'g'},
+     * {@code 'o'}, or {@code 'a'} meaning the owner (user), group, others, or
+     * all (owner, group, and others) respectively.
+     *
+     * <p> <i>operator</i> is the character {@code '+'}, {@code '-'}, or {@code
+     * '='} signifying how permissions are to be changed. {@code '+'} means the
+     * permissions are added, {@code '-'} means the permissions are removed, and
+     * {@code '='} means the permissions are assigned absolutely.
+     *
+     * <p> <i>permissions</i> is a sequence of zero or more of the following:
+     * {@code 'r'} for read permission, {@code 'w'} for write permission, and
+     * {@code 'x'} for execute permission. If <i>permissions</i> is omitted
+     * when assigned absolutely, then the permissions are cleared for
+     * the owner, group, or others as identified by <i>who</i>. When omitted
+     * when adding or removing then the expression is ignored.
+     *
+     * <p> The following examples demonstrate possible values for the {@code
+     * exprs} parameter:
+     *
+     * <table border="0">
+     * <tr>
+     *   <td> {@code u=rw} </td>
+     *   <td> Sets the owner permissions to be read and write. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@code ug+w} </td>
+     *   <td> Sets the owner write and group write permissions. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@code u+w,o-rwx} </td>
+     *   <td> Sets the owner write, and removes the others read, others write
+     *     and others execute permissions. </td>
+     * </tr>
+     * <tr>
+     *   <td> {@code o=} </td>
+     *   <td> Sets the others permission to none (others read, others write and
+     *     others execute permissions are removed if set) </td>
+     * </tr>
+     * </table>
+     *
+     * @param   exprs
+     *          List of one or more <em>symbolic mode expressions</em>
+     *
+     * @return  A {@code Changer} that may be used to changer a set of
+     *          file permissions
+     *
+     * @throws  IllegalArgumentException
+     *          If the value of the {@code exprs} parameter is invalid
+     */
+    public static Changer compile(String exprs) {
+        // minimum is who and operator (u= for example)
+        if (exprs.length() < 2)
+            throw new IllegalArgumentException("Invalid mode");
+
+        // permissions that the changer will add or remove
+        final Set<PosixFilePermission> toAdd = new HashSet<PosixFilePermission>();
+        final Set<PosixFilePermission> toRemove = new HashSet<PosixFilePermission>();
+
+        // iterate over each of expression modes
+        for (String expr: exprs.split(",")) {
+            // minimum of who and operator
+            if (expr.length() < 2)
+                throw new IllegalArgumentException("Invalid mode");
+
+            int pos = 0;
+
+            // who
+            boolean u = false;
+            boolean g = false;
+            boolean o = false;
+            boolean done = false;
+            for (;;) {
+                switch (expr.charAt(pos)) {
+                    case 'u' : u = true; break;
+                    case 'g' : g = true; break;
+                    case 'o' : o = true; break;
+                    case 'a' : u = true; g = true; o = true; break;
+                    default : done = true;
+                }
+                if (done)
+                    break;
+                pos++;
+            }
+            if (!u && !g && !o)
+                throw new IllegalArgumentException("Invalid mode");
+
+            // get operator and permissions
+            char op = expr.charAt(pos++);
+            String mask = (expr.length() == pos) ? "" : expr.substring(pos);
+
+            // operator
+            boolean add = (op == '+');
+            boolean remove = (op == '-');
+            boolean assign = (op == '=');
+            if (!add && !remove && !assign)
+                throw new IllegalArgumentException("Invalid mode");
+
+            // who= means remove all
+            if (assign && mask.length() == 0) {
+                assign = false;
+                remove = true;
+                mask = "rwx";
+            }
+
+            // permissions
+            boolean r = false;
+            boolean w = false;
+            boolean x = false;
+            for (int i=0; i<mask.length(); i++) {
+                switch (mask.charAt(i)) {
+                    case 'r' : r = true; break;
+                    case 'w' : w = true; break;
+                    case 'x' : x = true; break;
+                    default:
+                        throw new IllegalArgumentException("Invalid mode");
+                }
+            }
+
+            // update permissions set
+            if (add) {
+                if (u) {
+                    if (r) toAdd.add(OWNER_READ);
+                    if (w) toAdd.add(OWNER_WRITE);
+                    if (x) toAdd.add(OWNER_EXECUTE);
+                }
+                if (g) {
+                    if (r) toAdd.add(GROUP_READ);
+                    if (w) toAdd.add(GROUP_WRITE);
+                    if (x) toAdd.add(GROUP_EXECUTE);
+                }
+                if (o) {
+                    if (r) toAdd.add(OTHERS_READ);
+                    if (w) toAdd.add(OTHERS_WRITE);
+                    if (x) toAdd.add(OTHERS_EXECUTE);
+                }
+            }
+            if (remove) {
+                if (u) {
+                    if (r) toRemove.add(OWNER_READ);
+                    if (w) toRemove.add(OWNER_WRITE);
+                    if (x) toRemove.add(OWNER_EXECUTE);
+                }
+                if (g) {
+                    if (r) toRemove.add(GROUP_READ);
+                    if (w) toRemove.add(GROUP_WRITE);
+                    if (x) toRemove.add(GROUP_EXECUTE);
+                }
+                if (o) {
+                    if (r) toRemove.add(OTHERS_READ);
+                    if (w) toRemove.add(OTHERS_WRITE);
+                    if (x) toRemove.add(OTHERS_EXECUTE);
+                }
+            }
+            if (assign) {
+                if (u) {
+                    if (r) toAdd.add(OWNER_READ);
+                      else toRemove.add(OWNER_READ);
+                    if (w) toAdd.add(OWNER_WRITE);
+                      else toRemove.add(OWNER_WRITE);
+                    if (x) toAdd.add(OWNER_EXECUTE);
+                      else toRemove.add(OWNER_EXECUTE);
+                }
+                if (g) {
+                    if (r) toAdd.add(GROUP_READ);
+                      else toRemove.add(GROUP_READ);
+                    if (w) toAdd.add(GROUP_WRITE);
+                      else toRemove.add(GROUP_WRITE);
+                    if (x) toAdd.add(GROUP_EXECUTE);
+                      else toRemove.add(GROUP_EXECUTE);
+                }
+                if (o) {
+                    if (r) toAdd.add(OTHERS_READ);
+                      else toRemove.add(OTHERS_READ);
+                    if (w) toAdd.add(OTHERS_WRITE);
+                      else toRemove.add(OTHERS_WRITE);
+                    if (x) toAdd.add(OTHERS_EXECUTE);
+                      else toRemove.add(OTHERS_EXECUTE);
+                }
+            }
+        }
+
+        // return changer
+        return new Changer() {
+
+            public Set<PosixFilePermission> change(Set<PosixFilePermission> perms) {
+                perms.addAll(toAdd);
+                perms.removeAll(toRemove);
+                return perms;
+            }
+        };
+    }
+
+    /**
+     * A task that <i>changes</i> a set of {@link PosixFilePermission} elements.
+     */
+    public interface Changer {
+        /**
+         * Applies the changes to the given set of permissions.
+         *
+         * @param   perms
+         *          The set of permissions to change
+         *
+         * @return  The {@code perms} parameter
+         */
+        Set<PosixFilePermission> change(Set<PosixFilePermission> perms);
+    }
+
+    /**
+     * Changes the permissions of the file using the given Changer.
+     */
+    static void chmod(FileRef file, Changer changer) {
+        try {
+            Set<PosixFilePermission> perms = Attributes
+                .readPosixFileAttributes(file).permissions();
+            Attributes.setPosixFilePermissions(file, changer.change(perms));
+        } catch (IOException x) {
+            System.err.println(x);
+        }
+    }
+
+    /**
+     * Changes the permission of each file and directory visited
+     */
+    static class TreeVisitor implements FileVisitor<FileRef> {
+        private final Changer changer;
+
+        TreeVisitor(Changer changer) {
+            this.changer = changer;
+        }
+
+
+        public FileVisitResult preVisitDirectory(FileRef dir) {
+            chmod(dir, changer);
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) {
+            System.err.println("WARNING: " + exc);
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
+            chmod(file, changer);
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) {
+            if (exc != null)
+                System.err.println("WARNING: " + exc);
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult visitFileFailed(FileRef file, IOException exc) {
+            System.err.println("WARNING: " + exc);
+            return CONTINUE;
+        }
+    }
+
+    static void usage() {
+        System.err.println("java Chmod [-R] symbolic-mode-list file...");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (args.length < 2)
+            usage();
+        int argi = 0;
+        int maxDepth = 0;
+        if (args[argi].equals("-R")) {
+            if (args.length < 3)
+                usage();
+            argi++;
+            maxDepth = -1;
+        }
+
+        // compile the symbolic mode expressions
+        Changer changer = compile(args[argi++]);
+        TreeVisitor visitor = new TreeVisitor(changer);
+
+        Set<FileVisitOption> opts = Collections.emptySet();
+        while (argi < args.length) {
+            Path file = Paths.get(args[argi]);
+            Files.walkFileTree(file, opts, maxDepth, visitor);
+            argi++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Copy.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.CopyOption;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileVisitor;
+import org.classpath.icedtea.java.nio.file.FileVisitResult;
+import org.classpath.icedtea.java.nio.file.Path;
+
+import static org.classpath.icedtea.java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
+import static org.classpath.icedtea.java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+
+import static org.classpath.icedtea.java.nio.file.FileVisitResult.CONTINUE;
+import static org.classpath.icedtea.java.nio.file.FileVisitResult.SKIP_SUBTREE;
+
+/**
+ * Sample code that copies files in a similar manner to the cp(1) program.
+ */
+
+public class Copy {
+
+    /**
+     * Returns {@code true} if okay to overwrite a  file ("cp -i")
+     */
+    static boolean okayToOverwrite(FileRef file) {
+        String answer = System.console().readLine("overwrite %s (yes/no)? ", file);
+        return (answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("yes"));
+    }
+
+    /**
+     * Copy source file to target location. If {@code prompt} is true then
+     * prompted user to overwrite target if it exists. The {@code preserve}
+     * parameter determines if file attributes should be copied/preserved.
+     */
+    static void copyFile(Path source, Path target, boolean prompt, boolean preserve) {
+        CopyOption[] options = (preserve) ?
+            new CopyOption[] { COPY_ATTRIBUTES, REPLACE_EXISTING } :
+            new CopyOption[] { REPLACE_EXISTING };
+        if (!prompt || target.notExists() || okayToOverwrite(target)) {
+            try {
+                source.copyTo(target, options);
+            } catch (IOException x) {
+                System.err.format("Unable to create: %s: %s%n", target, x);
+            }
+        }
+    }
+
+    /**
+     * A {@code FileVisitor} that copies a file-tree ("cp -r")
+     */
+    static class TreeCopier implements FileVisitor<Path> {
+        private final Path source;
+        private final Path target;
+        private final boolean prompt;
+        private final boolean preserve;
+
+        TreeCopier(Path source, Path target, boolean prompt, boolean preserve) {
+            this.source = source;
+            this.target = target;
+            this.prompt = prompt;
+            this.preserve = preserve;
+        }
+
+
+        public FileVisitResult preVisitDirectory(Path dir) {
+            // before visiting entries in a directory we copy the directory
+            // (okay if directory already exists).
+            CopyOption[] options = (preserve) ?
+                new CopyOption[] { COPY_ATTRIBUTES } : new CopyOption[0];
+
+            Path newdir = target.resolve(source.relativize(dir));
+            try {
+                dir.copyTo(newdir, options);
+            } catch (FileAlreadyExistsException x) {
+                // ignore
+            } catch (IOException x) {
+                System.err.format("Unable to create: %s: %s%n", newdir, x);
+                return SKIP_SUBTREE;
+            }
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
+            System.err.format("Unable to copy: %s: %s%n", dir, exc);
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+            if (attrs.isDirectory()) {
+                System.err.println("cycle detected: " + file);
+            } else {
+                copyFile(file, target.resolve(source.relativize(file)),
+                         prompt, preserve);
+            }
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+            // fix up modification time of directory when done
+            if (exc == null && preserve) {
+                try {
+                    BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir);
+                    Path newdir = target.resolve(source.relativize(dir));
+                    Attributes.setLastModifiedTime(newdir,
+                        attrs.lastModifiedTime(), attrs.resolution());
+                } catch (IOException x) {
+                    // ignore
+                }
+            }
+            return CONTINUE;
+        }
+
+
+        public FileVisitResult visitFileFailed(Path file, IOException exc) {
+            System.err.format("Unable to copy: %s: %s%n", file, exc);
+            return CONTINUE;
+        }
+    }
+
+    static void usage() {
+        System.err.println("java Copy [-ip] source... target");
+        System.err.println("java Copy -r [-ip] source-dir... target");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        boolean recursive = false;
+        boolean prompt = false;
+        boolean preserve = false;
+
+        // process options
+        int argi = 0;
+        while (argi < args.length) {
+            String arg = args[argi];
+            if (!arg.startsWith("-"))
+                break;
+            if (arg.length() < 2)
+                usage();
+            for (int i=1; i<arg.length(); i++) {
+                char c = arg.charAt(i);
+                switch (c) {
+                    case 'r' : recursive = true; break;
+                    case 'i' : prompt = true; break;
+                    case 'p' : preserve = true; break;
+                    default : usage();
+                }
+            }
+            argi++;
+        }
+
+        // remaining arguments are the source files(s) and the target location
+        int remaining = args.length - argi;
+        if (remaining < 2)
+            usage();
+        Path[] source = new Path[remaining-1];
+        int i=0;
+        while (remaining > 1) {
+            source[i++] = Paths.get(args[argi++]);
+            remaining--;
+        }
+        Path target = Paths.get(args[argi]);
+
+        // check if target is a directory
+        boolean isDir = false;
+        try {
+            isDir = Attributes.readBasicFileAttributes(target).isDirectory();
+        } catch (IOException x) {
+        }
+
+        // copy each source file/directory to target
+        for (i=0; i<source.length; i++) {
+            Path dest = (isDir) ? target.resolve(source[i].getName()) : target;
+
+            if (recursive) {
+                // follow links when copying files
+                EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
+                TreeCopier tc = new TreeCopier(source[i], dest, prompt, preserve);
+                Files.walkFileTree(source[i], opts, -1, tc);
+            } else {
+                // not recursive so source must not be a directory
+                try {
+                    if (Attributes.readBasicFileAttributes(source[i]).isDirectory()) {
+                        System.err.format("%s: is a directory%n", source[i]);
+                        continue;
+                    }
+                } catch (IOException x) { }
+                copyFile(source[i], dest, prompt, preserve);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/DiskUsage.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributes;
+
+/**
+ * Example utility that works like the df(1M) program to print out disk space
+ * information
+ */
+
+public class DiskUsage {
+
+    static final long K = 1024;
+
+    static void printFileStore(FileStore store) throws IOException {
+        FileStoreSpaceAttributes attrs = Attributes.readFileStoreSpaceAttributes(store);
+
+        long total = attrs.totalSpace() / K;
+        long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / K;
+        long avail = attrs.usableSpace() / K;
+
+        String s = store.toString();
+        if (s.length() > 20) {
+            System.out.println(s);
+            s = "";
+        }
+        System.out.format("%-20s %12d %12d %12d\n", s, total, used, avail);
+    }
+
+    public static void main(String[] args) throws IOException {
+        System.out.format("%-20s %12s %12s %12s\n", "Filesystem", "kbytes", "used", "avail");
+        if (args.length == 0) {
+            FileSystem fs = FileSystems.getDefault();
+            for (FileStore store: fs.getFileStores()) {
+                printFileStore(store);
+            }
+        } else {
+            for (String file: args) {
+                FileStore store = Paths.get(file).getFileStore();
+                printFileStore(store);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/FileType.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.Files;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.Paths;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+
+public class FileType {
+    public static void main(String[] args) throws IOException {
+        if (args.length == 0) {
+            System.err.println("usage: java FileType file...");
+            System.exit(-1);
+        }
+        for (String arg: args) {
+            Path file = Paths.get(arg);
+            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
+
+            String type;
+            if (attrs.isDirectory()) {
+                type = "directory";
+            } else {
+                type = Files.probeContentType(file);
+                if (type == null)
+                    type = "<not recognized>";
+            }
+            System.out.format("%s\t%s%n", file, type);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/WatchDir.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.*;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileSystems;
+import org.classpath.icedtea.java.nio.file.FileVisitResult;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.SimpleFileVisitor;
+import org.classpath.icedtea.java.nio.file.WatchDir;
+import org.classpath.icedtea.java.nio.file.WatchEvent;
+import org.classpath.icedtea.java.nio.file.WatchKey;
+import org.classpath.icedtea.java.nio.file.WatchService;
+
+import static org.classpath.icedtea.java.nio.file.StandardWatchEventKind.ENTRY_CREATE;
+import static org.classpath.icedtea.java.nio.file.StandardWatchEventKind.ENTRY_DELETE;
+import static org.classpath.icedtea.java.nio.file.StandardWatchEventKind.ENTRY_MODIFY;
+
+import static org.classpath.icedtea.java.nio.file.LinkOption.NOFOLLOW_LINKS;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+
+/**
+ * Example to watch a directory (or tree) for changes to files.
+ */
+
+public class WatchDir {
+
+    private final WatchService watcher;
+    private final Map<WatchKey,Path> keys;
+    private final boolean recursive;
+    private boolean trace = false;
+
+    /**
+     * Register the given directory with the WatchService
+     */
+    private void register(Path dir) throws IOException {
+        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+        if (trace) {
+            FileRef prev = keys.get(key);
+            if (prev == null) {
+                System.out.format("register: %s\n", dir);
+            } else {
+                if (!dir.equals(prev)) {
+                    System.out.format("update: %s -> %s\n", prev, dir);
+                }
+            }
+        }
+        keys.put(key, dir);
+    }
+
+    /**
+     * Register the given directory, and all its sub-directories, with the
+     * WatchService.
+     */
+    private void registerAll(final Path start) throws IOException {
+        // register directory and sub-directories
+        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
+
+            public FileVisitResult preVisitDirectory(Path dir) {
+                try {
+                    register(dir);
+                } catch (IOException x) {
+                    throw new IOError(x);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    /**
+     * Creates a WatchService and registers the given directory
+     */
+    WatchDir(Path dir, boolean recursive) throws IOException {
+        this.watcher = FileSystems.getDefault().newWatchService();
+        this.keys = new HashMap<WatchKey,Path>();
+        this.recursive = recursive;
+
+        if (recursive) {
+            System.out.format("Scanning %s ...\n", dir);
+            registerAll(dir);
+            System.out.println("Done.");
+        } else {
+            register(dir);
+        }
+
+        // enable trace after initial registration
+        this.trace = true;
+    }
+
+    /**
+     * Process all events for keys queued to the watcher
+     */
+    void processEvents() {
+        for (;;) {
+
+            // wait for key to be signalled
+            WatchKey key;
+            try {
+                key = watcher.take();
+            } catch (InterruptedException x) {
+                return;
+            }
+
+            Path dir = keys.get(key);
+            if (dir == null) {
+                System.err.println("WatchKey not recognized!!");
+                continue;
+            }
+
+            for (WatchEvent<?> event: key.pollEvents()) {
+                WatchEvent.Kind kind = event.kind();
+
+                // TBD - provide example of how OVERFLOW event is handled
+                if (kind == OVERFLOW) {
+                    continue;
+                }
+
+                // Context for directory entry event is the file name of entry
+                Path name = ((WatchEvent<Path>)event).context();
+                Path child = dir.resolve(name);
+
+                // print out event
+                System.out.format("%s: %s\n", event.kind().name(), child);
+
+                // if directory is created, and watching recursively, then
+                // register it and its sub-directories
+                if (recursive && (kind == ENTRY_CREATE)) {
+                    try {
+                        if (Attributes.readBasicFileAttributes(child, NOFOLLOW_LINKS).isDirectory()) {
+                            registerAll(child);
+                        }
+                    } catch (IOException x) {
+                        // ignore to keep sample readbale
+                    }
+                }
+            }
+
+            // reset key and remove from set if directory no longer accessible
+            boolean valid = key.reset();
+            if (!valid) {
+                keys.remove(key);
+
+                // all directories are inaccessible
+                if (keys.isEmpty()) {
+                    break;
+                }
+            }
+        }
+    }
+
+    static void usage() {
+        System.err.println("usage: java WatchDir [-r] dir");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        // parse arguments
+        if (args.length == 0 || args.length > 2)
+            usage();
+        boolean recursive = false;
+        int dirArg = 0;
+        if (args[0].equals("-r")) {
+            if (args.length < 2)
+                usage();
+            recursive = true;
+            dirArg++;
+        }
+
+        // register directory and process its events
+        Path dir = Paths.get(args[dirArg]);
+        new WatchDir(dir, recursive).processEvents();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/file/Xdd.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+import java.io.IOException;
+
+import java.nio.ByteBuffer;
+
+import java.nio.charset.Charset;
+
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.Path;
+
+import org.classpath.icedtea.java.nio.file.attribute.NamedAttributeView;
+
+/**
+ * Example code to list/set/get/delete the named attributes of a file.
+ */
+
+public class Xdd {
+
+    static void usage() {
+        System.out.println("Usage: java Xdd <file>");
+        System.out.println("       java Xdd -set <name>=<value> <file>");
+        System.out.println("       java Xdd -get <name> <file>");
+        System.out.println("       java Xdd -del <name> <file>");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        // one or three parameters
+        if (args.length != 1 && args.length != 3)
+            usage();
+
+        Path file = (args.length == 1) ?
+            Paths.get(args[0]) : Paths.get(args[2]);
+
+        // check that named attributes are supported by the file system
+        FileStore store = file.getFileStore();
+        if (!store.supportsFileAttributeView("xattr")) {
+            System.err.format("NamedAttributeView not supported on %s\n", store);
+            System.exit(-1);
+
+        }
+        NamedAttributeView view = file.
+            getFileAttributeView(NamedAttributeView.class);
+
+
+        // list named attributes
+        if (args.length == 1) {
+            System.out.println("    Size  Name");
+            System.out.println("--------  --------------------------------------");
+            for (String name: view.list()) {
+                System.out.format("%8d  %s\n", view.size(name), name);
+            }
+            return;
+        }
+
+        // Add/replace a file's named attribute
+        if (args[0].equals("-set")) {
+            // name=value
+            String[] s = args[1].split("=");
+            if (s.length != 2)
+                usage();
+            String name = s[0];
+            String value = s[1];
+            view.write(name, Charset.defaultCharset().encode(value));
+            return;
+        }
+
+        // Print out the value of a file's named attribute
+        if (args[0].equals("-get")) {
+            String name = args[1];
+            int size = view.size(name);
+            ByteBuffer buf = ByteBuffer.allocateDirect(size);
+            view.read(name, buf);
+            buf.flip();
+            System.out.println(Charset.defaultCharset().decode(buf).toString());
+            return;
+        }
+
+        // Delete a file's named attribute
+        if (args[0].equals("-del")) {
+            view.delete(args[1]);
+            return;
+        }
+
+        // option not recognized
+        usage();
+    }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007 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.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Creates this platform's default asynchronous channel provider
+ */
+
+public class DefaultAsynchronousChannelProvider {
+
+    /**
+     * Prevent instantiation.
+     */
+    private DefaultAsynchronousChannelProvider() { }
+
+    /**
+     * Returns the default AsynchronousChannelProvider.
+     */
+    public static AsynchronousChannelProvider create() {
+        String osname = AccessController
+            .doPrivileged(new GetPropertyAction("os.name"));
+        if (osname.equals("SunOS"))
+            return new SolarisAsynchronousChannelProvider();
+        if (osname.equals("Linux"))
+            return new LinuxAsynchronousChannelProvider();
+        throw new InternalError("platform not recognized");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.util.concurrent.ExecutorService;
+import java.net.ProtocolFamily;
+import java.io.IOException;
+
+public class LinuxAsynchronousChannelProvider
+    extends AsynchronousChannelProvider
+{
+    private static volatile EPollPort defaultPort;
+
+    private EPollPort defaultEventPort() throws IOException {
+        if (defaultPort == null) {
+            synchronized (LinuxAsynchronousChannelProvider.class) {
+                if (defaultPort == null) {
+                    defaultPort = new EPollPort(this, ThreadPool.getDefault()).start();
+                }
+            }
+        }
+        return defaultPort;
+    }
+
+    public LinuxAsynchronousChannelProvider() {
+    }
+
+
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(ThreadPoolType poolType,
+                                                                 ExecutorService executor,
+                                                                 int nThreads)
+        throws IOException
+    {
+        return new EPollPort(this, ThreadPool.create(poolType, executor, nThreads)).start();
+    }
+
+    private Port toPort(AsynchronousChannelGroup group) throws IOException {
+        if (group == null) {
+            return defaultEventPort();
+        } else {
+            if (!(group instanceof EPollPort))
+                throw new IllegalChannelGroupException();
+            return (Port)group;
+        }
+    }
+
+
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousServerSocketChannelImpl(toPort(group));
+    }
+
+
+    public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousSocketChannelImpl(toPort(group));
+    }
+
+
+    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
+                                                                       AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new SimpleAsynchronousDatagramChannelImpl(family, toPort(group));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.util.concurrent.ExecutorService;
+import java.net.ProtocolFamily;
+import java.io.IOException;
+
+public class SolarisAsynchronousChannelProvider
+    extends AsynchronousChannelProvider
+{
+    private static volatile SolarisEventPort defaultEventPort;
+
+    private SolarisEventPort defaultEventPort() throws IOException {
+        if (defaultEventPort == null) {
+            synchronized (SolarisAsynchronousChannelProvider.class) {
+                if (defaultEventPort == null) {
+                    defaultEventPort =
+                        new SolarisEventPort(this, ThreadPool.getDefault()).start();
+                }
+            }
+        }
+        return defaultEventPort;
+    }
+
+    public SolarisAsynchronousChannelProvider() {
+    }
+
+
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(ThreadPoolType poolType,
+                                                                 ExecutorService executor,
+                                                                 int nThreads)
+        throws IOException
+    {
+        return new SolarisEventPort(this, ThreadPool.create(poolType, executor, nThreads)).start();
+    }
+
+    private SolarisEventPort toEventPort(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        if (group == null) {
+            return defaultEventPort();
+        } else {
+            if (!(group instanceof SolarisEventPort))
+                throw new IllegalChannelGroupException();
+            return (SolarisEventPort)group;
+        }
+    }
+
+
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousServerSocketChannelImpl(toEventPort(group));
+    }
+
+
+    public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
+    }
+
+
+    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
+                                                                       AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new SimpleAsynchronousDatagramChannelImpl(family, toEventPort(group));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.util.concurrent.RejectedExecutionException;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+/**
+ * AsynchronousChannelGroup implementation based on the Solaris 10 event port
+ * framework.
+ */
+
+class SolarisEventPort
+    extends Port
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final int addressSize = unsafe.addressSize();
+
+    private static int dependsArch(int value32, int value64) {
+        return (addressSize == 4) ? value32 : value64;
+    }
+
+    /*
+     * typedef struct port_event {
+     *     int             portev_events;
+     *     ushort_t        portev_source;
+     *     ushort_t        portev_pad;
+     *     uintptr_t       portev_object;
+     *     void            *portev_user;
+     * } port_event_t;
+     */
+    private static final int SIZEOF_PORT_EVENT  = dependsArch(16, 24);
+    private static final int OFFSETOF_EVENTS    = 0;
+    private static final int OFFSETOF_SOURCE    = 4;
+    private static final int OFFSETOF_OBJECT    = 8;
+
+    // port sources
+    private static final short PORT_SOURCE_USER     = 3;
+    private static final short PORT_SOURCE_FD       = 4;
+
+    // file descriptor to event port.
+    private final int port;
+
+    // true when port is closed
+    private boolean closed;
+
+    SolarisEventPort(AsynchronousChannelProvider provider, ThreadPool pool)
+        throws IOException
+    {
+        super(provider, pool);
+
+        // create event port
+        this.port = portCreate();
+    }
+
+    SolarisEventPort start() {
+        startThreads(new EventHandlerTask());
+        return this;
+    }
+
+    // releass resources
+    private void implClose() {
+        synchronized (this) {
+            if (closed)
+                return;
+            closed = true;
+        }
+        portClose(port);
+    }
+
+    private void wakeup() {
+        try {
+            portSend(port, 0);
+        } catch (IOException x) {
+            throw new AssertionError(x);
+        }
+    }
+
+
+    void executeOnHandlerTask(Runnable task) {
+        synchronized (this) {
+            if (closed)
+                throw new RejectedExecutionException();
+            offerTask(task);
+            wakeup();
+        }
+    }
+
+
+    void shutdownHandlerTasks() {
+       /*
+         * If no tasks are running then just release resources; otherwise
+         * write to the one end of the socketpair to wakeup any polling threads..
+         */
+        int nThreads = threadCount();
+        if (nThreads == 0) {
+            implClose();
+        } else {
+            // send user event to wakeup each thread
+            while (nThreads-- > 0) {
+                try {
+                    portSend(port, 0);
+                } catch (IOException x) {
+                    throw new AssertionError(x);
+                }
+            }
+        }
+    }
+
+
+    void startPoll(int fd, int events) {
+        // (re-)associate file descriptor
+        try {
+            portAssociate(port, PORT_SOURCE_FD, fd, events);
+        } catch (IOException x) {
+            throw new AssertionError();     // should not happen
+        }
+    }
+
+    /*
+     * Task to read a single event from the port and dispatch it to the
+     * channel's onEvent handler.
+     */
+    private class EventHandlerTask implements Runnable {
+        public void run() {
+            Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+                Invoker.getGroupAndInvokeCount();
+            boolean replaceMe = false;
+            long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
+            try {
+                for (;;) {
+                    // reset invoke count
+                    if (myGroupAndInvokeCount != null)
+                        myGroupAndInvokeCount.resetInvokeCount();
+
+                    // wait for I/O completion event
+                    // A error here is fatal (thread will not be replaced)
+                    replaceMe = false;
+                    try {
+                        portGet(port, address);
+                    } catch (IOException x) {
+                        x.printStackTrace();
+                        return;
+                    }
+
+                    // event source
+                    short source = unsafe.getShort(address + OFFSETOF_SOURCE);
+                    if (source != PORT_SOURCE_FD) {
+                        // user event is trigger to invoke task or shutdown
+                        if (source == PORT_SOURCE_USER) {
+                            Runnable task = pollTask();
+                            if (task == null) {
+                                // shutdown request
+                                return;
+                            }
+                            // run task (may throw error/exception)
+                            replaceMe = true;
+                            task.run();
+                        }
+                        // ignore
+                        continue;
+                    }
+
+                    // pe->portev_object is file descriptor
+                    int fd = (int)unsafe.getAddress(address + OFFSETOF_OBJECT);
+                    // pe->portev_events
+                    int events = unsafe.getInt(address + OFFSETOF_EVENTS);
+
+                    // lookup channel
+                    PollableChannel ch;
+                    fdToChannelLock.readLock().lock();
+                    try {
+                        ch = fdToChannel.get(fd);
+                    } finally {
+                        fdToChannelLock.readLock().unlock();
+                    }
+
+                    // notify channel
+                    if (ch != null) {
+                        replaceMe = true;
+                        ch.onEvent(events);
+                    }
+                }
+            } finally {
+                // free per-thread resources
+                unsafe.freeMemory(address);
+                // last task to exit when shutdown release resources
+                int remaining = threadExit(this, replaceMe);
+                if (remaining == 0 && isShutdown())
+                    implClose();
+            }
+        }
+    }
+
+    // -- Native methods --
+
+    private static native void init();
+
+    private static native int portCreate() throws IOException;
+
+    private static native void portAssociate(int port, int source, long object,
+        int events) throws IOException;
+
+    private static native void portGet(int port, long pe) throws IOException;
+
+    private static native int portGetn(int port, long address, int max)
+        throws IOException;
+
+    private static native void portSend(int port, int events) throws IOException;
+
+    private static native void portClose(int port);
+
+    static {
+        Util.load();
+        init();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.net.InetSocketAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Unix implementation of AsynchronousServerSocketChannel
+ */
+
+class UnixAsynchronousServerSocketChannelImpl
+    extends AsynchronousServerSocketChannelImpl
+    implements Port.PollableChannel
+{
+    private final static NativeDispatcher nd = new SocketDispatcher();
+
+    private final Port port;
+    private final int fdVal;
+
+    UnixAsynchronousServerSocketChannelImpl(Port port)
+        throws IOException
+    {
+        super(port);
+
+        try {
+            IOUtil.configureBlocking(fd, false);
+        } catch (IOException x) {
+            nd.close(fd);  // prevent leak
+            throw x;
+        }
+        this.port = port;
+        this.fdVal = IOUtil.fdVal(fd);
+
+        // add mapping from file descriptor to this channel
+        port.register(fdVal, this);
+    }
+
+
+    void implClose() throws IOException {
+        // remove the mapping
+        port.unregister(fdVal);
+
+        // close file descriptor
+        nd.close(fd);
+
+        // if there is a pending accept then complete it
+        final PendingFuture<AsynchronousSocketChannel,Object> result =
+            grabPendingAccept();
+        if (result != null) {
+            // discard the stack trace as otherwise it may appear that implClose
+            // has thrown the exception.
+            AsynchronousCloseException x = new AsynchronousCloseException();
+            x.setStackTrace(new StackTraceElement[0]);
+            result.setFailure(x);
+
+            // invoke by submitting task rather than directly
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    }
+
+
+    public AsynchronousChannelGroupImpl group() {
+        return port;
+    }
+
+    // flag to indicate an accept is outstanding
+    private final AtomicBoolean accepting = new AtomicBoolean();
+    private void enableAccept() {
+        accepting.set(false);
+    }
+
+    // the pending result
+    private AtomicReference<PendingFuture<AsynchronousSocketChannel,Object>>
+        pendingAccept = new AtomicReference<PendingFuture<AsynchronousSocketChannel,Object>>();
+    private PendingFuture<AsynchronousSocketChannel,Object> grabPendingAccept() {
+        return pendingAccept.getAndSet(null);
+    }
+
+    // context for permission check when security manager set
+    private volatile AccessControlContext acc;
+
+    /**
+     * Invoked by event handling thread when listener socket is polled
+     */
+
+    public void onEvent(int events) {
+        PendingFuture<AsynchronousSocketChannel,Object> result =
+            grabPendingAccept();
+        if (result == null) {
+            // may have been grabbed by asynchronous close
+            return;
+        }
+
+        // attempt to accept connection
+        FileDescriptor newfd = new FileDescriptor();
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+        boolean accepted = false;
+        try {
+            begin();
+            int n = accept0(this.fd, newfd, isaa);
+
+            // spurious wakeup, is this possible?
+            if (n == IOStatus.UNAVAILABLE) {
+                pendingAccept.set(result);
+                port.startPoll(fdVal, Port.POLLIN);
+                return;
+            }
+
+            // connection accepted
+            accepted = true;
+
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            enableAccept();
+            result.setFailure(x);
+        } finally {
+            end();
+        }
+
+        // Connection accepted so finish it when not holding locks.
+        AsynchronousSocketChannel child = null;
+        if (accepted) {
+            try {
+                child = finishAccept(newfd, isaa[0], acc);
+                enableAccept();
+                result.setResult(child);
+            } catch (Throwable x) {
+                enableAccept();
+                if (!(x instanceof IOException) && !(x instanceof SecurityException))
+                    x = new IOException(x);
+                result.setFailure(x);
+            }
+        }
+
+        // if an async cancel has already cancelled the operation then
+        // close the new channel so as to free resources
+        if (child != null && result.isCancelled()) {
+            try {
+                child.close();
+            } catch (IOException ignore) { }
+        }
+
+        // invoke the handler
+        Invoker.invoke(result.handler(), result);
+    }
+
+    /**
+     * Completes the accept by creating the AsynchronousSocketChannel for
+     * the given file descriptor and remote address. If this method completes
+     * with an IOException or SecurityException then the channel/file descriptor
+     * will be closed.
+     */
+    private AsynchronousSocketChannel finishAccept(FileDescriptor newfd,
+                                                   final InetSocketAddress remote,
+                                                   AccessControlContext acc)
+        throws IOException, SecurityException
+    {
+        AsynchronousSocketChannel ch = null;
+        try {
+            ch = new UnixAsynchronousSocketChannelImpl(port, newfd, remote);
+        } catch (IOException x) {
+            nd.close(newfd);
+            throw x;
+        }
+
+        // permission check must always be in initiator's context
+        try {
+            if (acc != null) {
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    public Void run() {
+                        SecurityManager sm = System.getSecurityManager();
+                        sm.checkAccept(remote.getAddress().getHostAddress(),
+                                       remote.getPort());
+                        return null;
+                    }
+                }, acc);
+            } else {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    sm.checkAccept(remote.getAddress().getHostAddress(),
+                                   remote.getPort());
+                }
+            }
+        } catch (SecurityException x) {
+            try {
+                ch.close();
+            } catch (IOException ignore) { }
+            throw x;
+        }
+        return ch;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <A> Future<AsynchronousSocketChannel> accept(A attachment,
+        final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+    {
+        // complete immediately if channel is closed
+        if (!isOpen()) {
+            CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invokeIndirectly(handler, result);
+            return result;
+        }
+        if (localAddress == null)
+            throw new NotYetBoundException();
+
+        // cancel was invoked with pending accept so connection may have been
+        // dropped.
+        if (isAcceptKilled())
+            throw new RuntimeException("Accept not allowed due cancellation");
+
+        // check and set flag to prevent concurrent accepting
+        if (!accepting.compareAndSet(false, true))
+            throw new AcceptPendingException();
+
+        // attempt accept
+        AbstractFuture<AsynchronousSocketChannel,A> result = null;
+        FileDescriptor newfd = new FileDescriptor();
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+        try {
+            begin();
+
+            int n = accept0(this.fd, newfd, isaa);
+            if (n == IOStatus.UNAVAILABLE) {
+                // no connection to accept
+                result = new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
+
+                // need calling context when there is security manager as
+                // permission check may be done in a different thread without
+                // any application call frames on the stack
+                this.acc = (System.getSecurityManager() == null) ?
+                    null : AccessController.getContext();
+                this.pendingAccept.set((PendingFuture<AsynchronousSocketChannel,Object>)result);
+
+                // register for connections
+                port.startPoll(fdVal, Port.POLLIN);
+                return result;
+            }
+        } catch (Throwable x) {
+            // accept failed
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            result = CompletedFuture.withFailure(this, x, attachment);
+        } finally {
+            end();
+        }
+
+        // connection accepted immediately
+        if (result == null) {
+            try {
+                AsynchronousSocketChannel ch = finishAccept(newfd, isaa[0], null);
+                result = CompletedFuture.withResult(this, ch, attachment);
+            } catch (Throwable x) {
+                result = CompletedFuture.withFailure(this, x, attachment);
+            }
+        }
+
+        // re-enable accepting and invoke handler
+        enableAccept();
+        Invoker.invokeIndirectly(handler, result);
+        return result;
+    }
+
+    // -- Native methods --
+
+    private static native void initIDs();
+
+    // Accepts a new connection, setting the given file descriptor to refer to
+    // the new socket and setting isaa[0] to the socket's remote address.
+    // Returns 1 on success, or IOStatus.UNAVAILABLE.
+    //
+    private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
+                               InetSocketAddress[] isaa)
+        throws IOException;
+
+    static {
+        Util.load();
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2007-2008 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 conne02110-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.ch;
+
+import java.nio.channels.*;
+import java.nio.ByteBuffer;
+import java.net.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetBooleanAction;
+
+/**
+ * Unix implementation of AsynchronousSocketChannel
+ */
+
+class UnixAsynchronousSocketChannelImpl
+    extends AsynchronousSocketChannelImpl implements Port.PollableChannel
+{
+    private final static NativeDispatcher nd = new SocketDispatcher();
+    private static enum OpType { CONNECT, READ, WRITE };
+
+    private static final boolean DISABLE_SYNCHRONOUS_READ;
+    static {
+        PrivilegedAction<Boolean> pa =
+            new GetBooleanAction("sun.nio.ch.disableSynchronousRead");
+        DISABLE_SYNCHRONOUS_READ = AccessController.doPrivileged(pa).booleanValue();
+    }
+
+    private final Port port;
+    private final int fdVal;
+
+    UnixAsynchronousSocketChannelImpl(Port port)
+        throws IOException
+    {
+        super(port);
+
+        // set non-blocking
+        try {
+            IOUtil.configureBlocking(fd, false);
+        } catch (IOException x) {
+            nd.close(fd);
+            throw x;
+        }
+
+        this.port = port;
+        this.fdVal = IOUtil.fdVal(fd);
+
+        // add mapping from file descriptor to this channel
+        port.register(fdVal, this);
+    }
+
+    // Constructor for sockets created by UnixAsynchronousServerSocketChannelImpl
+    UnixAsynchronousSocketChannelImpl(Port port,
+                                      FileDescriptor fd,
+                                      InetSocketAddress remote)
+        throws IOException
+    {
+        super(port, fd, remote);
+
+        this.fdVal = IOUtil.fdVal(fd);
+        IOUtil.configureBlocking(fd, false);
+
+        try {
+            port.register(fdVal, this);
+        } catch (ShutdownChannelGroupException x) {
+            // ShutdownChannelGroupException thrown if we attempt to register a
+            // new channel after the group is shutdown
+            throw new IOException(x);
+        }
+
+        this.port = port;
+    }
+
+
+    public AsynchronousChannelGroupImpl group() {
+        return port;
+    }
+
+    // lock used when updating interest events for this channel
+    private final Object updateLock = new Object();
+
+    // pending results for each operation type.
+    private PendingFuture<Void,Object> pendingConnect;
+    private PendingFuture<Number,Object> pendingRead;
+    private PendingFuture<Number,Object> pendingWrite;
+
+    private void updateEvents() {
+        synchronized (updateLock) {
+            int events = 0;
+            if (pendingRead != null)
+                events |= Port.POLLIN;
+            if (pendingConnect != null || pendingWrite != null)
+                events |= Port.POLLOUT;
+            if (events != 0)
+                port.startPoll(fdVal, events);
+        }
+    }
+
+    /**
+     * Invoked by event handler thread when file descriptor is polled
+     */
+
+    public void onEvent(int events) {
+        boolean readable = (events & Port.POLLIN) > 0;
+        boolean writable = (events & Port.POLLOUT) > 0;
+        if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
+            readable = true;
+            writable = true;
+        }
+
+        PendingFuture<Void,Object> connectResult = null;
+        PendingFuture<Number,Object> readResult = null;
+        PendingFuture<Number,Object> writeResult = null;
+
+        // map event to pending result
+        synchronized (updateLock) {
+            if (readable && (pendingRead != null)) {
+                readResult = pendingRead;
+                pendingRead = null;
+            }
+            if (writable) {
+                if (pendingWrite != null) {
+                    writeResult = pendingWrite;
+                    pendingWrite = null;
+                } else if (pendingConnect != null) {
+                    connectResult = pendingConnect;
+                    pendingConnect = null;
+                }
+            }
+        }
+
+        // complete the I/O operation. Special case for when channel is
+        // ready for both reading and writing. In that case, submit task to
+        // complete write if write operation has a completion handler.
+        if (readResult != null) {
+            if (writeResult != null)
+                finishWrite(writeResult, false);
+            finishRead(readResult, true);
+            return;
+        }
+        if (writeResult != null) {
+            finishWrite(writeResult, true);
+        }
+        if (connectResult != null) {
+            finishConnect(connectResult, true);
+        }
+    }
+
+    // invoked by connect when connection could not be established immediately
+    void setPendingConnect(PendingFuture<Void,Object> result)
+        throws IOException
+    {
+        synchronized (updateLock) {
+            pendingConnect = result;
+        }
+        updateEvents();
+    }
+
+    // invoked by read when there is no data to read
+    void setPendingRead(PendingFuture<Number,Object> result)
+        throws IOException
+    {
+        synchronized (updateLock) {
+            pendingRead = result;
+        }
+        updateEvents();
+    }
+
+    // invoked by write when socket buffer is full and write cannot complete
+    // immediately
+    void setPendingWrite(PendingFuture<Number,Object> result)
+        throws IOException
+    {
+        synchronized (updateLock) {
+            pendingWrite = result;
+        }
+        updateEvents();
+    }
+
+    // returns and clears the result of a pending read
+    PendingFuture<Number,Object> grabPendingRead() {
+        synchronized (updateLock) {
+            PendingFuture<Number,Object> result = pendingRead;
+            pendingRead = null;
+            return result;
+        }
+    }
+
+    // returns and clears the result of a pending write
+    PendingFuture<Number,Object> grabPendingWrite() {
+        synchronized (updateLock) {
+            PendingFuture<Number,Object> result = pendingWrite;
+            pendingWrite = null;
+            return result;
+        }
+    }
+
+
+    void implClose() throws IOException {
+        // remove the mapping
+        port.unregister(fdVal);
+
+        // close file descriptor
+        nd.close(fd);
+
+        // All outstanding I/O operations are required to fail
+        final PendingFuture<Void,Object> readyToConnect;
+        final PendingFuture<Number,Object> readyToRead;
+        final PendingFuture<Number,Object> readyToWrite;
+        synchronized (updateLock) {
+            readyToConnect = pendingConnect;
+            pendingConnect = null;
+            readyToRead = pendingRead;
+            pendingRead = null;
+            readyToWrite = pendingWrite;
+            pendingWrite = null;
+        }
+        if (readyToConnect != null) {
+            finishConnect(readyToConnect, false);
+        }
+        if (readyToRead != null) {
+            finishRead(readyToRead, false);
+        }
+        if (readyToWrite != null) {
+            finishWrite(readyToWrite, false);
+        }
+    }
+
+
+    public void onCancel(PendingFuture<?,?> task) {
+        if (task.getContext() == OpType.CONNECT)
+            killConnect();
+        if (task.getContext() == OpType.READ)
+            killConnect();
+        if (task.getContext() == OpType.WRITE)
+            killConnect();
+    }
+
+    // -- connect --
+
+    // need stateLock to access
+    private SocketAddress pendingRemote;
+
+    private void setConnected() throws IOException {
+        synchronized (stateLock) {
+            state = ST_CONNECTED;
+            localAddress = Net.localAddress(fd);
+            remoteAddress = pendingRemote;
+        }
+    }
+
+    private void finishConnect(PendingFuture<Void,Object> result,
+                               boolean invokeDirect)
+    {
+        Throwable e = null;
+        try {
+            begin();
+            checkConnect(fdVal);
+            setConnected();
+            result.setResult(null);
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            e = x;
+        } finally {
+            end();
+        }
+        if (e != null) {
+            // close channel if connection cannot be established
+            try {
+                close();
+            } catch (IOException ignore) { }
+            result.setFailure(e);
+        }
+        if (invokeDirect) {
+            Invoker.invoke(result.handler(), result);
+        } else {
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <A> Future<Void> connect(SocketAddress remote,
+                                    A attachment,
+                                    CompletionHandler<Void,? super A> handler)
+    {
+        if (!isOpen()) {
+            CompletedFuture<Void,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        InetSocketAddress isa = Net.checkAddress(remote);
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
+
+        // check and set state
+        synchronized (stateLock) {
+            if (state == ST_CONNECTED)
+                throw new AlreadyConnectedException();
+            if (state == ST_PENDING)
+                throw new ConnectionPendingException();
+            state = ST_PENDING;
+            pendingRemote = remote;
+        }
+
+        AbstractFuture<Void,A> result = null;
+        Throwable e = null;
+        try {
+            begin();
+            int n = Net.connect(fd, isa.getAddress(), isa.getPort());
+            if (n == IOStatus.UNAVAILABLE) {
+                // connection could not be established immediately
+                result = new PendingFuture<Void,A>(this, handler, attachment, OpType.CONNECT);
+                setPendingConnect((PendingFuture<Void,Object>)result);
+                return result;
+            }
+            setConnected();
+            result = CompletedFuture.withResult(this, null, attachment);
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            e = x;
+        } finally {
+            end();
+        }
+
+        // close channel if connect fails
+        if (e != null) {
+            try {
+                close();
+            } catch (IOException ignore) { }
+            result = CompletedFuture.withFailure(this, e, attachment);
+        }
+
+        Invoker.invoke(handler, result);
+        return result;
+    }
+
+    // -- read --
+
+    // buffers used for the read
+    private volatile ByteBuffer[] readBuffers;
+    // true if the read is a scattering read (multiple buffers)
+    private volatile boolean scatteringRead;
+
+    @SuppressWarnings("unchecked")
+    private void finishRead(PendingFuture<Number,Object> result,
+                            boolean invokeDirect)
+    {
+        int n = -1;
+        try {
+            begin();
+
+            ByteBuffer[] dsts = readBuffers;
+            if (dsts.length == 1) {
+                n = IOUtil.read(fd, dsts[0], -1, nd, null);
+            } else {
+                n = (int)IOUtil.read(fd, dsts, nd);
+            }
+            if (n == IOStatus.UNAVAILABLE) {
+                // spurious wakeup, is this possible?
+                setPendingRead(result);
+                return;
+            }
+
+            // allow buffer(s) to be GC'ed.
+            readBuffers = null;
+
+            // allow another read to be initiated
+            boolean wasScatteringRead = scatteringRead;
+            enableReading();
+
+            // result is Integer or Long
+            if (wasScatteringRead) {
+                result.setResult(Long.valueOf(n));
+            } else {
+                result.setResult(Integer.valueOf(n));
+            }
+
+        } catch (Throwable x) {
+            enableReading();
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            result.setFailure(x);
+        } finally {
+            updateEvents();
+            end();
+        }
+
+        if (invokeDirect) {
+            Invoker.invoke(result.handler(), result);
+        } else {
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    }
+
+    private Runnable readTimeoutTask = new Runnable() {
+        public void run() {
+            PendingFuture<Number,Object> result = grabPendingRead();
+            if (result == null)
+                return;     // already completed
+
+            // kill further reading before releasing waiters
+            enableReading(true);
+
+            // set completed and invoke handler
+            result.setFailure(new InterruptedByTimeoutException());
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    };
+
+    /**
+     * Initiates a read or scattering read operation
+     */
+
+    @SuppressWarnings("unchecked")
+    <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
+                                            boolean isScatteringRead,
+                                            long timeout,
+                                            TimeUnit unit,
+                                            A attachment,
+                                            CompletionHandler<V,? super A> handler)
+    {
+        // A synchronous read is not attempted if disallowed by system property
+        // or, we are using a fixed thread pool and the completion handler may
+        // not be invoked directly (because the thread is not a pooled thread or
+        // there are too many handlers on the stack).
+        Invoker.GroupAndInvokeCount myGroupAndInvokeCount = null;
+        boolean invokeDirect = false;
+        boolean attemptRead = false;
+        if (!DISABLE_SYNCHRONOUS_READ) {
+            myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount();
+            invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
+            attemptRead = (handler == null) || invokeDirect ||
+                !port.isFixedThreadPool();  // okay to attempt read when cached thread pool
+        }
+
+        AbstractFuture<V,A> result;
+        try {
+            begin();
+
+            int n;
+            if (attemptRead) {
+                if (isScatteringRead) {
+                    n = (int)IOUtil.read(fd, dsts, nd);
+                } else {
+                    n = IOUtil.read(fd, dsts[0], -1, nd, null);
+                }
+            } else {
+                n = IOStatus.UNAVAILABLE;
+            }
+
+            if (n == IOStatus.UNAVAILABLE) {
+                this.readBuffers = dsts;
+                this.scatteringRead = isScatteringRead;
+                result = new PendingFuture<V,A>(this, handler, attachment, OpType.READ);
+                setPendingRead((PendingFuture<Number,Object>)result);
+
+                // schedule timeout
+                if (timeout > 0L) {
+                    Future<?> timeoutTask =
+                        port.schedule(readTimeoutTask, timeout, unit);
+                    ((PendingFuture<V,A>)result).setTimeoutTask(timeoutTask);
+                }
+                return result;
+            }
+
+            // data available
+            enableReading();
+
+            // result type is Long or Integer
+            if (isScatteringRead) {
+                result = (CompletedFuture<V,A>)CompletedFuture
+                    .withResult(this, Long.valueOf(n), attachment);
+            } else {
+                result = (CompletedFuture<V,A>)CompletedFuture
+                    .withResult(this, Integer.valueOf(n), attachment);
+            }
+        } catch (Throwable x) {
+            enableReading();
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            result = CompletedFuture.withFailure(this, x, attachment);
+        } finally {
+            end();
+        }
+
+        if (invokeDirect) {
+            Invoker.invokeDirect(myGroupAndInvokeCount, handler, result);
+        } else {
+            Invoker.invokeIndirectly(handler, result);
+        }
+        return result;
+    }
+
+    // -- write --
+
+    private volatile ByteBuffer[] writeBuffers;
+    private volatile boolean gatheringWrite;
+
+    private void finishWrite(PendingFuture<Number,Object> result,
+                             boolean invokeDirect)
+    {
+        try {
+            begin();
+
+            ByteBuffer[] srcs = writeBuffers;
+            int n;
+            if (srcs.length == 1) {
+                n = IOUtil.write(fd, srcs[0], -1, nd, null);
+            } else {
+                n = (int)IOUtil.write(fd, srcs, nd);
+            }
+            if (n == IOStatus.UNAVAILABLE) {
+                // spurious wakeup, is this possible?
+                setPendingWrite(result);
+                return;
+            }
+
+            // allow buffer(s) to be GC'ed.
+            writeBuffers = null;
+
+            // allow another write to be initiated
+            boolean wasGatheringWrite = gatheringWrite;
+            enableWriting();
+
+            // result is a Long or Integer
+            if (wasGatheringWrite) {
+                result.setResult(Long.valueOf(n));
+            } else {
+                result.setResult(Integer.valueOf(n));
+            }
+
+        } catch (Throwable x) {
+            enableWriting();
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            result.setFailure(x);
+        } finally {
+            updateEvents();
+            end();
+        }
+        if (invokeDirect) {
+            Invoker.invoke(result.handler(), result);
+        } else {
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    }
+
+    private Runnable writeTimeoutTask = new Runnable() {
+        public void run() {
+            PendingFuture<Number,Object> result = grabPendingWrite();
+            if (result == null)
+                return;     // already completed
+
+            // kill further writing before releasing waiters
+            enableWriting(true);
+
+            // set completed and invoke handler
+            result.setFailure(new InterruptedByTimeoutException());
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    };
+
+
+    /**
+     * Initiates a read or scattering read operation
+     */
+
+    @SuppressWarnings("unchecked")
+    <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
+                                             boolean isGatheringWrite,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<V,? super A> handler)
+    {
+        Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+            Invoker.getGroupAndInvokeCount();
+        boolean invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
+        boolean attemptWrite = (handler == null) || invokeDirect ||
+            !port.isFixedThreadPool();  // okay to attempt read when cached thread pool
+
+        AbstractFuture<V,A> result;
+        try {
+            begin();
+
+            int n;
+            if (attemptWrite) {
+                if (isGatheringWrite) {
+                    n = (int)IOUtil.write(fd, srcs, nd);
+                } else {
+                    n = IOUtil.write(fd, srcs[0], -1, nd, null);
+                }
+            } else {
+                n = IOStatus.UNAVAILABLE;
+            }
+
+            if (n == IOStatus.UNAVAILABLE) {
+                this.writeBuffers = srcs;
+                this.gatheringWrite = isGatheringWrite;
+                result = new PendingFuture<V,A>(this, handler, attachment, OpType.WRITE);
+                setPendingWrite((PendingFuture<Number,Object>)result);
+
+                // schedule timeout
+                if (timeout > 0L) {
+                    Future<?> timeoutTask =
+                        port.schedule(writeTimeoutTask, timeout, unit);
+                    ((PendingFuture<V,A>)result).setTimeoutTask(timeoutTask);
+                }
+                return result;
+            }
+
+            // data available
+            enableWriting();
+            if (isGatheringWrite) {
+                result = (CompletedFuture<V,A>)CompletedFuture
+                    .withResult(this, Long.valueOf(n), attachment);
+            } else {
+                result = (CompletedFuture<V,A>)CompletedFuture
+                    .withResult(this, Integer.valueOf(n), attachment);
+            }
+        } catch (Throwable x) {
+            enableWriting();
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            result = CompletedFuture.withFailure(this, x, attachment);
+        } finally {
+            end();
+        }
+        if (invokeDirect) {
+            Invoker.invokeDirect(myGroupAndInvokeCount, handler, result);
+        } else {
+            Invoker.invokeIndirectly(handler, result);
+        }
+        return result;
+    }
+
+    // -- Native methods --
+
+    private static native void checkConnect(int fdVal) throws IOException;
+
+    static {
+        Util.load();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2007-2008 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.spi.FileSystemProvider;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+    private DefaultFileSystemProvider() { }
+
+    @SuppressWarnings("unchecked")
+    private static FileSystemProvider createProvider(final String cn) {
+        return AccessController
+            .doPrivileged(new PrivilegedAction<FileSystemProvider>() {
+                public FileSystemProvider run() {
+                    Class<FileSystemProvider> c;
+                    try {
+                        c = (Class<FileSystemProvider>)Class.forName(cn, true, null);
+                    } catch (ClassNotFoundException x) {
+                        throw new AssertionError(x);
+                    }
+                    try {
+                        return c.newInstance();
+                    } catch (IllegalAccessException x) {
+                        throw new AssertionError(x);
+                    } catch (InstantiationException x) {
+                        throw new AssertionError(x);
+                    }
+            }});
+    }
+
+    /**
+     * Returns the default FileSystemProvider.
+     */
+    public static FileSystemProvider create() {
+        String osname = AccessController
+            .doPrivileged(new GetPropertyAction("os.name"));
+        if (osname.equals("SunOS"))
+            return createProvider("sun.nio.fs.SolarisFileSystemProvider");
+        if (osname.equals("Linux"))
+            return createProvider("sun.nio.fs.LinuxFileSystemProvider");
+        throw new AssertionError("Platform not recognized");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2007-2008 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.spi.FileTypeDetector;
+
+public class DefaultFileTypeDetector {
+    private DefaultFileTypeDetector() { }
+
+    public static FileTypeDetector create() {
+        return new GnomeFileTypeDetector();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2007-2008 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.FileRef;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * File type detector that uses the GNOME I/O library or the deprecated
+ * GNOME VFS to guess the MIME type of a file.
+ */
+
+public class GnomeFileTypeDetector
+    extends AbstractFileTypeDetector
+{
+    // true if GIO available
+    private final boolean gioAvailable;
+
+    // true if GNOME VFS available and GIO is not available
+    private final boolean gnomeVfsAvailable;
+
+    public GnomeFileTypeDetector() {
+        gioAvailable = initializeGio();
+        if (gioAvailable) {
+            gnomeVfsAvailable = false;
+        } else {
+            gnomeVfsAvailable = initializeGnomeVfs();
+        }
+    }
+
+
+    public String implProbeContentType(FileRef obj) throws IOException {
+        if (!gioAvailable && !gnomeVfsAvailable)
+            return null;
+        if (!(obj instanceof UnixPath))
+            return null;
+
+        UnixPath path = (UnixPath)obj;
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
+        try {
+            if (gioAvailable) {
+                byte[] type = probeUsingGio(buffer.address());
+                return (type == null) ? null : new String(type);
+            } else {
+                byte[] type = probeUsingGnomeVfs(buffer.address());
+                if (type == null)
+                    return null;
+                String s = new String(type);
+                return s.equals("application/octet-stream") ? null : s;
+            }
+
+        } finally {
+            buffer.release();
+        }
+
+    }
+
+    // GIO
+    private static native boolean initializeGio();
+    private static native byte[] probeUsingGio(long pathAddress);
+
+    // GNOME VFS
+    private static native boolean initializeGnomeVfs();
+    private static native byte[] probeUsingGnomeVfs(long pathAddress);
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2007-2008 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.util.*;
+import java.util.concurrent.TimeUnit;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+/**
+ * Linux implementation of DosFileAttributeView for use on file systems such
+ * as ext3 that have extended attributes enabled and SAMBA configured to store
+ * DOS attributes.
+ */
+
+class LinuxDosFileAttributeView
+    extends UnixFileAttributeViews.Basic implements DosFileAttributeView
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private static final String READONLY_NAME = "readOnly";
+    private static final String ARCHIVE_NAME = "archive";
+    private static final String SYSTEM_NAME = "system";
+    private static final String HIDDEN_NAME = "hidden";
+
+    private static final String DOS_XATTR_NAME = "user.DOSATTRIB";
+    private static final byte[] DOS_XATTR_NAME_AS_BYTES = DOS_XATTR_NAME.getBytes();
+
+    private static final int DOS_XATTR_READONLY = 0x01;
+    private static final int DOS_XATTR_HIDDEN   = 0x02;
+    private static final int DOS_XATTR_SYSTEM   = 0x04;
+    private static final int DOS_XATTR_ARCHIVE  = 0x20;
+
+    LinuxDosFileAttributeView(UnixPath file, boolean followLinks) {
+        super(file, followLinks);
+    }
+
+
+    public String name() {
+        return "dos";
+    }
+
+
+    public Object getAttribute(String attribute) throws IOException {
+        if (attribute.equals(READONLY_NAME))
+            return readAttributes().isReadOnly();
+        if (attribute.equals(ARCHIVE_NAME))
+            return readAttributes().isArchive();
+        if (attribute.equals(SYSTEM_NAME))
+            return readAttributes().isSystem();
+        if (attribute.equals(HIDDEN_NAME))
+            return readAttributes().isHidden();
+        return super.getAttribute(attribute);
+    }
+
+
+    public void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        if (attribute.equals(READONLY_NAME)) {
+            setReadOnly((Boolean)value);
+            return;
+        }
+        if (attribute.equals(ARCHIVE_NAME)) {
+            setArchive((Boolean)value);
+            return;
+        }
+        if (attribute.equals(SYSTEM_NAME)) {
+            setSystem((Boolean)value);
+            return;
+        }
+        if (attribute.equals(HIDDEN_NAME)) {
+            setHidden((Boolean)value);
+            return;
+        }
+        super.setAttribute(attribute, value);
+    }
+
+
+    public Map<String,?> readAttributes(String first, String[] rest)
+        throws IOException
+    {
+        AttributesBuilder builder = AttributesBuilder.create(first, rest);
+        DosFileAttributes attrs = readAttributes();
+        addBasicAttributesToBuilder(attrs, builder);
+        if (builder.match(READONLY_NAME))
+            builder.add(READONLY_NAME, attrs.isReadOnly());
+        if (builder.match(ARCHIVE_NAME))
+            builder.add(ARCHIVE_NAME, attrs.isArchive());
+        if (builder.match(SYSTEM_NAME))
+            builder.add(SYSTEM_NAME, attrs.isSystem());
+        if (builder.match(HIDDEN_NAME))
+            builder.add(HIDDEN_NAME, attrs.isHidden());
+        return builder.unmodifiableMap();
+    }
+
+
+    public DosFileAttributes readAttributes() throws IOException {
+        file.checkRead();
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+             final UnixFileAttributes attrs = UnixFileAttributes.get(fd);
+             final int dosAttribute = getDosAttribute(fd);
+
+             return new DosFileAttributes() {
+
+                public long lastModifiedTime() {
+                    return attrs.lastModifiedTime();
+                }
+
+                public long lastAccessTime() {
+                    return attrs.lastAccessTime();
+                }
+
+                public long creationTime() {
+                    return attrs.creationTime();
+                }
+
+                public TimeUnit resolution() {
+                    return attrs.resolution();
+                }
+
+                public boolean isRegularFile() {
+                    return attrs.isRegularFile();
+                }
+
+                public boolean isDirectory() {
+                    return attrs.isDirectory();
+                }
+
+                public boolean isSymbolicLink() {
+                    return attrs.isSymbolicLink();
+                }
+
+                public boolean isOther() {
+                    return attrs.isOther();
+                }
+
+                public long size() {
+                    return attrs.size();
+                }
+
+                public int linkCount() {
+                    return attrs.linkCount();
+                }
+
+                public Object fileKey() {
+                    return attrs.fileKey();
+                }
+
+                public boolean isReadOnly() {
+                    return (dosAttribute & DOS_XATTR_READONLY) != 0;
+                }
+
+                public boolean isHidden() {
+                    return (dosAttribute & DOS_XATTR_HIDDEN) != 0;
+                }
+
+                public boolean isArchive() {
+                    return (dosAttribute & DOS_XATTR_ARCHIVE) != 0;
+                }
+
+                public boolean isSystem() {
+                    return (dosAttribute & DOS_XATTR_SYSTEM) != 0;
+                }
+             };
+
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+            return null;    // keep compiler happy
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public void setReadOnly(boolean value) throws IOException {
+        updateDosAttribute(DOS_XATTR_READONLY, value);
+    }
+
+
+    public void setHidden(boolean value) throws IOException {
+        updateDosAttribute(DOS_XATTR_HIDDEN, value);
+    }
+
+
+    public void setArchive(boolean value) throws IOException {
+        updateDosAttribute(DOS_XATTR_ARCHIVE, value);
+    }
+
+
+    public void setSystem(boolean value) throws IOException {
+        updateDosAttribute(DOS_XATTR_SYSTEM, value);
+    }
+
+    /**
+     * Reads the value of the user.DOSATTRIB extended attribute
+     */
+    private int getDosAttribute(int fd) throws UnixException {
+        final int size = 24;
+
+        NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
+        try {
+            int len = LinuxNativeDispatcher
+                .fgetxattr(fd, DOS_XATTR_NAME_AS_BYTES, buffer.address(), size);
+
+            if (len > 0) {
+                // ignore null terminator
+                if (unsafe.getByte(buffer.address()+len-1) == 0)
+                    len--;
+
+                // convert to String and parse
+                byte[] buf = new byte[len];
+                unsafe.copyMemory(null, buffer.address(), buf,
+                    Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
+                String value = new String(buf); // platform encoding
+
+                // should be something like 0x20
+                if (value.length() >= 3 && value.startsWith("0x")) {
+                    try {
+                        return Integer.parseInt(value.substring(2), 16);
+                    } catch (NumberFormatException x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+            throw new UnixException("Value of " + DOS_XATTR_NAME + " attribute is invalid");
+        } catch (UnixException x) {
+            // default value when attribute does not exist
+            if (x.errno() == ENODATA)
+                return 0;
+            throw x;
+        } finally {
+            buffer.release();
+        }
+    }
+
+    /**
+     * Updates the value of the user.DOSATTRIB extended attribute
+     */
+    private void updateDosAttribute(int flag, boolean enable) throws IOException {
+        file.checkWrite();
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            int oldValue = getDosAttribute(fd);
+            int newValue = oldValue;
+            if (enable) {
+                newValue |= flag;
+            } else {
+                newValue &= ~flag;
+            }
+            if (newValue != oldValue) {
+                byte[] value = ("0x" + Integer.toHexString(newValue)).getBytes();
+                NativeBuffer buffer = NativeBuffers.asNativeBuffer(value);
+                try {
+                    LinuxNativeDispatcher.fsetxattr(fd, DOS_XATTR_NAME_AS_BYTES,
+                        buffer.address(), value.length+1);
+                } finally {
+                    buffer.release();
+                }
+            }
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+        } finally {
+            close(fd);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2007-2008 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.*;
+import java.io.IOException;
+
+/**
+ * Linux implementation of FileStore
+ */
+
+class LinuxFileStore
+    extends UnixFileStore
+{
+    LinuxFileStore(UnixPath file) throws IOException {
+        super(file);
+    }
+
+    LinuxFileStore(UnixFileSystem fs, UnixMountEntry entry) {
+        super(fs, entry);
+    }
+
+    /**
+     * Finds, and returns, the mount entry for the file system where the file
+     * resides.
+     */
+
+    UnixMountEntry findMountEntry(UnixFileSystem fs) throws IOException {
+        // step 1: get realpath
+        UnixPath path = null;
+        try {
+            byte[] rp = UnixNativeDispatcher.realpath(file());
+            path = new UnixPath(fs, rp);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file());
+        }
+
+        // step 2: find mount point
+        UnixPath parent = path.getParent();
+        while (parent != null) {
+            UnixFileAttributes attrs = null;
+            try {
+                attrs = UnixFileAttributes.get(parent, true);
+            } catch (UnixException x) {
+                x.rethrowAsIOException(parent);
+            }
+            if (attrs.dev() != dev())
+                break;
+            path = parent;
+            parent = parent.getParent();
+        }
+
+        // step 3: lookup mounted file systems
+        byte[] dir = path.asByteArray();
+        for (UnixMountEntry entry: fs.getMountEntries()) {
+            if (Arrays.equals(dir, entry.dir()))
+                return entry;
+        }
+
+        throw new IOException("Mount point not found in mtab");
+    }
+
+
+    public boolean supportsFileAttributeView(String name) {
+        // support DosFileAttributeView and NamedAttributeView if extended
+        // attributes enabled
+        if (name.equals("dos") || name.equals("xattr")) {
+            // lookup fstypes.properties
+            FeatureStatus status = checkIfFeaturePresent("user_xattr");
+            if (status == FeatureStatus.PRESENT)
+                return true;
+            if (status == FeatureStatus.NOT_PRESENT)
+                return false;
+            return (entry().hasOption("user_xattr"));
+        }
+
+        return super.supportsFileAttributeView(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+import static sun.nio.fs.LinuxNativeDispatcher.*;
+
+/**
+ * Linux implementation of FileSystem
+ */
+
+class LinuxFileSystem extends UnixFileSystem {
+    private final int majorVersion;
+    private final int minorVersion;
+    private final int microVersion;
+
+    LinuxFileSystem(UnixFileSystemProvider provider, String dir) {
+        super(provider, dir);
+
+        // assume X.Y[-Z] format
+        String osversion = AccessController
+            .doPrivileged(new GetPropertyAction("os.version"));
+        String[] vers = osversion.split("\\.", 0);
+        if (vers.length >= 2) {
+            this.majorVersion = Integer.parseInt(vers[0]);
+            this.minorVersion = Integer.parseInt(vers[1]);
+            if (vers.length > 2) {
+                String[] microVers = vers[2].split("-", 0);
+                this.microVersion = (microVers.length > 0) ?
+                    Integer.parseInt(microVers[0]) : 0;
+            } else {
+                this.microVersion = 0;
+            }
+        } else {
+            throw new AssertionError();
+        }
+    }
+
+
+    public WatchService newWatchService()
+        throws IOException
+    {
+        // inotify available since 2.6.13
+        if ((majorVersion > 2) ||
+            (majorVersion == 2 && minorVersion > 6) ||
+            ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13)))
+        {
+            return new LinuxWatchService(this);
+        }
+
+        // use polling implementation on older kernels
+        return new PollingWatchService();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
+                                                                UnixPath file,
+                                                                LinkOption... options)
+    {
+        if (view == DosFileAttributeView.class)
+            return (V) new LinuxDosFileAttributeView(file, followLinks(options));
+        if (view == NamedAttributeView.class)
+            return (V) new LinuxNamedAttributeView(file, followLinks(options));
+        return super.newFileAttributeView(view, file, options);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public FileAttributeView newFileAttributeView(String name,
+                                                  UnixPath file,
+                                                  LinkOption... options)
+    {
+        if (name.equals("dos"))
+            return new LinuxDosFileAttributeView(file, followLinks(options));
+        if (name.equals("xattr"))
+            return new LinuxNamedAttributeView(file, followLinks(options));
+        return super.newFileAttributeView(name, file, options);
+    }
+
+    // lazy initialization of the list of supported attribute views
+    private static class LazyInitialization {
+        static final Set<String> supportedFileAttributeViews =
+            supportedFileAttributeViews();
+        private static Set<String> supportedFileAttributeViews() {
+            Set<String> result = new HashSet<String>();
+            result.addAll(UnixFileSystem.standardFileAttributeViews());
+            // additional Linux-specific views
+            result.add("dos");
+            result.add("xattr");
+            return Collections.unmodifiableSet(result);
+        }
+    }
+
+
+    public Set<String> supportedFileAttributeViews() {
+        return LazyInitialization.supportedFileAttributeViews;
+    }
+
+
+    void copyNonPosixAttributes(int ofd, int nfd) {
+        LinuxNamedAttributeView.copyExtendedAttributes(ofd, nfd);
+    }
+
+
+    boolean supportsSecureDirectoryStreams() {
+        // openat etc. available since 2.6.16
+        if ((majorVersion > 2) ||
+            (majorVersion == 2 && minorVersion > 6) ||
+            ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 16)))
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns object to iterate over entries in /etc/mtab
+     */
+
+    Iterable<UnixMountEntry> getMountEntries() {
+        ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
+        try {
+            long fp = setmntent("/etc/mtab".getBytes(), "r".getBytes());
+            try {
+                for (;;) {
+                    UnixMountEntry entry = new UnixMountEntry();
+                    int res = getextmntent(fp, entry);
+                    if (res < 0)
+                        break;
+                    entries.add(entry);
+                }
+            } finally {
+                endmntent(fp);
+            }
+
+        } catch (UnixException x) {
+            // nothing we can do
+        }
+        return entries;
+    }
+
+
+    FileStore getFileStore(UnixPath path) throws IOException {
+        return new LinuxFileStore(path);
+    }
+
+
+    FileStore getFileStore(UnixMountEntry entry) {
+        return new LinuxFileStore(this, entry);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007-2008 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;
+
+/**
+ * Linux implementation of FileSystemProvider
+ */
+
+public class LinuxFileSystemProvider extends UnixFileSystemProvider {
+    public LinuxFileSystemProvider() {
+        super();
+    }
+
+
+    LinuxFileSystem newFileSystem(String dir) {
+        return new LinuxFileSystem(this, dir);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNamedAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2007-2008 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 java.nio.ByteBuffer;
+import java.io.IOException;
+import java.util.*;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.UnixConstants.*;
+import static sun.nio.fs.LinuxNativeDispatcher.*;
+
+/**
+ * Linux implementation of NamedAttributeView using extended attributes.
+ */
+
+class LinuxNamedAttributeView
+    extends AbstractNamedAttributeView
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // maximum bytes in extended attribute name
+    private static final int XATTR_NAME_MAX = 255;
+
+    private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
+        byte[] bytes = name.getBytes();
+        if (bytes.length > XATTR_NAME_MAX) {
+            throw new FileSystemException(file.getPathForExecptionMessage(),
+                null, "'" + name + "' is too big");
+        }
+        return bytes;
+    }
+
+    // Parses buffer as array of NULL-terminated C strings.
+    private List<String> asList(long address, int size) {
+        final List<String> list = new ArrayList<String>();
+        int start = 0;
+        int pos = 0;
+        while (pos < size) {
+            if (unsafe.getByte(address + pos) == 0) {
+                int len = pos - start;
+                byte[] value = new byte[len];
+                unsafe.copyMemory(null, address+start, value,
+                    Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
+                list.add(new String(value));
+                start = pos + 1;
+            }
+            pos++;
+        }
+        return list;
+    }
+
+    private final UnixPath file;
+    private final boolean followLinks;
+
+    LinuxNamedAttributeView(UnixPath file, boolean followLinks) {
+        this.file = file;
+        this.followLinks = followLinks;
+    }
+
+
+    public List<String> list() throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        NativeBuffer buffer = null;
+        try {
+            int size = 1024;
+            buffer = NativeBuffers.getNativeBuffer(size);
+            for (;;) {
+                try {
+                    int n = flistxattr(fd, buffer.address(), size);
+                    List<String> list = asList(buffer.address(), n);
+                    return Collections.unmodifiableList(list);
+                } catch (UnixException x) {
+                    // allocate larger buffer if required
+                    if (x.errno() == ERANGE && size < 32*1024) {
+                        buffer.release();
+                        size *= 2;
+                        buffer = null;
+                        buffer = NativeBuffers.getNativeBuffer(size);
+                        continue;
+                    }
+                    throw new FileSystemException(file.getPathForExecptionMessage(),
+                        null, "Unable to get list of named attributes: " +
+                        x.getMessage());
+                }
+            }
+        } finally {
+            if (buffer != null)
+                buffer.release();
+            close(fd);
+        }
+    }
+
+
+    public int size(String name) throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            // fgetxattr returns size if called with size==0
+            return fgetxattr(fd, nameAsBytes(file,name), 0L, 0);
+        } catch (UnixException x) {
+            throw new FileSystemException(file.getPathForExecptionMessage(),
+                null, "Unable to get size of named attribute '" + name +
+                "': " + x.getMessage());
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public int read(String name, ByteBuffer dst) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        int pos = dst.position();
+        int lim = dst.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        NativeBuffer nb;
+        long address;
+        if (dst instanceof sun.nio.ch.DirectBuffer) {
+            nb = null;
+            address = ((sun.nio.ch.DirectBuffer)dst).address() + pos;
+        } else {
+            // substitute with native buffer
+            nb = NativeBuffers.getNativeBuffer(rem);
+            address = nb.address();
+        }
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                int n = fgetxattr(fd, nameAsBytes(file,name), address, rem);
+
+                // if remaining is zero then fgetxattr returns the size
+                if (rem == 0) {
+                    if (n > 0)
+                        throw new UnixException(ERANGE);
+                    return 0;
+                }
+
+                // copy from buffer into backing array if necessary
+                if (nb != null) {
+                    int off = dst.arrayOffset() + pos + Unsafe.ARRAY_BYTE_BASE_OFFSET;
+                    unsafe.copyMemory(null, address, dst.array(), off, n);
+                }
+                dst.position(pos + n);
+                return n;
+            } catch (UnixException x) {
+                String msg = (x.errno() == ERANGE) ?
+                    "Insufficient space in buffer" : x.getMessage();
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Error reading named attribute '" + name + "': " + msg);
+            } finally {
+                close(fd);
+            }
+        } finally {
+            if (nb != null)
+                nb.release();
+        }
+    }
+
+
+    public int write(String name, ByteBuffer src) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        int pos = src.position();
+        int lim = src.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        NativeBuffer nb;
+        long address;
+        if (src instanceof sun.nio.ch.DirectBuffer) {
+            nb = null;
+            address = ((sun.nio.ch.DirectBuffer)src).address() + pos;
+        } else {
+            // substitute with native buffer
+            nb = NativeBuffers.getNativeBuffer(rem);
+            address = nb.address();
+
+            if (src.hasArray()) {
+                // copy from backing array into buffer
+                int off = src.arrayOffset() + pos + Unsafe.ARRAY_BYTE_BASE_OFFSET;
+                unsafe.copyMemory(src.array(), off, null, address, rem);
+            } else {
+                // backing array not accessible so transfer via temporary array
+                byte[] tmp = new byte[rem];
+                src.get(tmp);
+                src.position(pos);  // reset position as write may fail
+                unsafe.copyMemory(tmp, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
+                    address, rem);
+            }
+        }
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                fsetxattr(fd, nameAsBytes(file,name), address, rem);
+                src.position(pos + rem);
+                return rem;
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Error writing named attribute '" + name + "': " +
+                    x.getMessage());
+            } finally {
+                close(fd);
+            }
+        } finally {
+            if (nb != null)
+                nb.release();
+        }
+    }
+
+
+    public void delete(String name) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            fremovexattr(fd, nameAsBytes(file,name));
+        } catch (UnixException x) {
+            throw new FileSystemException(file.getPathForExecptionMessage(),
+                null, "Unable to delete named attribute '" + name + "': " + x.getMessage());
+        } finally {
+            close(fd);
+        }
+    }
+
+    /**
+     * Used by copyTo/moveTo to copy extended attributes from source to target.
+     *
+     * @param   ofd
+     *          file descriptor for source file
+     * @param   nfd
+     *          file descriptor for target file
+     */
+    static void copyExtendedAttributes(int ofd, int nfd) {
+        NativeBuffer buffer = null;
+        try {
+
+            // call flistxattr to get list of extended attributes.
+            int size = 1024;
+            buffer = NativeBuffers.getNativeBuffer(size);
+            for (;;) {
+                try {
+                    size = flistxattr(ofd, buffer.address(), size);
+                    break;
+                } catch (UnixException x) {
+                    // allocate larger buffer if required
+                    if (x.errno() == ERANGE && size < 32*1024) {
+                        buffer.release();
+                        size *= 2;
+                        buffer = null;
+                        buffer = NativeBuffers.getNativeBuffer(size);
+                        continue;
+                    }
+
+                    // unable to get list of attributes
+                    return;
+                }
+            }
+
+            // parse buffer as array of NULL-terminated C strings.
+            long address = buffer.address();
+            int start = 0;
+            int pos = 0;
+            while (pos < size) {
+                if (unsafe.getByte(address + pos) == 0) {
+                    // extract attribute name and copy attribute to target.
+                    // FIXME: We can avoid needless copying by using address+pos
+                    // as the address of the name.
+                    int len = pos - start;
+                    byte[] name = new byte[len];
+                    unsafe.copyMemory(null, address+start, name,
+                        Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
+                    try {
+                        copyExtendedAttribute(ofd, name, nfd);
+                    } catch (UnixException ignore) {
+                        // ignore
+                    }
+                    start = pos + 1;
+                }
+                pos++;
+            }
+
+        } finally {
+            if (buffer != null)
+                buffer.release();
+        }
+    }
+
+    private static void copyExtendedAttribute(int ofd, byte[] name, int nfd)
+        throws UnixException
+    {
+        int size = fgetxattr(ofd, name, 0L, 0);
+        NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
+        try {
+            long address = buffer.address();
+            size = fgetxattr(ofd, name, address, size);
+            fsetxattr(nfd, name, address, size);
+        } finally {
+            buffer.release();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007-2008 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.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Linux specific system calls.
+ */
+
+class LinuxNativeDispatcher extends UnixNativeDispatcher {
+    private LinuxNativeDispatcher() { }
+
+   /**
+    * FILE *setmntent(const char *filename, const char *type);
+    */
+    static long setmntent(byte[] filename, byte[] type) throws UnixException {
+        NativeBuffer pathBuffer = NativeBuffers.asNativeBuffer(filename);
+        NativeBuffer typeBuffer = NativeBuffers.asNativeBuffer(type);
+        try {
+            return setmntent0(pathBuffer.address(), typeBuffer.address());
+        } finally {
+            typeBuffer.release();
+            pathBuffer.release();
+        }
+    }
+    private static native long setmntent0(long pathAddress, long typeAddress)
+        throws UnixException;
+
+   /**
+    * int endmntent(FILE* filep);
+    */
+    static native void endmntent(long stream) throws UnixException;
+
+    /**
+     * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size);
+     */
+    static int fgetxattr(int filedes, byte[] name, long valueAddress,
+                         int valueLen) throws UnixException
+    {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(name);
+        try {
+            return fgetxattr0(filedes, buffer.address(), valueAddress, valueLen);
+        } finally {
+            buffer.release();
+        }
+    }
+
+    private static native int fgetxattr0(int filedes, long nameAddress,
+        long valueAdddress, int valueLen) throws UnixException;
+
+    /**
+     *  fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags);
+     */
+    static void fsetxattr(int filedes, byte[] name, long valueAddress,
+        int valueLen) throws UnixException
+    {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(name);
+        try {
+            fsetxattr0(filedes, buffer.address(), valueAddress, valueLen);
+        } finally {
+            buffer.release();
+        }
+    }
+
+    private static native void fsetxattr0(int filedes, long nameAddress,
+        long valueAdddress, int valueLen) throws UnixException;
+
+
+    /**
+     * fremovexattr(int filedes, const char *name);
+     */
+    static void fremovexattr(int filedes, byte[] name) throws UnixException {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(name);
+        try {
+            fremovexattr0(filedes, buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+
+    private static native void fremovexattr0(int filedes, long nameAddress)
+        throws UnixException;
+
+    /**
+     * size_t flistxattr(int filedes, const char *list, size_t size)
+     */
+    static native int flistxattr(int filedes, long listAddress, int size)
+        throws UnixException;
+
+    // initialize
+    private static native void init();
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+        init();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2007-2008 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 java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+/**
+ * Linux implementation of WatchService based on inotify.
+ *
+ * In summary a background thread polls inotify plus a socket used for the wakeup
+ * mechanism. Requests to add or remove a watch, or close the watch service,
+ * cause the thread to wakeup and process the request. Events are processed
+ * by the thread which causes it to signal/queue the corresponding watch keys.
+ */
+
+class LinuxWatchService
+    extends AbstractWatchService
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // background thread to read change events
+    private final Poller poller;
+
+    LinuxWatchService(UnixFileSystem fs) throws IOException {
+        // initialize inotify
+        int ifd = - 1;
+        try {
+            ifd = inotifyInit();
+        } catch (UnixException x) {
+            throw new IOException(x.errorString());
+        }
+
+        // configure inotify to be non-blocking
+        // create socketpair used in the close mechanism
+        int sp[] = new int[2];
+        try {
+            configureBlocking(ifd, false);
+            socketpair(sp);
+            configureBlocking(sp[0], false);
+        } catch (UnixException x) {
+            UnixNativeDispatcher.close(ifd);
+            throw new IOException(x.errorString());
+        }
+
+        this.poller = new Poller(fs, this, ifd, sp);
+        this.poller.start();
+    }
+
+
+    WatchKey register(Path dir,
+                      WatchEvent.Kind<?>[] events,
+                      WatchEvent.Modifier... modifiers)
+         throws IOException
+    {
+        // delegate to poller
+        return poller.register(dir, events, modifiers);
+    }
+
+
+    void implClose() throws IOException {
+        // delegate to poller
+        poller.close();
+    }
+
+    /**
+     * WatchKey implementation
+     */
+    private class LinuxWatchKey extends AbstractWatchKey {
+        // inotify descriptor
+        private final int ifd;
+        // watch descriptor
+        private volatile int wd;
+
+        LinuxWatchKey(LinuxWatchService watcher, int ifd, int wd) {
+            super(watcher);
+            this.ifd = ifd;
+            this.wd = wd;
+        }
+
+        int descriptor() {
+            return wd;
+        }
+
+        void invalidate(boolean remove) {
+            if (remove) {
+                try {
+                    inotifyRmWatch(ifd, wd);
+                } catch (UnixException x) {
+                    // ignore
+                }
+            }
+            wd = -1;
+        }
+
+
+        public boolean isValid() {
+            return (wd != -1);
+        }
+
+
+        public void cancel() {
+            if (isValid()) {
+                // delegate to poller
+                poller.cancel(this);
+            }
+        }
+    }
+
+    /**
+     * Background thread to read from inotify
+     */
+    private class Poller extends AbstractPoller {
+        /**
+         * struct inotify_event {
+         *     int          wd;
+         *     uint32_t     mask;
+         *     uint32_t     len;
+         *     char name    __flexarr;  // present if len > 0
+         * } act_t;
+         */
+        private static final short SIZEOF_INOTIFY_EVENT = 16;
+        private static final short OFFSETOF_WD          = 0;
+        private static final short OFFSETOF_MASK        = 4;
+        private static final short OFFSETOF_LEN         = 12;
+        private static final short OFFSETOF_NAME        = 16;
+
+        private static final int IN_MODIFY          = 0x00000002;
+        private static final int IN_ATTRIB          = 0x00000004;
+        private static final int IN_MOVED_FROM      = 0x00000040;
+        private static final int IN_MOVED_TO        = 0x00000080;
+        private static final int IN_CREATE          = 0x00000100;
+        private static final int IN_DELETE          = 0x00000200;
+
+        private static final int IN_UNMOUNT         = 0x00002000;
+        private static final int IN_Q_OVERFLOW      = 0x00004000;
+        private static final int IN_IGNORED         = 0x00008000;
+
+        private static final int IN_ISDIR           = 0x40000000;
+        private static final int IN_MASK_ADD        = 0x20000000;
+
+        // sizeof buffer for when polling inotify
+        private static final int BUFFER_SIZE = 8192;
+
+        private final UnixFileSystem fs;
+        private final LinuxWatchService watcher;
+
+        // inotify file descriptor
+        private final int ifd;
+        // socketpair used to shutdown polling thread
+        private final int socketpair[];
+        // maps watch descriptor to Key
+        private final Map<Integer,LinuxWatchKey> wdToKey;
+        // address of read buffer
+        private final long address;
+
+        Poller(UnixFileSystem fs, LinuxWatchService watcher, int ifd, int[] sp) {
+            this.fs = fs;
+            this.watcher = watcher;
+            this.ifd = ifd;
+            this.socketpair = sp;
+            this.wdToKey = new HashMap<Integer,LinuxWatchKey>();
+            this.address = unsafe.allocateMemory(BUFFER_SIZE);
+        }
+
+
+        void wakeup() throws IOException {
+            // write to socketpair to wakeup polling thread
+            try {
+                write(socketpair[1], address, 1);
+            } catch (UnixException x) {
+                throw new IOException(x.errorString());
+            }
+        }
+
+
+        Object implRegister(Path obj,
+                            Set<? extends WatchEvent.Kind<?>> events,
+                            WatchEvent.Modifier... modifiers)
+        {
+            UnixPath dir = (UnixPath)obj;
+
+            int mask = 0;
+            for (WatchEvent.Kind<?> event: events) {
+                if (event == StandardWatchEventKind.ENTRY_CREATE) {
+                    mask |= IN_CREATE | IN_MOVED_TO;
+                    continue;
+                }
+                if (event == StandardWatchEventKind.ENTRY_DELETE) {
+                    mask |= IN_DELETE | IN_MOVED_FROM;
+                    continue;
+                }
+                if (event == StandardWatchEventKind.ENTRY_MODIFY) {
+                    mask |= IN_MODIFY | IN_ATTRIB;
+                    continue;
+                }
+            }
+
+            // no modifiers supported at this time
+            if (modifiers.length > 0) {
+                if (modifiers[0] == null)
+                    return new NullPointerException();
+                return new UnsupportedOperationException("Modifier not supported");
+            }
+
+            // check file is directory
+            UnixFileAttributes attrs = null;
+            try {
+                attrs = UnixFileAttributes.get(dir, true);
+            } catch (UnixException x) {
+                return x.asIOException(dir);
+            }
+            if (!attrs.isDirectory()) {
+                return new NotDirectoryException(dir.getPathForExecptionMessage());
+            }
+
+            // register with inotify (replaces existing mask if already registered)
+            int wd = -1;
+            try {
+                NativeBuffer buffer =
+                    NativeBuffers.asNativeBuffer(dir.getByteArrayForSysCalls());
+                try {
+                    wd = inotifyAddWatch(ifd, buffer.address(), mask);
+                } finally {
+                    buffer.release();
+                }
+            } catch (UnixException x) {
+                if (x.errno() == ENOSPC) {
+                    return new IOException("User limit of inotify watches reached");
+                }
+                return x.asIOException(dir);
+            }
+
+            // ensure watch descriptor is in map
+            LinuxWatchKey key = wdToKey.get(wd);
+            if (key == null) {
+                key = new LinuxWatchKey(watcher, ifd, wd);
+                wdToKey.put(wd, key);
+            }
+            return key;
+        }
+
+        // cancel single key
+
+        void implCancelKey(WatchKey obj) {
+            LinuxWatchKey key = (LinuxWatchKey)obj;
+            if (key.isValid()) {
+                wdToKey.remove(key.descriptor());
+                key.invalidate(true);
+            }
+        }
+
+        // close watch service
+
+        void implCloseAll() {
+            // invalidate all keys
+            for (Integer d: wdToKey.keySet()) {
+                LinuxWatchKey key = wdToKey.get(d);
+                if (key != null) {
+                    key.invalidate(true);
+                }
+            }
+            wdToKey.clear();
+
+            // free resources
+            unsafe.freeMemory(address);
+            UnixNativeDispatcher.close(socketpair[0]);
+            UnixNativeDispatcher.close(socketpair[1]);
+            UnixNativeDispatcher.close(ifd);
+        }
+
+        /**
+         * Poller main loop
+         */
+
+        public void run() {
+            try {
+                for (;;) {
+                    int n;
+
+                    // wait for close or inotify event
+                    n = poll(ifd, socketpair[0]);
+                    if (n == 0) {
+                        continue; // spurious wakeup?
+                    }
+
+                    // process any pending requests
+                    try {
+                        n = read(socketpair[0], address, BUFFER_SIZE);
+                        boolean shutdown = processRequests();
+                        if (shutdown)
+                            break;
+                    } catch (UnixException x) {
+                        if (x.errno() != UnixConstants.EAGAIN)
+                            throw x;
+                    }
+
+                    // read from inotify
+                    try {
+                        n = read(ifd, address, BUFFER_SIZE);
+                    } catch (UnixException x) {
+                        if (x.errno() == EAGAIN)
+                            continue;
+                        throw x;
+                    }
+
+                    // iterate over buffer to decode events
+                    int offset = 0;
+                    while (offset < n) {
+                        long event = address + offset;
+                        int wd = unsafe.getInt(event + OFFSETOF_WD);
+                        int mask = unsafe.getInt(event + OFFSETOF_MASK);
+                        int len = unsafe.getInt(event + OFFSETOF_LEN);
+
+                        // file name
+                        UnixPath name = null;
+                        if (len > 0) {
+                            int actual = len;
+
+                            // null-terminated and maybe additional null bytes to
+                            // align the next event
+                            while (actual > 0) {
+                                long last = event + OFFSETOF_NAME + actual - 1;
+                                if (unsafe.getByte(last) != 0)
+                                    break;
+                                actual--;
+                            }
+                            if (actual > 0) {
+                                byte[] buf = new byte[actual];
+                                unsafe.copyMemory(null, event + OFFSETOF_NAME,
+                                    buf, Unsafe.ARRAY_BYTE_BASE_OFFSET, actual);
+                                name = new UnixPath(fs, buf);
+                            }
+                        }
+
+                        // process event
+                        processEvent(wd, mask, name);
+
+                        offset += (SIZEOF_INOTIFY_EVENT + len);
+                    }
+                }
+            } catch (UnixException x) {
+                x.printStackTrace();
+            }
+        }
+
+
+        /**
+         * map inotify event to WatchEvent.Kind
+         */
+        private WatchEvent.Kind<?> maskToEventKind(int mask) {
+            if ((mask & IN_MODIFY) > 0)
+                return StandardWatchEventKind.ENTRY_MODIFY;
+            if ((mask & IN_ATTRIB) > 0)
+                return StandardWatchEventKind.ENTRY_MODIFY;
+            if ((mask & IN_CREATE) > 0)
+                return StandardWatchEventKind.ENTRY_CREATE;
+            if ((mask & IN_MOVED_TO) > 0)
+                return StandardWatchEventKind.ENTRY_CREATE;
+            if ((mask & IN_DELETE) > 0)
+                return StandardWatchEventKind.ENTRY_DELETE;
+            if ((mask & IN_MOVED_FROM) > 0)
+                return StandardWatchEventKind.ENTRY_DELETE;
+            return null;
+        }
+
+        /**
+         * Process event from inotify
+         */
+        private void processEvent(int wd, int mask, final UnixPath name) {
+            // overflow - signal all keys
+            if ((mask & IN_Q_OVERFLOW) > 0) {
+                for (Integer d: wdToKey.keySet()) {
+                    LinuxWatchKey key = wdToKey.get(d);
+                    if (key != null) {
+                        key.signalEvent(StandardWatchEventKind.OVERFLOW, null);
+                    }
+                }
+                return;
+            }
+
+            // lookup wd to get key
+            LinuxWatchKey key = wdToKey.get(wd);
+            if (key == null)
+                return; // should not happen
+
+            // file deleted
+            if ((mask & IN_IGNORED) > 0) {
+                wdToKey.remove(wd);
+                key.invalidate(false);
+                key.signal();
+                return;
+            }
+
+            // event for directory itself
+            if (name == null)
+                return;
+
+            // map to event and queue to key
+            WatchEvent.Kind<?> kind = maskToEventKind(mask);
+            if (kind != null) {
+                key.signalEvent(kind, name);
+            }
+        }
+    }
+
+    // -- native methods --
+
+    private static native void init();
+
+    private static native int inotifyInit() throws UnixException;
+
+    private static native int inotifyAddWatch(int fd, long pathAddress, int mask)
+        throws UnixException;
+
+    private static native void inotifyRmWatch(int fd, int wd)
+        throws UnixException;
+
+    private static native void configureBlocking(int fd, boolean blocking)
+        throws UnixException;
+
+    private static native void socketpair(int[] sv) throws UnixException;
+
+    private static native int poll(int fd1, int fd2) throws UnixException;
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+        init();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.util.*;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.UnixConstants.*;
+import static sun.nio.fs.SolarisConstants.*;
+import static sun.nio.fs.SolarisNativeDispatcher.*;
+
+
+/**
+ * Solaris implementation of AclFileAttributeView with native support for
+ * NFSv4 ACLs on ZFS.
+ */
+
+class SolarisAclFileAttributeView
+    extends AbstractAclFileAttributeView
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // Maximum number of entries allowed in an ACL
+    private static final int MAX_ACL_ENTRIES = 1024;
+
+    /**
+     * typedef struct ace {
+     *     uid_t        a_who;
+     *     uitn32_t     a_access_mark;
+     *     uint16_t     a_flags;
+     *     uint16_t     a_type;
+     * } act_t;
+     */
+    private static final short SIZEOF_ACE_T     = 12;
+    private static final short OFFSETOF_UID     = 0;
+    private static final short OFFSETOF_MASK    = 4;
+    private static final short OFFSETOF_FLAGS   = 8;
+    private static final short OFFSETOF_TYPE    = 10;
+
+    private final UnixPath file;
+    private final boolean followLinks;
+
+    SolarisAclFileAttributeView(UnixPath file, boolean followLinks) {
+        this.file = file;
+        this.followLinks = followLinks;
+    }
+
+    /**
+     * Permission checks to access file
+     */
+    private void checkAccess(UnixPath file,
+                             boolean checkRead,
+                             boolean checkWrite)
+    {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (checkRead)
+                file.checkRead();
+            if (checkWrite)
+                file.checkWrite();
+            sm.checkPermission(new RuntimePermission("accessUserInformation"));
+        }
+    }
+
+    /**
+     * Encode the ACL to the given buffer
+     */
+    private static void encode(List<AclEntry> acl, long address) {
+        long offset = address;
+        for (AclEntry ace: acl) {
+            int flags = 0;
+
+            // map UserPrincipal to uid and flags
+            UserPrincipal who = ace.principal();
+            if (!(who instanceof UnixUserPrincipals))
+                throw new ProviderMismatchException();
+            UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
+            int uid;
+            if (user.isSpecial()) {
+                uid = -1;
+                if (who.getName().equals(UnixUserPrincipals.SPECIAL_OWNER.getName()))
+                    flags |= ACE_OWNER;
+                else if (who.getName().equals(UnixUserPrincipals.SPECIAL_GROUP.getName()))
+                    flags |= ACE_GROUP;
+                else if (who.getName().equals(UnixUserPrincipals.SPECIAL_EVERYONE.getName()))
+                    flags |= ACE_EVERYONE;
+                else
+                    throw new AssertionError("Unable to map special identifier");
+            } else {
+                if (user instanceof UnixUserPrincipals.Group) {
+                    uid = user.gid();
+                    flags |= ACE_IDENTIFIER_GROUP;
+                } else {
+                    uid = user.uid();
+                }
+            }
+
+            // map ACE type
+            int type;
+            switch (ace.type()) {
+                case ALLOW:
+                    type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+                    break;
+                case DENY:
+                    type = ACE_ACCESS_DENIED_ACE_TYPE;
+                    break;
+                case AUDIT:
+                    type = ACE_SYSTEM_AUDIT_ACE_TYPE;
+                    break;
+                case ALARM:
+                    type = ACE_SYSTEM_ALARM_ACE_TYPE;
+                    break;
+                default:
+                    throw new AssertionError("Unable to map ACE type");
+            }
+
+            // map permissions
+            Set<AclEntryPermission> aceMask = ace.permissions();
+            int mask = 0;
+            if (aceMask.contains(AclEntryPermission.READ_DATA))
+                mask |= ACE_READ_DATA;
+            if (aceMask.contains(AclEntryPermission.WRITE_DATA))
+                mask |= ACE_WRITE_DATA;
+            if (aceMask.contains(AclEntryPermission.APPEND_DATA))
+                mask |= ACE_APPEND_DATA;
+            if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS))
+                mask |= ACE_READ_NAMED_ATTRS;
+            if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS))
+                mask |= ACE_WRITE_NAMED_ATTRS;
+            if (aceMask.contains(AclEntryPermission.EXECUTE))
+                mask |= ACE_EXECUTE;
+            if (aceMask.contains(AclEntryPermission.DELETE_CHILD))
+                mask |= ACE_DELETE_CHILD;
+            if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES))
+                mask |= ACE_READ_ATTRIBUTES;
+            if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES))
+                mask |= ACE_WRITE_ATTRIBUTES;
+            if (aceMask.contains(AclEntryPermission.DELETE))
+                mask |= ACE_DELETE;
+            if (aceMask.contains(AclEntryPermission.READ_ACL))
+                mask |= ACE_READ_ACL;
+            if (aceMask.contains(AclEntryPermission.WRITE_ACL))
+                mask |= ACE_WRITE_ACL;
+            if (aceMask.contains(AclEntryPermission.WRITE_OWNER))
+                mask |= ACE_WRITE_OWNER;
+            if (aceMask.contains(AclEntryPermission.SYNCHRONIZE))
+                mask |= ACE_SYNCHRONIZE;
+
+            // FIXME - it would be desirable to know here if the file is a
+            // directory or not. Solaris returns EINVAL if an ACE has a directory
+            // -only flag and the file is not a directory.
+            Set<AclEntryFlag> aceFlags = ace.flags();
+            if (aceFlags.contains(AclEntryFlag.FILE_INHERIT))
+                flags |= ACE_FILE_INHERIT_ACE;
+            if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT))
+                flags |= ACE_DIRECTORY_INHERIT_ACE;
+            if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
+                flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
+            if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY))
+                flags |= ACE_INHERIT_ONLY_ACE;
+
+            unsafe.putInt(offset + OFFSETOF_UID, uid);
+            unsafe.putInt(offset + OFFSETOF_MASK, mask);
+            unsafe.putShort(offset + OFFSETOF_FLAGS, (short)flags);
+            unsafe.putShort(offset + OFFSETOF_TYPE, (short)type);
+
+            offset += SIZEOF_ACE_T;
+        }
+    }
+
+    /**
+     * Decode the buffer, returning an ACL
+     */
+    private static List<AclEntry> decode(long address, int n) {
+        ArrayList<AclEntry> acl = new ArrayList<AclEntry>(n);
+        for (int i=0; i<n; i++) {
+            long offset = address + i*SIZEOF_ACE_T;
+
+            int uid = unsafe.getInt(offset + OFFSETOF_UID);
+            int mask = unsafe.getInt(offset + OFFSETOF_MASK);
+            int flags = (int)unsafe.getShort(offset + OFFSETOF_FLAGS);
+            int type = (int)unsafe.getShort(offset + OFFSETOF_TYPE);
+
+            // map uid and flags to UserPrincipal
+            UnixUserPrincipals.User who = null;
+            if (uid == -1) {
+                if ((flags & ACE_OWNER) > 0)
+                    who = UnixUserPrincipals.SPECIAL_OWNER;
+                if ((flags & ACE_GROUP) > 0)
+                    who = UnixUserPrincipals.SPECIAL_GROUP;
+                if ((flags & ACE_EVERYONE) > 0)
+                    who = UnixUserPrincipals.SPECIAL_EVERYONE;
+                if (who == null)
+                    throw new AssertionError("ACE who not handled");
+            } else {
+                // can be gid
+                if ((flags & ACE_IDENTIFIER_GROUP) > 0)
+                    who = UnixUserPrincipals.fromGid(uid);
+                else
+                    who = UnixUserPrincipals.fromUid(uid);
+            }
+
+            AclEntryType aceType = null;
+            switch (type) {
+                case ACE_ACCESS_ALLOWED_ACE_TYPE:
+                    aceType = AclEntryType.ALLOW;
+                    break;
+                case ACE_ACCESS_DENIED_ACE_TYPE:
+                    aceType = AclEntryType.DENY;
+                    break;
+                case ACE_SYSTEM_AUDIT_ACE_TYPE:
+                    aceType = AclEntryType.AUDIT;
+                    break;
+                case ACE_SYSTEM_ALARM_ACE_TYPE:
+                    aceType = AclEntryType.ALARM;
+                    break;
+                default:
+                    assert false;
+            }
+
+            HashSet<AclEntryPermission> aceMask = new HashSet<AclEntryPermission>();
+            if ((mask & ACE_READ_DATA) > 0)
+                aceMask.add(AclEntryPermission.READ_DATA);
+            if ((mask & ACE_WRITE_DATA) > 0)
+                aceMask.add(AclEntryPermission.WRITE_DATA);
+            if ((mask & ACE_APPEND_DATA ) > 0)
+                aceMask.add(AclEntryPermission.APPEND_DATA);
+            if ((mask & ACE_READ_NAMED_ATTRS) > 0)
+                aceMask.add(AclEntryPermission.READ_NAMED_ATTRS);
+            if ((mask & ACE_WRITE_NAMED_ATTRS) > 0)
+                aceMask.add(AclEntryPermission.WRITE_NAMED_ATTRS);
+            if ((mask & ACE_EXECUTE) > 0)
+                aceMask.add(AclEntryPermission.EXECUTE);
+            if ((mask & ACE_DELETE_CHILD ) > 0)
+                aceMask.add(AclEntryPermission.DELETE_CHILD);
+            if ((mask & ACE_READ_ATTRIBUTES) > 0)
+                aceMask.add(AclEntryPermission.READ_ATTRIBUTES);
+            if ((mask & ACE_WRITE_ATTRIBUTES) > 0)
+                aceMask.add(AclEntryPermission.WRITE_ATTRIBUTES);
+            if ((mask & ACE_DELETE) > 0)
+                aceMask.add(AclEntryPermission.DELETE);
+            if ((mask & ACE_READ_ACL) > 0)
+                aceMask.add(AclEntryPermission.READ_ACL);
+            if ((mask & ACE_WRITE_ACL) > 0)
+                aceMask.add(AclEntryPermission.WRITE_ACL);
+            if ((mask & ACE_WRITE_OWNER) > 0)
+                aceMask.add(AclEntryPermission.WRITE_OWNER);
+            if ((mask & ACE_SYNCHRONIZE) > 0)
+                aceMask.add(AclEntryPermission.SYNCHRONIZE);
+
+            HashSet<AclEntryFlag> aceFlags = new HashSet<AclEntryFlag>();
+            if ((flags & ACE_FILE_INHERIT_ACE) > 0)
+                aceFlags.add(AclEntryFlag.FILE_INHERIT);
+            if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0)
+                aceFlags.add(AclEntryFlag.DIRECTORY_INHERIT);
+            if ((flags & ACE_NO_PROPAGATE_INHERIT_ACE) > 0)
+                aceFlags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
+            if ((flags & ACE_INHERIT_ONLY_ACE ) > 0)
+                aceFlags.add(AclEntryFlag.INHERIT_ONLY);
+
+            // build the ACL entry and add it to the list
+            AclEntry ace = AclEntry.newBuilder()
+                .setType(aceType)
+                .setPrincipal(who)
+                .setPermissions(aceMask).setFlags(aceFlags).build();
+            acl.add(ace);
+        }
+
+        return acl;
+    }
+
+    // Retrns true if NFSv4 ACLs not enabled on file system
+    private static boolean isAclsEnabled(int fd) {
+        try {
+            long enabled = fpathconf(fd, _PC_ACL_ENABLED);
+            if (enabled == _ACL_ACE_ENABLED)
+                return true;
+        } catch (UnixException x) {
+        }
+        return false;
+    }
+
+
+    public List<AclEntry> getAcl()
+        throws IOException
+    {
+        // permission check
+        checkAccess(file, true, false);
+
+        // open file (will fail if file is a link and not following links)
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES);
+            try {
+                // read ACL and decode it
+                int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address);
+                assert n >= 0;
+                return decode(address, n);
+            } catch (UnixException x) {
+                if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
+                    throw new FileSystemException(file.getPathForExecptionMessage(),
+                        null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
+                }
+                x.rethrowAsIOException(file);
+                return null;    // keep compiler happy
+            } finally {
+                unsafe.freeMemory(address);
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public void setAcl(List<AclEntry> acl) throws IOException {
+        // permission check
+        checkAccess(file, false, true);
+
+        // open file (will fail if file is a link and not following links)
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            // SECURITY: need to copy list as can change during processing
+            acl = new ArrayList<AclEntry>(acl);
+            int n = acl.size();
+
+            long address = unsafe.allocateMemory(SIZEOF_ACE_T * n);
+            try {
+                encode(acl, address);
+                facl(fd, ACE_SETACL, n, address);
+            } catch (UnixException x) {
+                if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
+                    throw new FileSystemException(file.getPathForExecptionMessage(),
+                        null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
+                }
+                if (x.errno() == EINVAL && (n < 3))
+                    throw new IOException("ACL must contain at least 3 entries");
+                x.rethrowAsIOException(file);
+            } finally {
+                unsafe.freeMemory(address);
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public UserPrincipal getOwner()
+        throws IOException
+    {
+        checkAccess(file, true, false);
+
+        try {
+            UnixFileAttributes attrs =
+                UnixFileAttributes.get(file, followLinks);
+            return UnixUserPrincipals.fromUid(attrs.uid());
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+            return null; // keep compile happy
+        }
+    }
+
+
+    public void setOwner(UserPrincipal owner) throws IOException {
+        checkAccess(file, true, false);
+
+        if (!(owner instanceof UnixUserPrincipals.User))
+            throw new ProviderMismatchException();
+        if (owner instanceof UnixUserPrincipals.Group)
+            throw new IOException("'owner' parameter is a group");
+        int uid = ((UnixUserPrincipals.User)owner).uid();
+
+        try {
+            if (followLinks) {
+                lchown(file, uid, -1);
+            } else {
+                chown(file, uid, -1);
+            }
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.io.IOException;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.SolarisConstants.*;
+
+/**
+ * Solaris implementation of FileStore
+ */
+
+class SolarisFileStore
+    extends UnixFileStore
+{
+    private final boolean xattrEnabled;
+
+    SolarisFileStore(UnixPath file) throws IOException {
+        super(file);
+        this.xattrEnabled = xattrEnabled();
+    }
+
+    SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) {
+        super(fs, entry);
+        this.xattrEnabled = xattrEnabled();
+    }
+
+    // returns true if extended attributes enabled
+    private boolean xattrEnabled() {
+        long res = 0L;
+        try {
+            res = pathconf(file(), _PC_XATTR_ENABLED);
+        } catch (UnixException x) {
+            // ignore
+        }
+        return (res != 0L);
+    }
+
+
+    UnixMountEntry findMountEntry(UnixFileSystem fs) throws IOException {
+        // On Solaris iterate over the entries in the mount table to find device
+        for (UnixMountEntry entry: fs.getMountEntries()) {
+            if (entry.dev() == dev()) {
+                return entry;
+            }
+        }
+        throw new IOException("Device not found in mnttab");
+    }
+
+
+    public boolean supportsFileAttributeView(String name) {
+        if (name.equals("acl")) {
+            // lookup fstypes.properties
+            FeatureStatus status = checkIfFeaturePresent("nfsv4acl");
+            if (status == FeatureStatus.PRESENT)
+                return true;
+            if (status == FeatureStatus.NOT_PRESENT)
+                return false;
+            // AclFileAttributeView available on ZFS
+            return (type().equals("zfs"));
+        }
+        if (name.equals("xattr")) {
+            // lookup fstypes.properties
+            FeatureStatus status = checkIfFeaturePresent("xattr");
+            if (status == FeatureStatus.PRESENT)
+                return true;
+            if (status == FeatureStatus.NOT_PRESENT)
+                return false;
+            return xattrEnabled;
+        }
+
+        return super.supportsFileAttributeView(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+import static sun.nio.fs.UnixNativeDispatcher.*;
+
+/**
+ * Solaris implementation of FileSystem
+ */
+
+class SolarisFileSystem extends UnixFileSystem {
+    private final int majorVersion;
+    private final int minorVersion;
+
+    SolarisFileSystem(UnixFileSystemProvider provider, String dir) {
+        super(provider, dir);
+
+        String osversion = AccessController
+            .doPrivileged(new GetPropertyAction("os.version"));
+        String[] vers = osversion.split("\\.", 0);
+        if (vers.length >= 2) {
+            this.majorVersion = Integer.parseInt(vers[0]);
+            this.minorVersion = Integer.parseInt(vers[1]);
+        } else {
+            // should not get here
+            throw new AssertionError();
+        }
+
+        // O_NOFOLLOW not supported prior to Solaris 10
+        if ((majorVersion < 5) || (majorVersion == 5 && minorVersion < 10))
+            throw new RuntimeException("Need Solaris 10 or greater");
+    }
+
+    private boolean hasSolaris11Features() {
+        if (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    boolean isSolaris() {
+        return true;
+    }
+
+
+    public WatchService newWatchService()
+        throws IOException
+    {
+        // FEN available since Solaris 11
+        if (hasSolaris11Features()) {
+            return new SolarisWatchService(this);
+        } else {
+            return new PollingWatchService();
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
+                                                                UnixPath file, LinkOption... options)
+    {
+        if (view == AclFileAttributeView.class)
+            return (V) new SolarisAclFileAttributeView(file, followLinks(options));
+        if (view == NamedAttributeView.class) {
+            return(V) new SolarisNamedAttributeView(file, followLinks(options));
+        }
+        return super.newFileAttributeView(view, file, options);
+    }
+
+
+    protected FileAttributeView newFileAttributeView(String name,
+                                                     UnixPath file,
+                                                     LinkOption... options)
+    {
+        if (name.equals("acl"))
+            return new SolarisAclFileAttributeView(file, followLinks(options));
+        if (name.equals("xattr"))
+            return new SolarisNamedAttributeView(file, followLinks(options));
+        return super.newFileAttributeView(name, file, options);
+    }
+
+    // lazy initialization of the list of supported attribute views
+    private static class LazyInitialization {
+        static final Set<String> supportedFileAttributeViews =
+            supportedFileAttributeViews();
+        private static Set<String> supportedFileAttributeViews() {
+            Set<String> result = new HashSet<String>();
+            result.addAll(UnixFileSystem.standardFileAttributeViews());
+            // additional Solaris-specific views
+            result.add("acl");
+            result.add("xattr");
+            return Collections.unmodifiableSet(result);
+        }
+    }
+
+
+    public Set<String> supportedFileAttributeViews() {
+        return LazyInitialization.supportedFileAttributeViews;
+    }
+
+
+    void copyNonPosixAttributes(int ofd, int nfd) {
+        SolarisNamedAttributeView.copyExtendedAttributes(ofd, nfd);
+        // TDB: copy ACL from source to target
+    }
+
+
+    boolean supportsSecureDirectoryStreams() {
+        return true;
+    }
+
+    /**
+     * Returns object to iterate over entries in /etc/mnttab
+     */
+
+    Iterable<UnixMountEntry> getMountEntries() {
+        ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
+        try {
+            UnixPath mnttab = new UnixPath(this, "/etc/mnttab");
+            long fp = fopen(mnttab, "r");
+            try {
+                for (;;) {
+                    UnixMountEntry entry = new UnixMountEntry();
+                    int res = getextmntent(fp, entry);
+                    if (res < 0)
+                        break;
+                    entries.add(entry);
+                }
+            } finally {
+                fclose(fp);
+            }
+        } catch (UnixException x) {
+            // nothing we can do
+        }
+        return entries;
+    }
+
+
+    FileStore getFileStore(UnixPath path) throws IOException {
+        return new SolarisFileStore(path);
+    }
+
+
+    FileStore getFileStore(UnixMountEntry entry) {
+        return new SolarisFileStore(this, entry);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007-2008 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;
+
+/**
+ * Solaris implementation of FileSystemProvider
+ */
+
+public class SolarisFileSystemProvider extends UnixFileSystemProvider {
+    public SolarisFileSystemProvider() {
+        super();
+    }
+
+
+    SolarisFileSystem newFileSystem(String dir) {
+        return new SolarisFileSystem(this, dir);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNamedAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2007-2008 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 java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.io.IOException;
+import java.util.*;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+import static sun.nio.fs.SolarisConstants.*;
+
+/**
+ * Solaris emulation of NamedAttributeView using extended attributes.
+ */
+
+class SolarisNamedAttributeView
+    extends AbstractNamedAttributeView
+{
+    private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
+        byte[] bytes = name.getBytes();
+        //  "", "." and ".." not allowed
+        if (bytes.length == 0 || bytes[0] == '.') {
+            if (bytes.length <= 1 ||
+                (bytes.length == 2 && bytes[1] == '.'))
+            {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "'" + name + "' is not a valid name");
+            }
+        }
+        return bytes;
+    }
+
+    private final UnixPath file;
+    private final boolean followLinks;
+
+    SolarisNamedAttributeView(UnixPath file, boolean followLinks) {
+        this.file = file;
+        this.followLinks = followLinks;
+    }
+
+
+    public List<String> list() throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open extended attribute directory
+                int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+                long dp;
+                try {
+                    dp = fdopendir(dfd);
+                } catch (UnixException x) {
+                    close(dfd);
+                    throw x;
+                }
+
+                // read list of extended attributes
+                final List<String> list = new ArrayList<String>();
+                try {
+                    byte[] name;
+                    while ((name = readdir(dp)) != null) {
+                        String s = new String(name);
+                        if (!s.equals(".") && !s.equals(".."))
+                            list.add(new String(name));
+                    }
+                } finally {
+                    closedir(dp);
+                }
+                return Collections.unmodifiableList(list);
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to get list of extended attributes: " +
+                    x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public int size(String name) throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open attribute file
+                int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
+                try {
+                    // read attribute's attributes
+                    UnixFileAttributes attrs = UnixFileAttributes.get(afd);
+                    long size = attrs.size();
+                    if (size > Integer.MAX_VALUE)
+                        throw new ArithmeticException("Extended attribute value too large");
+                    return (int)size;
+                } finally {
+                    close(afd);
+                }
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to get size of extended attribute '" + name +
+                    "': " + x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public int read(String name, ByteBuffer dst) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open attribute file
+                int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
+
+                // wrap with channel
+                FileChannel fc = UnixChannelFactory.newFileChannel(afd, true, false);
+
+                // read to EOF (nothing we can do if I/O error occurs)
+                try {
+                    if (fc.size() > dst.remaining())
+                        throw new IOException("Extended attribute file too large");
+                    int total = 0;
+                    while (dst.hasRemaining()) {
+                        int n = fc.read(dst);
+                        if (n < 0)
+                            break;
+                        total += n;
+                    }
+                    return total;
+                } finally {
+                    fc.close();
+                }
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to read extended attribute '" + name +
+                    "': " + x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public int write(String name, ByteBuffer src) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open/create attribute file
+                int afd = openat(fd, nameAsBytes(file,name),
+                                 (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR),
+                                 UnixFileModeAttribute.ALL_PERMISSIONS);
+
+                // wrap with channel
+                FileChannel fc = UnixChannelFactory.newFileChannel(afd, false, true);
+
+                // write value (nothing we can do if I/O error occurs)
+                try {
+                    int rem = src.remaining();
+                    while (src.hasRemaining()) {
+                        fc.write(src);
+                    }
+                    return rem;
+                } finally {
+                    fc.close();
+                }
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to write extended attribute '" + name +
+                    "': " + x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+
+    public void delete(String name) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+            try {
+                unlinkat(dfd, nameAsBytes(file,name), 0);
+            } finally {
+                close(dfd);
+            }
+        } catch (UnixException x) {
+            throw new FileSystemException(file.getPathForExecptionMessage(),
+                null, "Unable to delete extended attribute '" + name +
+                "': " + x.getMessage());
+        } finally {
+            close(fd);
+        }
+    }
+
+    /**
+     * Used by copyTo/moveTo to copy extended attributes from source to target.
+     *
+     * @param   ofd
+     *          file descriptor for source file
+     * @param   nfd
+     *          file descriptor for target file
+     */
+    static void copyExtendedAttributes(int ofd, int nfd) {
+        try {
+            // open extended attribute directory
+            int dfd = openat(ofd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+            long dp = 0L;
+            try {
+                dp = fdopendir(dfd);
+            } catch (UnixException x) {
+                close(dfd);
+                throw x;
+            }
+
+            // copy each extended attribute
+            try {
+                byte[] name;
+                while ((name = readdir(dp)) != null) {
+                    // ignore "." and ".."
+                    if (name[0] == '.') {
+                        if (name.length == 1)
+                            continue;
+                        if (name.length == 2 && name[1] == '.')
+                            continue;
+                    }
+                    copyExtendedAttribute(ofd, name, nfd);
+                }
+            } finally {
+                closedir(dp);
+            }
+        } catch (UnixException ignore) {
+        }
+    }
+
+    private static void copyExtendedAttribute(int ofd, byte[] name, int nfd)
+        throws UnixException
+    {
+        // open source attribute file
+        int src = openat(ofd, name, (O_RDONLY|O_XATTR), 0);
+        try {
+            // create target attribute file
+            int dst = openat(nfd, name, (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR),
+                UnixFileModeAttribute.ALL_PERMISSIONS);
+            try {
+                UnixCopyFile.transfer(dst, src, 0L);
+            } finally {
+                close(dst);
+            }
+        } finally {
+            close(src);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007-2008 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.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Solaris specific system calls.
+ */
+
+class SolarisNativeDispatcher extends UnixNativeDispatcher {
+    private SolarisNativeDispatcher() { }
+
+    /**
+     * int facl(int filedes, int cmd, int nentries, void aclbufp)
+     */
+    static native int facl(int fd, int cmd, int nentries, long aclbufp)
+        throws UnixException;
+
+
+    // initialize
+    private static native void init();
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+        init();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2007-2008 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 java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+/**
+ * Solaris implementation of WatchService based on file events notification
+ * facility.
+ */
+
+class SolarisWatchService
+    extends AbstractWatchService
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static int addressSize = unsafe.addressSize();
+
+    private static int dependsArch(int value32, int value64) {
+        return (addressSize == 4) ? value32 : value64;
+    }
+
+    /*
+     * typedef struct port_event {
+     *     int             portev_events;
+     *     ushort_t        portev_source;
+     *     ushort_t        portev_pad;
+     *     uintptr_t       portev_object;
+     *     void            *portev_user;
+     * } port_event_t;
+     */
+    private static final int SIZEOF_PORT_EVENT  = dependsArch(16, 24);
+    private static final int OFFSETOF_EVENTS    = 0;
+    private static final int OFFSETOF_SOURCE    = 4;
+    private static final int OFFSETOF_OBJECT    = 8;
+
+    /*
+     * typedef struct file_obj {
+     *     timestruc_t     fo_atime;
+     *     timestruc_t     fo_mtime;
+     *     timestruc_t     fo_ctime;
+     *     uintptr_t       fo_pad[3];
+     *     char            *fo_name;
+     * } file_obj_t;
+     */
+    private static final int SIZEOF_FILEOBJ    = dependsArch(40, 80);
+    private static final int OFFSET_FO_NAME    = dependsArch(36, 72);
+
+    // port sources
+    private static final short PORT_SOURCE_USER     = 3;
+    private static final short PORT_SOURCE_FILE     = 7;
+
+    // user-watchable events
+    private static final int FILE_MODIFIED      = 0x00000002;
+    private static final int FILE_ATTRIB        = 0x00000004;
+    private static final int FILE_NOFOLLOW      = 0x10000000;
+
+    // exception events
+    private static final int FILE_DELETE        = 0x00000010;
+    private static final int FILE_RENAME_TO     = 0x00000020;
+    private static final int FILE_RENAME_FROM   = 0x00000040;
+    private static final int UNMOUNTED          = 0x20000000;
+    private static final int MOUNTEDOVER        = 0x40000000;
+
+    // background thread to read change events
+    private final Poller poller;
+
+    SolarisWatchService(UnixFileSystem fs) throws IOException {
+        int port = -1;
+        try {
+            port = portCreate();
+        } catch (UnixException x) {
+            throw new IOException(x.errorString());
+        }
+
+        this.poller = new Poller(fs, this, port);
+        this.poller.start();
+    }
+
+
+    WatchKey register(Path dir,
+                      WatchEvent.Kind<?>[] events,
+                      WatchEvent.Modifier... modifiers)
+         throws IOException
+    {
+        // delegate to poller
+        return poller.register(dir, events, modifiers);
+    }
+
+
+    void implClose() throws IOException {
+        // delegate to poller
+        poller.close();
+    }
+
+    /**
+     * WatchKey implementation
+     */
+    private class SolarisWatchKey extends AbstractWatchKey
+        implements DirectoryNode
+    {
+        private final UnixPath dir;
+        private final UnixFileKey fileKey;
+
+        // pointer to native file_obj object
+        private final long object;
+
+        // events (may be changed). set to null when watch key is invalid
+        private volatile Set<? extends WatchEvent.Kind<?>> events;
+
+        // map of entries in directory; created lazily; accessed only by
+        // poller thread.
+        private Map<Path,EntryNode> children;
+
+        SolarisWatchKey(SolarisWatchService watcher,
+                        UnixPath dir,
+                        UnixFileKey fileKey,
+                        long object,
+                        Set<? extends WatchEvent.Kind<?>> events)
+        {
+            super(watcher);
+            this.dir = dir;
+            this.fileKey = fileKey;
+            this.object = object;
+            this.events = events;
+        }
+
+        UnixPath getFileRef() {
+            return dir;
+        }
+
+        UnixFileKey getFileKey() {
+            return fileKey;
+        }
+
+
+        public long object() {
+            return object;
+        }
+
+        void invalidate() {
+            events = null;
+        }
+
+        Set<? extends WatchEvent.Kind<?>> events() {
+            return events;
+        }
+
+        void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
+            this.events = events;
+        }
+
+
+        public boolean isValid() {
+            return events != null;
+        }
+
+
+        public void cancel() {
+            if (isValid()) {
+                // delegate to poller
+                poller.cancel(this);
+            }
+        }
+
+
+        public void addChild(Path name, EntryNode node) {
+            if (children == null)
+                children = new HashMap<Path,EntryNode>();
+            children.put(name, node);
+        }
+
+
+        public void removeChild(Path name) {
+            children.remove(name);
+        }
+
+
+        public EntryNode getChild(Path name) {
+            if (children != null)
+                return children.get(name);
+            return null;
+        }
+    }
+
+    /**
+     * Background thread to read from port
+     */
+    private class Poller extends AbstractPoller {
+
+        // maximum number of events to read per call to port_getn
+        private static final int MAX_EVENT_COUNT            = 128;
+
+        // events that map to ENTRY_DELETE
+        private static final int FILE_REMOVED =
+            (FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM);
+
+        // events that tell us not to re-associate the object
+        private static final int FILE_EXCEPTION =
+            (FILE_REMOVED|UNMOUNTED|MOUNTEDOVER);
+
+        // address of event buffers (used to receive events with port_getn)
+        private final long bufferAddress;
+
+        private final SolarisWatchService watcher;
+
+        // the I/O port
+        private final int port;
+
+        // maps file key (dev/inode) to WatchKey
+        private final Map<UnixFileKey,SolarisWatchKey> fileKey2WatchKey;
+
+        // maps file_obj object to Node
+        private final Map<Long,Node> object2Node;
+
+        /**
+         * Create a new instance
+         */
+        Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) {
+            this.watcher = watcher;
+            this.port = port;
+            this.bufferAddress =
+                unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT);
+            this.fileKey2WatchKey = new HashMap<UnixFileKey,SolarisWatchKey>();
+            this.object2Node = new HashMap<Long,Node>();
+        }
+
+
+        void wakeup() throws IOException {
+            // write to port to wakeup polling thread
+            try {
+                portSend(port, 0);
+            } catch (UnixException x) {
+                throw new IOException(x.errorString());
+            }
+        }
+
+
+        Object implRegister(Path obj,
+                            Set<? extends WatchEvent.Kind<?>> events,
+                            WatchEvent.Modifier... modifiers)
+        {
+            // no modifiers supported at this time
+            if (modifiers.length > 0) {
+                if (modifiers[0] == null)
+                    return new NullPointerException();
+                return new UnsupportedOperationException("Modifier not supported");
+            }
+
+            UnixPath dir = (UnixPath)obj;
+
+            // check file is directory
+            UnixFileAttributes attrs = null;
+            try {
+                attrs = UnixFileAttributes.get(dir, true);
+            } catch (UnixException x) {
+                return x.asIOException(dir);
+            }
+            if (!attrs.isDirectory()) {
+                return new NotDirectoryException(dir.getPathForExecptionMessage());
+            }
+
+            // return existing watch key after updating events if already
+            // registered
+            UnixFileKey fileKey = attrs.fileKey();
+            SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
+            if (watchKey != null) {
+                updateEvents(watchKey, events);
+                return watchKey;
+            }
+
+            // register directory
+            long object = 0L;
+            try {
+                object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB));
+            } catch (UnixException x) {
+                return x.asIOException(dir);
+            }
+
+            // create watch key and insert it into maps
+            watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events);
+            object2Node.put(object, watchKey);
+            fileKey2WatchKey.put(fileKey, watchKey);
+
+            // register all entries in directory
+            registerChildren(dir, watchKey, false);
+
+            return watchKey;
+        }
+
+        // cancel single key
+
+        void implCancelKey(WatchKey obj) {
+           SolarisWatchKey key = (SolarisWatchKey)obj;
+           if (key.isValid()) {
+               fileKey2WatchKey.remove(key.getFileKey());
+
+               // release resources for entries in directory
+               if (key.children != null) {
+                    for (Path name: key.children.keySet()) {
+                        EntryNode node = key.children.get(name);
+                        long object = node.object();
+                        object2Node.remove(object);
+                        releaseObject(object, true);
+                    }
+               }
+
+               // release resources for directory
+               long object = key.object();
+               object2Node.remove(object);
+               releaseObject(object, true);
+
+               // and finally invalidate the key
+               key.invalidate();
+           }
+        }
+
+        // close watch service
+
+        void implCloseAll() {
+            // release all native resources
+            for (Long object: object2Node.keySet()) {
+                releaseObject(object, true);
+            }
+
+            // invalidate all keys
+            for (UnixFileKey fileKey: fileKey2WatchKey.keySet()) {
+                SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
+                if (watchKey != null)
+                    watchKey.invalidate();
+            }
+
+            // clean-up
+            object2Node.clear();
+            fileKey2WatchKey.clear();
+
+            // free global resources
+            unsafe.freeMemory(bufferAddress);
+            UnixNativeDispatcher.close(port);
+        }
+
+        /**
+         * Poller main loop. Blocks on port_getn waiting for events and then
+         * processes them.
+         */
+
+        public void run() {
+            try {
+                for (;;) {
+                    int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT);
+                    assert n > 0;
+
+                    long address = bufferAddress;
+                    for (int i=0; i<n; i++) {
+                        boolean shutdown = processEvent(address);
+                        if (shutdown)
+                            return;
+                        address += SIZEOF_PORT_EVENT;
+                    }
+                }
+            } catch (UnixException x) {
+                x.printStackTrace();
+            }
+        }
+
+        /**
+         * Process a single port_event
+         *
+         * Returns true if poller thread is requested to shutdown.
+         */
+        boolean processEvent(long address) {
+            // pe->portev_source
+            short source = unsafe.getShort(address + OFFSETOF_SOURCE);
+            // pe->portev_object
+            long object = unsafe.getAddress(address + OFFSETOF_OBJECT);
+            // pe->portev_events
+            int events = unsafe.getInt(address + OFFSETOF_EVENTS);
+
+            // user event is trigger to process pending requests
+            if (source != PORT_SOURCE_FILE) {
+                if (source == PORT_SOURCE_USER) {
+                    // process any pending requests
+                    boolean shutdown = processRequests();
+                    if (shutdown)
+                        return true;
+                }
+                return false;
+            }
+
+            // lookup object to get Node
+            Node node = object2Node.get(object);
+            if (node == null) {
+                // should not happen
+                return false;
+            }
+
+            // As a workaround for 6642290 and 6636438/6636412 we don't use
+            // FILE_EXCEPTION events to tell use not to register the file.
+            // boolean reregister = (events & FILE_EXCEPTION) == 0;
+            boolean reregister = true;
+
+            // If node is EntryNode then event relates to entry in directory
+            // If node is a SolarisWatchKey (DirectoryNode) then event relates
+            // to a watched directory.
+            boolean isDirectory = (node instanceof SolarisWatchKey);
+            if (isDirectory) {
+                processDirectoryEvents((SolarisWatchKey)node, events);
+            } else {
+                boolean ignore = processEntryEvents((EntryNode)node, events);
+                if (ignore)
+                    reregister = false;
+            }
+
+            // need to re-associate to get further events
+            if (reregister) {
+                try {
+                    events = FILE_MODIFIED | FILE_ATTRIB;
+                    if (!isDirectory) events |= FILE_NOFOLLOW;
+                    portAssociate(port,
+                                  PORT_SOURCE_FILE,
+                                  object,
+                                  events);
+                } catch (UnixException x) {
+                    // unable to re-register
+                    reregister = false;
+                }
+            }
+
+            // object is not re-registered so release resources. If
+            // object is a watched directory then signal key
+            if (!reregister) {
+                // release resources
+                object2Node.remove(object);
+                releaseObject(object, false);
+
+                // if watch key then signal it
+                if (isDirectory) {
+                    SolarisWatchKey key = (SolarisWatchKey)node;
+                    fileKey2WatchKey.remove( key.getFileKey() );
+                    key.invalidate();
+                    key.signal();
+                } else {
+                    // if entry then remove it from parent
+                    EntryNode entry = (EntryNode)node;
+                    SolarisWatchKey key = (SolarisWatchKey)entry.parent();
+                    key.removeChild(entry.name());
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * Process directory events. If directory is modified then re-scan
+         * directory to register any new entries
+         */
+        void processDirectoryEvents(SolarisWatchKey key, int mask) {
+            if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
+                registerChildren(key.getFileRef(), key,
+                    key.events().contains(StandardWatchEventKind.ENTRY_CREATE));
+            }
+        }
+
+        /**
+         * Process events for entries in registered directories. Returns {@code
+         * true} if events are ignored because the watch key has been cancelled.
+         */
+        boolean processEntryEvents(EntryNode node, int mask) {
+            SolarisWatchKey key = (SolarisWatchKey)node.parent();
+            Set<? extends WatchEvent.Kind<?>> events = key.events();
+            if (events == null) {
+                // key has been cancelled so ignore event
+                return true;
+            }
+
+            // entry modified
+            if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) &&
+                events.contains(StandardWatchEventKind.ENTRY_MODIFY))
+            {
+                key.signalEvent(StandardWatchEventKind.ENTRY_MODIFY, node.name());
+            }
+
+            // entry removed
+            if (((mask & (FILE_REMOVED)) != 0) &&
+                events.contains(StandardWatchEventKind.ENTRY_DELETE))
+            {
+                // Due to 6636438/6636412 we may get a remove event for cases
+                // where a rmdir/unlink/rename is attempted but fails. Until
+                // this issue is resolved we re-lstat the file to check if it
+                // exists. If it exists then we ignore the event. To keep the
+                // workaround simple we don't check the st_ino so it isn't
+                // effective when the file is replaced.
+                boolean removed = true;
+                try {
+                    UnixFileAttributes
+                        .get(key.getFileRef().resolve(node.name()), false);
+                    removed = false;
+                } catch (UnixException x) { }
+
+                if (removed)
+                    key.signalEvent(StandardWatchEventKind.ENTRY_DELETE, node.name());
+            }
+            return false;
+        }
+
+        /**
+         * Registers all entries in the given directory
+         *
+         * The {@code sendEvents} parameter indicates if ENTRY_CREATE events
+         * should be queued when new entries are found. When initially
+         * registering a directory then will always be false. When re-scanning
+         * a directory then it depends on if the event is enabled or not.
+         */
+        void registerChildren(UnixPath dir,
+                              SolarisWatchKey parent,
+                              boolean sendEvents)
+        {
+            // if the ENTRY_MODIFY event is not enabled then we don't need
+            // modification events for entries in the directory
+            int events = FILE_NOFOLLOW;
+            if (parent.events().contains(StandardWatchEventKind.ENTRY_MODIFY))
+                events |= (FILE_MODIFIED | FILE_ATTRIB);
+
+            DirectoryStream<Path> stream = null;
+            try {
+                stream = dir.newDirectoryStream();
+            } catch (IOException x) {
+                // nothing we can do
+                return;
+            }
+            try {
+                for (Path entry: stream) {
+                    Path name = entry.getName();
+
+                    // skip entry if already registered
+                    if (parent.getChild(name) != null)
+                        continue;
+
+                    // send ENTRY_CREATE if enabled
+                    if (sendEvents) {
+                        parent.signalEvent(StandardWatchEventKind.ENTRY_CREATE, name);
+                    }
+
+                    // register it
+                    long object = 0L;
+                    try {
+                        object = registerImpl((UnixPath)entry, events);
+                    } catch (UnixException x) {
+                        // can't register so ignore for now.
+                        continue;
+                    }
+
+                    // create node
+                    EntryNode node = new EntryNode(object, entry.getName(), parent);
+                    // tell the parent about it
+                    parent.addChild(entry.getName(), node);
+                    object2Node.put(object, node);
+                }
+            } catch (ConcurrentModificationException x) {
+                // error during iteration which we ignore for now
+            } finally {
+                try {
+                    stream.close();
+                } catch (IOException x) { }
+            }
+        }
+
+        /**
+         * Update watch key's events. Where the ENTRY_MODIFY changes then we
+         * need to update the events of registered children.
+         */
+        void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events) {
+            // update events, rembering if ENTRY_MODIFY was previously
+            // enabled or disabled.
+            boolean wasModifyEnabled = key.events()
+                .contains(StandardWatchEventKind.ENTRY_MODIFY);
+            key.setEvents(events);
+
+            // check if ENTRY_MODIFY has changed
+            boolean isModifyEnabled = events
+                .contains(StandardWatchEventKind.ENTRY_MODIFY);
+            if (wasModifyEnabled == isModifyEnabled) {
+                return;
+            }
+
+            // if changed then update events of children
+            if (key.children != null) {
+                int ev = FILE_NOFOLLOW;
+                if (isModifyEnabled)
+                    ev |= (FILE_MODIFIED | FILE_ATTRIB);
+
+                for (Path name: key.children.keySet()) {
+                    EntryNode node = key.children.get(name);
+                    long object = node.object();
+
+                    try {
+                        portAssociate(port,
+                                      PORT_SOURCE_FILE,
+                                      object,
+                                      ev);
+                    } catch (UnixException x) {
+                        // nothing we can do.
+                    }
+                }
+            }
+        }
+
+        /**
+         * Calls port_associate to register the given path.
+         * Returns pointer to fileobj structure that is allocated for
+         * the registration.
+         */
+        long registerImpl(UnixPath dir, int events)
+            throws UnixException
+        {
+            // allocate memory for the path (file_obj->fo_name field)
+            byte[] path = dir.getByteArrayForSysCalls();
+            int len = path.length;
+            long name = unsafe.allocateMemory(len+1);
+            unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
+                name, (long)len);
+            unsafe.putByte(name + len, (byte)0);
+
+            // allocate memory for filedatanode structure - this is the object
+            // to port_associate
+            long object = unsafe.allocateMemory(SIZEOF_FILEOBJ);
+            unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0);
+            unsafe.putAddress(object + OFFSET_FO_NAME, name);
+
+            // associate the object with the port
+            try {
+                portAssociate(port,
+                              PORT_SOURCE_FILE,
+                              object,
+                              events);
+            } catch (UnixException x) {
+                // debugging
+                if (x.errno() == EAGAIN) {
+                    System.err.println("The maximum number of objects associated "+
+                        "with the port has been reached");
+                }
+
+                unsafe.freeMemory(name);
+                unsafe.freeMemory(object);
+                throw x;
+            }
+            return object;
+        }
+
+        /**
+         * Frees all resources for an file_obj object; optionally remove
+         * association from port
+         */
+        void releaseObject(long object, boolean dissociate) {
+            // remove association
+            if (dissociate) {
+                try {
+                    portDissociate(port, PORT_SOURCE_FILE, object);
+                } catch (UnixException x) {
+                    // ignore
+                }
+            }
+
+            // free native memory
+            long name = unsafe.getAddress(object + OFFSET_FO_NAME);
+            unsafe.freeMemory(name);
+            unsafe.freeMemory(object);
+        }
+    }
+
+    /**
+     * A node with native (file_obj) resources
+     */
+    private static interface Node {
+        long object();
+    }
+
+    /**
+     * A directory node with a map of the entries in the directory
+     */
+    private static interface DirectoryNode extends Node {
+        void addChild(Path name, EntryNode node);
+        void removeChild(Path name);
+        EntryNode getChild(Path name);
+    }
+
+    /**
+     * An implementation of a node that is an entry in a directory.
+     */
+    private static class EntryNode implements Node {
+        private final long object;
+        private final Path name;
+        private final DirectoryNode parent;
+
+        EntryNode(long object, Path name, DirectoryNode parent) {
+            this.object = object;
+            this.name = name;
+            this.parent = parent;
+        }
+
+
+        public long object() {
+            return object;
+        }
+
+        Path name() {
+            return name;
+        }
+
+        DirectoryNode parent() {
+            return parent;
+        }
+    }
+
+    // -- native methods --
+
+    private static native void init();
+
+    private static native int portCreate() throws UnixException;
+
+    private static native void portAssociate(int port, int source, long object, int events)
+        throws UnixException;
+
+    private static native void portDissociate(int port, int source, long object)
+        throws UnixException;
+
+    private static native void portSend(int port, int events)
+        throws UnixException;
+
+    private static native int portGetn(int port, long address, int max)
+        throws UnixException;
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+        init();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2007-2008 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 java.nio.channels.*;
+import java.io.FileDescriptor;
+import java.util.Set;
+
+import sun.nio.ch.FileChannelImpl;
+import sun.nio.ch.ThreadPool;
+import sun.nio.ch.SimpleAsynchronousFileChannelImpl;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaIOFileDescriptorAccess;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+/**
+ * Factory for FileChannels and AsynchronousFileChannels
+ */
+
+class UnixChannelFactory {
+    private static final JavaIOFileDescriptorAccess fdAccess =
+        SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private UnixChannelFactory() {
+    }
+
+    /**
+     * Represents the flags from a user-supplied set of open options.
+     */
+    private static class Flags {
+        boolean read;
+        boolean write;
+        boolean append;
+        boolean truncateExisting;
+        boolean noFollowLinks;
+        boolean create;
+        boolean createNew;
+        boolean deleteOnClose;
+        boolean sync;
+        boolean dsync;
+
+        static Flags toFlags(Set<? extends OpenOption> options) {
+            Flags flags = new Flags();
+            for (OpenOption option: options) {
+                if (!(option instanceof StandardOpenOption)) {
+                    if (option == LinkOption.NOFOLLOW_LINKS) {
+                        flags.noFollowLinks = true;
+                        continue;
+                    }
+                    if (option == null)
+                        throw new NullPointerException();
+                    throw new UnsupportedOperationException("Unsupported open option");
+                }
+                switch ((StandardOpenOption)option) {
+                    case READ : flags.read = true; break;
+                    case WRITE : flags.write = true; break;
+                    case APPEND : flags.append = true; break;
+                    case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
+                    case CREATE : flags.create = true; break;
+                    case CREATE_NEW : flags.createNew = true; break;
+                    case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
+                    case SPARSE : /* ignore */ break;
+                    case SYNC : flags.sync = true; break;
+                    case DSYNC : flags.dsync = true; break;
+                    default: throw new AssertionError("Should not get here");
+                }
+            }
+            return flags;
+        }
+    }
+
+
+    /**
+     * Constructs a file channel from an existing (open) file descriptor
+     */
+    static FileChannel newFileChannel(int fd, boolean reading, boolean writing) {
+        FileDescriptor fdObj = new FileDescriptor();
+        fdAccess.set(fdObj, fd);
+        return FileChannelImpl.open(fdObj, reading, writing, null);
+    }
+
+    /**
+     * Constructs a file channel by opening a file using a dfd/path pair
+     */
+    static FileChannel newFileChannel(int dfd,
+                                      UnixPath path,
+                                      String pathForPermissionCheck,
+                                      Set<? extends OpenOption> options,
+                                      int mode)
+        throws UnixException
+    {
+        Flags flags = Flags.toFlags(options);
+
+        // default is reading; append => writing
+        if (!flags.read && !flags.write) {
+            if (flags.append) {
+                flags.write = true;
+            } else {
+                flags.read = true;
+            }
+        }
+
+        // validation
+        if (flags.read && flags.append)
+            throw new IllegalArgumentException("READ + APPEND not allowed");
+        if (flags.append && flags.truncateExisting)
+            throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
+
+        FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);
+        return FileChannelImpl.open(fdObj, flags.read, flags.write, null);
+    }
+
+    /**
+     * Constructs a file channel by opening the given file.
+     */
+    static FileChannel newFileChannel(UnixPath path,
+                                      Set<? extends OpenOption> options,
+                                      int mode)
+        throws UnixException
+    {
+        return newFileChannel(-1, path, null, options, mode);
+    }
+
+    /**
+     * Constructs an asynchronous file channel by opening the given file.
+     */
+    static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path,
+                                                              Set<? extends OpenOption> options,
+                                                              int mode,
+                                                              ThreadPool pool)
+        throws UnixException
+    {
+        Flags flags = Flags.toFlags(options);
+
+        // default is reading
+        if (!flags.read && !flags.write) {
+            flags.read = true;
+        }
+
+        // validation
+        if (flags.append)
+            throw new UnsupportedOperationException("APPEND not allowed");
+
+        // for now assume that direct/raw I/O is not supported so return
+        // "portable" AsynchronousFileChannel based on underlying file channel
+        FileDescriptor fdObj = open(-1, path, null, flags, mode);
+        return SimpleAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
+    }
+
+    /**
+     * 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)
+        throws UnixException
+    {
+        // map to oflags
+        int oflags;
+        if (flags.read && flags.write) {
+            oflags = O_RDWR;
+        } else {
+            oflags = (flags.write) ? O_WRONLY : O_RDONLY;
+        }
+        if (flags.write) {
+            if (flags.truncateExisting)
+                oflags |= O_TRUNC;
+            if (flags.append)
+                oflags |= O_APPEND;
+
+            // create flags
+            if (flags.createNew) {
+                byte[] pathForSysCall = path.asByteArray();
+
+                // throw exception if file name is "." to avoid confusing error
+                if ((pathForSysCall[pathForSysCall.length-1] == '.') &&
+                    (pathForSysCall.length == 1 ||
+                    (pathForSysCall[pathForSysCall.length-2] == '/')))
+                {
+                    throw new UnixException(EEXIST);
+                }
+                oflags |= (O_CREAT | O_EXCL);
+            } else {
+                if (flags.create)
+                    oflags |= O_CREAT;
+            }
+        }
+
+        // follow links by default
+        boolean followLinks = true;
+        if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) {
+            followLinks = false;
+            oflags |= O_NOFOLLOW;
+        }
+
+        if (flags.dsync)
+            oflags |= O_DSYNC;
+        if (flags.sync)
+            oflags |= O_SYNC;
+
+        // permission check before we open the file
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (pathForPermissionCheck == null)
+                pathForPermissionCheck = path.getPathForPermissionCheck();
+            if (flags.read)
+                sm.checkRead(pathForPermissionCheck);
+            if (flags.write)
+                sm.checkWrite(pathForPermissionCheck);
+            if (flags.deleteOnClose)
+                sm.checkDelete(pathForPermissionCheck);
+        }
+
+        int fd;
+        try {
+            if (dfd >= 0) {
+                fd = openat(dfd, path.asByteArray(), oflags, mode);
+            } else {
+                fd = UnixNativeDispatcher.open(path, oflags, mode);
+            }
+        } catch (UnixException x) {
+            // Linux error can be EISDIR or EEXIST when file exists
+            if (flags.createNew && (x.errno() == EISDIR)) {
+                x.setError(EEXIST);
+            }
+
+            // handle ELOOP to avoid confusing message
+            if (!followLinks && (x.errno() == ELOOP)) {
+                x = new UnixException(x.getMessage() + " (NOFOLLOW_LINKS specified)");
+            }
+
+            throw x;
+        }
+
+        // unlink file immediately if delete on close. The spec is clear that
+        // an implementation cannot guarantee to unlink the correct file when
+        // replaced by an attacker after it is opened.
+        if (flags.deleteOnClose) {
+            try {
+                if (dfd >= 0) {
+                    unlinkat(dfd, path.asByteArray(), 0);
+                } else {
+                    unlink(path);
+                }
+            } catch (UnixException ignore) {
+                // best-effort
+            }
+        }
+
+        // create java.io.FileDescriptor
+        FileDescriptor fdObj = new FileDescriptor();
+        fdAccess.set(fdObj, fd);
+        return fdObj;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,608 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ExecutionException;
+import com.sun.nio.file.ExtendedCopyOption;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+
+/**
+ * Unix implementation of Path#copyTo and Path#moveTo methods.
+ */
+
+class UnixCopyFile {
+    private UnixCopyFile() {  }
+
+    // The flags that control how a file is copied or moved
+    private static class Flags {
+        boolean replaceExisting;
+        boolean atomicMove;
+        boolean followLinks;
+        boolean interruptible;
+
+        // the attributes to copy
+        boolean copyBasicAttributes;
+        boolean copyPosixAttributes;
+        boolean copyNonPosixAttributes;
+
+        // flags that indicate if we should fail if attributes cannot be copied
+        boolean failIfUnableToCopyBasic;
+        boolean failIfUnableToCopyPosix;
+        boolean failIfUnableToCopyNonPosix;
+
+        static Flags fromCopyOptions(CopyOption... options) {
+            Flags flags = new Flags();
+            flags.followLinks = true;
+            for (CopyOption option: options) {
+                if (option == StandardCopyOption.REPLACE_EXISTING) {
+                    flags.replaceExisting = true;
+                    continue;
+                }
+                if (option == LinkOption.NOFOLLOW_LINKS) {
+                    flags.followLinks = false;
+                    continue;
+                }
+                if (option == StandardCopyOption.COPY_ATTRIBUTES) {
+                    // copy all attributes but only fail if basic attributes
+                    // cannot be copied
+                    flags.copyBasicAttributes = true;
+                    flags.copyPosixAttributes = true;
+                    flags.copyNonPosixAttributes = true;
+                    flags.failIfUnableToCopyBasic = true;
+                    continue;
+                }
+                if (option == ExtendedCopyOption.INTERRUPTIBLE) {
+                    flags.interruptible = true;
+                    continue;
+                }
+                if (option == null)
+                    throw new NullPointerException();
+                throw new UnsupportedOperationException("Unsupported copy option");
+            }
+            return flags;
+        }
+
+        static Flags fromMoveOptions(CopyOption... options) {
+            Flags flags = new Flags();
+            for (CopyOption option: options) {
+                if (option == StandardCopyOption.ATOMIC_MOVE) {
+                    flags.atomicMove = true;
+                    continue;
+                }
+                if (option == StandardCopyOption.REPLACE_EXISTING) {
+                    flags.replaceExisting = true;
+                    continue;
+                }
+                if (option == LinkOption.NOFOLLOW_LINKS) {
+                    // ignore
+                    continue;
+                }
+                if (option == null)
+                    throw new NullPointerException();
+                throw new UnsupportedOperationException("Unsupported copy option");
+            }
+
+            // a move requires that all attributes be copied but only fail if
+            // the basic attributes cannot be copied
+            flags.copyBasicAttributes = true;
+            flags.copyPosixAttributes = true;
+            flags.copyNonPosixAttributes = true;
+            flags.failIfUnableToCopyBasic = true;
+            return flags;
+        }
+    }
+
+    // copy directory from source to target
+    private static void copyDirectory(UnixPath source,
+                                      UnixFileAttributes attrs,
+                                      UnixPath target,
+                                      Flags flags)
+        throws IOException
+    {
+        try {
+            mkdir(target, attrs.mode());
+        } catch (UnixException x) {
+            x.rethrowAsIOException(target);
+        }
+
+        // no attributes to copy
+        if (!flags.copyBasicAttributes &&
+            !flags.copyPosixAttributes &&
+            !flags.copyNonPosixAttributes) return;
+
+        // open target directory if possible (this can fail when copying a
+        // directory for which we don't have read access).
+        int dfd = -1;
+        try {
+            dfd = open(target, O_RDONLY, 0);
+        } catch (UnixException x) {
+            // access to target directory required to copy named attributes
+            if (flags.copyNonPosixAttributes && flags.failIfUnableToCopyNonPosix) {
+                try { rmdir(target); } catch (UnixException ignore) { }
+                x.rethrowAsIOException(target);
+            }
+        }
+
+        boolean done = false;
+        try {
+            // copy owner/group/permissions
+            if (flags.copyPosixAttributes){
+                try {
+                    if (dfd >= 0) {
+                        fchown(dfd, attrs.uid(), attrs.gid());
+                        fchmod(dfd, attrs.mode());
+                    } else {
+                        chown(target, attrs.uid(), attrs.gid());
+                        chmod(target, attrs.mode());
+                    }
+                } catch (UnixException x) {
+                    // unable to set owner/group
+                    if (flags.failIfUnableToCopyPosix)
+                        x.rethrowAsIOException(target);
+                }
+            }
+            // copy other attributes
+            if (flags.copyNonPosixAttributes && (dfd >= 0)) {
+                int sfd = -1;
+                try {
+                    sfd = open(source, O_RDONLY, 0);
+                } catch (UnixException x) {
+                    if (flags.failIfUnableToCopyNonPosix)
+                        x.rethrowAsIOException(source);
+                }
+                if (sfd >= 0) {
+                    source.getFileSystem().copyNonPosixAttributes(sfd, dfd);
+                    close(sfd);
+                }
+            }
+            // copy time stamps last
+            if (flags.copyBasicAttributes) {
+                try {
+                    if (dfd >= 0) {
+                        futimes(dfd, attrs.lastAccessTime(),
+                            attrs.lastModifiedTime());
+                    } else {
+                        utimes(target, attrs.lastAccessTime(),
+                            attrs.lastModifiedTime());
+                    }
+                } catch (UnixException x) {
+                    // unable to set times
+                    if (flags.failIfUnableToCopyBasic)
+                        x.rethrowAsIOException(target);
+                }
+            }
+            done = true;
+        } finally {
+            if (dfd >= 0)
+                close(dfd);
+            if (!done) {
+                // rollback
+                try { rmdir(target); } catch (UnixException ignore) { }
+            }
+        }
+    }
+
+    // copy regular file from source to target
+    private static void copyFile(UnixPath source,
+                                 UnixFileAttributes attrs,
+                                 UnixPath  target,
+                                 Flags flags,
+                                 long addressToPollForCancel)
+        throws IOException
+    {
+        int fi = -1;
+        try {
+            fi = open(source, O_RDONLY, 0);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(source);
+        }
+
+        try {
+            // open new file
+            int fo = -1;
+            try {
+                fo = open(target,
+                           (O_WRONLY |
+                            O_CREAT |
+                            O_TRUNC),
+                           attrs.mode());
+            } catch (UnixException x) {
+                x.rethrowAsIOException(target);
+            }
+
+            // set to true when file and attributes copied
+            boolean complete = false;
+            try {
+                // transfer bytes to target file
+                try {
+                    transfer(fo, fi, addressToPollForCancel);
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(source, target);
+                }
+                // copy owner/permissions
+                if (flags.copyPosixAttributes) {
+                    try {
+                        fchown(fo, attrs.uid(), attrs.gid());
+                        fchmod(fo, attrs.mode());
+                    } catch (UnixException x) {
+                        if (flags.failIfUnableToCopyPosix)
+                            x.rethrowAsIOException(target);
+                    }
+                }
+                // copy non POSIX attributes (depends on file system)
+                if (flags.copyNonPosixAttributes) {
+                    source.getFileSystem().copyNonPosixAttributes(fi, fo);
+                }
+                // copy time attributes
+                if (flags.copyBasicAttributes) {
+                    try {
+                        futimes(fo, attrs.lastAccessTime(), attrs.lastModifiedTime());
+                    } catch (UnixException x) {
+                        if (flags.failIfUnableToCopyBasic)
+                            x.rethrowAsIOException(target);
+                    }
+                }
+                complete = true;
+            } finally {
+                close(fo);
+
+                // copy of file or attributes failed so rollback
+                if (!complete) {
+                    try {
+                        unlink(target);
+                    } catch (UnixException ignore) { }
+                }
+            }
+        } finally {
+            close(fi);
+        }
+    }
+
+    // copy symbolic link from source to target
+    private static void copyLink(UnixPath source,
+                                 UnixFileAttributes attrs,
+                                 UnixPath  target,
+                                 Flags flags)
+        throws IOException
+    {
+        byte[] linktarget = null;
+        try {
+            linktarget = readlink(source);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(source);
+        }
+        try {
+            symlink(linktarget, target);
+
+            if (flags.copyPosixAttributes) {
+                try {
+                    lchown(target, attrs.uid(), attrs.gid());
+                } catch (UnixException x) {
+                    // ignore since link attributes not required to be copied
+                }
+            }
+        } catch (UnixException x) {
+            x.rethrowAsIOException(target);
+        }
+    }
+
+    // copy special file from source to target
+    private static void copySpecial(UnixPath source,
+                                    UnixFileAttributes attrs,
+                                    UnixPath  target,
+                                    Flags flags)
+        throws IOException
+    {
+        try {
+            mknod(target, attrs.mode(), attrs.rdev());
+        } catch (UnixException x) {
+            x.rethrowAsIOException(target);
+        }
+        boolean done = false;
+        try {
+            if (flags.copyPosixAttributes) {
+                try {
+                    chown(target, attrs.uid(), attrs.gid());
+                    chmod(target, attrs.mode());
+                } catch (UnixException x) {
+                    if (flags.failIfUnableToCopyPosix)
+                        x.rethrowAsIOException(target);
+                }
+            }
+            if (flags.copyBasicAttributes) {
+                try {
+                    utimes(target, attrs.lastAccessTime(), attrs.lastModifiedTime());
+                } catch (UnixException x) {
+                    if (flags.failIfUnableToCopyBasic)
+                        x.rethrowAsIOException(target);
+                }
+            }
+            done = true;
+        } finally {
+            if (!done) {
+                try { unlink(target); } catch (UnixException ignore) { }
+            }
+        }
+    }
+
+    // move file from source to target
+    static void move(UnixPath source, UnixPath target, CopyOption... options)
+        throws IOException
+    {
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            source.checkWrite();
+            target.checkWrite();
+        }
+
+        // translate options into flags
+        Flags flags = Flags.fromMoveOptions(options);
+
+        // handle atomic rename case
+        if (flags.atomicMove) {
+            try {
+                rename(source, target);
+            } catch (UnixException x) {
+                if (x.errno() == EXDEV) {
+                    throw new AtomicMoveNotSupportedException(
+                        source.getPathForExecptionMessage(),
+                        target.getPathForExecptionMessage(),
+                        x.errorString());
+                }
+                x.rethrowAsIOException(source, target);
+            }
+            return;
+        }
+
+        // move using rename or copy+delete
+        UnixFileAttributes sourceAttrs = null;
+        UnixFileAttributes targetAttrs = null;
+
+        // get attributes of source file (don't follow links)
+        try {
+            sourceAttrs = UnixFileAttributes.get(source, false);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(source);
+        }
+
+        // get attributes of target file (don't follow links)
+        try {
+            targetAttrs = UnixFileAttributes.get(target, false);
+        } catch (UnixException x) {
+            // ignore
+        }
+        boolean targetExists = (targetAttrs != null);
+
+        // if the target exists:
+        // 1. check if source and target are the same file
+        // 2. throw exception if REPLACE_EXISTING option is not set
+        // 3. delete target if REPLACE_EXISTING option set
+        if (targetExists) {
+            if (sourceAttrs.isSameFile(targetAttrs))
+                return;  // nothing to do as files are identical
+            if (!flags.replaceExisting) {
+                throw new FileAlreadyExistsException(
+                    target.getPathForExecptionMessage());
+            }
+
+            // attempt to delete target
+            try {
+                if (targetAttrs.isDirectory()) {
+                    rmdir(target);
+                } else {
+                    unlink(target);
+                }
+            } catch (UnixException x) {
+                // target is non-empty directory that can't be replaced.
+                if (targetAttrs.isDirectory() &&
+                   (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
+                {
+                    throw new FileAlreadyExistsException(
+                        source.getPathForExecptionMessage(),
+                        target.getPathForExecptionMessage(),
+                        x.getMessage());
+                }
+                x.rethrowAsIOException(target);
+            }
+        }
+
+        // first try rename
+        try {
+            rename(source, target);
+            return;
+        } catch (UnixException x) {
+            if (x.errno() != EXDEV && x.errno() != EISDIR) {
+                x.rethrowAsIOException(source, target);
+            }
+        }
+
+        // copy source to target
+        if (sourceAttrs.isDirectory()) {
+            copyDirectory(source, sourceAttrs, target, flags);
+        } else {
+            if (sourceAttrs.isSymbolicLink()) {
+                copyLink(source, sourceAttrs, target, flags);
+            } else {
+                if (sourceAttrs.isDevice()) {
+                    copySpecial(source, sourceAttrs, target, flags);
+                } else {
+                    copyFile(source, sourceAttrs, target, flags, 0L);
+                }
+            }
+        }
+
+        // delete source
+        try {
+            if (sourceAttrs.isDirectory()) {
+                rmdir(source);
+            } else {
+                unlink(source);
+            }
+        } catch (UnixException x) {
+            // file was copied but unable to unlink the source file so attempt
+            // to remove the target and throw a reasonable exception
+            try {
+                if (sourceAttrs.isDirectory()) {
+                    rmdir(target);
+                } else {
+                    unlink(target);
+                }
+            } catch (UnixException ignore) { }
+
+            if (sourceAttrs.isDirectory() &&
+                (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
+            {
+                throw new DirectoryNotEmptyException(
+                    source.getPathForExecptionMessage());
+            }
+            x.rethrowAsIOException(source);
+        }
+    }
+
+    // copy file from source to target
+    static void copy(final UnixPath source,
+                     final UnixPath target,
+                     CopyOption... options) throws IOException
+    {
+        // permission checks
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            source.checkRead();
+            target.checkWrite();
+        }
+
+        // translate options into flags
+        final Flags flags = Flags.fromCopyOptions(options);
+
+        UnixFileAttributes sourceAttrs = null;
+        UnixFileAttributes targetAttrs = null;
+
+        // get attributes of source file
+        try {
+            sourceAttrs = UnixFileAttributes.get(source, flags.followLinks);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(source);
+        }
+
+        // if source file is symbolic link then we must check LinkPermission
+        if (sm != null && sourceAttrs.isSymbolicLink()) {
+            sm.checkPermission(new LinkPermission("symbolic"));
+        }
+
+        // get attributes of target file (don't follow links)
+        try {
+            targetAttrs = UnixFileAttributes.get(target, false);
+        } catch (UnixException x) {
+            // ignore
+        }
+        boolean targetExists = (targetAttrs != null);
+
+        // if the target exists:
+        // 1. check if source and target are the same file
+        // 2. throw exception if REPLACE_EXISTING option is not set
+        // 3. try to unlink the target
+        if (targetExists) {
+            if (sourceAttrs.isSameFile(targetAttrs))
+                return;  // nothing to do as files are identical
+            if (!flags.replaceExisting)
+                throw new FileAlreadyExistsException(
+                    target.getPathForExecptionMessage());
+            try {
+                if (targetAttrs.isDirectory()) {
+                    rmdir(target);
+                } else {
+                    unlink(target);
+                }
+            } catch (UnixException x) {
+                // target is non-empty directory that can't be replaced.
+                if (targetAttrs.isDirectory() &&
+                   (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
+                {
+                    throw new FileAlreadyExistsException(
+                        source.getPathForExecptionMessage(),
+                        target.getPathForExecptionMessage(),
+                        x.getMessage());
+                }
+                x.rethrowAsIOException(target);
+            }
+        }
+
+        // do the copy
+        if (sourceAttrs.isDirectory()) {
+            copyDirectory(source, sourceAttrs, target, flags);
+            return;
+        }
+        if (sourceAttrs.isSymbolicLink()) {
+            copyLink(source, sourceAttrs, target, flags);
+            return;
+        }
+        if (!flags.interruptible) {
+            // non-interruptible file copy
+            copyFile(source, sourceAttrs, target, flags, 0L);
+            return;
+        }
+
+        // interruptible file copy
+        final UnixFileAttributes attrsToCopy = sourceAttrs;
+        Cancellable copyTask = new Cancellable() {
+ public void implRun() throws IOException {
+                copyFile(source, attrsToCopy, target, flags,
+                    addressToPollForCancel());
+            }
+        };
+        try {
+            Cancellable.runInterruptibly(copyTask);
+        } catch (ExecutionException e) {
+            Throwable t = e.getCause();
+            if (t instanceof IOException)
+                throw (IOException)t;
+            throw new IOException(t);
+        }
+    }
+
+    // -- native methods --
+
+    static native void transfer(int dst, int src, long addressToPollForCancel)
+        throws UnixException;
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+            }});
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2007-2008 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 java.util.Iterator;
+import java.util.ConcurrentModificationException;
+import java.util.NoSuchElementException;
+import java.util.concurrent.locks.*;
+import java.io.IOException;
+import static sun.nio.fs.UnixNativeDispatcher.*;
+
+/**
+ * Unix implementation of java.nio.file.DirectoryStream
+ */
+
+class UnixDirectoryStream
+    implements DirectoryStream<Path>
+{
+    // path to directory when originally opened
+    private final UnixPath dir;
+
+    // directory pointer (returned by opendir)
+    private final long dp;
+
+    // filter (may be null)
+    private final DirectoryStream.Filter<? super Path> filter;
+
+    // used to coorindate closing of directory stream
+    private final ReentrantReadWriteLock streamLock =
+        new ReentrantReadWriteLock(true);
+
+    // indicates if directory stream is open (synchronize on closeLock)
+    private volatile boolean isClosed;
+
+    // directory iterator
+    private Iterator<Path> iterator;
+
+    /**
+     * Initializes a new instance
+     */
+    UnixDirectoryStream(UnixPath dir, long dp, DirectoryStream.Filter<? super Path> filter) {
+        this.dir = dir;
+        this.dp = dp;
+        this.filter = filter;
+    }
+
+    protected final UnixPath directory() {
+        return dir;
+    }
+
+    protected final Lock readLock() {
+        return streamLock.readLock();
+    }
+
+    protected final Lock writeLock() {
+        return streamLock.writeLock();
+    }
+
+    protected final boolean isOpen() {
+        return !isClosed;
+    }
+
+    protected final boolean closeImpl() throws IOException {
+        if (!isClosed) {
+            isClosed = true;
+            try {
+                closedir(dp);
+            } catch (UnixException x) {
+                throw new IOException(x.errorString());
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    public void close()
+        throws IOException
+    {
+        writeLock().lock();
+        try {
+            closeImpl();
+        } finally {
+            writeLock().unlock();
+        }
+    }
+
+    protected final Iterator<Path> iterator(DirectoryStream<Path> ds) {
+        if (isClosed) {
+            throw new IllegalStateException("Directory stream is closed");
+        }
+        synchronized (this) {
+            if (iterator != null)
+                throw new IllegalStateException("Iterator already obtained");
+            iterator = new UnixDirectoryIterator(ds);
+            return iterator;
+        }
+    }
+
+
+    public Iterator<Path> iterator() {
+        return iterator(this);
+    }
+
+    /**
+     * Iterator implementation
+     */
+    private class UnixDirectoryIterator implements Iterator<Path> {
+        private final DirectoryStream<Path> stream;
+
+        // true when at EOF
+        private boolean atEof;
+
+        // next entry to return
+        private Path nextEntry;
+
+        // previous entry returned by next method (needed by remove method)
+        private Path prevEntry;
+
+        UnixDirectoryIterator(DirectoryStream<Path> stream) {
+            atEof = false;
+            this.stream = stream;
+        }
+
+        // Return true if file name is "." or ".."
+        private boolean isSelfOrParent(byte[] nameAsBytes) {
+            if (nameAsBytes[0] == '.') {
+                if ((nameAsBytes.length == 1) ||
+                    (nameAsBytes.length == 2 && nameAsBytes[1] == '.')) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        // Returns next entry (or null)
+        private Path readNextEntry() {
+            assert Thread.holdsLock(this);
+
+            for (;;) {
+                byte[] nameAsBytes = null;
+
+                // prevent close while reading
+                readLock().lock();
+                try {
+                    if (isClosed)
+                        throwAsConcurrentModificationException(new
+                            ClosedDirectoryStreamException());
+                    try {
+                        nameAsBytes = readdir(dp);
+                    } catch (UnixException x) {
+                        try {
+                            x.rethrowAsIOException(dir);
+                        } catch (IOException ioe) {
+                            throwAsConcurrentModificationException(ioe);
+                        }
+                    }
+                } finally {
+                    readLock().unlock();
+                }
+
+                // EOF
+                if (nameAsBytes == null) {
+                    return null;
+                }
+
+                // ignore "." and ".."
+                if (!isSelfOrParent(nameAsBytes)) {
+                    Path entry = dir.resolve(nameAsBytes);
+
+                    // return entry if no filter or filter accepts it
+                    if (filter.accept(entry)) {
+                        return entry;
+                    }
+                }
+            }
+        }
+
+
+        public synchronized boolean hasNext() {
+            if (nextEntry == null && !atEof) {
+                nextEntry = readNextEntry();
+
+                // at EOF?
+                if (nextEntry == null)
+                    atEof = true;
+            }
+            return nextEntry != null;
+        }
+
+
+        public synchronized Path next() {
+            if (nextEntry == null) {
+                if (!atEof) {
+                    nextEntry = readNextEntry();
+                }
+                if (nextEntry == null) {
+                    atEof = true;
+                    throw new NoSuchElementException();
+                }
+            }
+            prevEntry = nextEntry;
+            nextEntry = null;
+            return prevEntry;
+        }
+
+
+        public void remove() {
+            if (isClosed) {
+                throw new ClosedDirectoryStreamException();
+            }
+            Path entry;
+            synchronized (this) {
+                if (prevEntry == null)
+                    throw new IllegalStateException("No previous entry to remove");
+                entry = prevEntry;
+                prevEntry = null;
+            }
+
+            // use (race-free) unlinkat if available
+            try {
+                if (stream instanceof UnixSecureDirectoryStream) {
+                    ((UnixSecureDirectoryStream)stream)
+                        .implDelete(entry.getName(), false, 0);
+                } else {
+                    entry.delete(true);
+                }
+            } catch (IOException ioe) {
+                throwAsConcurrentModificationException(ioe);
+            } catch (SecurityException se) {
+                throwAsConcurrentModificationException(se);
+            }
+        }
+    }
+
+    private static void throwAsConcurrentModificationException(Throwable t) {
+        ConcurrentModificationException cme = new ConcurrentModificationException();
+        cme.initCause(t);
+        throw cme;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+
+/**
+ * Internal exception thrown by native methods when error detected.
+ */
+
+class UnixException extends Exception {
+    static final long serialVersionUID = 7227016794320723218L;
+
+    private int errno;
+    private String msg;
+
+    UnixException(int errno) {
+        this.errno = errno;
+        this.msg = null;
+    }
+
+    UnixException(String msg) {
+        this.errno = 0;
+        this.msg = msg;
+    }
+
+    int errno() {
+        return errno;
+    }
+
+    void setError(int errno) {
+        this.errno = errno;
+        this.msg = null;
+    }
+
+    String errorString() {
+        if (msg != null) {
+            return msg;
+        } else {
+            return new String(UnixNativeDispatcher.strerror(errno()));
+        }
+    }
+
+
+    public String getMessage() {
+        return errorString();
+    }
+
+    /**
+     * Map well known errors to specific exceptions where possible; otherwise
+     * return more general FileSystemException.
+     */
+    private IOException translateToIOException(String file, String other) {
+        // created with message rather than errno
+        if (msg != null)
+            return new IOException(msg);
+
+        // handle specific cases
+        if (errno() == UnixConstants.EACCES)
+            return new AccessDeniedException(file, other, null);
+        if (errno() == UnixConstants.ENOENT)
+            return new NoSuchFileException(file, other, null);
+        if (errno() == UnixConstants.EEXIST)
+            return new FileAlreadyExistsException(file, other, null);
+
+        // fallback to the more general exception
+        return new FileSystemException(file, other, errorString());
+    }
+
+    void rethrowAsIOException(String file) throws IOException {
+        IOException x = translateToIOException(file, null);
+        throw x;
+    }
+
+    void rethrowAsIOException(UnixPath file, UnixPath other) throws IOException {
+        String a = (file == null) ? null : file.getPathForExecptionMessage();
+        String b = (other == null) ? null : other.getPathForExecptionMessage();
+        IOException x = translateToIOException(a, b);
+        throw x;
+    }
+
+    void rethrowAsIOException(UnixPath file) throws IOException {
+        rethrowAsIOException(file, null);
+    }
+
+    IOException asIOException(UnixPath file) {
+        return translateToIOException(file.getPathForExecptionMessage(), null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.io.IOException;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+
+class UnixFileAttributeViews {
+
+    static class Basic extends AbstractBasicFileAttributeView {
+        protected final UnixPath file;
+        protected final boolean followLinks;
+
+        Basic(UnixPath file, boolean followLinks) {
+            this.file = file;
+            this.followLinks = followLinks;
+        }
+
+
+        public BasicFileAttributes readAttributes() throws IOException {
+            file.checkRead();
+            try {
+                 UnixFileAttributes attrs =
+                     UnixFileAttributes.get(file, followLinks);
+                 return attrs.asBasicFileAttributes();
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+                return null;    // keep compiler happy
+            }
+        }
+
+        public void setTimes(Long lastModifiedTime,
+                             Long lastAccessTime,
+                             Long createTime,
+                             TimeUnit unit) throws IOException
+        {
+            // null => don't change
+            if (lastModifiedTime == null && lastAccessTime == null) {
+                // no effect
+                return;
+            }
+
+            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);
+                    } 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();
+                    }
+                }
+
+                try {
+                    futimes(fd, accTime, modTime);
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(file);
+                }
+            } finally {
+                close(fd);
+            }
+        }
+    }
+
+    private static class Posix extends Basic implements PosixFileAttributeView {
+        private static final String PERMISSIONS_NAME = "permissions";
+        private static final String OWNER_NAME = "owner";
+        private static final String GROUP_NAME = "group";
+
+        Posix(UnixPath file, boolean followLinks) {
+            super(file, followLinks);
+        }
+
+        final void checkReadExtended() {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                file.checkRead();
+                sm.checkPermission(new RuntimePermission("accessUserInformation"));
+            }
+        }
+
+        final void checkWriteExtended() {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                file.checkWrite();
+                sm.checkPermission(new RuntimePermission("accessUserInformation"));
+            }
+        }
+
+
+        public String name() {
+            return "posix";
+        }
+
+
+        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);
+        }
+
+
+        @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);
+        }
+
+        /**
+         * Invoked by readAttributes or sub-classes to add all matching posix
+         * attributes to the builder
+         */
+        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());
+        }
+
+
+        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();
+        }
+
+
+        public UnixFileAttributes readAttributes() throws IOException {
+            checkReadExtended();
+            try {
+                 return UnixFileAttributes.get(file, followLinks);
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+                return null;    // keep compiler happy
+            }
+        }
+
+        // chmod
+        final void setMode(int mode) throws IOException {
+            checkWriteExtended();
+            try {
+                if (followLinks) {
+                    chmod(file, mode);
+                } else {
+                    int fd = file.openForAttributeAccess(false);
+                    try {
+                        fchmod(fd, mode);
+                    } finally {
+                        close(fd);
+                    }
+                }
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+            }
+        }
+
+        // chown
+        final void setOwners(int uid, int gid) throws IOException {
+            checkWriteExtended();
+            try {
+                if (followLinks) {
+                    chown(file, uid, gid);
+                } else {
+                    lchown(file, uid, gid);
+                }
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+            }
+        }
+
+
+        public void setPermissions(Set<PosixFilePermission> perms)
+            throws IOException
+        {
+            setMode(UnixFileModeAttribute.toUnixMode(perms));
+        }
+
+
+        public void setOwner(UserPrincipal owner)
+            throws IOException
+        {
+            if (owner == null)
+                throw new NullPointerException("'owner' is null");
+            if (!(owner instanceof UnixUserPrincipals.User))
+                throw new ProviderMismatchException();
+            if (owner instanceof UnixUserPrincipals.Group)
+                throw new IOException("'owner' parameter can't be a group");
+            int uid = ((UnixUserPrincipals.User)owner).uid();
+            setOwners(uid, -1);
+        }
+
+
+        public UserPrincipal getOwner() throws IOException {
+            return readAttributes().owner();
+        }
+
+
+        public void setGroup(GroupPrincipal group)
+            throws IOException
+        {
+            if (group == null)
+                throw new NullPointerException("'owner' is null");
+            if (!(group instanceof UnixUserPrincipals.Group))
+                throw new ProviderMismatchException();
+            int gid = ((UnixUserPrincipals.Group)group).gid();
+            setOwners(-1, gid);
+        }
+    }
+
+    private static class Unix extends Posix {
+        private static final String MODE_NAME = "mode";
+        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 UID_NAME = "uid";
+        private static final String GID_NAME = "gid";
+        private static final String CTIME_NAME = "ctime";
+
+        Unix(UnixPath file, boolean followLinks) {
+            super(file, followLinks);
+        }
+
+
+        public String name() {
+            return "unix";
+        }
+
+
+        public Object getAttribute(String attribute) throws IOException {
+            if (attribute.equals(MODE_NAME))
+                return readAttributes().mode();
+            if (attribute.equals(INO_NAME))
+                return readAttributes().ino();
+            if (attribute.equals(DEV_NAME))
+                return readAttributes().dev();
+            if (attribute.equals(RDEV_NAME))
+                return readAttributes().rdev();
+            if (attribute.equals(UID_NAME))
+                return readAttributes().uid();
+            if (attribute.equals(GID_NAME))
+                return readAttributes().gid();
+            if (attribute.equals(CTIME_NAME))
+                return readAttributes().ctime();
+            return super.getAttribute(attribute);
+        }
+
+
+        public void setAttribute(String attribute, Object value)
+            throws IOException
+        {
+            if (attribute.equals(MODE_NAME)) {
+                setMode((Integer)value);
+                return;
+            }
+            if (attribute.equals(UID_NAME)) {
+                setOwners((Integer)value, -1);
+                return;
+            }
+            if (attribute.equals(GID_NAME)) {
+                setOwners(-1, (Integer)value);
+                return;
+            }
+            super.setAttribute(attribute, value);
+        }
+
+
+        public Map<String,?> readAttributes(String first, String[] rest)
+            throws IOException
+        {
+            AttributesBuilder builder = AttributesBuilder.create(first, rest);
+            UnixFileAttributes attrs = readAttributes();
+            addBasicAttributesToBuilder(attrs, builder);
+            addPosixAttributesToBuilder(attrs, builder);
+            if (builder.match(MODE_NAME))
+                builder.add(MODE_NAME, attrs.mode());
+            if (builder.match(INO_NAME))
+                builder.add(INO_NAME, attrs.ino());
+            if (builder.match(DEV_NAME))
+                builder.add(DEV_NAME, attrs.dev());
+            if (builder.match(RDEV_NAME))
+                builder.add(RDEV_NAME, attrs.rdev());
+            if (builder.match(UID_NAME))
+                builder.add(UID_NAME, attrs.uid());
+            if (builder.match(GID_NAME))
+                builder.add(GID_NAME, attrs.gid());
+            if (builder.match(CTIME_NAME))
+                builder.add(CTIME_NAME, attrs.ctime());
+            return builder.unmodifiableMap();
+        }
+    }
+
+    static BasicFileAttributeView createBasicView(UnixPath file, boolean followLinks) {
+        return new Basic(file, followLinks);
+    }
+
+    static PosixFileAttributeView createPosixView(UnixPath file, boolean followLinks) {
+        return new Posix(file, followLinks);
+    }
+
+    static PosixFileAttributeView createUnixView(UnixPath file, boolean followLinks) {
+        return new Unix(file, followLinks);
+    }
+
+    static FileOwnerAttributeView createOwnerView(UnixPath file, boolean followLinks) {
+        return new FileOwnerAttributeViewImpl(createPosixView(file, followLinks));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2007-2008 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.util.concurrent.TimeUnit;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * Unix implementation of PosixFileAttributes.
+ */
+
+class UnixFileAttributes
+    implements PosixFileAttributes
+{
+    private int     st_mode;
+    private long    st_ino;
+    private long    st_dev;
+    private long    st_rdev;
+    private int     st_nlink;
+    private int     st_uid;
+    private int     st_gid;
+    private long    st_size;
+    private long    st_atime;
+    private long    st_mtime;
+    private long    st_ctime;
+
+    // created lazily
+    private volatile UserPrincipal owner;
+    private volatile GroupPrincipal group;
+    private volatile UnixFileKey key;
+
+    private UnixFileAttributes() {
+    }
+
+    // get the UnixFileAttributes for a given file
+    static UnixFileAttributes get(UnixPath path, boolean followLinks)
+        throws UnixException
+    {
+        UnixFileAttributes attrs = new UnixFileAttributes();
+        if (followLinks) {
+            UnixNativeDispatcher.stat(path, attrs);
+        } else {
+            UnixNativeDispatcher.lstat(path, attrs);
+        }
+        return attrs;
+    }
+
+    // get the UnixFileAttributes for an open file
+    static UnixFileAttributes get(int fd) throws UnixException {
+        UnixFileAttributes attrs = new UnixFileAttributes();
+        UnixNativeDispatcher.fstat(fd, attrs);
+        return attrs;
+    }
+
+    // get the UnixFileAttributes for a given file, relative to open directory
+    static UnixFileAttributes get(int dfd, UnixPath path, boolean followLinks)
+        throws UnixException
+    {
+        UnixFileAttributes attrs = new UnixFileAttributes();
+        int flag = (followLinks) ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW;
+        UnixNativeDispatcher.fstatat(dfd, path.asByteArray(), flag, attrs);
+        return attrs;
+    }
+
+    // package-private
+    boolean isSameFile(UnixFileAttributes attrs) {
+        return ((st_ino == attrs.st_ino) && (st_dev == attrs.st_dev));
+    }
+
+    // package-private
+    int mode()  { return st_mode; }
+    long ino()  { return st_ino; }
+    long dev()  { return st_dev; }
+    long rdev() { return st_rdev; }
+    int uid()   { return st_uid; }
+    int gid()   { return st_gid; }
+    long ctime() { return st_ctime; }
+
+    boolean isDevice() {
+        int type = st_mode & UnixConstants.S_IFMT;
+        return (type == UnixConstants.S_IFCHR ||
+                type == UnixConstants.S_IFBLK  ||
+                type == UnixConstants.S_IFIFO);
+    }
+
+
+    public long lastModifiedTime() {
+        return st_mtime;
+    }
+
+
+    public long lastAccessTime() {
+        return st_atime;
+    }
+
+
+    public long creationTime() {
+        return -1L;
+    }
+
+
+    public TimeUnit resolution() {
+        return TimeUnit.MILLISECONDS;
+    }
+
+
+    public boolean isRegularFile() {
+       return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFREG);
+    }
+
+
+    public boolean isDirectory() {
+        return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR);
+    }
+
+
+    public boolean isSymbolicLink() {
+        return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFLNK);
+    }
+
+
+    public boolean isOther() {
+        int type = st_mode & UnixConstants.S_IFMT;
+        return (type != UnixConstants.S_IFREG &&
+                type != UnixConstants.S_IFDIR &&
+                type != UnixConstants.S_IFLNK);
+    }
+
+
+    public long size() {
+        return st_size;
+    }
+
+
+    public int linkCount() {
+        return st_nlink;
+    }
+
+
+    public UnixFileKey fileKey() {
+        if (key == null) {
+            synchronized (this) {
+                if (key == null) {
+                    key = new UnixFileKey(st_dev, st_ino);
+                }
+            }
+        }
+        return key;
+    }
+
+
+    public UserPrincipal owner() {
+        if (owner == null) {
+            synchronized (this) {
+                if (owner == null) {
+                    owner = UnixUserPrincipals.fromUid(st_uid);
+                }
+            }
+        }
+        return owner;
+    }
+
+
+    public GroupPrincipal group() {
+        if (group == null) {
+            synchronized (this) {
+                if (group == null) {
+                    group = UnixUserPrincipals.fromGid(st_gid);
+                }
+            }
+        }
+        return group;
+    }
+
+
+    public Set<PosixFilePermission> permissions() {
+        int bits = (st_mode & UnixConstants.S_IAMB);
+        HashSet<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
+
+        if ((bits & UnixConstants.S_IRUSR) > 0)
+            perms.add(PosixFilePermission.OWNER_READ);
+        if ((bits & UnixConstants.S_IWUSR) > 0)
+            perms.add(PosixFilePermission.OWNER_WRITE);
+        if ((bits & UnixConstants.S_IXUSR) > 0)
+            perms.add(PosixFilePermission.OWNER_EXECUTE);
+
+        if ((bits & UnixConstants.S_IRGRP) > 0)
+            perms.add(PosixFilePermission.GROUP_READ);
+        if ((bits & UnixConstants.S_IWGRP) > 0)
+            perms.add(PosixFilePermission.GROUP_WRITE);
+        if ((bits & UnixConstants.S_IXGRP) > 0)
+            perms.add(PosixFilePermission.GROUP_EXECUTE);
+
+        if ((bits & UnixConstants.S_IROTH) > 0)
+            perms.add(PosixFilePermission.OTHERS_READ);
+        if ((bits & UnixConstants.S_IWOTH) > 0)
+            perms.add(PosixFilePermission.OTHERS_WRITE);
+        if ((bits & UnixConstants.S_IXOTH) > 0)
+            perms.add(PosixFilePermission.OTHERS_EXECUTE);
+
+        return perms;
+    }
+
+    // wrap this object with BasicFileAttributes object to prevent leaking of
+    // user information
+    BasicFileAttributes asBasicFileAttributes() {
+        return UnixAsBasicFileAttributes.wrap(this);
+    }
+
+    // unwrap BasicFileAttributes to get the underlying UnixFileAttributes
+    // object. Returns null is not wrapped.
+    static UnixFileAttributes toUnixFileAttributes(BasicFileAttributes attrs) {
+        if (attrs instanceof UnixFileAttributes)
+            return (UnixFileAttributes)attrs;
+        if (attrs instanceof UnixAsBasicFileAttributes) {
+            return ((UnixAsBasicFileAttributes)attrs).unwrap();
+        }
+        return null;
+    }
+
+    // wrap a UnixFileAttributes object as a BasicFileAttributes
+    private static class UnixAsBasicFileAttributes implements BasicFileAttributes {
+        private final UnixFileAttributes attrs;
+
+        private UnixAsBasicFileAttributes(UnixFileAttributes attrs) {
+            this.attrs = attrs;
+        }
+
+        static UnixAsBasicFileAttributes wrap(UnixFileAttributes attrs) {
+            return new UnixAsBasicFileAttributes(attrs);
+        }
+
+        UnixFileAttributes unwrap() {
+            return attrs;
+        }
+
+
+        public long lastModifiedTime() {
+            return attrs.lastModifiedTime();
+        }
+
+        public long lastAccessTime() {
+            return attrs.lastAccessTime();
+        }
+
+        public long creationTime() {
+            return attrs.creationTime();
+        }
+
+        public TimeUnit resolution() {
+            return attrs.resolution();
+        }
+
+        public boolean isRegularFile() {
+            return attrs.isRegularFile();
+        }
+
+        public boolean isDirectory() {
+            return attrs.isDirectory();
+        }
+
+        public boolean isSymbolicLink() {
+            return attrs.isSymbolicLink();
+        }
+
+        public boolean isOther() {
+            return attrs.isOther();
+        }
+
+        public long size() {
+            return attrs.size();
+        }
+
+        public int linkCount() {
+            return attrs.linkCount();
+        }
+
+        public Object fileKey() {
+            return attrs.fileKey();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2007-2008 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;
+
+/**
+ * Container for device/inode to uniquely identify file.
+ */
+
+class UnixFileKey {
+    private final long st_dev;
+    private final long st_ino;
+
+    UnixFileKey(long st_dev, long st_ino) {
+        this.st_dev = st_dev;
+        this.st_ino = st_ino;
+    }
+
+
+    public int hashCode() {
+        return (int)(st_dev ^ (st_dev >>> 32)) +
+               (int)(st_ino ^ (st_ino >>> 32));
+    }
+
+
+    public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+        if (!(obj instanceof UnixFileKey))
+            return false;
+        UnixFileKey other = (UnixFileKey)obj;
+        if ((this.st_dev != other.st_dev) ||
+            (this.st_ino != other.st_ino)) {
+            return false;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2007-2008 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.util.*;
+
+class UnixFileModeAttribute {
+    static final int ALL_PERMISSIONS =
+        UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR |
+        UnixConstants.S_IRGRP | UnixConstants.S_IWGRP | UnixConstants.S_IXGRP |
+        UnixConstants.S_IROTH | UnixConstants.S_IWOTH | UnixConstants. S_IXOTH;
+
+    static final int ALL_READWRITE =
+        UnixConstants.S_IRUSR | UnixConstants.S_IWUSR |
+        UnixConstants.S_IRGRP | UnixConstants.S_IWGRP |
+        UnixConstants.S_IROTH | UnixConstants.S_IWOTH;
+
+    static final int TEMPFILE_PERMISSIONS =
+        UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR;
+
+    private Set<PosixFilePermission> perms;
+
+    UnixFileModeAttribute() {
+        perms = Collections.emptySet();
+    }
+
+    static int toUnixMode(Set<PosixFilePermission> perms) {
+        int mode = 0;
+        for (PosixFilePermission perm: perms) {
+            if (perm == null)
+                throw new NullPointerException();
+            switch (perm) {
+                case OWNER_READ :     mode |= UnixConstants.S_IRUSR; break;
+                case OWNER_WRITE :    mode |= UnixConstants.S_IWUSR; break;
+                case OWNER_EXECUTE :  mode |= UnixConstants.S_IXUSR; break;
+                case GROUP_READ :     mode |= UnixConstants.S_IRGRP; break;
+                case GROUP_WRITE :    mode |= UnixConstants.S_IWGRP; break;
+                case GROUP_EXECUTE :  mode |= UnixConstants.S_IXGRP; break;
+                case OTHERS_READ :    mode |= UnixConstants.S_IROTH; break;
+                case OTHERS_WRITE :   mode |= UnixConstants.S_IWOTH; break;
+                case OTHERS_EXECUTE : mode |= UnixConstants.S_IXOTH; break;
+            }
+        }
+        return mode;
+    }
+
+    @SuppressWarnings("unchecked")
+    static int toUnixMode(int defaultMode, FileAttribute<?>... attrs) {
+        int mode = defaultMode;
+        for (FileAttribute<?> attr: attrs) {
+            String name = attr.name();
+            if (!name.equals("posix:permissions") && !name.equals("unix:permissions")) {
+                throw new UnsupportedOperationException("'" + attr.name() +
+                   "' not supported as initial attribute");
+            }
+            mode = toUnixMode((Set<PosixFilePermission>)attr.value());
+        }
+        return mode;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Base implementation of FileStore for Unix/like implementations.
+ */
+
+abstract class UnixFileStore
+    extends FileStore
+{
+    // original path of file that identified file system
+    private final UnixPath file;
+
+    // device ID
+    private final long dev;
+
+    // entry in the mount tab
+    private final UnixMountEntry entry;
+
+    UnixFileStore(UnixPath file) throws IOException {
+        // need device ID
+        long devID = 0;
+        try {
+            devID = UnixFileAttributes.get(file, true).dev();
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+        }
+        this.file = file;
+        this.dev = devID;
+        this.entry = findMountEntry(file.getFileSystem());
+    }
+
+    UnixFileStore(UnixFileSystem fs, UnixMountEntry entry) {
+        this.file = new UnixPath(fs, entry.dir());
+        this.dev = entry.dev();
+        this.entry = entry;
+    }
+
+    /**
+     * Find the mount entry for this file system
+     */
+    abstract UnixMountEntry findMountEntry(UnixFileSystem fs) throws IOException;
+
+    UnixPath file() {
+        return file;
+    }
+
+    long dev() {
+        return dev;
+    }
+
+    UnixMountEntry entry() {
+        return entry;
+    }
+
+
+    public String name() {
+        return entry.name();
+    }
+
+
+    public String type() {
+        return entry.fstype();
+    }
+
+
+    public boolean isReadOnly() {
+        return entry.isReadOnly();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> viewType)
+    {
+        if (viewType == FileStoreSpaceAttributeView.class)
+            return (V) new UnixFileStoreSpaceAttributeView(this);
+        return (V) null;
+    }
+
+
+    public FileStoreAttributeView getFileStoreAttributeView(String name) {
+        if (name.equals("space"))
+            return new UnixFileStoreSpaceAttributeView(this);
+        return  null;
+    }
+
+
+    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        if (type == BasicFileAttributeView.class)
+            return true;
+        if (type == PosixFileAttributeView.class ||
+            type == FileOwnerAttributeView.class)
+        {
+            // lookup fstypes.properties
+            FeatureStatus status = checkIfFeaturePresent("posix");
+            if (status == FeatureStatus.NOT_PRESENT)
+                return false;
+            return true;
+        }
+        return false;
+    }
+
+
+    public boolean supportsFileAttributeView(String name) {
+        if (name.equals("basic") || name.equals("unix"))
+            return true;
+        if (name.equals("posix"))
+            return supportsFileAttributeView(PosixFileAttributeView.class);
+        if (name.equals("owner"))
+            return supportsFileAttributeView(FileOwnerAttributeView.class);
+        return false;
+    }
+
+
+    public boolean equals(Object ob) {
+        if (ob == this)
+            return true;
+        if (!(ob instanceof UnixFileStore))
+            return false;
+        UnixFileStore other = (UnixFileStore)ob;
+        return dev == other.dev;
+    }
+
+
+    public int hashCode() {
+        return (int)(dev ^ (dev >>> 32));
+    }
+
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(new String(entry.dir()));
+        sb.append(" (");
+        sb.append(entry.name());
+        sb.append(")");
+        return sb.toString();
+    }
+
+    private static class UnixFileStoreSpaceAttributeView
+        extends AbstractFileStoreSpaceAttributeView
+    {
+        private final UnixFileStore fs;
+
+        UnixFileStoreSpaceAttributeView(UnixFileStore fs) {
+            this.fs = fs;
+        }
+
+
+        public FileStoreSpaceAttributes readAttributes()
+            throws IOException
+        {
+            UnixPath file = fs.file();
+
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                file.checkRead();
+                sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
+            }
+            final UnixFileStoreAttributes attrs;
+            try {
+                attrs = UnixFileStoreAttributes.get(file);
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+                return null;    // keep compile happy
+            }
+
+            return new FileStoreSpaceAttributes() {
+
+                public long totalSpace() {
+                    return attrs.blockSize() * attrs.totalBlocks();
+                }
+
+                public long usableSpace() {
+                    return attrs.blockSize() * attrs.availableBlocks();
+                }
+
+                public long unallocatedSpace() {
+                    return attrs.blockSize() * attrs.freeBlocks();
+                }
+            };
+        }
+    }
+
+    // -- fstypes.properties --
+
+    private static final Object loadLock = new Object();
+    private static volatile Properties props;
+
+    enum FeatureStatus {
+        PRESENT,
+        NOT_PRESENT,
+        UNKNOWN;
+    }
+
+    /**
+     * Returns status to indicate if file system supports a given feature
+     */
+    FeatureStatus checkIfFeaturePresent(String feature) {
+        if (props == null) {
+            synchronized (loadLock) {
+                if (props == null) {
+                    props = AccessController.doPrivileged(
+                        new PrivilegedAction<Properties>() {
+
+                            public Properties run() {
+                                return loadProperties();
+                            }});
+                }
+            }
+        }
+
+        String value = props.getProperty(type());
+        if (value != null) {
+            String[] values = value.split("\\s");
+            for (String s: values) {
+                s = s.trim().toLowerCase();
+                if (s.equals(feature)) {
+                    return FeatureStatus.PRESENT;
+                }
+                if (s.startsWith("no")) {
+                    s = s.substring(2);
+                    if (s.equals(feature)) {
+                        return FeatureStatus.NOT_PRESENT;
+                    }
+                }
+            }
+        }
+        return FeatureStatus.UNKNOWN;
+    }
+
+    private static Properties loadProperties() {
+        Properties result = new Properties();
+        String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
+        FileRef file = Paths.get(fstypes);
+        try {
+            ReadableByteChannel rbc = file.newByteChannel();
+            try {
+                result.load(Channels.newReader(rbc, "UTF-8"));
+            } finally {
+                rbc.close();
+            }
+        } catch (IOException x) {
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2007-2008 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;
+
+class UnixFileStoreAttributes {
+    private long f_frsize;          // block size
+    private long f_blocks;          // total
+    private long f_bfree;           // free
+    private long f_bavail;          // usable
+
+    private UnixFileStoreAttributes() {
+    }
+
+    static UnixFileStoreAttributes get(UnixPath path) throws UnixException {
+        UnixFileStoreAttributes attrs = new UnixFileStoreAttributes();
+        UnixNativeDispatcher.statvfs(path, attrs);
+        return attrs;
+    }
+
+    long blockSize() {
+        return f_frsize;
+    }
+
+    long totalBlocks() {
+        return f_blocks;
+    }
+
+    long freeBlocks() {
+        return f_bfree;
+    }
+
+    long availableBlocks() {
+        return f_bavail;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.file.spi.*;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import sun.security.action.GetBooleanAction;
+
+/**
+ * Base implementation of FileSystem for Unix-like implementations.
+ */
+
+abstract class UnixFileSystem
+    extends FileSystem
+{
+    private final UnixFileSystemProvider provider;
+    private final byte[] defaultDirectory;
+    private final boolean needToResolveAgainstDefaultDirectory;
+    private final UnixPath rootDirectory;
+
+    // package-private
+    UnixFileSystem(UnixFileSystemProvider provider, String dir) {
+        this.provider = provider;
+        this.defaultDirectory = UnixPath.normalizeAndCheck(dir).getBytes();
+        if (this.defaultDirectory[0] != '/') {
+            throw new RuntimeException("default directory must be absolute");
+        }
+
+        // if process-wide chdir is allowed or default directory is not the
+        // process working directory then paths must be resolved against the
+        // default directory.
+        PrivilegedAction<Boolean> pa = new GetBooleanAction("sun.nio.fs.chdirAllowed");
+        if (AccessController.doPrivileged(pa).booleanValue()) {
+            this.needToResolveAgainstDefaultDirectory = true;
+        } else {
+            byte[] cwd = UnixNativeDispatcher.getcwd();
+            boolean defaultIsCwd = (cwd.length == defaultDirectory.length);
+            if (defaultIsCwd) {
+                for (int i=0; i<cwd.length; i++) {
+                    if (cwd[i] != defaultDirectory[i]) {
+                        defaultIsCwd = false;
+                        break;
+                    }
+                }
+            }
+            this.needToResolveAgainstDefaultDirectory = !defaultIsCwd;
+        }
+
+        // the root directory
+        this.rootDirectory = new UnixPath(this, "/");
+    }
+
+    // package-private
+    byte[] defaultDirectory() {
+        return defaultDirectory;
+    }
+
+    boolean needToResolveAgainstDefaultDirectory() {
+        return needToResolveAgainstDefaultDirectory;
+    }
+
+    UnixPath rootDirectory() {
+        return rootDirectory;
+    }
+
+    boolean isSolaris() {
+        return false;
+    }
+
+
+    public final FileSystemProvider provider() {
+        return provider;
+    }
+
+
+    public final String getSeparator() {
+        return "/";
+    }
+
+
+    public final boolean isOpen() {
+        return true;
+    }
+
+
+    public final boolean isReadOnly() {
+        return false;
+    }
+
+
+    public final void close() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Copies non-POSIX attributes from the source to target file.
+     *
+     * Copying a file preserving attributes, or moving a file, will preserve
+     * the file owner/group/permissions/timestamps but it does not preserve
+     * other non-POSIX attributes. This method is invoked by the
+     * copy or move operation to preserve these attributes. It should copy
+     * extended attributes, ACLs, or other attributes.
+     *
+     * @param   sfd
+     *          Open file descriptor to source file
+     * @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();
+
+    /**
+     * Unix systems only have a single root directory (/)
+     */
+
+    public final Iterable<Path> getRootDirectories() {
+        final List<Path> allowedList =
+           Collections.unmodifiableList(Arrays.asList((Path)rootDirectory));
+        return new Iterable<Path>() {
+            public Iterator<Path> iterator() {
+                try {
+                    SecurityManager sm = System.getSecurityManager();
+                    if (sm != null)
+                        sm.checkRead(rootDirectory.toString());
+                    return allowedList.iterator();
+                } catch (SecurityException x) {
+                    List<Path> disallowed = Collections.emptyList();
+                    return disallowed.iterator();
+                }
+            }
+        };
+    }
+
+    /**
+     * Returns object to iterate over entries in mounttab or equivalent
+     */
+    abstract Iterable<UnixMountEntry> getMountEntries();
+
+    /**
+     * Returns a FileStore to represent the file system where the given file
+     * reside.
+     */
+    abstract FileStore getFileStore(UnixPath path) throws IOException;
+
+    /**
+     * Returns a FileStore to represent the file system for the given mount
+     * mount.
+     */
+    abstract FileStore getFileStore(UnixMountEntry entry);
+
+    /**
+     * Iterator returned by getFileStores method.
+     */
+    private class FileStoreIterator implements Iterator<FileStore> {
+        private final Iterator<UnixMountEntry> entries;
+        private FileStore next;
+
+        FileStoreIterator() {
+            this.entries = getMountEntries().iterator();
+        }
+
+        private FileStore readNext() {
+            assert Thread.holdsLock(this);
+            for (;;) {
+                if (!entries.hasNext())
+                    return null;
+                UnixMountEntry entry = entries.next();
+
+                // skip entries with the "ignore" option
+                if (entry.isIgnored())
+                    continue;
+
+                // check permission to read mount point
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    try {
+                        sm.checkRead(new String(entry.dir()));
+                    } catch (SecurityException x) {
+                        continue;
+                    }
+                }
+                return getFileStore(entry);
+            }
+        }
+
+
+        public synchronized boolean hasNext() {
+            if (next != null)
+                return true;
+            next = readNext();
+            return next != null;
+        }
+
+
+        public synchronized FileStore next() {
+            if (next == null)
+                next = readNext();
+            if (next == null) {
+                throw new NoSuchElementException();
+            } else {
+                FileStore result = next;
+                next = null;
+                return result;
+            }
+        }
+
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+
+    public final Iterable<FileStore> getFileStores() {
+        return new Iterable<FileStore>() {
+            public Iterator<FileStore> iterator() {
+                return new FileStoreIterator();
+            }
+        };
+    }
+
+
+    public final UnixPath getPath(String path) {
+        return new UnixPath(this, path);
+    }
+
+
+    public PathMatcher getNameMatcher(String syntax, String input) {
+        String expr;
+        if (syntax.equals(GLOB_SYNTAX)) {
+            expr = Globs.toRegexPattern(input);
+        } else {
+            if (syntax.equals(REGEX_SYNTAX)) {
+                expr = input;
+            } else {
+                throw new UnsupportedOperationException("Syntax '" + syntax +
+                    "' not recognized");
+            }
+        }
+
+        // return matcher
+        final Pattern pattern = Pattern.compile(expr);
+        return new PathMatcher() {
+
+            public boolean matches(Path path) {
+                // match on file name only
+                Path name = path.getName();
+                if (name == null)
+                    return false;
+                return pattern.matcher(name.toString()).matches();
+            }
+        };
+    }
+    private static final String GLOB_SYNTAX = "glob";
+    private static final String REGEX_SYNTAX = "regex";
+
+    protected boolean followLinks(LinkOption... options) {
+        boolean followLinks = true;
+        for (LinkOption option: options) {
+            if (option == LinkOption.NOFOLLOW_LINKS) {
+                followLinks = false;
+                continue;
+            }
+            throw new AssertionError("Should not get here");
+        }
+        return followLinks;
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
+                                                                   UnixPath file,
+                                                                   LinkOption... options)
+    {
+        if (view == null)
+            throw new NullPointerException();
+        boolean followLinks = followLinks(options);
+        Class<?> c = view;
+        if (c == BasicFileAttributeView.class)
+            return (V) UnixFileAttributeViews.createBasicView(file, followLinks);
+        if (c == PosixFileAttributeView.class)
+            return (V) UnixFileAttributeViews.createPosixView(file, followLinks);
+        if (c == FileOwnerAttributeView.class)
+            return (V) UnixFileAttributeViews.createOwnerView(file, followLinks);
+        return (V) null;
+    }
+
+    static List<String> standardFileAttributeViews() {
+        return Arrays.asList("basic", "posix", "unix", "owner");
+    }
+
+    protected FileAttributeView newFileAttributeView(String name,
+                                                     UnixPath file,
+                                                     LinkOption... options)
+    {
+        boolean followLinks = followLinks(options);
+        if (name.equals("basic"))
+            return UnixFileAttributeViews.createBasicView(file, followLinks);
+        if (name.equals("posix"))
+            return UnixFileAttributeViews.createPosixView(file, followLinks);
+        if (name.equals("unix"))
+            return UnixFileAttributeViews.createUnixView(file, followLinks);
+        if (name.equals("owner"))
+            return UnixFileAttributeViews.createOwnerView(file, followLinks);
+        return null;
+    }
+
+
+    public final UserPrincipalLookupService getUserPrincipalLookupService() {
+        return theLookupService;
+    }
+
+    private static final UserPrincipalLookupService theLookupService =
+        new UserPrincipalLookupService() {
+
+            public UserPrincipal lookupPrincipalByName(String name)
+                throws IOException
+            {
+                return UnixUserPrincipals.lookupUser(name);
+            }
+
+
+            public GroupPrincipal lookupPrincipalByGroupName(String group)
+                throws IOException
+            {
+                return UnixUserPrincipals.lookupGroup(group);
+            }
+        };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.file.spi.FileSystemProvider;
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+import java.net.URI;
+import java.util.concurrent.ExecutorService;
+import java.io.IOException;
+import java.util.*;
+
+import sun.nio.ch.ThreadPool;
+
+/**
+ * Base implementation of FileSystemProvider
+ */
+
+public abstract class UnixFileSystemProvider
+    extends FileSystemProvider
+{
+    private static final String USER_DIR = "user.dir";
+    private final UnixFileSystem theFileSystem;
+
+    public UnixFileSystemProvider() {
+        String userDir = System.getProperty(USER_DIR);
+        theFileSystem = newFileSystem(userDir);
+    }
+
+    /**
+     * Constructs a new file system using the given default directory.
+     */
+    abstract UnixFileSystem newFileSystem(String dir);
+
+
+    public final String getScheme() {
+        return "file";
+    }
+
+    private void checkUri(URI uri) {
+        if (!uri.getScheme().equalsIgnoreCase(getScheme()))
+            throw new IllegalArgumentException("URI does not match this provider");
+        if (uri.getAuthority() != null)
+            throw new IllegalArgumentException("Authority component present");
+        if (uri.getPath() == null)
+            throw new IllegalArgumentException("Path component is undefined");
+        if (!uri.getPath().equals("/"))
+            throw new IllegalArgumentException("Path component should be '/'");
+        if (uri.getQuery() != null)
+            throw new IllegalArgumentException("Query component present");
+        if (uri.getFragment() != null)
+            throw new IllegalArgumentException("Fragment component present");
+    }
+
+
+    public final FileSystem newFileSystem(URI uri, Map<String,?> env) {
+        checkUri(uri);
+        throw new FileSystemAlreadyExistsException();
+    }
+
+
+    public final FileSystem getFileSystem(URI uri) {
+        checkUri(uri);
+        return theFileSystem;
+    }
+
+
+    public Path getPath(URI uri) {
+        return UnixUriUtils.fromUri(theFileSystem, uri);
+    }
+
+    private UnixPath checkPath(Path obj) {
+        if (obj == null)
+            throw new NullPointerException();
+        if (!(obj instanceof UnixPath))
+            throw new ProviderMismatchException();
+        return (UnixPath)obj;
+    }
+
+
+    public final FileChannel newFileChannel(Path obj,
+                                            Set<? extends OpenOption> options,
+                                            FileAttribute<?>... attrs)
+        throws IOException
+    {
+        UnixPath file = checkPath(obj);
+        int mode = UnixFileModeAttribute
+            .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
+        try {
+            return UnixChannelFactory.newFileChannel(file, options, mode);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+            return null;
+        }
+    }
+
+
+    public final AsynchronousFileChannel newAsynchronousFileChannel(Path obj,
+                                                                    Set<? extends OpenOption> options,
+                                                                    ExecutorService executor,
+                                                                    FileAttribute<?>... attrs) throws IOException
+    {
+        UnixPath file = checkPath(obj);
+        int mode = UnixFileModeAttribute
+            .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
+        ThreadPool pool = (executor == null) ? null :
+            ThreadPool.create(ThreadPoolType.CACHED, executor, 0);
+        try {
+            return UnixChannelFactory
+                .newAsynchronousFileChannel(file, options, mode, pool);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(file);
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2007-2008 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 an entry in the mount table.
+ */
+
+class UnixMountEntry {
+    private byte[] name;        // file system name
+    private byte[] dir;         // directory (mount point)
+    private byte[] fstype;      // ufs, nfs, ...
+    private byte[] opts;        // mount options
+    private long dev;           // device ID
+
+    private volatile String optionsAsString;
+
+    UnixMountEntry() {
+    }
+
+    String name() {
+        return new String(name);
+    }
+
+    String fstype() {
+        return new String(fstype);
+    }
+
+    byte[] dir() {
+        return dir;
+    }
+
+    long dev() {
+        return dev;
+    }
+
+    /**
+     * Tells whether the mount entry has the given option.
+     */
+    boolean hasOption(String requested) {
+        if (optionsAsString == null)
+            optionsAsString = new String(opts);
+        for (String opt: optionsAsString.split("\\,", 0)) {
+            if (opt.equals(requested))
+                return true;
+        }
+        return false;
+    }
+
+    // generic option
+    boolean isIgnored() {
+        return hasOption("ignore");
+    }
+
+    // generic option
+    boolean isReadOnly() {
+        return hasOption("ro");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2007-2008 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.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Unix system and library calls.
+ */
+
+class UnixNativeDispatcher {
+    protected UnixNativeDispatcher() { }
+
+    // returns a NativeBuffer containing the given path
+    private static NativeBuffer copyToNativeBuffer(UnixPath path) {
+        byte[] cstr = path.getByteArrayForSysCalls();
+        int size = cstr.length + 1;
+        NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(size);
+        if (buffer == null) {
+            buffer = NativeBuffers.allocNativeBuffer(size);
+        } else {
+            // buffer already contains the path
+            if (buffer.owner() == path)
+                return buffer;
+        }
+        NativeBuffers.copyCStringToNativeBuffer(cstr, buffer);
+        buffer.setOwner(path);
+        return buffer;
+    }
+
+    /**
+     * char *getcwd(char *buf, size_t size);
+     */
+    static native byte[] getcwd();
+
+    /**
+     * int dup(int filedes)
+     */
+    static native int dup(int filedes) throws UnixException;
+
+    /**
+     * int open(const char* path, int oflag, mode_t mode)
+     */
+    static int open(UnixPath path, int flags, int mode) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return open0(buffer.address(), flags, mode);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int open0(long pathAddress, int flags, int mode)
+        throws UnixException;
+
+    /**
+     * int openat(int dfd, const char* path, int oflag, mode_t mode)
+     */
+    static int openat(int dfd, byte[] path, int flags, int mode) throws UnixException {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
+        try {
+            return openat0(dfd, buffer.address(), flags, mode);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int openat0(int dfd, long pathAddress, int flags, int mode)
+        throws UnixException;
+
+    /**
+     * close(int filedes)
+     */
+    static native void close(int fd);
+
+    /**
+     * FILE* fopen(const char *filename, const char* mode);
+     */
+    static long fopen(UnixPath filename, String mode) throws UnixException {
+        NativeBuffer pathBuffer = copyToNativeBuffer(filename);
+        NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(mode.getBytes());
+        try {
+            return fopen0(pathBuffer.address(), modeBuffer.address());
+        } finally {
+            modeBuffer.release();
+            pathBuffer.release();
+        }
+    }
+    private static native long fopen0(long pathAddress, long modeAddress)
+        throws UnixException;
+
+    /**
+     * fclose(FILE* stream)
+     */
+    static native void fclose(long stream) throws UnixException;
+
+    /**
+     * link(const char* existing, const char* new)
+     */
+    static void link(UnixPath existing, UnixPath newfile) throws UnixException {
+        NativeBuffer existingBuffer = copyToNativeBuffer(existing);
+        NativeBuffer newBuffer = copyToNativeBuffer(newfile);
+        try {
+            link0(existingBuffer.address(), newBuffer.address());
+        } finally {
+            newBuffer.release();
+            existingBuffer.release();
+        }
+    }
+    private static native void link0(long existingAddress, long newAddress)
+        throws UnixException;
+
+    /**
+     * unlink(const char* path)
+     */
+    static void unlink(UnixPath path) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            unlink0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void unlink0(long pathAddress) throws UnixException;
+
+    /**
+     * unlinkat(int dfd, const char* path, int flag)
+     */
+    static void unlinkat(int dfd, byte[] path, int flag) throws UnixException {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
+        try {
+            unlinkat0(dfd, buffer.address(), flag);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void unlinkat0(int dfd, long pathAddress, int flag)
+        throws UnixException;
+
+    /**
+     * mknod(const char* path, mode_t mode, dev_t dev)
+     */
+    static void mknod(UnixPath path, int mode, long dev) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            mknod0(buffer.address(), mode, dev);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void mknod0(long pathAddress, int mode, long dev)
+        throws UnixException;
+
+    /**
+     *  rename(const char* old, const char* new)
+     */
+    static void rename(UnixPath from, UnixPath to) throws UnixException {
+        NativeBuffer fromBuffer = copyToNativeBuffer(from);
+        NativeBuffer toBuffer = copyToNativeBuffer(to);
+        try {
+            rename0(fromBuffer.address(), toBuffer.address());
+        } finally {
+            toBuffer.release();
+            fromBuffer.release();
+        }
+    }
+    private static native void rename0(long fromAddress, long toAddress)
+        throws UnixException;
+
+    /**
+     *  renameat(int fromfd, const char* old, int tofd, const char* new)
+     */
+    static void renameat(int fromfd, byte[] from, int tofd, byte[] to) throws UnixException {
+        NativeBuffer fromBuffer = NativeBuffers.asNativeBuffer(from);
+        NativeBuffer toBuffer = NativeBuffers.asNativeBuffer(to);
+        try {
+            renameat0(fromfd, fromBuffer.address(), tofd, toBuffer.address());
+        } finally {
+            toBuffer.release();
+            fromBuffer.release();
+        }
+    }
+    private static native void renameat0(int fromfd, long fromAddress, int tofd, long toAddress)
+        throws UnixException;
+
+    /**
+     * mkdir(const char* path, mode_t mode)
+     */
+    static void mkdir(UnixPath path, int mode) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            mkdir0(buffer.address(), mode);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void mkdir0(long pathAddress, int mode) throws UnixException;
+
+    /**
+     * rmdir(const char* path)
+     */
+    static void rmdir(UnixPath path) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            rmdir0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void rmdir0(long pathAddress) throws UnixException;
+
+    /**
+     * readlink(const char* path, char* buf, size_t bufsize)
+     *
+     * @return  link target
+     */
+    static byte[] readlink(UnixPath path) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return readlink0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native byte[] readlink0(long pathAddress) throws UnixException;
+
+    /**
+     * realpath(const char* path, char* resolved_name)
+     *
+     * @return  resolved path
+     */
+    static byte[] realpath(UnixPath path) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return realpath0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native byte[] realpath0(long pathAddress) throws UnixException;
+
+    /**
+     * symlink(const char* name1, const char* name2)
+     */
+    static void symlink(byte[] name1, UnixPath name2) throws UnixException {
+        NativeBuffer targetBuffer = NativeBuffers.asNativeBuffer(name1);
+        NativeBuffer linkBuffer = copyToNativeBuffer(name2);
+        try {
+            symlink0(targetBuffer.address(), linkBuffer.address());
+        } finally {
+            linkBuffer.release();
+            targetBuffer.release();
+        }
+    }
+    private static native void symlink0(long name1, long name2)
+        throws UnixException;
+
+    /**
+     * stat(const char* path, struct stat* buf)
+     */
+    static void stat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            stat0(buffer.address(), attrs);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void stat0(long pathAddress, UnixFileAttributes attrs)
+        throws UnixException;
+
+    /**
+     * lstat(const char* path, struct stat* buf)
+     */
+    static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            lstat0(buffer.address(), attrs);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void lstat0(long pathAddress, UnixFileAttributes attrs)
+        throws UnixException;
+
+    /**
+     * fstat(int filedes, struct stat* buf)
+     */
+    static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException;
+
+    /**
+     * fstatat(int filedes,const char* path,  struct stat* buf, int flag)
+     */
+    static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)
+        throws UnixException
+    {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
+        try {
+            fstatat0(dfd, buffer.address(), flag, attrs);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void fstatat0(int dfd, long pathAddress, int flag,
+        UnixFileAttributes attrs) throws UnixException;
+
+    /**
+     * chown(const char* path, uid_t owner, gid_t group)
+     */
+    static void chown(UnixPath path, int uid, int gid) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            chown0(buffer.address(), uid, gid);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void chown0(long pathAddress, int uid, int gid)
+        throws UnixException;
+
+    /**
+     * lchown(const char* path, uid_t owner, gid_t group)
+     */
+    static void lchown(UnixPath path, int uid, int gid) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            lchown0(buffer.address(), uid, gid);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void lchown0(long pathAddress, int uid, int gid)
+        throws UnixException;
+
+    /**
+     * fchown(int filedes, uid_t owner, gid_t group)
+     */
+    static native void fchown(int fd, int uid, int gid) throws UnixException;
+
+    /**
+     * chmod(const char* path, mode_t mode)
+     */
+    static void chmod(UnixPath path, int mode) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            chmod0(buffer.address(), mode);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void chmod0(long pathAddress, int mode)
+        throws UnixException;
+
+    /**
+     * fchmod(int fildes, mode_t mode)
+     */
+    static native void fchmod(int fd, int mode) throws UnixException;
+
+    /**
+     * utimes(conar char* path, const struct timeval times[2])
+     */
+    static void utimes(UnixPath path, long times0, long times1)
+        throws UnixException
+    {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            utimes0(buffer.address(), times0, times1);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void utimes0(long pathAddress, long times0, long times1)
+        throws UnixException;
+
+    /**
+     * futimes(int fildes,, const struct timeval times[2])
+     */
+    static native void futimes(int fd, long times0, long times1) throws UnixException;
+
+    /**
+     * DIR *opendir(const char* dirname)
+     */
+    static long opendir(UnixPath path) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return opendir0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native long opendir0(long pathAddress) throws UnixException;
+
+    /**
+     * DIR* fdopendir(int filedes)
+     */
+    static native long fdopendir(int dfd) throws UnixException;
+
+
+    /**
+     * closedir(DIR* dirp)
+     */
+    static native void closedir(long dir) throws UnixException;
+
+    /**
+     * struct dirent* readdir(DIR *dirp)
+     *
+     * @return  dirent->d_name
+     */
+    static native byte[] readdir(long dir) throws UnixException;
+
+    /**
+     * size_t read(int fildes, void* buf, size_t nbyte)
+     */
+    static native int read(int fildes, long buf, int nbyte) throws UnixException;
+
+    /**
+     * size_t writeint fildes, void* buf, size_t nbyte)
+     */
+    static native int write(int fildes, long buf, int nbyte) throws UnixException;
+
+    /**
+     * access(const char* path, int amode);
+     */
+    static void access(UnixPath path, int amode) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            access0(buffer.address(), amode);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void access0(long pathAddress, int amode) throws UnixException;
+
+    /**
+     * struct passwd *getpwuid(uid_t uid);
+     *
+     * @return  passwd->pw_name
+     */
+    static native byte[] getpwuid(int uid) throws UnixException;
+
+    /**
+     * struct group *getgrgid(gid_t gid);
+     *
+     * @return  group->gr_name
+     */
+    static native byte[] getgrgid(int gid) throws UnixException;
+
+    /**
+     * struct passwd *getpwnam(const char *name);
+     *
+     * @return  passwd->pw_uid
+     */
+    static int getpwnam(String name) throws UnixException {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(name.getBytes());
+        try {
+            return getpwnam0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int getpwnam0(long nameAddress) throws UnixException;
+
+    /**
+     * struct group *getgrnam(const char *name);
+     *
+     * @return  group->gr_name
+     */
+    static int getgrnam(String name) throws UnixException {
+        NativeBuffer buffer = NativeBuffers.asNativeBuffer(name.getBytes());
+        try {
+            return getgrnam0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int getgrnam0(long nameAddress) throws UnixException;
+
+    /**
+     * int getextmntent(FILE *fp, struct extmnttab *mp, int len);
+     */
+    static native int getextmntent(long fp, UnixMountEntry entry) throws UnixException;
+
+    /**
+     * statvfs(const char* path, struct statvfs *buf)
+     */
+    static void statvfs(UnixPath path, UnixFileStoreAttributes attrs)
+        throws UnixException
+    {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            statvfs0(buffer.address(), attrs);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs)
+        throws UnixException;
+
+    /**
+     * long int pathconf(const char *path, int name);
+     */
+    static long pathconf(UnixPath path, int name) throws UnixException {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return pathconf0(buffer.address(), name);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native long pathconf0(long pathAddress, int name)
+        throws UnixException;
+
+    /**
+     * long fpathconf(int fildes, int name);
+     */
+    static native long fpathconf(int filedes, int name) throws UnixException;
+
+    /**
+     * char* strerror(int errnum)
+     */
+    static native byte[] strerror(int errnum);
+
+    // initialize field IDs
+    private static native void initIDs();
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1174 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.file.spi.AbstractPath;
+import java.nio.channels.*;
+import java.security.AccessController;
+import java.io.*;
+import java.net.URI;
+import java.util.*;
+import sun.security.util.SecurityConstants;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+/**
+ * Solaris/Linux implementation of java.nio.file.Path
+ */
+
+class UnixPath
+    extends AbstractPath
+{
+    // FIXME - eliminate this reference to reduce space
+    private final UnixFileSystem fs;
+
+    // internal representation
+    private final byte[] path;
+
+    // String representation (created lazily)
+    private volatile String stringValue;
+
+    // cached hashcode (created lazily, no need to be volatile)
+    private int hash;
+
+    // array of offsets of elements in path (created lazily)
+    private volatile int[] offsets;
+
+    // file permissions (created lazily)
+    private volatile FilePermission[] perms;
+
+    UnixPath(UnixFileSystem fs, byte[] path) {
+        this.fs = fs;
+        this.path = path;
+    }
+
+    UnixPath(UnixFileSystem fs, String input) {
+        // removes redundant slashes and checks for invalid characters
+        this(fs, normalizeAndCheck(input).getBytes());
+    }
+
+    // package-private
+    // removes redundant slashes and check input for invalid characters
+    static String normalizeAndCheck(String input) {
+        int n = input.length();
+        if (n == 0)
+            throw new InvalidPathException(input, "Path is empty");
+        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);
+            prevChar = c;
+        }
+        if (prevChar == '/')
+            return normalize(input, n, n - 1);
+        return input;
+    }
+
+    private static String normalize(String input, int len, int off) {
+        if (len == 0)
+            return input;
+        int n = len;
+        while ((n > 0) && (input.charAt(n - 1) == '/')) n--;
+        if (n == 0)
+            return "/";
+        StringBuilder sb = new StringBuilder(input.length());
+        if (off > 0)
+            sb.append(input.substring(0, off));
+        char prevChar = 0;
+        for (int i=off; i < n; i++) {
+            char c = input.charAt(i);
+            if ((c == '/') && (prevChar == '/'))
+                continue;
+            sb.append(c);
+            prevChar = c;
+        }
+        return sb.toString();
+    }
+
+    // package-private
+    byte[] asByteArray() {
+        return path;
+    }
+
+    // use this path when making system/library calls
+    byte[] getByteArrayForSysCalls() {
+        // resolve against default directory if required (chdir allowed or
+        // file system default directory is not working directory)
+        if (getFileSystem().needToResolveAgainstDefaultDirectory()) {
+            return resolve(getFileSystem().defaultDirectory(), path);
+        } else {
+            return path;
+        }
+    }
+
+    // use this message when throwing exceptions
+    String getPathForExecptionMessage() {
+        return toString();
+    }
+
+    // use this path for permission checks
+    String getPathForPermissionCheck() {
+        if (getFileSystem().needToResolveAgainstDefaultDirectory()) {
+            return new String(getByteArrayForSysCalls());
+        } else {
+            return toString();
+        }
+    }
+
+    // Checks that the given file is a UnixPath
+    private UnixPath checkPath(FileRef obj) {
+        if (obj == null)
+            throw new NullPointerException();
+        if (!(obj instanceof UnixPath))
+            throw new ProviderMismatchException();
+        return (UnixPath)obj;
+    }
+
+    // create offset list if not already created
+    private void initOffsets() {
+        if (offsets == null) {
+            int count, index;
+
+            // count names
+            count = 0;
+            index = 0;
+            while (index < path.length) {
+                byte c = path[index++];
+                if (c != '/') {
+                    count++;
+                    while (index < path.length && path[index] != '/')
+                        index++;
+                }
+            }
+
+            // populate offsets
+            int[] result = new int[count];
+            count = 0;
+            index = 0;
+            while (index < path.length) {
+                byte c = path[index];
+                if (c == '/') {
+                    index++;
+                } else {
+                    result[count++] = index++;
+                    while (index < path.length && path[index] != '/')
+                        index++;
+                }
+            }
+            synchronized (this) {
+                if (offsets == null)
+                    offsets = result;
+            }
+        }
+    }
+
+
+    public UnixFileSystem getFileSystem() {
+        return fs;
+    }
+
+
+    public UnixPath getRoot() {
+        if (path[0] == '/') {
+            return getFileSystem().rootDirectory();
+        } else {
+            return null;
+        }
+    }
+
+
+    public UnixPath getName() {
+        initOffsets();
+
+        int count = offsets.length;
+        if (count == 0)
+            return null;  // no elements so no name
+
+        if (count == 1 && path[0] != '/')
+            return this;
+
+        int lastOffset = offsets[count-1];
+        int len = path.length - lastOffset;
+        byte[] result = new byte[len];
+        System.arraycopy(path, lastOffset, result, 0, len);
+        return new UnixPath(getFileSystem(), result);
+    }
+
+
+    public UnixPath getParent() {
+        initOffsets();
+
+        int count = offsets.length;
+        if (count == 0) {
+            // no elements so no parent
+            return null;
+        }
+        int len = offsets[count-1] - 1;
+        if (len <= 0) {
+            // parent is root only (may be null)
+            return getRoot();
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(path, 0, result, 0, len);
+        return new UnixPath(getFileSystem(), result);
+    }
+
+
+    public int getNameCount() {
+        initOffsets();
+        return offsets.length;
+    }
+
+
+    public UnixPath getName(int index) {
+        initOffsets();
+        if (index < 0)
+            throw new IllegalArgumentException();
+        if (index >= offsets.length)
+            throw new IllegalArgumentException();
+
+        int begin = offsets[index];
+        int len;
+        if (index == (offsets.length-1)) {
+            len = path.length - begin;
+        } else {
+            len = offsets[index+1] - begin - 1;
+        }
+
+        // construct result
+        byte[] result = new byte[len];
+        System.arraycopy(path, begin, result, 0, len);
+        return new UnixPath(getFileSystem(), result);
+    }
+
+
+    public UnixPath subpath(int beginIndex, int endIndex) {
+        initOffsets();
+
+        if (beginIndex < 0)
+            throw new IllegalArgumentException();
+        if (beginIndex >= offsets.length)
+            throw new IllegalArgumentException();
+        if (endIndex > offsets.length)
+            throw new IllegalArgumentException();
+        if (beginIndex >= endIndex) {
+            throw new IllegalArgumentException();
+        }
+
+        // starting offset and length
+        int begin = offsets[beginIndex];
+        int len;
+        if (endIndex == offsets.length) {
+            len = path.length - begin;
+        } else {
+            len = offsets[endIndex] - begin - 1;
+        }
+
+        // construct result
+        byte[] result = new byte[len];
+        System.arraycopy(path, begin, result, 0, len);
+        return new UnixPath(getFileSystem(), result);
+    }
+
+
+    public boolean isAbsolute() {
+        return (path[0] == '/');
+    }
+
+    // Resolve child against given base
+    private static byte[] resolve(byte[] base, byte[] child) {
+        if (child[0] == '/')
+            return child;
+        byte[] result;
+        if (base.length == 1 && base[0] == '/') {
+            result = new byte[child.length + 1];
+            result[0] = '/';
+            System.arraycopy(child, 0, result, 1, child.length);
+        } else {
+            result = new byte[base.length + 1 + child.length];
+            System.arraycopy(base, 0, result, 0, base.length);
+            result[base.length] = '/';
+            System.arraycopy(child, 0, result,  base.length+1, child.length);
+        }
+        return result;
+    }
+
+
+    public UnixPath resolve(Path obj) {
+        if (obj == null)
+            return this;
+        byte[] other = checkPath(obj).path;
+        if (other[0] == '/')
+            return ((UnixPath)obj);
+        byte[] result = resolve(path, other);
+        return new UnixPath(getFileSystem(), result);
+    }
+
+
+    public UnixPath resolve(String other) {
+        return resolve(new UnixPath(getFileSystem(), other));
+    }
+
+    UnixPath resolve(byte[] other) {
+        return resolve(new UnixPath(getFileSystem(), other));
+    }
+
+
+    public UnixPath relativize(Path obj) {
+        UnixPath other = checkPath(obj);
+        if (other.equals(this))
+            return null;
+
+        // can only relativize paths of the same type
+        if (this.isAbsolute() != other.isAbsolute())
+            throw new IllegalArgumentException("'other' is different type of Path");
+
+        int bn = this.getNameCount();
+        int cn = other.getNameCount();
+
+        // skip matching names
+        int n = (bn > cn) ? cn : bn;
+        int i = 0;
+        while (i < n) {
+            if (!this.getName(i).equals(other.getName(i)))
+                break;
+            i++;
+        }
+
+        int dotdots = bn - i;
+        if (i < cn) {
+            // remaining name components in other
+            UnixPath remainder = other.subpath(i, cn);
+            if (dotdots == 0)
+                return remainder;
+
+            // result is a  "../" for each remaining name in base
+            // followed by the remaining names in other
+            byte[] result = new byte[dotdots*3 + remainder.path.length];
+            int pos = 0;
+            while (dotdots > 0) {
+                result[pos++] = (byte)'.';
+                result[pos++] = (byte)'.';
+                result[pos++] = (byte)'/';
+                dotdots--;
+            }
+            System.arraycopy(remainder.path, 0, result, pos, remainder.path.length);
+            return new UnixPath(getFileSystem(), result);
+        } else {
+            // no remaining names in other so result is simply a sequence of ".."
+            byte[] result = new byte[dotdots*3 - 1];
+            int pos = 0;
+            while (dotdots > 0) {
+                result[pos++] = (byte)'.';
+                result[pos++] = (byte)'.';
+                // no tailing slash at the end
+                if (dotdots > 1)
+                    result[pos++] = (byte)'/';
+                dotdots--;
+            }
+            return new UnixPath(getFileSystem(), result);
+        }
+    }
+
+
+    public Path normalize() {
+        final int count = getNameCount();
+        if (count == 0)
+            return this;
+
+        boolean[] ignore = new boolean[count];      // true => ignore name
+        int[] size = new int[count];                // length of name
+        int remaining = count;                      // number of names remaining
+        boolean hasDotDot = false;                  // has at least one ..
+        boolean isAbsolute = path[0] == '/';
+
+        // first pass:
+        //   1. compute length of names
+        //   2. mark all occurences of "." to ignore
+        //   3. and look for any occurences of ".."
+        for (int i=0; i<count; i++) {
+            int begin = offsets[i];
+            int len;
+            if (i == (offsets.length-1)) {
+                len = path.length - begin;
+            } else {
+                len = offsets[i+1] - begin - 1;
+            }
+            size[i] = len;
+
+            if (path[begin] == '.') {
+                if (len == 1) {
+                    ignore[i] = true;  // ignore  "."
+                    remaining--;
+                }
+                else {
+                    if (path[begin+1] == '.')   // ".." found
+                        hasDotDot = true;
+                }
+            }
+        }
+
+        // multiple passes to eliminate all occurences of name/..
+        if (hasDotDot) {
+            int prevRemaining;
+            do {
+                prevRemaining = remaining;
+                int prevName = -1;
+                for (int i=0; i<count; i++) {
+                    if (ignore[i])
+                        continue;
+
+                    // not a ".."
+                    if (size[i] != 2) {
+                        prevName = i;
+                        continue;
+                    }
+
+                    int begin = offsets[i];
+                    if (path[begin] != '.' || path[begin+1] != '.') {
+                        prevName = i;
+                        continue;
+                    }
+
+                    // ".." found
+                    if (prevName >= 0) {
+                        // name/<ignored>/.. found so mark name and ".." to be
+                        // ignored
+                        ignore[prevName] = true;
+                        ignore[i] = true;
+                        remaining = remaining - 2;
+                        prevName = -1;
+                    } else {
+                        // Case: /<ignored>/.. so mark ".." as ignored
+                        if (isAbsolute) {
+                            boolean hasPrevious = false;
+                            for (int j=0; j<i; j++) {
+                                if (!ignore[j]) {
+                                    hasPrevious = true;
+                                    break;
+                                }
+                            }
+                            if (!hasPrevious) {
+                                // all proceeding names are ignored
+                                ignore[i] = true;
+                                remaining--;
+                            }
+                        }
+                    }
+                }
+            } while (prevRemaining > remaining);
+        }
+
+        // no redundant names
+        if (remaining == count)
+            return this;
+
+        // corner case - all names removed
+        if (remaining == 0) {
+            return isAbsolute ? getFileSystem().rootDirectory() : null;
+        }
+
+        // compute length of result
+        int len = remaining - 1;
+        if (isAbsolute)
+            len++;
+
+        for (int i=0; i<count; i++) {
+            if (!ignore[i])
+                len += size[i];
+        }
+        byte[] result = new byte[len];
+
+        // copy names into result
+        int pos = 0;
+        if (isAbsolute)
+            result[pos++] = '/';
+        for (int i=0; i<count; i++) {
+            if (!ignore[i]) {
+                System.arraycopy(path, offsets[i], result, pos, size[i]);
+                pos += size[i];
+                if (--remaining > 0) {
+                    result[pos++] = '/';
+                }
+            }
+        }
+        return new UnixPath(getFileSystem(), result);
+    }
+
+
+    public boolean startsWith(Path other) {
+        UnixPath that = checkPath(other);
+
+        // other path is longer
+        if (that.path.length > path.length) {
+            return false;
+        }
+
+        int thisOffsetCount = getNameCount();
+        int thatOffsetCount = that.getNameCount();
+
+        // given path has more elements that this path
+        if (thatOffsetCount > thisOffsetCount) {
+            return false;
+        }
+
+        // same number of elements so must be exact match
+        if ((thatOffsetCount == thisOffsetCount) &&
+            (path.length != that.path.length)) {
+            return false;
+        }
+
+        // check offsets of elements match
+        for (int i=0; i<thatOffsetCount; i++) {
+            Integer o1 = offsets[i];
+            Integer o2 = that.offsets[i];
+            if (!o1.equals(o2))
+                return false;
+        }
+
+        // offsets match so need to compare bytes
+        int i=0;
+        while (i < that.path.length) {
+            if (this.path[i] != that.path[i])
+                return false;
+            i++;
+        }
+
+        // final check that match is on name boundary
+        if (i < path.length && this.path[i] != '/') {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    public boolean endsWith(Path other) {
+        UnixPath that = checkPath(other);
+
+        // other path is longer
+        if (that.path.length > path.length) {
+            return false;
+        }
+
+        int thisOffsetCount = getNameCount();
+        int thatOffsetCount = that.getNameCount();
+
+        // given path has more elements that this path
+        if (thatOffsetCount > thisOffsetCount) {
+            return false;
+        }
+
+        // same number of elements so must be same length
+        if (thatOffsetCount == thisOffsetCount) {
+            if (path.length != that.path.length)
+                return false;
+            if (thisOffsetCount == 0)
+                return true;
+        }
+
+        // this path has more elements so given path must be relative
+        if (thatOffsetCount < thisOffsetCount && that.isAbsolute()) {
+            return false;
+        }
+
+        // compare bytes
+        int thisPos = offsets[thisOffsetCount - thatOffsetCount];
+        int thisRemaining = path.length - thisPos;
+        if (thisRemaining != that.path.length)
+            return false;
+        int thatPos = that.offsets[0];
+        while (thatPos < that.path.length) {
+            if (this.path[thisPos++] != that.path[thatPos++])
+                return false;
+        }
+
+        return true;
+    }
+
+
+    public int compareTo(Path other) {
+        int len1 = path.length;
+        int len2 = ((UnixPath) other).path.length;
+
+        int n = Math.min(len1, len2);
+        byte v1[] = path;
+        byte v2[] = ((UnixPath) other).path;
+
+        int k = 0;
+        while (k < n) {
+            int c1 = v1[k] & 0xff;
+            int c2 = v2[k] & 0xff;
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+            k++;
+        }
+        return len1 - len2;
+    }
+
+
+    public boolean equals(Object ob) {
+        if ((ob != null) && (ob instanceof UnixPath)) {
+            return compareTo((Path)ob) == 0;
+        }
+        return false;
+    }
+
+
+    public int hashCode() {
+        // OK if two or more threads compute hash
+        int h = hash;
+        if (h == 0) {
+            for (int i = 0; i< path.length; i++) {
+                h = 31*h + (path[i] & 0xff);
+            }
+            hash = h;
+        }
+        return h;
+    }
+
+
+    public String toString() {
+        // OK if two or more threads create a String
+        if (stringValue == null)
+            stringValue = new String(path);     // platform encoding
+        return stringValue;
+    }
+
+
+    public Iterator<Path> iterator() {
+        initOffsets();
+        return new Iterator<Path>() {
+            int i = 0;
+
+            public boolean hasNext() {
+                return (i < offsets.length);
+            }
+
+            public Path next() {
+                if (i < offsets.length) {
+                    Path result = getName(i);
+                    i++;
+                    return result;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    // -- file operations --
+
+    // package-private
+    int openForAttributeAccess(boolean followLinks) throws IOException {
+        int flags = O_RDONLY;
+        if (!followLinks)
+            flags |= O_NOFOLLOW;
+        try {
+            return open(this, flags, 0);
+        } catch (UnixException x) {
+            // HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380)
+            if (getFileSystem().isSolaris() && x.errno() == EINVAL)
+                x.setError(ELOOP);
+
+            if (x.errno() == ELOOP)
+                throw new FileSystemException(getPathForExecptionMessage(), null,
+                    x.getMessage() + " or unable to access attributes of symbolic link");
+
+            x.rethrowAsIOException(this);
+            return -1; // keep compile happy
+        }
+    }
+
+    // create file permissions used for read and write checks
+    private void checkReadOrWrite(boolean checkRead) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null)
+            return;
+        if (perms == null) {
+            synchronized (this) {
+                if (perms == null) {
+                    FilePermission[] p = new FilePermission[2];
+                    String pathForPermCheck = getPathForPermissionCheck();
+                    p[0] = new FilePermission(pathForPermCheck,
+                        SecurityConstants.FILE_READ_ACTION);
+                    p[1] = new FilePermission(pathForPermCheck,
+                        SecurityConstants.FILE_WRITE_ACTION);
+                    perms = p;
+                }
+            }
+        }
+        if (checkRead) {
+            sm.checkPermission(perms[0]);
+        } else {
+            sm.checkPermission(perms[1]);
+        }
+    }
+
+    void checkRead() {
+        checkReadOrWrite(true);
+    }
+
+    void checkWrite() {
+        checkReadOrWrite(false);
+    }
+
+    void checkDelete() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            // permission not cached
+            sm.checkDelete(getPathForPermissionCheck());
+        }
+    }
+
+
+    public FileStore getFileStore()
+        throws IOException
+    {
+        checkRead();
+        return getFileSystem().getFileStore(this);
+    }
+
+
+    public void checkAccess(AccessMode... modes) throws IOException {
+        boolean e = false;
+        boolean r = false;
+        boolean w = false;
+        boolean x = false;
+
+        if (modes.length == 0) {
+            e = true;
+        } else {
+            for (AccessMode mode: modes) {
+                switch (mode) {
+                    case READ : r = true; break;
+                    case WRITE : w = true; break;
+                    case EXECUTE : x = true; break;
+                    default: throw new AssertionError("Should not get here");
+                }
+            }
+        }
+
+        int mode = 0;
+        if (e || r) {
+            checkRead();
+            mode |= (r) ? R_OK : F_OK;
+        }
+        if (w) {
+            checkWrite();
+            mode |= W_OK;
+        }
+        if (x) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                // not cached
+                sm.checkExec(getPathForPermissionCheck());
+            }
+            mode |= X_OK;
+        }
+        try {
+            access(this, mode);
+        } catch (UnixException exc) {
+            exc.rethrowAsIOException(this);
+        }
+    }
+
+
+    public void delete(boolean failIfNotExists) throws IOException {
+        checkDelete();
+
+        // need file attributes to know if file is directory
+        UnixFileAttributes attrs = null;
+        try {
+            attrs = UnixFileAttributes.get(this, false);
+            if (attrs.isDirectory()) {
+                rmdir(this);
+            } else {
+                unlink(this);
+            }
+        } catch (UnixException x) {
+            // no-op if file does not exist
+            if (!failIfNotExists && x.errno() == ENOENT)
+                return;
+
+            // DirectoryNotEmptyException if not empty
+            if (attrs != null && attrs.isDirectory() &&
+                (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
+                throw new DirectoryNotEmptyException(getPathForExecptionMessage());
+
+            x.rethrowAsIOException(this);
+        }
+    }
+
+
+    public DirectoryStream<Path> newDirectoryStream(DirectoryStream.Filter<? super Path> filter)
+        throws IOException
+    {
+        if (filter == null)
+            throw new NullPointerException();
+        checkRead();
+
+        // can't return SecureDirectoryStream on older kernels.
+        if (!getFileSystem().supportsSecureDirectoryStreams()) {
+            try {
+                long ptr = opendir(this);
+                return new UnixDirectoryStream(this, ptr, filter);
+            } catch (UnixException x) {
+                if (x.errno() == UnixConstants.ENOTDIR)
+                    throw new NotDirectoryException(getPathForExecptionMessage());
+                x.rethrowAsIOException(this);
+            }
+        }
+
+        // open directory and dup file descriptor for use by
+        // opendir/readdir/closedir
+        int dfd1 = -1;
+        int dfd2 = -1;
+        long dp = 0L;
+        try {
+            dfd1 = open(this, O_RDONLY, 0);
+            dfd2 = dup(dfd1);
+            dp = fdopendir(dfd1);
+        } catch (UnixException x) {
+            if (dfd1 != -1)
+                close(dfd1);
+            if (dfd2 != -1)
+                close(dfd2);
+            if (x.errno() == UnixConstants.ENOTDIR)
+                throw new NotDirectoryException(getPathForExecptionMessage());
+            x.rethrowAsIOException(this);
+        }
+        return new UnixSecureDirectoryStream(this, dp, dfd2, filter);
+    }
+
+    // invoked by AbstractPath#copyTo
+
+    public void implCopyTo(Path obj, CopyOption... options)
+        throws IOException
+    {
+        UnixPath target = (UnixPath)obj;
+        UnixCopyFile.copy(this, target, options);
+    }
+
+
+    public void implMoveTo(Path obj, CopyOption... options)
+        throws IOException
+    {
+        UnixPath target = (UnixPath)obj;
+        UnixCopyFile.move(this, target, options);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V
+        getFileAttributeView(Class<V> type, LinkOption... options)
+    {
+        FileAttributeView view = getFileSystem()
+            .newFileAttributeView(type, this, options);
+        if (view == null)
+            return null;
+        return (V) view;
+    }
+
+
+    public FileAttributeView getFileAttributeView(String name, LinkOption... options) {
+        return getFileSystem().newFileAttributeView(name, this, options);
+    }
+
+
+    public Path createDirectory(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkWrite();
+
+        int mode = UnixFileModeAttribute
+            .toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs);
+        try {
+            mkdir(this, mode);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(this);
+        }
+        return this;
+    }
+
+
+    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
+        }
+    }
+
+
+    public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+                                                      FileAttribute<?>... attrs)
+         throws IOException
+    {
+        int mode = UnixFileModeAttribute
+            .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
+        try {
+            return UnixChannelFactory.newFileChannel(this, options, mode);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(this);
+            return null;  // keep compiler happy
+        }
+    }
+
+
+    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
+        }
+    }
+
+
+    public boolean isSameFile(FileRef obj) throws IOException {
+        if (this.equals(obj))
+            return true;
+        if (!(obj instanceof UnixPath))  // includes null check
+            return false;
+        UnixPath other = (UnixPath)obj;
+
+        // check security manager access to both files
+        this.checkRead();
+        other.checkRead();
+
+        UnixFileAttributes thisAttrs;
+        UnixFileAttributes otherAttrs;
+        try {
+             thisAttrs = UnixFileAttributes.get(this, true);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(this);
+            return false;    // keep compiler happy
+        }
+        try {
+            otherAttrs = UnixFileAttributes.get(other, true);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(other);
+            return false;    // keep compiler happy
+        }
+        return thisAttrs.isSameFile(otherAttrs);
+    }
+
+
+    public Path createSymbolicLink(Path obj, FileAttribute<?>... attrs)
+        throws IOException
+    {
+        UnixPath target = checkPath(obj);
+
+        // no attributes supported when creating links
+        for (FileAttribute<?> attr: attrs) {
+            if (attr == null)
+                throw new NullPointerException();
+            throw new ProviderMismatchException();
+        }
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new LinkPermission("symbolic"));
+            checkWrite();
+        }
+
+        // create link
+        try {
+            symlink(target.asByteArray(), this);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(this);
+        }
+
+        return this;
+    }
+
+
+    public Path createLink(Path obj) throws IOException {
+        UnixPath existing = checkPath(obj);
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new LinkPermission("hard"));
+            this.checkWrite();
+            existing.checkWrite();
+        }
+        try {
+            link(existing, this);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(this, existing);
+        }
+        return this;
+    }
+
+
+    public Path readSymbolicLink() throws IOException {
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            FilePermission perm = new FilePermission(getPathForPermissionCheck(),
+                SecurityConstants.FILE_READLINK_ACTION);
+            AccessController.checkPermission(perm);
+        }
+        try {
+            byte[] target = readlink(this);
+            return new UnixPath(getFileSystem(), target);
+        } catch (UnixException x) {
+           if (x.errno() == UnixConstants.EINVAL)
+                throw new NotLinkException(getPathForExecptionMessage());
+            x.rethrowAsIOException(this);
+            return null;    // keep compiler happy
+        }
+    }
+
+
+    public UnixPath toAbsolutePath() {
+        if (isAbsolute()) {
+            return this;
+        }
+        // The path is relative so need to resolve against default directory,
+        // taking care not to reveal the user.dir
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPropertyAccess("user.dir");
+        }
+        return new UnixPath(getFileSystem(),
+            resolve(getFileSystem().defaultDirectory(), path));
+    }
+
+
+    public UnixPath toRealPath(boolean resolveLinks) throws IOException {
+        checkRead();
+
+        UnixPath absolute = toAbsolutePath();
+
+        // if resolveLinks is true then use realpath
+        if (resolveLinks) {
+            try {
+                byte[] rp = realpath(absolute);
+                return new UnixPath(getFileSystem(), rp);
+            } catch (UnixException x) {
+                x.rethrowAsIOException(this);
+            }
+        }
+
+        // if resolveLinks is false then eliminate "." and also ".."
+        // where the previous element is not a link.
+        UnixPath root = getFileSystem().rootDirectory();
+        UnixPath result = root;
+        for (int i=0; i<absolute.getNameCount(); i++) {
+            UnixPath element = absolute.getName(i);
+
+            // eliminate "."
+            if ((element.asByteArray().length == 1) && (element.asByteArray()[0] == '.'))
+                continue;
+
+            // cannot eliminate ".." if previous element is a link
+            if ((element.asByteArray().length == 2) && (element.asByteArray()[0] == '.') &&
+                (element.asByteArray()[1] == '.'))
+            {
+                UnixFileAttributes attrs = null;
+                try {
+                    attrs = UnixFileAttributes.get(result, false);
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(result);
+                }
+                if (!attrs.isSymbolicLink()) {
+                    result = result.getParent();
+                    if (result == null) {
+                        result = root;
+                    }
+                    continue;
+                }
+            }
+            result = result.resolve(element);
+        }
+
+        // finally check that file exists
+        try {
+            UnixFileAttributes.get(result, true);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(result);
+        }
+        return result;
+    }
+
+
+    public boolean isHidden() {
+        checkRead();
+        UnixPath name = getName();
+        if (name == null)
+            return false;
+        return (name.asByteArray()[0] == '.');
+    }
+
+
+    public URI toUri() {
+        return UnixUriUtils.toUri(this);
+    }
+
+
+    public WatchKey register(WatchService watcher,
+                             WatchEvent.Kind<?>[] events,
+                             WatchEvent.Modifier... modifiers)
+        throws IOException
+    {
+        if (watcher == null)
+            throw new NullPointerException();
+        if (!(watcher instanceof AbstractWatchService))
+            throw new ProviderMismatchException();
+        checkRead();
+        return ((AbstractWatchService)watcher).register(this, events, modifiers);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,643 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.channels.SeekableByteChannel;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.io.IOException;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+
+/**
+ * Unix implementation of SecureDirectoryStream.
+ */
+
+class UnixSecureDirectoryStream
+    extends SecureDirectoryStream
+{
+    private final UnixDirectoryStream ds;
+    private final int dfd;
+
+    UnixSecureDirectoryStream(UnixPath dir,
+                              long dp,
+                              int dfd,
+                              DirectoryStream.Filter<? super Path> filter)
+    {
+        this.ds = new UnixDirectoryStream(dir, dp, filter);
+        this.dfd = dfd;
+    }
+
+
+    public void close()
+        throws IOException
+    {
+        ds.writeLock().lock();
+        try {
+            if (ds.closeImpl()) {
+                UnixNativeDispatcher.close(dfd);
+            }
+        } finally {
+            ds.writeLock().unlock();
+        }
+    }
+
+
+    public Iterator<Path> iterator() {
+        return ds.iterator(this);
+    }
+
+    private UnixPath getName(Path obj) {
+        if (obj == null)
+            throw new NullPointerException();
+        if (!(obj instanceof UnixPath))
+            throw new ProviderMismatchException();
+        return (UnixPath)obj;
+    }
+
+    /**
+     * Opens sub-directory in this directory
+     */
+
+    public SecureDirectoryStream newDirectoryStream(Path obj,
+                                                    boolean followLinks,
+                                                    DirectoryStream.Filter<? super Path> filter)
+        throws IOException
+    {
+        UnixPath file = getName(obj);
+        UnixPath child = ds.directory().resolve(file);
+
+        // permission check using name resolved against original path of directory
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            child.checkRead();
+        }
+
+        ds.readLock().lock();
+        try {
+            if (!ds.isOpen())
+                throw new ClosedDirectoryStreamException();
+
+            // open directory and create new secure directory stream
+            int newdfd1 = -1;
+            int newdfd2 = -1;
+            long ptr = 0L;
+            try {
+                int flags = O_RDONLY;
+                if (!followLinks)
+                    flags |= O_NOFOLLOW;
+                newdfd1 = openat(dfd, file.asByteArray(), flags , 0);
+                newdfd2 = dup(newdfd1);
+                ptr = fdopendir(newdfd1);
+            } catch (UnixException x) {
+                if (newdfd1 != -1)
+                    UnixNativeDispatcher.close(newdfd1);
+                if (newdfd2 != -1)
+                    UnixNativeDispatcher.close(newdfd2);
+                if (x.errno() == UnixConstants.ENOTDIR)
+                    throw new NotDirectoryException(file.toString());
+                x.rethrowAsIOException(file);
+            }
+            return new UnixSecureDirectoryStream(child, ptr, newdfd2, filter);
+        } finally {
+            ds.readLock().unlock();
+        }
+    }
+
+    /**
+     * Opens file in this directory
+     */
+
+    public SeekableByteChannel newByteChannel(Path obj,
+                                              Set<? extends OpenOption> options,
+                                              FileAttribute<?>... attrs)
+        throws IOException
+    {
+        UnixPath file = getName(obj);
+
+        int mode = UnixFileModeAttribute
+            .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
+
+        // path for permission check
+        String pathToCheck = ds.directory().resolve(file).getPathForPermissionCheck();
+
+        ds.readLock().lock();
+        try {
+            if (!ds.isOpen())
+                throw new ClosedDirectoryStreamException();
+            try {
+                return UnixChannelFactory.newFileChannel(dfd, file, pathToCheck, options, mode);
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+                return null; // keep compiler happy
+            }
+        } finally {
+            ds.readLock().unlock();
+        }
+    }
+
+    /**
+     * Deletes file/directory in this directory. Works in a race-free manner
+     * when invoked with flags.
+     */
+    void implDelete(Path obj, boolean haveFlags, int flags)
+        throws IOException
+    {
+        UnixPath file = getName(obj);
+
+        // permission check using name resolved against original path of directory
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            ds.directory().resolve(file).checkDelete();
+        }
+
+        ds.readLock().lock();
+        try {
+            if (!ds.isOpen())
+                throw new ClosedDirectoryStreamException();
+
+            if (!haveFlags) {
+                // need file attribute to know if file is directory. This creates
+                // a race in that the file may be replaced by a directory or a
+                // directory replaced by a file between the time we query the
+                // file type and unlink it.
+                UnixFileAttributes attrs = null;
+                try {
+                    attrs = UnixFileAttributes.get(dfd, file, false);
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(file);
+                }
+                flags = (attrs.isDirectory()) ? AT_REMOVEDIR : 0;
+            }
+
+            try {
+                unlinkat(dfd, file.asByteArray(), flags);
+            } catch (UnixException x) {
+                if ((flags & AT_REMOVEDIR) != 0) {
+                    if (x.errno() == EEXIST || x.errno() == ENOTEMPTY) {
+                        throw new DirectoryNotEmptyException(null);
+                    }
+                }
+                x.rethrowAsIOException(file);
+            }
+        } finally {
+            ds.readLock().unlock();
+        }
+    }
+
+
+    public void deleteFile(Path file) throws IOException {
+        implDelete(file, true, 0);
+    }
+
+
+    public void deleteDirectory(Path dir) throws IOException {
+        implDelete(dir, true, AT_REMOVEDIR);
+    }
+
+    /**
+     * Rename/move file in this directory to another (open) directory
+     */
+
+    public void move(Path fromObj, SecureDirectoryStream dir, Path toObj)
+        throws IOException
+    {
+        UnixPath from = getName(fromObj);
+        UnixPath to = getName(toObj);
+        if (dir == null)
+            throw new NullPointerException();
+        if (!(dir instanceof UnixSecureDirectoryStream))
+            throw new ProviderMismatchException();
+        UnixSecureDirectoryStream that = (UnixSecureDirectoryStream)dir;
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            this.ds.directory().resolve(from).checkWrite();
+            that.ds.directory().resolve(to).checkWrite();
+        }
+
+        // lock ordering doesn't matter
+        this.ds.readLock().lock();
+        try {
+            that.ds.readLock().lock();
+            try {
+                if (!this.ds.isOpen() || !that.ds.isOpen())
+                    throw new ClosedDirectoryStreamException();
+                try {
+                    renameat(this.dfd, from.asByteArray(), that.dfd, to.asByteArray());
+                } catch (UnixException x) {
+                    if (x.errno() == EXDEV) {
+                        throw new AtomicMoveNotSupportedException(
+                            from.toString(), to.toString(), x.errorString());
+                    }
+                    x.rethrowAsIOException(from, to);
+                }
+            } finally {
+                that.ds.readLock().unlock();
+            }
+        } finally {
+            this.ds.readLock().unlock();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private <V extends FileAttributeView> V getFileAttributeViewImpl(UnixPath file,
+                                                                     Class<V> type,
+                                                                     boolean followLinks)
+    {
+        if (type == null)
+            throw new NullPointerException();
+        Class<?> c = type;
+        if (c == BasicFileAttributeView.class) {
+            return (V) new BasicFileAttributeViewImpl(file, followLinks);
+        }
+        if (c == PosixFileAttributeView.class || c == FileOwnerAttributeView.class) {
+            return (V) new PosixFileAttributeViewImpl(file, followLinks);
+        }
+        // TBD - should also support AclFileAttributeView
+        return (V) null;
+    }
+
+    /**
+     * Returns file attribute view bound to this directory
+     */
+
+    public <V extends FileAttributeView> V getFileAttributeView(Class<V> type) {
+        return getFileAttributeViewImpl(null, type, false);
+    }
+
+    /**
+     * Returns file attribute view bound to dfd/filename.
+     */
+
+    public <V extends FileAttributeView> V getFileAttributeView(Path obj,
+                                                                Class<V> type,
+                                                                LinkOption... options)
+    {
+        UnixPath file = getName(obj);
+        boolean followLinks = file.getFileSystem().followLinks(options);
+        return getFileAttributeViewImpl(file, type, followLinks);
+    }
+
+    /**
+     * A BasicFileAttributeView implementation that using a dfd/name pair.
+     */
+    private class BasicFileAttributeViewImpl
+        extends AbstractBasicFileAttributeView
+    {
+        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;
+            this.followLinks = followLinks;
+        }
+
+        int open() throws IOException {
+            int oflags = O_RDONLY;
+            if (!followLinks)
+                oflags |= O_NOFOLLOW;
+            try {
+                return openat(dfd, file.asByteArray(), oflags, 0);
+            } catch (UnixException x) {
+                x.rethrowAsIOException(file);
+                return -1; // keep compiler happy
+            }
+        }
+
+        private void checkWriteAccess() {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                ds.directory().resolve(file).checkWrite();
+            }
+        }
+
+
+        public String name() {
+            return "basic";
+        }
+
+
+        public BasicFileAttributes readAttributes() throws IOException {
+            ds.readLock().lock();
+            try {
+                if (!ds.isOpen())
+                    throw new ClosedDirectoryStreamException();
+
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    if (file == null) {
+                        ds.directory().checkRead();
+                    } else {
+                        ds.directory().resolve(file).checkRead();
+                    }
+                }
+                try {
+                     UnixFileAttributes attrs = (file == null) ?
+                         UnixFileAttributes.get(dfd) :
+                         UnixFileAttributes.get(dfd, file, followLinks);
+
+                     // SECURITY: must return as BasicFileAttribute
+                     return attrs.asBasicFileAttributes();
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(file);
+                    return null;    // keep compiler happy
+                }
+            } finally {
+                ds.readLock().unlock();
+            }
+        }
+
+
+        public void setTimes(Long lastModifiedTime,
+                             Long lastAccessTime,
+                             Long createTime, // ignore
+                             TimeUnit unit)
+            throws IOException
+        {
+            // no effect
+            if (lastModifiedTime == null && lastAccessTime == null) {
+                return;
+            }
+
+            checkWriteAccess();
+
+            ds.readLock().lock();
+            try {
+                if (!ds.isOpen())
+                    throw new ClosedDirectoryStreamException();
+
+                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);
+                        } 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();
+                        }
+                    }
+
+                    try {
+                        futimes(fd, accTime, modTime);
+                    } catch (UnixException x) {
+                        x.rethrowAsIOException(file);
+                    }
+                } finally {
+                    if (file != null)
+                        UnixNativeDispatcher.close(fd);
+                }
+            } finally {
+                ds.readLock().unlock();
+            }
+        }
+    }
+
+    /**
+     * A PosixFileAttributeView implementation that using a dfd/name pair.
+     */
+    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);
+        }
+
+        private void checkWriteAndUserAccess() {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                super.checkWriteAccess();
+                sm.checkPermission(new RuntimePermission("accessUserInformation"));
+            }
+        }
+
+
+        public String name() {
+            return "posix";
+        }
+
+
+        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);
+        }
+
+
+        @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());
+        }
+
+
+        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();
+        }
+
+
+        public PosixFileAttributes readAttributes() throws IOException {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                if (file == null)
+                    ds.directory().checkRead();
+                else
+                    ds.directory().resolve(file).checkRead();
+                sm.checkPermission(new RuntimePermission("accessUserInformation"));
+            }
+
+            ds.readLock().lock();
+            try {
+                if (!ds.isOpen())
+                    throw new ClosedDirectoryStreamException();
+
+                try {
+                     UnixFileAttributes attrs = (file == null) ?
+                         UnixFileAttributes.get(dfd) :
+                         UnixFileAttributes.get(dfd, file, followLinks);
+                     return attrs;
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(file);
+                    return null;    // keep compiler happy
+                }
+            } finally {
+                ds.readLock().unlock();
+            }
+        }
+
+
+        public void setPermissions(Set<PosixFilePermission> perms)
+            throws IOException
+        {
+            // permission check
+            checkWriteAndUserAccess();
+
+            ds.readLock().lock();
+            try {
+                if (!ds.isOpen())
+                    throw new ClosedDirectoryStreamException();
+
+                int fd = (file == null) ? dfd : open();
+                try {
+                    fchmod(fd, UnixFileModeAttribute.toUnixMode(perms));
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(file);
+                } finally {
+                    if (file != null && fd >= 0)
+                        UnixNativeDispatcher.close(fd);
+                }
+            } finally {
+                ds.readLock().unlock();
+            }
+        }
+
+        private void setOwners(int uid, int gid) throws IOException {
+            // permission check
+            checkWriteAndUserAccess();
+
+            ds.readLock().lock();
+            try {
+                if (!ds.isOpen())
+                    throw new ClosedDirectoryStreamException();
+
+                int fd = (file == null) ? dfd : open();
+                try {
+                    fchown(fd, uid, gid);
+                } catch (UnixException x) {
+                    x.rethrowAsIOException(file);
+                } finally {
+                    if (file != null && fd >= 0)
+                        UnixNativeDispatcher.close(fd);
+                }
+            } finally {
+                ds.readLock().unlock();
+            }
+        }
+
+
+        public UserPrincipal getOwner() throws IOException {
+            return readAttributes().owner();
+        }
+
+
+        public void setOwner(UserPrincipal owner)
+            throws IOException
+        {
+            if (!(owner instanceof UnixUserPrincipals.User))
+                throw new ProviderMismatchException();
+            if (owner instanceof UnixUserPrincipals.Group)
+                throw new IOException("'owner' parameter can't be a group");
+            int uid = ((UnixUserPrincipals.User)owner).uid();
+            setOwners(uid, -1);
+        }
+
+
+        public void setGroup(GroupPrincipal group)
+            throws IOException
+        {
+            if (!(group instanceof UnixUserPrincipals.Group))
+                throw new ProviderMismatchException();
+            int gid = ((UnixUserPrincipals.Group)group).gid();
+            setOwners(-1, gid);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2007-2008 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.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Unix specific Path <--> URI conversion
+ */
+
+class UnixUriUtils {
+    private UnixUriUtils() { }
+
+    /**
+     * Converts URI to Path
+     */
+    static UnixPath fromUri(UnixFileSystem fs, URI uri) {
+        if (!uri.isAbsolute())
+            throw new IllegalArgumentException("URI is not absolute");
+        if (uri.isOpaque())
+            throw new IllegalArgumentException("URI is not hierarchical");
+        String scheme = uri.getScheme();
+        if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
+            throw new IllegalArgumentException("URI scheme is not \"file\"");
+        if (uri.getAuthority() != null)
+            throw new IllegalArgumentException("URI has an authority component");
+        if (uri.getFragment() != null)
+            throw new IllegalArgumentException("URI has a fragment component");
+        if (uri.getQuery() != null)
+            throw new IllegalArgumentException("URI has a query component");
+
+        String path = uri.getPath();
+        if (path.equals(""))
+            throw new IllegalArgumentException("URI path component is empty");
+        if (path.endsWith("/") && (path.length() > 1)) {
+            // "/foo/" --> "/foo", but "/" --> "/"
+            path = path.substring(0, path.length() - 1);
+        }
+
+        // preserve bytes
+        byte[] result = new byte[path.length()];
+        for (int i=0; i<path.length(); i++) {
+            byte v = (byte)(path.charAt(i));
+            if (v == 0)
+                throw new IllegalArgumentException("Nul character not allowed");
+            result[i] = v;
+        }
+        return new UnixPath(fs, result);
+    }
+
+    /**
+     * Converts Path to URI
+     */
+    static URI toUri(UnixPath up) {
+        byte[] path = up.toAbsolutePath().asByteArray();
+        StringBuilder sb = new StringBuilder("file:///");
+        assert path[0] == '/';
+        for (int i=1; i<path.length; i++) {
+            char c = (char)(path[i] & 0xff);
+            if (match(c, L_PATH, H_PATH)) {
+                sb.append(c);
+            } else {
+               sb.append('%');
+               sb.append(hexDigits[(c >> 4) & 0x0f]);
+               sb.append(hexDigits[(c >> 0) & 0x0f]);
+            }
+        }
+
+        // trailing slash if directory
+        if (sb.charAt(sb.length()-1) != '/') {
+            try {
+                 if (UnixFileAttributes.get(up, true).isDirectory())
+                     sb.append('/');
+            } catch (UnixException x) {
+                // ignore
+            }
+        }
+
+        try {
+            return new URI(sb.toString());
+        } catch (URISyntaxException x) {
+            throw new AssertionError(x);  // should not happen
+        }
+    }
+
+    // The following is copied from java.net.URI
+
+    // Compute the low-order mask for the characters in the given string
+    private static long lowMask(String chars) {
+        int n = chars.length();
+        long m = 0;
+        for (int i = 0; i < n; i++) {
+            char c = chars.charAt(i);
+            if (c < 64)
+                m |= (1L << c);
+        }
+        return m;
+    }
+
+    // Compute the high-order mask for the characters in the given string
+    private static long highMask(String chars) {
+        int n = chars.length();
+        long m = 0;
+        for (int i = 0; i < n; i++) {
+            char c = chars.charAt(i);
+            if ((c >= 64) && (c < 128))
+                m |= (1L << (c - 64));
+        }
+        return m;
+    }
+
+    // Compute a low-order mask for the characters
+    // between first and last, inclusive
+    private static long lowMask(char first, char last) {
+        long m = 0;
+        int f = Math.max(Math.min(first, 63), 0);
+        int l = Math.max(Math.min(last, 63), 0);
+        for (int i = f; i <= l; i++)
+            m |= 1L << i;
+        return m;
+    }
+
+    // Compute a high-order mask for the characters
+    // between first and last, inclusive
+    private static long highMask(char first, char last) {
+        long m = 0;
+        int f = Math.max(Math.min(first, 127), 64) - 64;
+        int l = Math.max(Math.min(last, 127), 64) - 64;
+        for (int i = f; i <= l; i++)
+            m |= 1L << i;
+        return m;
+    }
+
+    // Tell whether the given character is permitted by the given mask pair
+    private static boolean match(char c, long lowMask, long highMask) {
+        if (c < 64)
+            return ((1L << c) & lowMask) != 0;
+        if (c < 128)
+            return ((1L << (c - 64)) & highMask) != 0;
+        return false;
+    }
+
+    // digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+    //            "8" | "9"
+    private static final long L_DIGIT = lowMask('0', '9');
+    private static final long H_DIGIT = 0L;
+
+    // upalpha  = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
+    //            "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
+    //            "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+    private static final long L_UPALPHA = 0L;
+    private static final long H_UPALPHA = highMask('A', 'Z');
+
+    // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
+    //            "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
+    //            "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
+    private static final long L_LOWALPHA = 0L;
+    private static final long H_LOWALPHA = highMask('a', 'z');
+
+    // alpha         = lowalpha | upalpha
+    private static final long L_ALPHA = L_LOWALPHA | L_UPALPHA;
+    private static final long H_ALPHA = H_LOWALPHA | H_UPALPHA;
+
+    // alphanum      = alpha | digit
+    private static final long L_ALPHANUM = L_DIGIT | L_ALPHA;
+    private static final long H_ALPHANUM = H_DIGIT | H_ALPHA;
+
+    // mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+    //                 "(" | ")"
+    private static final long L_MARK = lowMask("-_.!~*'()");
+    private static final long H_MARK = highMask("-_.!~*'()");
+
+    // unreserved    = alphanum | mark
+    private static final long L_UNRESERVED = L_ALPHANUM | L_MARK;
+    private static final long H_UNRESERVED = H_ALPHANUM | H_MARK;
+
+    // pchar         = unreserved | escaped |
+    //                 ":" | "@" | "&" | "=" | "+" | "$" | ","
+    private static final long L_PCHAR
+        = L_UNRESERVED | lowMask(":@&=+$,");
+    private static final long H_PCHAR
+        = H_UNRESERVED | highMask(":@&=+$,");
+
+   // All valid path characters
+   private static final long L_PATH = L_PCHAR | lowMask(";/");
+   private static final long H_PATH = H_PCHAR | highMask(";/");
+
+   private final static char[] hexDigits = {
+        '0', '1', '2', '3', '4', '5', '6', '7',
+        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2007-2008 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 static sun.nio.fs.UnixNativeDispatcher.*;
+
+/**
+ * Unix implementation of java.nio.file.attribute.UserPrincipal
+ */
+
+class UnixUserPrincipals {
+    private static User createSpecial(String name) { return new User(-1, name); }
+
+    static final User SPECIAL_OWNER = createSpecial("OWNER@");
+    static final User SPECIAL_GROUP = createSpecial("GROUP@");
+    static final User SPECIAL_EVERYONE = createSpecial("EVERYONE@");
+
+    static class User implements UserPrincipal {
+        private final int id;             // uid or gid
+        private final boolean isGroup;
+        private final String name;
+
+        private User(int id, boolean isGroup, String name) {
+            this.id = id;
+            this.isGroup = isGroup;
+            this.name = name;
+        }
+
+        User(int id, String name) {
+            this(id, false, name);
+        }
+
+        int uid() {
+            if (isGroup)
+                throw new AssertionError();
+            return id;
+        }
+
+        int gid() {
+            if (isGroup)
+                return id;
+            throw new AssertionError();
+        }
+
+        boolean isSpecial() {
+            return id == -1;
+        }
+
+
+        public String getName() {
+            return name;
+        }
+
+
+        public String toString() {
+            return name;
+        }
+
+
+        public boolean equals(Object obj) {
+            if (obj == this)
+                return true;
+            if (!(obj instanceof User))
+                return false;
+            User other = (User)obj;
+            if ((this.id != other.id) ||
+                (this.isGroup != other.isGroup)) {
+                return false;
+            }
+            // specials
+            if (this.id == -1 && other.id == -1)
+                return this.name.equals(other.name);
+
+            return true;
+        }
+
+
+        public int hashCode() {
+            return (id != -1) ? id : name.hashCode();
+        }
+    }
+
+    static class Group extends User implements GroupPrincipal {
+        Group(int id, String name) {
+            super(id, true, name);
+        }
+    }
+
+    // return UserPrincipal representing given uid
+    static User fromUid(int uid) {
+        String name = null;
+        try {
+            name = new String(getpwuid(uid));
+        } catch (UnixException x) {
+            name = Integer.toString(uid);
+        }
+        return new User(uid, name);
+    }
+
+    // return GroupPrincipal representing given gid
+    static Group fromGid(int gid) {
+        String name = null;
+        try {
+            name = new String(getgrgid(gid));
+        } catch (UnixException x) {
+            name = Integer.toString(gid);
+        }
+        return new Group(gid, name);
+    }
+
+    // lookup user or group name
+    private static int lookupName(String name, boolean isGroup)
+        throws IOException
+    {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("lookupUserInformation"));
+        }
+        int id = -1;
+        try {
+            id = (isGroup) ? getgrnam(name) : getpwnam(name);
+        } catch (UnixException x) {
+            throw new IOException(name + ": " + x.errorString());
+        }
+        if (id == -1)
+            throw new UserPrincipalNotFoundException(name);
+        return id;
+
+    }
+
+    // lookup user name
+    static UserPrincipal lookupUser(String name) throws IOException {
+        if (name.equals(SPECIAL_OWNER.getName()))
+            return SPECIAL_OWNER;
+        if (name.equals(SPECIAL_GROUP.getName()))
+            return SPECIAL_GROUP;
+        if (name.equals(SPECIAL_EVERYONE.getName()))
+            return SPECIAL_EVERYONE;
+        int uid = lookupName(name, false);
+        return new User(uid, name);
+    }
+
+    // lookup group name
+    static GroupPrincipal lookupGroup(String group)
+        throws IOException
+    {
+        int gid = lookupName(group, true);
+        return new Group(gid, group);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/EPollPort.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "nio_util.h"
+
+#include "sun_nio_ch_EPollPort.h"
+
+#include <dlfcn.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* epoll_wait(2) man page */
+
+typedef union epoll_data {
+    void *ptr;
+    int fd;
+    __uint32_t u32;
+    __uint64_t u64;
+} epoll_data_t;
+
+struct epoll_event {
+    __uint32_t events;  /* Epoll events */
+    epoll_data_t data;  /* User data variable */
+} __attribute__ ((__packed__));
+
+#ifdef  __cplusplus
+}
+#endif
+
+/*
+ * epoll event notification is new in 2.6 kernel. As the offical build
+ * platform for the JDK is on a 2.4-based distribution then we must
+ * obtain the addresses of the epoll functions dynamically.
+ */
+typedef int (*epoll_create_t)(int size);
+typedef int (*epoll_ctl_t)   (int epfd, int op, int fd, struct epoll_event *event);
+typedef int (*epoll_wait_t)  (int epfd, struct epoll_event *events, int maxevents, int timeout);
+
+static epoll_create_t epoll_create_func;
+static epoll_ctl_t    epoll_ctl_func;
+static epoll_wait_t   epoll_wait_func;
+
+#ifndef EPOLL_CTL_ADD
+#define EPOLL_CTL_ADD   1
+#define EPOLL_CTL_DEL   2
+#define EPOLL_CTL_MOD   3
+#endif
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPollPort_init(JNIEnv *env, jclass this)
+{
+    epoll_create_func = (epoll_create_t) dlsym(RTLD_DEFAULT, "epoll_create");
+    epoll_ctl_func    = (epoll_ctl_t)    dlsym(RTLD_DEFAULT, "epoll_ctl");
+    epoll_wait_func   = (epoll_wait_t)   dlsym(RTLD_DEFAULT, "epoll_wait");
+
+    if ((epoll_create_func == NULL) || (epoll_ctl_func == NULL) ||
+        (epoll_wait_func == NULL)) {
+        JNU_ThrowInternalError(env, "unable to get address of epoll functions, pre-2.6 kernel?");
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPollPort_epollCreate(JNIEnv *env, jclass c) {
+    /*
+     * epoll_create expects a size as a hint to the kernel about how to
+     * dimension internal structures. We can't predict the size in advance.
+     */
+    int epfd = (*epoll_create_func)(256);
+    if (epfd < 0) {
+       JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
+    }
+    return epfd;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPollPort_epollCtl(JNIEnv *env, jclass c, jint epfd,
+                                   jint opcode, jint fd, jint events)
+{
+    struct epoll_event event;
+    int res;
+
+    event.events = events;
+    event.data.fd = fd;
+
+    RESTARTABLE((*epoll_ctl_func)(epfd, (int)opcode, (int)fd, &event), res);
+
+    return (res == 0) ? 0 : errno;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPollPort_epollWait(JNIEnv *env, jclass c,
+                                    jint epfd, jlong address, jint numfds)
+{
+    struct epoll_event *events = jlong_to_ptr(address);
+    int res;
+
+    RESTARTABLE((*epoll_wait_func)(epfd, events, numfds, -1), res);
+    if (res < 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
+    }
+    return res;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
+    int sp[2];
+    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
+    } else {
+        jint res[2];
+        res[0] = (jint)sp[0];
+        res[1] = (jint)sp[1];
+        (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
+    int res;
+    int buf[1];
+    buf[0] = 1;
+    RESTARTABLE(write(fd, buf, 1), res);
+    if (res < 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "write failed");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
+    int res;
+    char buf[1];
+    RESTARTABLE(read(fd, buf, 1), res);
+    if (res < 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint epfd) {
+    int res;
+    RESTARTABLE(close(epfd), res);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "nio_util.h"
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+
+#include "sun_nio_ch_SolarisEventPort.h"
+
+/*
+ * Definitions from sys/port.h to allow build on pre-Solaris 10 machines.
+ */
+typedef struct my_port_event {
+    int             portev_events;  /* event data is source specific */
+    ushort_t        portev_source;  /* event source */
+    ushort_t        portev_pad;     /* port internal use */
+    uintptr_t       portev_object;  /* source specific object */
+    void            *portev_user;   /* user cookie */
+} my_port_event_t;
+
+typedef int port_create_func(void);
+typedef int port_associate_func(int port, int source, uintptr_t object, int events, void* user);
+typedef int port_dissociate_func(int port, int source, uintptr_t object);
+typedef int port_send_func(int port, int events, void* user);
+typedef int port_get_func(int port, my_port_event_t* pe, const timespec_t* timeout);
+typedef int port_getn_func(int port, my_port_event_t list[], uint_t max, uint_t* nget,
+    const timespec_t* timeout);
+
+static port_create_func* my_port_create_func = NULL;
+static port_associate_func* my_port_associate_func = NULL;
+static port_dissociate_func* my_port_dissociate_func = NULL;
+static port_send_func* my_port_send_func = NULL;
+static port_get_func* my_port_get_func = NULL;
+static port_getn_func* my_port_getn_func = NULL;
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_SolarisEventPort_init(JNIEnv *env, jclass clazz)
+{
+    my_port_create_func = (port_create_func*)dlsym(RTLD_DEFAULT, "port_create");
+    my_port_associate_func = (port_associate_func*)dlsym(RTLD_DEFAULT, "port_associate");
+    my_port_dissociate_func = (port_dissociate_func*)dlsym(RTLD_DEFAULT, "port_dissociate");
+    my_port_send_func = (port_send_func*)dlsym(RTLD_DEFAULT, "port_send");
+    my_port_get_func = (port_get_func*)dlsym(RTLD_DEFAULT, "port_get");
+    my_port_getn_func = (port_getn_func*)dlsym(RTLD_DEFAULT, "port_getn");
+
+    if (my_port_create_func == NULL) {
+        JNU_ThrowInternalError(env, "unable to get address of port functions");
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_SolarisEventPort_portCreate
+    (JNIEnv* env, jclass clazz)
+{
+    int port = (*my_port_create_func)();
+    if (port == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "port_create");
+    }
+    return (jint)port;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_SolarisEventPort_portClose
+    (JNIEnv* env, jclass clazz, jint port)
+{
+    int res;
+    RESTARTABLE(close(port), res);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_SolarisEventPort_portAssociate
+    (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
+{
+    uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
+
+    if ((*my_port_associate_func)((int)port, (int)source, object, (int)events, NULL) == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "port_associate");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_SolarisEventPort_portDissociate
+    (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
+{
+    uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
+
+    if ((*my_port_dissociate_func)((int)port, (int)source, object) == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "port_dissociate");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_SolarisEventPort_portSend(JNIEnv* env, jclass clazz,
+    jint port, jint events)
+{
+    if ((*my_port_send_func)((int)port, (int)events, NULL) == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "port_send");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_SolarisEventPort_portGet(JNIEnv* env, jclass clazz,
+    jint port, jlong eventAddress)
+{
+    int res;
+    my_port_event_t* ev = (my_port_event_t*)jlong_to_ptr(eventAddress);
+
+    RESTARTABLE((*my_port_get_func)((int)port, ev, NULL), res);
+    if (res == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "port_get");
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_SolarisEventPort_portGetn(JNIEnv* env, jclass clazz,
+    jint port, jlong arrayAddress, jint max)
+{
+    int res;
+    uint_t n = 1;
+    my_port_event_t* list = (my_port_event_t*)jlong_to_ptr(arrayAddress);
+
+    RESTARTABLE((*my_port_getn_func)((int)port, list, (uint_t)max, &n, NULL), res);
+    if (res == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "port_getn");
+    }
+    return (jint)n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "sun_nio_ch_UnixAsynchronousServerSocketChannelImpl.h"
+
+extern void Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv* env,
+    jclass c);
+
+extern jint Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv* env,
+    jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa);
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env,
+    jclass c)
+{
+    Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(env, c);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0(JNIEnv* env,
+    jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa)
+{
+    return Java_sun_nio_ch_ServerSocketChannelImpl_accept0(env, this,
+        ssfdo, newfdo, isaa);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "net_util.h"
+#include "jlong.h"
+#include "sun_nio_ch_UnixAsynchronousSocketChannelImpl.h"
+#include "nio_util.h"
+#include "nio.h"
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect(JNIEnv *env,
+    jobject this, int fd)
+{
+    int error = 0;
+    int n = sizeof(error);
+    int result;
+
+    result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n);
+    if (result < 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "getsockopt");
+    } else {
+        if (error)
+            handleSocketError(env, error);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <link.h>
+
+#ifdef __solaris__
+#include <strings.h>
+#endif
+
+#ifdef __linux__
+#include <string.h>
+#endif
+
+/* Definitions for GIO */
+
+#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type"
+
+typedef void* gpointer;
+typedef struct _GFile GFile;
+typedef struct _GFileInfo GFileInfo;
+typedef struct _GCancellable GCancellable;
+typedef struct _GError GError;
+
+typedef enum {
+  G_FILE_QUERY_INFO_NONE = 0
+} GFileQueryInfoFlags;
+
+typedef void (*g_type_init_func)(void);
+typedef void (*g_object_unref_func)(gpointer object);
+typedef GFile* (*g_file_new_for_path_func)(const char* path);
+typedef GFileInfo* (*g_file_query_info_func)(GFile *file,
+    const char *attributes, GFileQueryInfoFlags flags,
+    GCancellable *cancellable, GError **error);
+typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info);
+
+static g_type_init_func g_type_init;
+static g_object_unref_func g_object_unref;
+static g_file_new_for_path_func g_file_new_for_path;
+static g_file_query_info_func g_file_query_info;
+static g_file_info_get_content_type_func g_file_info_get_content_type;
+
+
+/* Definitions for GNOME VFS */
+
+typedef int gboolean;
+
+typedef gboolean (*gnome_vfs_init_function)(void);
+typedef const char* (*gnome_vfs_mime_type_from_name_function)
+    (const char* filename);
+
+static gnome_vfs_init_function gnome_vfs_init;
+static gnome_vfs_mime_type_from_name_function gnome_vfs_mime_type_from_name;
+
+
+#include "sun_nio_fs_GnomeFileTypeDetector.h"
+
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio
+    (JNIEnv* env, jclass this)
+{
+    void* gio_handle;
+
+    gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
+    if (gio_handle == NULL) {
+        gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
+        if (gio_handle == NULL) {
+            return JNI_FALSE;
+        }
+    }
+
+    g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init");
+    (*g_type_init)();
+
+    g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref");
+
+    g_file_new_for_path =
+        (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path");
+
+    g_file_query_info =
+        (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info");
+
+    g_file_info_get_content_type = (g_file_info_get_content_type_func)
+        dlsym(gio_handle, "g_file_info_get_content_type");
+
+
+    if (g_type_init == NULL ||
+        g_object_unref == NULL ||
+        g_file_new_for_path == NULL ||
+        g_file_query_info == NULL ||
+        g_file_info_get_content_type == NULL)
+    {
+        dlclose(gio_handle);
+        return JNI_FALSE;
+    }
+
+    (*g_type_init)();
+    return JNI_TRUE;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio
+    (JNIEnv* env, jclass this, jlong pathAddress)
+{
+    char* path = (char*)jlong_to_ptr(pathAddress);
+    GFile* gfile;
+    GFileInfo* gfileinfo;
+    jbyteArray result = NULL;
+
+    gfile = (*g_file_new_for_path)(path);
+    gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+        G_FILE_QUERY_INFO_NONE, NULL, NULL);
+    if (gfileinfo != NULL) {
+        const char* mime = (*g_file_info_get_content_type)(gfileinfo);
+        if (mime != NULL) {
+            jsize len = strlen(mime);
+            result = (*env)->NewByteArray(env, len);
+            if (result != NULL) {
+                (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime);
+            }
+        }
+        (*g_object_unref)(gfileinfo);
+    }
+    (*g_object_unref)(gfile);
+
+    return result;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs
+    (JNIEnv* env, jclass this)
+{
+    void* vfs_handle;
+
+    vfs_handle = dlopen("libgnomevfs-2.so", RTLD_LAZY);
+    if (vfs_handle == NULL) {
+        vfs_handle = dlopen("libgnomevfs-2.so.0", RTLD_LAZY);
+    }
+    if (vfs_handle == NULL) {
+        return JNI_FALSE;
+    }
+
+    gnome_vfs_init = (gnome_vfs_init_function)dlsym(vfs_handle, "gnome_vfs_init");
+    gnome_vfs_mime_type_from_name = (gnome_vfs_mime_type_from_name_function)
+        dlsym(vfs_handle, "gnome_vfs_mime_type_from_name");
+
+    if (gnome_vfs_init == NULL ||
+        gnome_vfs_mime_type_from_name == NULL)
+    {
+        dlclose(vfs_handle);
+        return JNI_FALSE;
+    }
+
+    (*gnome_vfs_init)();
+    return JNI_TRUE;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs
+    (JNIEnv* env, jclass this, jlong pathAddress)
+{
+    char* path = (char*)jlong_to_ptr(pathAddress);
+    const char* mime = (*gnome_vfs_mime_type_from_name)(path);
+
+    if (mime == NULL) {
+        return NULL;
+    } else {
+        jbyteArray result;
+        jsize len = strlen(mime);
+        result = (*env)->NewByteArray(env, len);
+        if (result != NULL) {
+            (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <mntent.h>
+
+#include "sun_nio_fs_LinuxNativeDispatcher.h"
+
+typedef size_t fgetxattr_func(int fd, const char* name, void* value, size_t size);
+typedef int fsetxattr_func(int fd, const char* name, void* value, size_t size, int flags);
+typedef int fremovexattr_func(int fd, const char* name);
+typedef int flistxattr_func(int fd, char* list, size_t size);
+
+fgetxattr_func* my_fgetxattr_func = NULL;
+fsetxattr_func* my_fsetxattr_func = NULL;
+fremovexattr_func* my_fremovexattr_func = NULL;
+flistxattr_func* my_flistxattr_func = NULL;
+
+static void throwUnixException(JNIEnv* env, int errnum) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
+        "(I)V", errnum);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_init(JNIEnv *env, jclass clazz)
+{
+    my_fgetxattr_func = (fgetxattr_func*)dlsym(RTLD_DEFAULT, "fgetxattr");
+    my_fsetxattr_func = (fsetxattr_func*)dlsym(RTLD_DEFAULT, "fsetxattr");
+    my_fremovexattr_func = (fremovexattr_func*)dlsym(RTLD_DEFAULT, "fremovexattr");
+    my_flistxattr_func = (flistxattr_func*)dlsym(RTLD_DEFAULT, "flistxattr");
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz,
+    jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
+{
+    size_t res = -1;
+    const char* name = jlong_to_ptr(nameAddress);
+    void* value = jlong_to_ptr(valueAddress);
+
+    if (my_fgetxattr_func == NULL) {
+        errno = ENOTSUP;
+    } else {
+        /* EINTR not documented */
+        res = (*my_fgetxattr_func)(fd, name, value, valueLen);
+    }
+    if (res == (size_t)-1)
+        throwUnixException(env, errno);
+    return (jint)res;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz,
+    jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
+{
+    int res = -1;
+    const char* name = jlong_to_ptr(nameAddress);
+    void* value = jlong_to_ptr(valueAddress);
+
+    if (my_fsetxattr_func == NULL) {
+        errno = ENOTSUP;
+    } else {
+        /* EINTR not documented */
+        res = (*my_fsetxattr_func)(fd, name, value, valueLen, 0);
+    }
+    if (res == -1)
+        throwUnixException(env, errno);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz,
+    jint fd, jlong nameAddress)
+{
+    int res = -1;
+    const char* name = jlong_to_ptr(nameAddress);
+
+    if (my_fremovexattr_func == NULL) {
+        errno = ENOTSUP;
+    } else {
+        /* EINTR not documented */
+        res = (*my_fremovexattr_func)(fd, name);
+    }
+    if (res == -1)
+        throwUnixException(env, errno);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz,
+    jint fd, jlong listAddress, jint size)
+{
+    size_t res = -1;
+    char* list = jlong_to_ptr(listAddress);
+
+    if (my_flistxattr_func == NULL) {
+        errno = ENOTSUP;
+    } else {
+        /* EINTR not documented */
+        res = (*my_flistxattr_func)(fd, list, (size_t)size);
+    }
+    if (res == (size_t)-1)
+        throwUnixException(env, errno);
+    return (jint)res;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0(JNIEnv* env, jclass this, jlong pathAddress,
+                                                 jlong modeAddress)
+{
+    FILE* fp = NULL;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+    const char* mode = (const char*)jlong_to_ptr(modeAddress);
+
+    do {
+        fp = setmntent(path, mode);
+    } while (fp == NULL && errno == EINTR);
+    if (fp == NULL) {
+        throwUnixException(env, errno);
+    }
+    return ptr_to_jlong(fp);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxNativeDispatcher_endmntent(JNIEnv* env, jclass this, jlong stream)
+{
+    FILE* fp = jlong_to_ptr(stream);
+    /* FIXME - man page doesn't explain how errors are returned */
+    endmntent(fp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+
+#include "sun_nio_fs_LinuxWatchService.h"
+
+typedef int inotify_init_func(void);
+typedef int inotify_add_watch_func(int fd, const char* path, uint32_t mask);
+typedef int inotify_rm_watch_func(int fd, uint32_t wd);
+
+inotify_init_func* my_inotify_init_func = NULL;
+inotify_add_watch_func* my_inotify_add_watch_func = NULL;
+inotify_rm_watch_func* my_inotify_rm_watch_func = NULL;
+
+static void throwUnixException(JNIEnv* env, int errnum) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
+        "(I)V", errnum);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxWatchService_init(JNIEnv *env, jclass clazz)
+{
+    my_inotify_init_func = (inotify_init_func*)
+        dlsym(RTLD_DEFAULT, "inotify_init");
+    my_inotify_add_watch_func =
+        (inotify_add_watch_func*) dlsym(RTLD_DEFAULT, "inotify_add_watch");
+    my_inotify_rm_watch_func =
+        (inotify_rm_watch_func*) dlsym(RTLD_DEFAULT, "inotify_rm_watch");
+
+    if ((my_inotify_init_func == NULL) || (my_inotify_add_watch_func == NULL) ||
+        (my_inotify_rm_watch_func == NULL)) {
+        JNU_ThrowInternalError(env, "unable to get address of inotify functions");
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_LinuxWatchService_inotifyInit
+    (JNIEnv* env, jclass clazz)
+{
+    int ifd = (*my_inotify_init_func)();
+    if (ifd == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)ifd;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch
+    (JNIEnv* env, jclass clazz, jint fd, jlong address, jint mask)
+{
+    int wfd = -1;
+    const char* path = (const char*)jlong_to_ptr(address);
+
+    wfd = (*my_inotify_add_watch_func)((int)fd, path, mask);
+    if (wfd == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)wfd;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch
+    (JNIEnv* env, jclass clazz, jint fd, jint wd)
+{
+    int err = (*my_inotify_rm_watch_func)((int)fd, (int)wd);
+    if (err == -1)
+        throwUnixException(env, errno);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxWatchService_configureBlocking
+    (JNIEnv* env, jclass clazz, jint fd, jboolean blocking)
+{
+    int flags = fcntl(fd, F_GETFL);
+
+    if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK))
+        fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+    else if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK))
+        fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_LinuxWatchService_socketpair
+    (JNIEnv* env, jclass clazz, jintArray sv)
+{
+    int sp[2];
+    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
+        throwUnixException(env, errno);
+    } else {
+        jint res[2];
+        res[0] = (jint)sp[0];
+        res[1] = (jint)sp[1];
+        (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
+    }
+
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_LinuxWatchService_poll
+    (JNIEnv* env, jclass clazz, jint fd1, jint fd2)
+{
+    struct pollfd ufds[2];
+    int n;
+
+    ufds[0].fd = fd1;
+    ufds[0].events = POLLIN;
+    ufds[1].fd = fd2;
+    ufds[1].events = POLLIN;
+
+    n = poll(&ufds[0], 2, -1);
+    if (n == -1) {
+        if (errno == EINTR) {
+            n = 0;
+        } else {
+            throwUnixException(env, errno);
+        }
+     }
+    return (jint)n;
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+
+#include "sun_nio_fs_SolarisNativeDispatcher.h"
+
+typedef int facl_func(int filedes, int cmd, int cnt, void *buf);
+
+static facl_func* my_facl_func = NULL;
+
+static void throwUnixException(JNIEnv* env, int errnum) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
+        "(I)V", errnum);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_SolarisNativeDispatcher_init(JNIEnv *env, jclass clazz) {
+    my_facl_func = (facl_func*) dlsym(RTLD_DEFAULT, "facl");
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd,
+    jint cmd, jint nentries, jlong address)
+{
+    void* aclbufp = jlong_to_ptr(address);
+    int n = -1;
+
+    if (my_facl_func == NULL) {
+        JNU_ThrowInternalError(env, "should not reach here");
+        return -1;
+    }
+
+    n = (*my_facl_func)((int)fd, (int)cmd, (int)nentries, aclbufp);
+    if (n == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+
+#include "sun_nio_fs_SolarisWatchService.h"
+
+/*
+ * Definitions from sys/port.h to allow build on pre-Solaris 10 machines.
+ */
+typedef struct my_port_event {
+        int             portev_events;  /* event data is source specific */
+        ushort_t        portev_source;  /* event source */
+        ushort_t        portev_pad;     /* port internal use */
+        uintptr_t       portev_object;  /* source specific object */
+        void            *portev_user;   /* user cookie */
+} my_port_event_t;
+
+typedef int port_create_func(void);
+typedef int port_associate_func(int port, int source, uintptr_t object, int events, void* user);
+typedef int port_dissociate_func(int port, int source, uintptr_t object);
+typedef int port_send_func(int port, int events, void* user);
+typedef int port_getn_func(int port, my_port_event_t list[], uint_t max, uint_t* nget,
+    const timespec_t* timeout);
+
+static port_create_func* my_port_create_func = NULL;
+static port_associate_func* my_port_associate_func = NULL;
+static port_dissociate_func* my_port_dissociate_func = NULL;
+static port_send_func* my_port_send_func = NULL;
+static port_getn_func* my_port_getn_func = NULL;
+
+static void throwUnixException(JNIEnv* env, int errnum) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
+        "(I)V", errnum);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_SolarisWatchService_init(JNIEnv *env, jclass clazz)
+{
+    my_port_create_func = (port_create_func*)dlsym(RTLD_DEFAULT, "port_create");
+    my_port_associate_func = (port_associate_func*)dlsym(RTLD_DEFAULT, "port_associate");
+    my_port_dissociate_func = (port_dissociate_func*)dlsym(RTLD_DEFAULT, "port_dissociate");
+    my_port_send_func = (port_send_func*)dlsym(RTLD_DEFAULT, "port_send");
+    my_port_getn_func = (port_getn_func*)dlsym(RTLD_DEFAULT, "port_getn");
+
+    if (my_port_create_func == NULL ||
+        my_port_associate_func == NULL ||
+        my_port_dissociate_func == NULL ||
+        my_port_send_func == NULL ||
+        my_port_getn_func == NULL)
+    {
+        JNU_ThrowInternalError(env, "unable to get address of port functions");
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_SolarisWatchService_portCreate
+    (JNIEnv* env, jclass clazz)
+{
+    int port = (*my_port_create_func)();
+    if (port == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)port;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_SolarisWatchService_portAssociate
+    (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
+{
+    uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
+
+    if ((*my_port_associate_func)((int)port, (int)source, object, (int)events, NULL) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_SolarisWatchService_portDissociate
+    (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
+{
+    uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
+
+    if ((*my_port_dissociate_func)((int)port, (int)source, object) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_SolarisWatchService_portSend(JNIEnv* env, jclass clazz,
+    jint port, jint events)
+{
+    if ((*my_port_send_func)((int)port, (int)events, NULL) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_SolarisWatchService_portGetn(JNIEnv* env, jclass clazz,
+    jint port, jlong arrayAddress, jint max)
+{
+    uint_t n = 1;
+    my_port_event_t* list = (my_port_event_t*)jlong_to_ptr(arrayAddress);
+
+    if( (*my_port_getn_func)((int)port, list, (uint_t)max, &n, NULL) == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "sun_nio_fs_UnixCopyFile.h"
+
+#define RESTARTABLE(_cmd, _result) do { \
+  do { \
+    _result = _cmd; \
+  } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+static void throwUnixException(JNIEnv* env, int errnum) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
+        "(I)V", errnum);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+/**
+ * Transfer all bytes from src to dst via user-space buffers
+ */
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixCopyFile_transfer
+    (JNIEnv* env, jclass this, jint dst, jint src, jlong cancelAddress)
+{
+    char buf[8192];
+    volatile jint* cancel = (jint*)jlong_to_ptr(cancelAddress);
+
+    for (;;) {
+        ssize_t n, pos, len;
+        RESTARTABLE(read((int)src, &buf, sizeof(buf)), n);
+        if (n <= 0) {
+            if (n < 0)
+                throwUnixException(env, errno);
+            return;
+        }
+        if (cancel != NULL && *cancel != 0) {
+            throwUnixException(env, ECANCELED);
+            return;
+        }
+        pos = 0;
+        len = n;
+        do {
+            char* bufp = buf;
+            bufp += pos;
+            RESTARTABLE(write((int)dst, bufp, len), n);
+            if (n == -1) {
+                throwUnixException(env, errno);
+                return;
+            }
+            pos += n;
+            len -= n;
+        } while (len > 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1078 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/time.h>
+
+#ifdef __solaris__
+#include <strings.h>
+#include <sys/mnttab.h>
+#include <sys/mkdev.h>
+#endif
+
+#ifdef __linux__
+#include <string.h>
+#include <mntent.h>
+#endif
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+
+#include "sun_nio_fs_UnixNativeDispatcher.h"
+
+#define RESTARTABLE(_cmd, _result) do { \
+  do { \
+    _result = _cmd; \
+  } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+static jfieldID attrs_st_mode;
+static jfieldID attrs_st_ino;
+static jfieldID attrs_st_dev;
+static jfieldID attrs_st_rdev;
+static jfieldID attrs_st_nlink;
+static jfieldID attrs_st_uid;
+static jfieldID attrs_st_gid;
+static jfieldID attrs_st_size;
+static jfieldID attrs_st_atime;
+static jfieldID attrs_st_mtime;
+static jfieldID attrs_st_ctime;
+
+static jfieldID attrs_f_frsize;
+static jfieldID attrs_f_blocks;
+static jfieldID attrs_f_bfree;
+static jfieldID attrs_f_bavail;
+
+static jfieldID entry_name;
+static jfieldID entry_dir;
+static jfieldID entry_fstype;
+static jfieldID entry_options;
+static jfieldID entry_dev;
+
+/**
+ * System calls that may not be available at build time.
+ */
+typedef int openat64_func(int, const char *, int, ...);
+typedef int fstatat64_func(int, const char *, struct stat64 *, int);
+typedef int unlinkat_func(int, const char*, int);
+typedef int renameat_func(int, const char*, int, const char*);
+typedef int futimesat_func(int, const char *, const struct timeval *);
+typedef DIR* fdopendir_func(int);
+
+static openat64_func* my_openat64_func = NULL;
+static fstatat64_func* my_fstatat64_func = NULL;
+static unlinkat_func* my_unlinkat_func = NULL;
+static renameat_func* my_renameat_func = NULL;
+static futimesat_func* my_futimesat_func = NULL;
+static fdopendir_func* my_fdopendir_func = NULL;
+
+/**
+ * fstatat missing from glibc on Linux. Temporary workaround
+ * for x86/x64, will fail to compile on other architectures.
+ */
+#if defined(__linux__) && defined(__i386)
+static int fstatat64_wrapper(int dfd, const char *path,
+                             struct stat64 *statbuf, int flag)
+{
+    #ifndef __NR_fstatat64
+    #define __NR_fstatat64  300
+    #endif
+    return syscall(__NR_fstatat64, dfd, path, statbuf, flag);
+}
+#endif
+
+#if defined(__linux__) && defined(__x86_64__)
+static int fstatat64_wrapper(int dfd, const char *path,
+                             struct stat64 *statbuf, int flag)
+{
+    #ifndef __NR_newfstatat
+    #define __NR_newfstatat  262
+    #endif
+    return syscall(__NR_newfstatat, dfd, path, statbuf, flag);
+}
+#endif
+
+/**
+ * Call this to throw an internal UnixException when a system/library
+ * call fails
+ */
+static void throwUnixException(JNIEnv* env, int errnum) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
+        "(I)V", errnum);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+/**
+ * Initialize jfieldIDs
+ */
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this)
+{
+    jclass clazz;
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileAttributes");
+    if (clazz == NULL) {
+        return;
+    }
+    attrs_st_mode = (*env)->GetFieldID(env, clazz, "st_mode", "I");
+    attrs_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J");
+    attrs_st_dev = (*env)->GetFieldID(env, clazz, "st_dev", "J");
+    attrs_st_rdev = (*env)->GetFieldID(env, clazz, "st_rdev", "J");
+    attrs_st_nlink = (*env)->GetFieldID(env, clazz, "st_nlink", "I");
+    attrs_st_uid = (*env)->GetFieldID(env, clazz, "st_uid", "I");
+    attrs_st_gid = (*env)->GetFieldID(env, clazz, "st_gid", "I");
+    attrs_st_size = (*env)->GetFieldID(env, clazz, "st_size", "J");
+    attrs_st_atime = (*env)->GetFieldID(env, clazz, "st_atime", "J");
+    attrs_st_mtime = (*env)->GetFieldID(env, clazz, "st_mtime", "J");
+    attrs_st_ctime = (*env)->GetFieldID(env, clazz, "st_ctime", "J");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
+    if (clazz == NULL) {
+        return;
+    }
+    attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J");
+    attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J");
+    attrs_f_bfree = (*env)->GetFieldID(env, clazz, "f_bfree", "J");
+    attrs_f_bavail = (*env)->GetFieldID(env, clazz, "f_bavail", "J");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
+    if (clazz == NULL) {
+        return;
+    }
+    entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
+    entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
+    entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
+    entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
+    entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
+
+    /* system calls that might not be available at build time */
+
+#if defined(__solaris__) && defined(_LP64)
+    /* Solaris 64-bit does not have openat64/fstatat64 */
+    my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
+    my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
+#else
+    my_openat64_func = (openat64_func*) dlsym(RTLD_DEFAULT, "openat64");
+    my_fstatat64_func = (fstatat64_func*) dlsym(RTLD_DEFAULT, "fstatat64");
+#endif
+    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(__linux__)
+    /* fstatat64 missing from glibc */
+    if (my_fstatat64_func == NULL)
+        my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
+#endif
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getcwd(JNIEnv* env, jclass this) {
+    jbyteArray result = NULL;
+    char buf[PATH_MAX+1];
+
+    /* EINTR not listed as a possible error */
+    char* cwd = getcwd(buf, sizeof(buf));
+    if (cwd == NULL) {
+        throwUnixException(env, errno);
+    } else {
+        jsize len = (jsize)strlen(buf);
+        result = (*env)->NewByteArray(env, len);
+        if (result != NULL) {
+            (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)buf);
+        }
+    }
+    return result;
+}
+
+JNIEXPORT jbyteArray
+Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
+{
+    char* msg;
+    jsize len;
+    jbyteArray bytes;
+
+    msg = strerror((int)error);
+    len = strlen(msg);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes != NULL) {
+        (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
+    }
+    return bytes;
+}
+
+JNIEXPORT jint
+Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) {
+
+    int res = -1;
+
+    RESTARTABLE(dup((int)fd), res);
+    if (fd == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)res;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fopen0(JNIEnv* env, jclass this,
+    jlong pathAddress, jlong modeAddress)
+{
+    FILE* fp = NULL;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+    const char* mode = (const char*)jlong_to_ptr(modeAddress);
+
+    do {
+        fp = fopen(path, mode);
+    } while (fp == NULL && errno == EINTR);
+
+    if (fp == NULL) {
+        throwUnixException(env, errno);
+    }
+
+    return ptr_to_jlong(fp);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fclose(JNIEnv* env, jclass this, jlong stream)
+{
+    int res;
+    FILE* fp = jlong_to_ptr(stream);
+
+    do {
+        res = fclose(fp);
+    } while (res == EOF && errno == EINTR);
+    if (res == EOF) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_open0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint oflags, jint mode)
+{
+    jint fd;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(open64(path, (int)oflags, (mode_t)mode), fd);
+    if (fd == -1) {
+        throwUnixException(env, errno);
+    }
+    return fd;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_openat0(JNIEnv* env, jclass this, jint dfd,
+    jlong pathAddress, jint oflags, jint mode)
+{
+    jint fd;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    if (my_openat64_func == NULL) {
+        JNU_ThrowInternalError(env, "should not reach here");
+        return -1;
+    }
+
+    RESTARTABLE((*my_openat64_func)(dfd, path, (int)oflags, (mode_t)mode), fd);
+    if (fd == -1) {
+        throwUnixException(env, errno);
+    }
+    return fd;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_close(JNIEnv* env, jclass this, jint fd) {
+    int err;
+    /* TDB - need to decide if EIO and other errors should cause exception */
+    RESTARTABLE(close((int)fd), err);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_read(JNIEnv* env, jclass this, jint fd,
+    jlong address, jint nbytes)
+{
+    ssize_t n;
+    void* bufp = jlong_to_ptr(address);
+    RESTARTABLE(read((int)fd, bufp, (size_t)nbytes), n);
+    if (n == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)n;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_write(JNIEnv* env, jclass this, jint fd,
+    jlong address, jint nbytes)
+{
+    ssize_t n;
+    void* bufp = jlong_to_ptr(address);
+    RESTARTABLE(write((int)fd, bufp, (size_t)nbytes), n);
+    if (n == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jint)n;
+}
+
+/**
+ * Copy stat64 members into sun.nio.fs.UnixFileAttributes
+ */
+static void prepAttributes(JNIEnv* env, struct stat64* buf, jobject attrs) {
+    (*env)->SetIntField(env, attrs, attrs_st_mode, (jint)buf->st_mode);
+    (*env)->SetLongField(env, attrs, attrs_st_ino, (jlong)buf->st_ino);
+    (*env)->SetLongField(env, attrs, attrs_st_dev, (jlong)buf->st_dev);
+    (*env)->SetLongField(env, attrs, attrs_st_rdev, (jlong)buf->st_rdev);
+    (*env)->SetIntField(env, attrs, attrs_st_nlink, (jint)buf->st_nlink);
+    (*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);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_stat0(JNIEnv* env, jclass this,
+    jlong pathAddress, jobject attrs)
+{
+    int err;
+    struct stat64 buf;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(stat64(path, &buf), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    } else {
+        prepAttributes(env, &buf, attrs);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_lstat0(JNIEnv* env, jclass this,
+    jlong pathAddress, jobject attrs)
+{
+    int err;
+    struct stat64 buf;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(lstat64(path, &buf), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    } else {
+        prepAttributes(env, &buf, attrs);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fstat(JNIEnv* env, jclass this, jint fd,
+    jobject attrs)
+{
+    int err;
+    struct stat64 buf;
+
+    RESTARTABLE(fstat64((int)fd, &buf), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    } else {
+        prepAttributes(env, &buf, attrs);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fstatat0(JNIEnv* env, jclass this, jint dfd,
+    jlong pathAddress, jint flag, jobject attrs)
+{
+    int err;
+    struct stat64 buf;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    if (my_fstatat64_func == NULL) {
+        JNU_ThrowInternalError(env, "should not reach here");
+        return;
+    }
+    RESTARTABLE((*my_fstatat64_func)((int)dfd, path, &buf, (int)flag), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    } else {
+        prepAttributes(env, &buf, attrs);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_chmod0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint mode)
+{
+    int err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(chmod(path, (mode_t)mode), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fchmod(JNIEnv* env, jclass this, jint filedes,
+    jint mode)
+{
+    int err;
+
+    RESTARTABLE(fchmod((int)filedes, (mode_t)mode), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_chown0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint uid, jint gid)
+{
+    int err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(chown(path, (uid_t)uid, (gid_t)gid), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_lchown0(JNIEnv* env, jclass this, jlong pathAddress, jint uid, jint gid)
+{
+    int err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(lchown(path, (uid_t)uid, (gid_t)gid), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fchown(JNIEnv* env, jclass this, jint filedes, jint uid, jint gid)
+{
+    int err;
+
+    RESTARTABLE(fchown(filedes, (uid_t)uid, (gid_t)gid), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this,
+    jlong pathAddress, jlong accessTime, jlong modificationTime)
+{
+    int err;
+    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[1].tv_sec = modificationTime / 1000;
+    times[1].tv_usec = (modificationTime % 1000) * 1000;
+
+    RESTARTABLE(utimes(path, &times[0]), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint filedes,
+    jlong accessTime, jlong modificationTime)
+{
+    struct timeval times[2];
+    int err = 0;
+
+    times[0].tv_sec = accessTime / 1000;
+    times[0].tv_usec = (accessTime % 1000) * 1000;
+
+    times[1].tv_sec = modificationTime / 1000;
+    times[1].tv_usec = (modificationTime % 1000) * 1000;
+
+    if (my_futimesat_func != NULL) {
+        RESTARTABLE((*my_futimesat_func)(filedes, NULL, &times[0]), err);
+        if (err == -1) {
+            throwUnixException(env, errno);
+        }
+    }
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
+    jlong pathAddress)
+{
+    DIR* dir;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    /* EINTR not listed as a possible error */
+    dir = opendir(path);
+    if (dir == NULL) {
+        throwUnixException(env, errno);
+    }
+    return ptr_to_jlong(dir);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) {
+    DIR* dir;
+
+    if (my_fdopendir_func == NULL) {
+        JNU_ThrowInternalError(env, "should not reach here");
+        return (jlong)-1;
+    }
+
+    /* EINTR not listed as a possible error */
+    dir = (*my_fdopendir_func)((int)dfd);
+    if (dir == NULL) {
+        throwUnixException(env, errno);
+    }
+    return ptr_to_jlong(dir);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) {
+    int err;
+    DIR* dirp = jlong_to_ptr(dir);
+
+    RESTARTABLE(closedir(dirp), err);
+    if (errno == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_readdir(JNIEnv* env, jclass this, jlong value) {
+    char entry[sizeof(struct dirent64) + PATH_MAX + 1];
+    struct dirent64* ptr = (struct dirent64*)&entry;
+    struct dirent64* result;
+    int res;
+    DIR* dirp = jlong_to_ptr(value);
+
+    /* EINTR not listed as a possible error */
+    /* TDB: reentrant version probably not required here */
+    res = readdir64_r(dirp, ptr, &result);
+    if (res != 0) {
+        throwUnixException(env, res);
+        return NULL;
+    } else {
+        if (result == NULL) {
+            return NULL;
+        } else {
+            jsize len = strlen(ptr->d_name);
+            jbyteArray bytes = (*env)->NewByteArray(env, len);
+            if (bytes != NULL) {
+                (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)(ptr->d_name));
+            }
+            return bytes;
+        }
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_mkdir0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint mode)
+{
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    /* EINTR not listed as a possible error */
+    if (mkdir(path, (mode_t)mode) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_rmdir0(JNIEnv* env, jclass this,
+    jlong pathAddress)
+{
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    /* EINTR not listed as a possible error */
+    if (rmdir(path) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_link0(JNIEnv* env, jclass this,
+    jlong existingAddress, jlong newAddress)
+{
+    int err;
+    const char* existing = (const char*)jlong_to_ptr(existingAddress);
+    const char* newname = (const char*)jlong_to_ptr(newAddress);
+
+    RESTARTABLE(link(existing, newname), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_unlink0(JNIEnv* env, jclass this,
+    jlong pathAddress)
+{
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    /* EINTR not listed as a possible error */
+    if (unlink(path) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0(JNIEnv* env, jclass this, jint dfd,
+                                               jlong pathAddress, jint flags)
+{
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    if (my_unlinkat_func == NULL) {
+        JNU_ThrowInternalError(env, "should not reach here");
+        return;
+    }
+
+    /* EINTR not listed as a possible error */
+    if ((*my_unlinkat_func)((int)dfd, path, (int)flags) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_rename0(JNIEnv* env, jclass this,
+    jlong fromAddress, jlong toAddress)
+{
+    const char* from = (const char*)jlong_to_ptr(fromAddress);
+    const char* to = (const char*)jlong_to_ptr(toAddress);
+
+    /* EINTR not listed as a possible error */
+    if (rename(from, to) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_renameat0(JNIEnv* env, jclass this,
+    jint fromfd, jlong fromAddress, jint tofd, jlong toAddress)
+{
+    const char* from = (const char*)jlong_to_ptr(fromAddress);
+    const char* to = (const char*)jlong_to_ptr(toAddress);
+
+    if (my_renameat_func == NULL) {
+        JNU_ThrowInternalError(env, "should not reach here");
+        return;
+    }
+
+    /* EINTR not listed as a possible error */
+    if ((*my_renameat_func)((int)fromfd, from, (int)tofd, to) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_symlink0(JNIEnv* env, jclass this,
+    jlong targetAddress, jlong linkAddress)
+{
+    const char* target = (const char*)jlong_to_ptr(targetAddress);
+    const char* link = (const char*)jlong_to_ptr(linkAddress);
+
+    /* EINTR not listed as a possible error */
+    if (symlink(target, link) == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_readlink0(JNIEnv* env, jclass this,
+    jlong pathAddress)
+{
+    jbyteArray result = NULL;
+    char target[PATH_MAX+1];
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    /* EINTR not listed as a possible error */
+    int n = readlink(path, target, sizeof(target));
+    if (n == -1) {
+        throwUnixException(env, errno);
+    } else {
+        jsize len;
+        if (n == sizeof(target)) {
+            n--;
+        }
+        target[n] = '\0';
+        len = (jsize)strlen(target);
+        result = (*env)->NewByteArray(env, len);
+        if (result != NULL) {
+            (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)target);
+        }
+    }
+    return result;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_realpath0(JNIEnv* env, jclass this,
+    jlong pathAddress)
+{
+    jbyteArray result = NULL;
+    char resolved[PATH_MAX+1];
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    /* EINTR not listed as a possible error */
+    if (realpath(path, resolved) == NULL) {
+        throwUnixException(env, errno);
+    } else {
+        jsize len = (jsize)strlen(resolved);
+        result = (*env)->NewByteArray(env, len);
+        if (result != NULL) {
+            (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)resolved);
+        }
+    }
+    return result;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_access0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint amode)
+{
+    int err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(access(path, (int)amode), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
+    jlong pathAddress, jobject attrs)
+{
+    int err;
+    struct statvfs64 buf;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+
+    RESTARTABLE(statvfs64(path, &buf), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    } else {
+        (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize));
+        (*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks));
+        (*env)->SetLongField(env, attrs, attrs_f_bfree,  long_to_jlong(buf.f_bfree));
+        (*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail));
+    }
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_pathconf0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint name)
+{
+    long err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    err = pathconf(path, (int)name);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jlong)err;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_fpathconf(JNIEnv* env, jclass this,
+    jint fd, jint name)
+{
+    long err;
+
+    err = fpathconf((int)fd, (int)name);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+    return (jlong)err;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_mknod0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint mode, jlong dev)
+{
+    int err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(mknod(path, (mode_t)mode, (dev_t)dev), err);
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getpwuid(JNIEnv* env, jclass this, jint uid)
+{
+    jbyteArray result = NULL;
+    int buflen;
+
+    buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
+    if (buflen == -1) {
+        throwUnixException(env, errno);
+    } else {
+        char* pwbuf = (char*)malloc(buflen);
+        if (pwbuf == NULL) {
+            JNU_ThrowOutOfMemoryError(env, "native heap");
+        } else {
+            struct passwd pwent;
+            struct passwd* p;
+            int res = 0;
+
+#ifdef __solaris__
+            p = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen);
+#else
+            res = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p);
+#endif
+
+            if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
+                throwUnixException(env, errno);
+            } else {
+                jsize len = strlen(p->pw_name);
+                result = (*env)->NewByteArray(env, len);
+                if (result != NULL) {
+                    (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name));
+                }
+            }
+            free(pwbuf);
+        }
+    }
+    return result;
+}
+
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid)
+{
+    jbyteArray result = NULL;
+    int buflen;
+
+    buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX);
+    if (buflen == -1) {
+        throwUnixException(env, errno);
+    } else {
+        char* grbuf = (char*)malloc(buflen);
+        if (grbuf == NULL) {
+            JNU_ThrowOutOfMemoryError(env, "native heap");
+        } else {
+            struct group grent;
+            struct group* g;
+            int res = 0;
+
+#ifdef __solaris__
+            g = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen);
+#else
+            res = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g);
+#endif
+            if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
+                throwUnixException(env, errno);
+            } else {
+                jsize len = strlen(g->gr_name);
+                result = (*env)->NewByteArray(env, len);
+                if (result != NULL) {
+                    (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name));
+                }
+            }
+            free(grbuf);
+        }
+    }
+    return result;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this,
+    jlong nameAddress)
+{
+    jint uid = -1;
+    int buflen;
+    char* pwbuf;
+    struct passwd pwent;
+    struct passwd* p;
+    int res = 0;
+    const char* name = (const char*)jlong_to_ptr(nameAddress);
+
+    buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
+    if (buflen == -1) {
+        throwUnixException(env, errno);
+        return -1;
+    }
+    pwbuf = (char*)malloc(buflen);
+    if (pwbuf == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "native heap");
+        return -1;
+    }
+
+#ifdef __solaris__
+    p = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen);
+#else
+    res = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p);
+#endif
+
+    if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
+        /* not found or error */
+    } else {
+        uid = p->pw_uid;
+    }
+
+    free(pwbuf);
+
+    return uid;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0(JNIEnv* env, jclass this,
+    jlong nameAddress)
+{
+    jint gid = -1;
+    int buflen;
+    char* grbuf;
+    struct group grent;
+    struct group* g;
+    int res = 0;
+    const char* name = (const char*)jlong_to_ptr(nameAddress);
+
+    buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX);
+    if (buflen == -1) {
+        throwUnixException(env, errno);
+        return -1;
+    }
+    grbuf = (char*)malloc(buflen);
+    if (grbuf == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "native heap");
+        return -1;
+    }
+
+#ifdef __solaris__
+    g = getgrnam_r(name, &grent, grbuf, (size_t)buflen);
+#else
+    res = getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g);
+#endif
+
+    if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
+        /* not found or error */
+    } else {
+        gid = g->gr_gid;
+    }
+    free(grbuf);
+
+    return gid;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getextmntent(JNIEnv* env, jclass this,
+    jlong value, jobject entry)
+{
+#ifdef __solaris__
+    struct extmnttab ent;
+#else
+    struct mntent ent;
+    char buf[1024];
+    int buflen = sizeof(buf);
+    struct mntent* m;
+#endif
+    FILE* fp = jlong_to_ptr(value);
+    jsize len;
+    jbyteArray bytes;
+    char* name;
+    char* dir;
+    char* fstype;
+    char* options;
+    dev_t dev;
+
+#ifdef __solaris__
+    if (getextmntent(fp, &ent, 0))
+        return -1;
+    name = ent.mnt_special;
+    dir = ent.mnt_mountp;
+    fstype = ent.mnt_fstype;
+    options = ent.mnt_mntopts;
+    dev = makedev(ent.mnt_major, ent.mnt_minor);
+    if (dev == NODEV) {
+        /* possible bug on Solaris 8 and 9 */
+        throwUnixException(env, errno);
+        return -1;
+    }
+#else
+    m = getmntent_r(fp, &ent, (char*)&buf, buflen);
+    if (m == NULL)
+        return -1;
+    name = m->mnt_fsname;
+    dir = m->mnt_dir;
+    fstype = m->mnt_type;
+    options = m->mnt_opts;
+    dev = 0;
+#endif
+
+    len = strlen(name);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
+    (*env)->SetObjectField(env, entry, entry_name, bytes);
+
+    len = strlen(dir);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
+    (*env)->SetObjectField(env, entry, entry_dir, bytes);
+
+    len = strlen(fstype);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
+    (*env)->SetObjectField(env, entry, entry_fstype, bytes);
+
+    len = strlen(options);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
+    (*env)->SetObjectField(env, entry, entry_options, bytes);
+
+    if (dev != 0)
+        (*env)->SetLongField(env, entry, entry_dev, (jlong)dev);
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+
+/**
+ * Generates sun.nio.fs.SolarisConstants
+ */
+
+static void out(char* s) {
+    printf("%s\n", s);
+}
+
+static void emit(char* name, int value) {
+    printf("    static final int %s = %d;\n", name, value);
+}
+
+static void emitX(char* name, int value) {
+    printf("    static final int %s = 0x%x;\n", name, value);
+}
+
+#define DEF(X) emit(#X, X);
+#define DEFX(X) emitX(#X, X);
+
+int main(int argc, const char* argv[]) {
+    out("// AUTOMATICALLY GENERATED FILE - DO NOT EDIT                                  ");
+    out("package sun.nio.fs;                                                            ");
+    out("class SolarisConstants {                                                       ");
+    out("    private SolarisConstants() { }                                             ");
+
+    // extended attributes
+    emitX("O_XATTR", 0x4000);
+    emit("_PC_XATTR_ENABLED", 100);
+
+    // ACL configuration
+    emit("_PC_ACL_ENABLED", 20);
+    emitX("_ACL_ACE_ENABLED", 0x2);
+
+    // ACL commands
+    emitX("ACE_GETACL",                         4);
+    emitX("ACE_SETACL",                         5);
+
+    // ACL mask/flags/types
+    emitX("ACE_ACCESS_ALLOWED_ACE_TYPE",        0x0000);
+    emitX("ACE_ACCESS_DENIED_ACE_TYPE",         0x0001);
+    emitX("ACE_SYSTEM_AUDIT_ACE_TYPE",          0x0002);
+    emitX("ACE_SYSTEM_ALARM_ACE_TYPE",          0x0003);
+    emitX("ACE_READ_DATA",                      0x00000001);
+    emitX("ACE_LIST_DIRECTORY",                 0x00000001);
+    emitX("ACE_WRITE_DATA",                     0x00000002);
+    emitX("ACE_ADD_FILE",                       0x00000002);
+    emitX("ACE_APPEND_DATA",                    0x00000004);
+    emitX("ACE_ADD_SUBDIRECTORY",               0x00000004);
+    emitX("ACE_READ_NAMED_ATTRS",               0x00000008);
+    emitX("ACE_WRITE_NAMED_ATTRS",              0x00000010);
+    emitX("ACE_EXECUTE",                        0x00000020);
+    emitX("ACE_DELETE_CHILD",                   0x00000040);
+    emitX("ACE_READ_ATTRIBUTES",                0x00000080);
+    emitX("ACE_WRITE_ATTRIBUTES",               0x00000100);
+    emitX("ACE_DELETE",                         0x00010000);
+    emitX("ACE_READ_ACL",                       0x00020000);
+    emitX("ACE_WRITE_ACL",                      0x00040000);
+    emitX("ACE_WRITE_OWNER",                    0x00080000);
+    emitX("ACE_SYNCHRONIZE",                    0x00100000);
+    emitX("ACE_FILE_INHERIT_ACE",               0x0001);
+    emitX("ACE_DIRECTORY_INHERIT_ACE",          0x0002);
+    emitX("ACE_NO_PROPAGATE_INHERIT_ACE",       0x0004);
+    emitX("ACE_INHERIT_ONLY_ACE",               0x0008);
+    emitX("ACE_SUCCESSFUL_ACCESS_ACE_FLAG",     0x0010);
+    emitX("ACE_FAILED_ACCESS_ACE_FLAG",         0x0020);
+    emitX("ACE_IDENTIFIER_GROUP",               0x0040);
+    emitX("ACE_OWNER",                          0x1000);
+    emitX("ACE_GROUP",                          0x2000);
+    emitX("ACE_EVERYONE",                       0x4000);
+
+    out("}                                                                              ");
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+
+/**
+ * Generates sun.nio.fs.UnixConstants
+ */
+
+static void out(char* s) {
+    printf("%s\n", s);
+}
+
+static void emit(char* name, int value) {
+    printf("    static final int %s = %d;\n", name, value);
+}
+
+static void emitX(char* name, int value) {
+    printf("    static final int %s = 0x%x;\n", name, value);
+}
+
+#define DEF(X) emit(#X, X);
+#define DEFX(X) emitX(#X, X);
+
+int main(int argc, const char* argv[]) {
+    out("// AUTOMATICALLY GENERATED FILE - DO NOT EDIT                                  ");
+    out("package sun.nio.fs;                                                            ");
+    out("class UnixConstants {                                                          ");
+    out("    private UnixConstants() { }                                                ");
+
+    // open flags
+    DEF(O_RDONLY);
+    DEF(O_WRONLY);
+    DEF(O_RDWR);
+    DEFX(O_APPEND);
+    DEFX(O_CREAT);
+    DEFX(O_EXCL);
+    DEFX(O_TRUNC);
+    DEFX(O_SYNC);
+    DEFX(O_DSYNC);
+#ifdef __solaris__
+    emitX("O_NOFOLLOW", 0x20000);
+#else
+    DEFX(O_NOFOLLOW);
+#endif
+
+    // flags used with openat/unlinkat/etc.
+#ifdef __solaris__
+    emitX("AT_SYMLINK_NOFOLLOW", 0x1000);       // since Solaris 9
+    emitX("AT_REMOVEDIR", 0x1);
+#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));
+    DEF(S_IRUSR);
+    DEF(S_IWUSR);
+    DEF(S_IXUSR);
+    DEF(S_IRGRP);
+    DEF(S_IWGRP);
+    DEF(S_IXGRP);
+    DEF(S_IROTH);
+    DEF(S_IWOTH);
+    DEF(S_IXOTH);
+    DEFX(S_IFMT);
+    DEFX(S_IFREG);
+    DEFX(S_IFDIR);
+    DEFX(S_IFLNK);
+    DEFX(S_IFCHR);
+    DEFX(S_IFBLK);
+    DEFX(S_IFIFO);
+
+    // access modes
+    DEF(R_OK);
+    DEF(W_OK);
+    DEF(X_OK);
+    DEF(F_OK);
+
+    // errors
+    DEF(ENOENT);
+    DEF(EACCES);
+    DEF(EEXIST);
+    DEF(ENOTDIR);
+    DEF(EINVAL);
+    DEF(EXDEV);
+    DEF(EISDIR);
+    DEF(ENOTEMPTY);
+    DEF(ENOSPC);
+    DEF(EAGAIN);
+    DEF(ENOSYS);
+    DEF(ELOOP);
+    DEF(EROFS);
+    DEF(ENODATA);
+    DEF(ERANGE);
+
+    out("}                                                                              ");
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * Creates this platform's default asynchronous channel provider
+ */
+
+public class DefaultAsynchronousChannelProvider {
+    private DefaultAsynchronousChannelProvider() { }
+
+    /**
+     * Returns the default AsynchronousChannelProvider.
+     */
+    public static AsynchronousChannelProvider create() {
+        return new WindowsAsynchronousChannelProvider();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/Iocp.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import sun.misc.Unsafe;
+
+/**
+ * Windows implementation of AsynchronousChannelGroup encapsulating an I/O
+ * completion port.
+ */
+
+class Iocp extends AsynchronousChannelGroupImpl {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // maps completion key to channel
+    private final ReadWriteLock keyToChannelLock = new ReentrantReadWriteLock();
+    private final Map<Integer,OverlappedChannel> keyToChannel =
+        new HashMap<Integer,OverlappedChannel>();
+    private int nextCompletionKey;
+
+    // handle to completion port
+    private final long port;
+
+    // true if port has been closed
+    private boolean closed;
+
+    // the set of "stale" OVERLAPPED structures. These OVERLAPPED structures
+    // relate to I/O operations where the completion notification was not
+    // received in a timely manner after the channel is closed.
+    private Set<Long> staleIoSet = new HashSet<Long>();
+
+    Iocp(AsynchronousChannelProvider provider, ThreadPool pool)
+        throws IOException
+    {
+        super(provider, pool);
+        this.port = createIoCompletionPort(-1L, 0, 0, fixedThreadCount());
+        this.nextCompletionKey = 1;
+    }
+
+    Iocp start() {
+        startThreads(new EventHandlerTask());
+        return this;
+    }
+
+    /*
+     * Channels implements this interface support overlapped I/O and can be
+     * associated with a completion port.
+     */
+    static interface OverlappedChannel extends Closeable {
+        /**
+         * Returns a reference to the pending I/O result.
+         */
+        <V,A> PendingFuture<V,A> getByOverlapped(long overlapped);
+    }
+
+    // release all resources
+    void implClose() {
+        synchronized (this) {
+            if (closed)
+                return;
+            closed = true;
+        }
+        close0(port);
+        synchronized (staleIoSet) {
+            for (Long ov: staleIoSet) {
+                unsafe.freeMemory(ov);
+            }
+            staleIoSet.clear();
+        }
+    }
+
+
+    boolean isEmpty() {
+        keyToChannelLock.writeLock().lock();
+        try {
+            return keyToChannel.isEmpty();
+        } finally {
+            keyToChannelLock.writeLock().unlock();
+        }
+    }
+
+
+    final Object attachForeignChannel(final Channel channel, FileDescriptor fdObj)
+        throws IOException
+    {
+        int key = associate(new OverlappedChannel() {
+            public <V,A> PendingFuture<V,A> getByOverlapped(long overlapped) {
+                return null;
+            }
+            public void close() throws IOException {
+                channel.close();
+            }
+        }, 0L);
+        return Integer.valueOf(key);
+    }
+
+
+    final void detachForeignChannel(Object key) {
+        disassociate((Integer)key);
+    }
+
+
+    void closeAllChannels() {
+        /**
+         * On Windows the close operation will close the socket/file handle
+         * and then wait until all outstanding I/O operations have aborted.
+         * This is necessary as each channel's cache of OVERLAPPED structures
+         * can only be freed once all I/O operations have completed. As I/O
+         * completion requires a lookup of the keyToChannel then we must close
+         * the channels when not holding the write lock.
+         */
+        final int MAX_BATCH_SIZE = 32;
+        OverlappedChannel channels[] = new OverlappedChannel[MAX_BATCH_SIZE];
+        int count;
+        do {
+            // grab a batch of up to 32 channels
+            keyToChannelLock.writeLock().lock();
+            count = 0;
+            try {
+                for (Integer key: keyToChannel.keySet()) {
+                    channels[count++] = keyToChannel.get(key);
+                    if (count >= MAX_BATCH_SIZE)
+                        break;
+                }
+            } finally {
+                keyToChannelLock.writeLock().unlock();
+            }
+
+            // close them
+            for (int i=0; i<count; i++) {
+                try {
+                    channels[i].close();
+                } catch (IOException ignore) { }
+            }
+        } while (count > 0);
+    }
+
+    private void wakeup() {
+        try {
+            postQueuedCompletionStatus(port, 0);
+        } catch (IOException e) {
+            // should not happen
+            throw new AssertionError(e);
+        }
+    }
+
+
+    void executeOnHandlerTask(Runnable task) {
+        synchronized (this) {
+            if (closed)
+                throw new RejectedExecutionException();
+            offerTask(task);
+            wakeup();
+        }
+
+    }
+
+
+    void shutdownHandlerTasks() {
+        // shutdown all handler threads
+        int nThreads = threadCount();
+        while (nThreads-- > 0) {
+            wakeup();
+        }
+    }
+
+    /**
+     * Associate the given handle with this group
+     */
+    int associate(OverlappedChannel ch, long handle) throws IOException {
+        keyToChannelLock.writeLock().lock();
+
+        // generate a completion key (if not shutdown)
+        int key;
+        try {
+            if (isShutdown())
+                throw new ShutdownChannelGroupException();
+
+            // generate unique key
+            do {
+                key = nextCompletionKey++;
+            } while ((key == 0) || keyToChannel.containsKey(key));
+
+            // associate with I/O completion port
+            if (handle != 0L)
+                createIoCompletionPort(handle, port, key, 0);
+
+            // setup mapping
+            keyToChannel.put(key, ch);
+        } finally {
+            keyToChannelLock.writeLock().unlock();
+        }
+        return key;
+    }
+
+    /**
+     * Disassociate channel from the group.
+     */
+    void disassociate(int key) {
+        boolean checkForShutdown = false;
+
+        keyToChannelLock.writeLock().lock();
+        try {
+            keyToChannel.remove(key);
+
+            // last key to be removed so check if group is shutdown
+            if (keyToChannel.isEmpty())
+                checkForShutdown = true;
+
+        } finally {
+            keyToChannelLock.writeLock().unlock();
+        }
+
+        // continue shutdown
+        if (checkForShutdown && isShutdown()) {
+            try {
+                shutdownNow();
+            } catch (IOException ignore) { }
+        }
+    }
+
+    /**
+     * Invoked when a channel associated with this port is closed before
+     * notifications for all outstanding I/O operations have been received.
+     */
+    void makeStale(Long overlapped) {
+        synchronized (staleIoSet) {
+            staleIoSet.add(overlapped);
+        }
+    }
+
+    /**
+     * Checks if the given OVERLAPPED is stale and if so, releases it.
+     */
+    private void checkIfStale(long ov) {
+        synchronized (staleIoSet) {
+            boolean removed = staleIoSet.remove(ov);
+            if (removed) {
+                unsafe.freeMemory(ov);
+            }
+        }
+    }
+
+    /**
+     * The handler for consuming the result of an asynchronous I/O operation.
+     */
+    static interface ResultHandler {
+        /**
+         * Invoked if the I/O operation completes successfully.
+         */
+        public void completed(int bytesTransferred);
+
+        /**
+         * Invoked if the I/O operation fails.
+         */
+        public void failed(int error, IOException ioe);
+    }
+
+    // Creates IOException for the given I/O error.
+    private static IOException translateErrorToIOException(int error) {
+        String msg = getErrorMessage(error);
+        if (msg == null)
+            msg = "Unknown error: 0x0" + Integer.toHexString(error);
+        return new IOException(msg);
+    }
+
+    /**
+     * Long-running task servicing system-wide or per-file completion port
+     */
+    private class EventHandlerTask implements Runnable {
+        public void run() {
+            Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+                Invoker.getGroupAndInvokeCount();
+            CompletionStatus ioResult = new CompletionStatus();
+            boolean replaceMe = false;
+
+            try {
+                for (;;) {
+                    // reset invoke count
+                    if (myGroupAndInvokeCount != null)
+                        myGroupAndInvokeCount.resetInvokeCount();
+
+                    // wait for I/O completion event
+                    // A error here is fatal (thread will not be replaced)
+                    replaceMe = false;
+                    try {
+                        getQueuedCompletionStatus(port, ioResult);
+                    } catch (IOException x) {
+                        // should not happen
+                        x.printStackTrace();
+                        return;
+                    }
+
+                    // handle wakeup to execute task or shutdown
+                    if (ioResult.completionKey() == 0 &&
+                        ioResult.overlapped() == 0L)
+                    {
+                        Runnable task = pollTask();
+                        if (task == null) {
+                            // shutdown request
+                            return;
+                        }
+
+                        // run task
+                        // (if error/exception then replace thread)
+                        replaceMe = true;
+                        task.run();
+                        continue;
+                    }
+
+                    // map key to channel
+                    OverlappedChannel ch = null;
+                    keyToChannelLock.readLock().lock();
+                    try {
+                        ch = keyToChannel.get(ioResult.completionKey());
+                        if (ch == null) {
+                            checkIfStale(ioResult.overlapped());
+                            continue;
+                        }
+                    } finally {
+                        keyToChannelLock.readLock().unlock();
+                    }
+
+                    // lookup I/O request
+                    PendingFuture<?,?> result = ch.getByOverlapped(ioResult.overlapped());
+                    if (result == null) {
+                        // we get here if the OVERLAPPED structure is associated
+                        // with an I/O operation on a channel that was closed
+                        // but the I/O operation event wasn't read in a timely
+                        // manner. Alternatively, it may be related to a
+                        // tryLock operation as the OVERLAPPED structures for
+                        // these operations are not in the I/O cache.
+                        checkIfStale(ioResult.overlapped());
+                        continue;
+                    }
+
+                    // synchronize on result in case I/O completed immediately
+                    // and was handled by initiator
+                    synchronized (result) {
+                        if (result.isDone()) {
+                            continue;
+                        }
+                        // not handled by initiator
+                    }
+
+                    // invoke I/O result handler
+                    int error = ioResult.error();
+                    ResultHandler rh = (ResultHandler)result.getContext();
+                    replaceMe = true; // (if error/exception then replace thread)
+                    if (error == 0) {
+                        rh.completed(ioResult.bytesTransferred());
+                    } else {
+                        rh.failed(error, translateErrorToIOException(error));
+                    }
+                }
+            } finally {
+                // last thread to exit when shutdown releases resources
+                int remaining = threadExit(this, replaceMe);
+                if (remaining == 0 && isShutdown()) {
+                    implClose();
+                }
+            }
+        }
+    }
+
+    /**
+     * Container for data returned by GetQueuedCompletionStatus
+     */
+    private static class CompletionStatus {
+        private int error;
+        private int bytesTransferred;
+        private int completionKey;
+        private long overlapped;
+
+        private CompletionStatus() { }
+        int error() { return error; }
+        int bytesTransferred() { return bytesTransferred; }
+        int completionKey() { return completionKey; }
+        long overlapped() { return overlapped; }
+    }
+
+    // -- native methods --
+
+    private static native void initIDs();
+
+    private static native long createIoCompletionPort(long handle,
+        long existingPort, int completionKey, int concurrency) throws IOException;
+
+    private static native void close0(long handle);
+
+    private static native void getQueuedCompletionStatus(long completionPort,
+        CompletionStatus status) throws IOException;
+
+    private static native void postQueuedCompletionStatus(long completionPort,
+        int completionKey) throws IOException;
+
+    private static native String getErrorMessage(int error);
+
+    static {
+        Util.load();
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.*;
+import sun.misc.Unsafe;
+
+/**
+ * Maintains a mapping of pending I/O requests (identified by the address of
+ * an OVERLAPPED structure) to Futures.
+ */
+
+class PendingIoCache {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final int addressSize = unsafe.addressSize();
+
+    private static int dependsArch(int value32, int value64) {
+        return (addressSize == 4) ? value32 : value64;
+    }
+
+    /*
+     * typedef struct _OVERLAPPED {
+     *     DWORD  Internal;
+     *     DWORD  InternalHigh;
+     *     DWORD  Offset;
+     *     DWORD  OffsetHigh;
+     *     HANDLE hEvent;
+     * } OVERLAPPED;
+     */
+    private static final int SIZEOF_OVERLAPPED = dependsArch(20, 32);
+
+    // set to true when closed
+    private boolean closed;
+
+    // set to true when thread is waiting for all I/O operations to complete
+    private boolean closePending;
+
+    // maps OVERLAPPED to PendingFuture
+    private final Map<Long,PendingFuture> pendingIoMap =
+        new HashMap<Long,PendingFuture>();
+
+    // per-channel cache of OVERLAPPED structures
+    private long[] overlappedCache = new long[4];
+    private int overlappedCacheCount = 0;
+
+    PendingIoCache() {
+    }
+
+    long add(PendingFuture<?,?> result) {
+        synchronized (this) {
+            if (closed)
+                throw new AssertionError("Should not get here");
+            long ov;
+            if (overlappedCacheCount > 0) {
+                ov = overlappedCache[--overlappedCacheCount];
+            } else {
+                ov = unsafe.allocateMemory(SIZEOF_OVERLAPPED);
+            }
+            pendingIoMap.put(ov, result);
+            return ov;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    <V,A> PendingFuture<V,A> remove(long overlapped) {
+        synchronized (this) {
+            PendingFuture<V,A> res = pendingIoMap.remove(overlapped);
+            if (res != null) {
+                if (overlappedCacheCount < overlappedCache.length) {
+                    overlappedCache[overlappedCacheCount++] = overlapped;
+                } else {
+                    // cache full or channel closing
+                    unsafe.freeMemory(overlapped);
+                }
+                // notify closing thread.
+                if (closePending) {
+                    this.notifyAll();
+                }
+            }
+            return res;
+        }
+    }
+
+    void close() {
+        synchronized (this) {
+            if (closed)
+                return;
+
+            // handle the case that where there are I/O operations that have
+            // not completed.
+            if (!pendingIoMap.isEmpty())
+                clearPendingIoMap();
+
+            // release memory for any cached OVERLAPPED structures
+            while (overlappedCacheCount > 0) {
+                unsafe.freeMemory( overlappedCache[--overlappedCacheCount] );
+            }
+
+            // done
+            closed = true;
+        }
+    }
+
+    private void clearPendingIoMap() {
+        assert Thread.holdsLock(this);
+
+        // wait up to 50ms for the I/O operations to complete
+        closePending = true;
+        try {
+            this.wait(50);
+        } catch (InterruptedException x) { }
+        closePending = false;
+        if (pendingIoMap.isEmpty())
+            return;
+
+        // cause all pending I/O operations to fail
+        // simulate the failure of all pending I/O operations.
+        for (Long ov: pendingIoMap.keySet()) {
+            PendingFuture<?,?> result = pendingIoMap.get(ov);
+            assert !result.isDone();
+
+            // make I/O port aware of the stale OVERLAPPED structure
+            Iocp iocp = (Iocp)((Groupable)result.channel()).group();
+            iocp.makeStale(ov);
+
+            // execute a task that invokes the result handler's failed method
+            final Iocp.ResultHandler rh = (Iocp.ResultHandler)result.getContext();
+            Runnable task = new Runnable() {
+                public void run() {
+                    rh.failed(-1, new AsynchronousCloseException());
+                }
+            };
+            iocp.executeOnPooledThread(task);
+        }
+        pendingIoMap.clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+import java.util.concurrent.ExecutorService;
+import java.net.ProtocolFamily;
+import java.io.IOException;
+
+public class WindowsAsynchronousChannelProvider
+    extends AsynchronousChannelProvider
+{
+    private static volatile Iocp defaultIocp;
+
+    public WindowsAsynchronousChannelProvider() {
+        // nothing to do
+    }
+
+    private Iocp defaultIocp() throws IOException {
+        if (defaultIocp == null) {
+            synchronized (WindowsAsynchronousChannelProvider.class) {
+                if (defaultIocp == null) {
+                    // default thread pool may be shared with AsynchronousFileChannels
+                    defaultIocp = new Iocp(this, ThreadPool.getDefault()).start();
+                }
+            }
+        }
+        return defaultIocp;
+    }
+
+
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(ThreadPoolType poolType,
+                                                                 ExecutorService executor,
+                                                                 int nThreads)
+        throws IOException
+    {
+        return new Iocp(this, ThreadPool.create(poolType, executor, nThreads)).start();
+    }
+
+    private Iocp toIocp(AsynchronousChannelGroup group) throws IOException {
+        if (group == null) {
+            return defaultIocp();
+        } else {
+            if (!(group instanceof Iocp))
+                throw new IllegalChannelGroupException();
+            return (Iocp)group;
+        }
+    }
+
+
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new WindowsAsynchronousServerSocketChannelImpl(toIocp(group));
+    }
+
+
+    public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new WindowsAsynchronousSocketChannelImpl(toIocp(group));
+    }
+
+
+    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
+                                                                       AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new SimpleAsynchronousDatagramChannelImpl(family, toIocp(group));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,736 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.nio.ByteBuffer;
+import java.nio.BufferOverflowException;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaIOFileDescriptorAccess;
+
+/**
+ * Windows implementation of AsynchronousFileChannel using overlapped I/O.
+ */
+
+public class WindowsAsynchronousFileChannelImpl
+    extends AsynchronousFileChannelImpl
+    implements Iocp.OverlappedChannel, Groupable
+{
+    private static final JavaIOFileDescriptorAccess fdAccess =
+        SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    // error when EOF is detected asynchronously.
+    private static final int ERROR_HANDLE_EOF = 38;
+
+    // Default I/O completion port
+    private static volatile Iocp defaultIocp;
+
+    private static Iocp defaultIocp() throws IOException {
+        if (defaultIocp == null) {
+            synchronized (WindowsAsynchronousFileChannelImpl.class) {
+                if (defaultIocp == null) {
+                    // create default thread pool
+                    defaultIocp = new Iocp(null, ThreadPool.createDefault()).start();
+                }
+            }
+        }
+        return defaultIocp;
+    }
+
+    // Used for force/truncate/size methods
+    private static final FileDispatcher nd = new FileDispatcherImpl();
+
+    // The handle is extracted for use in native methods invoked from this class.
+    private final long handle;
+
+    // The key that identifies the channel's association with the I/O port
+    private final int completionKey;
+
+    // I/O completion port (group)
+    private final Iocp iocp;
+
+    // Caches OVERLAPPED structure for each outstanding I/O operation
+    private final PendingIoCache ioCache;
+
+
+    private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj,
+                                               boolean reading,
+                                               boolean writing,
+                                               Iocp iocp)
+        throws IOException
+    {
+        super(fdObj, reading, writing, iocp.executor());
+        this.handle = fdAccess.getHandle(fdObj);
+        this.iocp = iocp;
+        this.ioCache = new PendingIoCache();
+        this.completionKey = iocp.associate(this, handle);
+    }
+
+    public static AsynchronousFileChannel open(FileDescriptor fdo,
+                                               boolean reading,
+                                               boolean writing,
+                                               ThreadPool pool)
+        throws IOException
+    {
+        Iocp iocp;
+        if (pool == null) {
+            iocp = defaultIocp();
+        } else {
+            iocp = new Iocp(null, pool).start();
+        }
+        try {
+            return new WindowsAsynchronousFileChannelImpl(fdo, reading, writing, iocp);
+        } catch (IOException x) {
+            // error binding to port so need to close it (if created for this channel)
+            if (iocp != defaultIocp) {
+                iocp.implClose();
+            }
+            throw x;
+        }
+    }
+
+
+    public <V,A> PendingFuture<V,A> getByOverlapped(long overlapped) {
+        return ioCache.remove(overlapped);
+    }
+
+
+    public void close() throws IOException {
+        closeLock.writeLock().lock();
+        try {
+            if (closed)
+                return;     // already closed
+            closed = true;
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+
+        // invalidate all locks held for this channel
+        invalidateAllLocks();
+
+        // close the file
+        close0(handle);
+
+        // waits until all I/O operations have completed
+        ioCache.close();
+
+        // disassociate from port and shutdown thread pool if not default
+        iocp.disassociate(completionKey);
+        if (iocp != defaultIocp) {
+            iocp.shutdown();
+        }
+    }
+
+
+    public AsynchronousChannelGroupImpl group() {
+        return iocp;
+    }
+
+    /**
+     * Translates Throwable to IOException
+     */
+    private static IOException toIOException(Throwable x) {
+        if (x instanceof IOException) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            return (IOException)x;
+        }
+        return new IOException(x);
+    }
+
+
+    public long size() throws IOException {
+        try {
+            begin();
+            return nd.size(fdObj);
+        } finally {
+            end();
+        }
+    }
+
+
+    public AsynchronousFileChannel truncate(long size) throws IOException {
+        if (size < 0)
+            throw new IllegalArgumentException("Negative size");
+        if (!writing)
+            throw new NonWritableChannelException();
+        try {
+            begin();
+            if (size > nd.size(fdObj))
+                return this;
+            nd.truncate(fdObj, size);
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+
+    public void force(boolean metaData) throws IOException {
+        try {
+            begin();
+            nd.force(fdObj, metaData);
+        } finally {
+            end();
+        }
+    }
+
+    // -- file locking --
+
+    /**
+     * Task that initiates locking operation and handles completion result.
+     */
+    private class LockTask<A> implements Runnable, Iocp.ResultHandler {
+        private final long position;
+        private final FileLockImpl fli;
+        private final PendingFuture<FileLock,A> result;
+
+        LockTask(long position,
+                 FileLockImpl fli,
+                 PendingFuture<FileLock,A> result)
+        {
+            this.position = position;
+            this.fli = fli;
+            this.result = result;
+        }
+
+
+        public void run() {
+            long overlapped = 0L;
+            try {
+                begin();
+
+                // allocate OVERLAPPED structure
+                overlapped = ioCache.add(result);
+
+                // synchronize on result to avoid race with handler thread
+                // when lock is acquired immediately.
+                synchronized (result) {
+                    int n = lockFile(handle, position, fli.size(), fli.isShared(),
+                                     overlapped);
+                    if (n == IOStatus.UNAVAILABLE) {
+                        // I/O is pending
+                        return;
+                    }
+                    // acquired lock immediately
+                    result.setResult(fli);
+                }
+
+            } catch (Throwable x) {
+                // lock failed or channel closed
+                removeFromFileLockTable(fli);
+                if (overlapped != 0L)
+                    ioCache.remove(overlapped);
+                result.setFailure(toIOException(x));
+            } finally {
+                end();
+            }
+
+            // invoke completion handler
+            Invoker.invoke(result.handler(), result);
+        }
+
+
+        public void completed(int bytesTransferred) {
+            // release waiters and invoke completion handler
+            result.setResult(fli);
+            Invoker.invoke(result.handler(), result);
+        }
+
+
+        public void failed(int error, IOException x) {
+            // lock not acquired so remove from lock table
+            removeFromFileLockTable(fli);
+
+            // release waiters
+            if (isOpen()) {
+                result.setFailure(x);
+            } else {
+                result.setFailure(new AsynchronousCloseException());
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+    }
+
+
+    public <A> Future<FileLock> lock(long position,
+                                     long size,
+                                     boolean shared,
+                                     A attachment,
+                                     CompletionHandler<FileLock,? super A> handler)
+    {
+        if (shared && !reading)
+            throw new NonReadableChannelException();
+        if (!shared && !writing)
+            throw new NonWritableChannelException();
+
+        // add to lock table
+        FileLockImpl fli = addToFileLockTable(position, size, shared);
+        if (fli == null) {
+            CompletedFuture<FileLock,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        // create Future and task that will be invoked to acquire lock
+        PendingFuture<FileLock,A> result =
+            new PendingFuture<FileLock,A>(this, handler, attachment);
+        LockTask lockTask = new LockTask<A>(position, fli, result);
+        result.setContext(lockTask);
+
+        // initiate I/O (can only be done from thread in thread pool)
+        try {
+            Invoker.invokeOnThreadInThreadPool(this, lockTask);
+        } catch (ShutdownChannelGroupException e) {
+            // rollback
+            removeFromFileLockTable(fli);
+            throw e;
+        }
+        return result;
+    }
+
+    static final int NO_LOCK = -1;       // Failed to lock
+    static final int LOCKED = 0;         // Obtained requested lock
+
+
+    public FileLock tryLock(long position, long size, boolean shared)
+        throws IOException
+    {
+        if (shared && !reading)
+            throw new NonReadableChannelException();
+        if (!shared && !writing)
+            throw new NonWritableChannelException();
+
+        // add to lock table
+        final FileLockImpl fli = addToFileLockTable(position, size, shared);
+        if (fli == null)
+            throw new ClosedChannelException();
+
+        boolean gotLock = false;
+        try {
+            begin();
+            // try to acquire the lock
+            int res = nd.lock(fdObj, false, position, size, shared);
+            if (res == NO_LOCK)
+                return null;
+            gotLock = true;
+            return fli;
+        } finally {
+            if (!gotLock)
+                removeFromFileLockTable(fli);
+            end();
+        }
+    }
+
+    // invoke by FileFileImpl to release lock
+
+    void release(FileLockImpl fli) throws IOException {
+        try {
+            begin();
+            nd.release(fdObj, fli.position(), fli.size());
+            removeFromFileLockTable(fli);
+        } finally {
+            end();
+        }
+    }
+
+    /**
+     * Task that initiates read operation and handles completion result.
+     */
+    private class ReadTask<A> implements Runnable, Iocp.ResultHandler {
+        private final ByteBuffer dst;
+        private final int pos, rem;     // buffer position/remaining
+        private final long position;    // file position
+        private final PendingFuture<Integer,A> result;
+
+        // set to dst if direct; otherwise set to substituted direct buffer
+        private volatile ByteBuffer buf;
+
+        ReadTask(ByteBuffer dst,
+                 int pos,
+                 int rem,
+                 long position,
+                 PendingFuture<Integer,A> result)
+        {
+            this.dst = dst;
+            this.pos = pos;
+            this.rem = rem;
+            this.position = position;
+            this.result = result;
+        }
+
+        void releaseBufferIfSubstituted() {
+            if (buf != dst)
+                Util.releaseTemporaryDirectBuffer(buf);
+        }
+
+        void updatePosition(int bytesTransferred) {
+            // if the I/O succeeded then adjust buffer position
+            if (bytesTransferred > 0) {
+                if (buf == dst) {
+                    try {
+                        dst.position(pos + bytesTransferred);
+                    } catch (IllegalArgumentException x) {
+                        // someone has changed the position; ignore
+                    }
+                } else {
+                    // had to substitute direct buffer
+                    buf.position(bytesTransferred).flip();
+                    try {
+                        dst.put(buf);
+                    } catch (BufferOverflowException x) {
+                        // someone has changed the position; ignore
+                    }
+                }
+            }
+        }
+
+
+        public void run() {
+            int n = -1;
+            long overlapped = 0L;
+            long address;
+
+            // Substitute a native buffer if not direct
+            if (dst instanceof DirectBuffer) {
+                buf = dst;
+                address = ((DirectBuffer)dst).address() + pos;
+            } else {
+                buf = Util.getTemporaryDirectBuffer(rem);
+                address = ((DirectBuffer)buf).address();
+            }
+
+            try {
+                begin();
+
+                // allocate OVERLAPPED
+                overlapped = ioCache.add(result);
+
+                // synchronize on result to allow this thread handle the case
+                // where the read completes immediately.
+                synchronized (result) {
+                    n = readFile(handle, address, rem, position, overlapped);
+                    if (n == IOStatus.UNAVAILABLE) {
+                        // I/O is pending
+                        return;
+                    }
+                    // read completed immediately:
+                    // 1. update buffer position
+                    // 2. release waiters
+                    updatePosition(n);
+                    result.setResult(n);
+                }
+            } catch (Throwable x) {
+                // failed to initiate read
+                result.setFailure(toIOException(x));
+            } finally {
+                end();
+            }
+
+            // read failed or EOF so completion port will not be notified
+            if (n < 0 && overlapped != 0L) {
+                ioCache.remove(overlapped);
+            }
+
+            // return direct buffer to cache if substituted
+            releaseBufferIfSubstituted();
+
+            // invoke completion handler
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Executed when the I/O has completed
+         */
+
+        public void completed(int bytesTransferred) {
+            updatePosition(bytesTransferred);
+
+            // return direct buffer to cache if substituted
+            releaseBufferIfSubstituted();
+
+            // release waiters and invoke completion handler
+            result.setResult(bytesTransferred);
+            Invoker.invoke(result.handler(), result);
+        }
+
+
+        public void failed(int error, IOException x) {
+            // if EOF detected asynchronously then it is reported as error
+            if (error == ERROR_HANDLE_EOF) {
+                completed(-1);
+            } else {
+                // return direct buffer to cache if substituted
+                releaseBufferIfSubstituted();
+
+                // release waiters
+                if (isOpen()) {
+                    result.setFailure(x);
+                } else {
+                    result.setFailure(new AsynchronousCloseException());
+                }
+                Invoker.invoke(result.handler(), result);
+            }
+        }
+    }
+
+
+    public <A> Future<Integer> read(ByteBuffer dst,
+                                    long position,
+                                    A attachment,
+                                    CompletionHandler<Integer,? super A> handler)
+    {
+        if (!reading)
+            throw new NonReadableChannelException();
+        if (position < 0)
+            throw new IllegalArgumentException("Negative position");
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+
+        // check if channel is closed
+        if (!isOpen()) {
+            CompletedFuture<Integer,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        int pos = dst.position();
+        int lim = dst.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        // no space remaining
+        if (rem == 0) {
+            CompletedFuture<Integer,A> result =
+                CompletedFuture.withResult(this, 0, attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        // create Future and task that initiates read
+        PendingFuture<Integer,A> result =
+            new PendingFuture<Integer,A>(this, handler, attachment);
+        ReadTask readTask = new ReadTask<A>(dst, pos, rem, position, result);
+        result.setContext(readTask);
+
+        // initiate I/O (can only be done from thread in thread pool)
+        Invoker.invokeOnThreadInThreadPool(this, readTask);
+        return result;
+    }
+
+    /**
+     * Task that initiates write operation and handles completion result.
+     */
+    private class WriteTask<A> implements Runnable, Iocp.ResultHandler {
+        private final ByteBuffer src;
+        private final int pos, rem;     // buffer position/remaining
+        private final long position;    // file position
+        private final PendingFuture<Integer,A> result;
+
+        // set to src if direct; otherwise set to substituted direct buffer
+        private volatile ByteBuffer buf;
+
+        WriteTask(ByteBuffer src,
+                  int pos,
+                  int rem,
+                  long position,
+                  PendingFuture<Integer,A> result)
+        {
+            this.src = src;
+            this.pos = pos;
+            this.rem = rem;
+            this.position = position;
+            this.result = result;
+        }
+
+        void releaseBufferIfSubstituted() {
+            if (buf != src)
+                Util.releaseTemporaryDirectBuffer(buf);
+        }
+
+        void updatePosition(int bytesTransferred) {
+            // if the I/O succeeded then adjust buffer position
+            if (bytesTransferred > 0) {
+                try {
+                    src.position(pos + bytesTransferred);
+                } catch (IllegalArgumentException x) {
+                    // someone has changed the position
+                }
+            }
+        }
+
+
+        public void run() {
+            int n = -1;
+            long overlapped = 0L;
+            long address;
+
+            // Substitute a native buffer if not direct
+            if (src instanceof DirectBuffer) {
+                buf = src;
+                address = ((DirectBuffer)src).address() + pos;
+            } else {
+                buf = Util.getTemporaryDirectBuffer(rem);
+                buf.put(src);
+                buf.flip();
+                // temporarily restore position as we don't know how many bytes
+                // will be written
+                src.position(pos);
+                address = ((DirectBuffer)buf).address();
+            }
+
+            try {
+                begin();
+
+                // allocate an OVERLAPPED structure
+                overlapped = ioCache.add(result);
+
+                // synchronize on result to allow this thread handle the case
+                // where the read completes immediately.
+                synchronized (result) {
+                    n = writeFile(handle, address, rem, position, overlapped);
+                    if (n == IOStatus.UNAVAILABLE) {
+                        // I/O is pending
+                        return;
+                    }
+                    // read completed immediately:
+                    // 1. update buffer position
+                    // 2. release waiters
+                    updatePosition(n);
+                    result.setResult(n);
+                }
+            } catch (Throwable x) {
+                // failed to initiate read:
+                result.setFailure(toIOException(x));
+
+                // release resources
+                if (overlapped != 0L)
+                    ioCache.remove(overlapped);
+                releaseBufferIfSubstituted();
+
+            } finally {
+                end();
+            }
+
+            // invoke completion handler
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Executed when the I/O has completed
+         */
+
+        public void completed(int bytesTransferred) {
+            updatePosition(bytesTransferred);
+
+            // return direct buffer to cache if substituted
+            releaseBufferIfSubstituted();
+
+            // release waiters and invoke completion handler
+            result.setResult(bytesTransferred);
+            Invoker.invoke(result.handler(), result);
+        }
+
+
+        public void failed(int error, IOException x) {
+            // return direct buffer to cache if substituted
+            releaseBufferIfSubstituted();
+
+            // release waiters and invoker completion handler
+            if (isOpen()) {
+                result.setFailure(x);
+            } else {
+                result.setFailure(new AsynchronousCloseException());
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+    }
+
+
+    public <A> Future<Integer> write(ByteBuffer src,
+                                     long position,
+                                     A attachment,
+                                     CompletionHandler<Integer,? super A> handler)
+    {
+        if (!writing)
+            throw new NonWritableChannelException();
+        if (position < 0)
+            throw new IllegalArgumentException("Negative position");
+
+        // check if channel is closed
+        if (!isOpen()) {
+            CompletedFuture<Integer,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        int pos = src.position();
+        int lim = src.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        // nothing to write
+        if (rem == 0) {
+            CompletedFuture<Integer,A> result =
+                CompletedFuture.withResult(this, 0, attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        // create Future and task to initiate write
+        PendingFuture<Integer,A> result =
+            new PendingFuture<Integer,A>(this, handler, attachment);
+        WriteTask writeTask = new WriteTask<A>(src, pos, rem, position, result);
+        result.setContext(writeTask);
+
+        // initiate I/O (can only be done from thread in thread pool)
+        Invoker.invokeOnThreadInThreadPool(this, writeTask);
+        return result;
+    }
+
+    // -- Native methods --
+
+    private static native int readFile(long handle, long address, int len,
+        long offset, long overlapped) throws IOException;
+
+    private static native int writeFile(long handle, long address, int len,
+        long offset, long overlapped) throws IOException;
+
+    private static native int lockFile(long handle, long position, long size,
+        boolean shared, long overlapped) throws IOException;
+
+    private static native void close0(long handle);
+
+    static {
+        Util.load();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2007-2008 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.ch;
+
+import java.nio.channels.*;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.io.IOException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.misc.Unsafe;
+
+/**
+ * Windows implementation of AsynchronousServerSocketChannel using overlapped I/O.
+ */
+
+class WindowsAsynchronousServerSocketChannelImpl
+    extends AsynchronousServerSocketChannelImpl implements Iocp.OverlappedChannel
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // 2 * (sizeof(SOCKET_ADDRESS) + 16)
+    private static final int DATA_BUFFER_SIZE = 88;
+
+    private final long handle;
+    private final int completionKey;
+    private final Iocp iocp;
+
+    // typically there will be zero, or one I/O operations pending. In rare
+    // cases there may be more. These rare cases arise when a sequence of accept
+    // operations complete immediately and handled by the initiating thread.
+    // The corresponding OVERLAPPED cannot be reused/released until the completion
+    // event has been posted.
+    private final PendingIoCache ioCache;
+
+    // the data buffer to receive the local/remote socket address
+    private final long dataBuffer;
+
+    // flag to indicate that an accept operation is outstanding
+    private AtomicBoolean accepting = new AtomicBoolean();
+
+
+    WindowsAsynchronousServerSocketChannelImpl(Iocp iocp) throws IOException {
+        super(iocp);
+
+        // associate socket with given completion port
+        long h = IOUtil.fdVal(fd);
+        int key;
+        try {
+            key = iocp.associate(this, h);
+        } catch (IOException x) {
+            closesocket0(h);   // prevent leak
+            throw x;
+        }
+
+        this.handle = h;
+        this.completionKey = key;
+        this.iocp = iocp;
+        this.ioCache = new PendingIoCache();
+        this.dataBuffer = unsafe.allocateMemory(DATA_BUFFER_SIZE);
+    }
+
+
+    public <V,A> PendingFuture<V,A> getByOverlapped(long overlapped) {
+        return ioCache.remove(overlapped);
+    }
+
+
+    void implClose() throws IOException {
+        // close socket (which may cause outstanding accept to be aborted).
+        closesocket0(handle);
+
+        // waits until the accept operations have completed
+        ioCache.close();
+
+        // finally disassociate from the completion port
+        iocp.disassociate(completionKey);
+
+        // release other resources
+        unsafe.freeMemory(dataBuffer);
+    }
+
+
+    public AsynchronousChannelGroupImpl group() {
+        return iocp;
+    }
+
+    /**
+     * Task to initiate accept operation and to handle result.
+     */
+    private class AcceptTask<A> implements Runnable, Iocp.ResultHandler {
+        private final WindowsAsynchronousSocketChannelImpl channel;
+        private final AccessControlContext acc;
+        private final PendingFuture<AsynchronousSocketChannel,A> result;
+
+        AcceptTask(WindowsAsynchronousSocketChannelImpl channel,
+                   AccessControlContext acc,
+                   PendingFuture<AsynchronousSocketChannel,A> result)
+        {
+            this.channel = channel;
+            this.acc = acc;
+            this.result = result;
+        }
+
+        void enableAccept() {
+            accepting.set(false);
+        }
+
+        void closeChildChannel() {
+            try {
+                channel.close();
+            } catch (IOException ignore) { }
+        }
+
+        // caller must have acquired read lock for the listener and child channel.
+        void finishAccept() throws IOException {
+            /**
+             * Set local/remote addresses. This is currently very inefficient
+             * in that it requires 2 calls to getsockname and 2 calls to getpeername.
+             * (should change this to use GetAcceptExSockaddrs)
+             */
+            updateAcceptContext(handle, channel.handle());
+
+            InetSocketAddress local = Net.localAddress(channel.fd);
+            final InetSocketAddress remote = Net.remoteAddress(channel.fd);
+            channel.setConnected(local, remote);
+
+            // permission check (in context of initiating thread)
+            if (acc != null) {
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    public Void run() {
+                        SecurityManager sm = System.getSecurityManager();
+                        sm.checkAccept(remote.getAddress().getHostAddress(),
+                                       remote.getPort());
+                        return null;
+                    }
+                }, acc);
+            }
+        }
+
+        /**
+         * Initiates the accept operation.
+         */
+
+        public void run() {
+            long overlapped = 0L;
+
+            try {
+                // begin usage of listener socket
+                begin();
+                try {
+                    // begin usage of child socket (as it is registered with
+                    // completion port and so may be closed in the event that
+                    // the group is forcefully closed).
+                    channel.begin();
+
+                    synchronized (result) {
+                        overlapped = ioCache.add(result);
+
+                        int n = accept0(handle, channel.handle(), overlapped, dataBuffer);
+                        if (n == IOStatus.UNAVAILABLE) {
+                            return;
+                        }
+
+                        // connection accepted immediately
+                        finishAccept();
+
+                        // allow another accept before the result is set
+                        enableAccept();
+                        result.setResult(channel);
+                    }
+                } finally {
+                    // end usage on child socket
+                    channel.end();
+                }
+            } catch (Throwable x) {
+                // failed to initiate accept so release resources
+                if (overlapped != 0L)
+                    ioCache.remove(overlapped);
+                closeChildChannel();
+                if (x instanceof ClosedChannelException)
+                    x = new AsynchronousCloseException();
+                if (!(x instanceof IOException) && !(x instanceof SecurityException))
+                    x = new IOException(x);
+                enableAccept();
+                result.setFailure(x);
+            } finally {
+                // end of usage of listener socket
+                end();
+            }
+
+            // accept completed immediately but may not have executed on
+            // initiating thread in which case the operation may have been
+            // cancelled.
+            if (result.isCancelled()) {
+                closeChildChannel();
+            }
+
+            // invoke completion handler
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+
+        /**
+         * Executed when the I/O has completed
+         */
+
+        public void completed(int bytesTransferred) {
+            try {
+                // connection accept after group has shutdown
+                if (iocp.isShutdown()) {
+                    throw new IOException(new ShutdownChannelGroupException());
+                }
+
+                // finish the accept
+                try {
+                    begin();
+                    try {
+                        channel.begin();
+                        finishAccept();
+                    } finally {
+                        channel.end();
+                    }
+                } finally {
+                    end();
+                }
+
+                // allow another accept before the result is set
+                enableAccept();
+                result.setResult(channel);
+            } catch (Throwable x) {
+                enableAccept();
+                closeChildChannel();
+                if (x instanceof ClosedChannelException)
+                    x = new AsynchronousCloseException();
+                if (!(x instanceof IOException) && !(x instanceof SecurityException))
+                    x = new IOException(x);
+                result.setFailure(x);
+            }
+
+            // if an async cancel has already cancelled the operation then
+            // close the new channel so as to free resources
+            if (result.isCancelled()) {
+                closeChildChannel();
+            }
+
+            // invoke handler (but not directly)
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+
+
+        public void failed(int error, IOException x) {
+            enableAccept();
+            closeChildChannel();
+
+            // release waiters
+            if (isOpen()) {
+                result.setFailure(x);
+            } else {
+                result.setFailure(new AsynchronousCloseException());
+            }
+            Invoker.invokeIndirectly(result.handler(), result);
+        }
+    }
+
+
+    public <A> Future<AsynchronousSocketChannel> accept(A attachment,
+        final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+    {
+        if (!isOpen()) {
+            CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invokeIndirectly(handler, result);
+            return result;
+        }
+        if (isAcceptKilled())
+            throw new RuntimeException("Accept not allowed due to cancellation");
+
+        // ensure channel is bound to local address
+        if (localAddress == null)
+            throw new NotYetBoundException();
+
+        // create the socket that will be accepted. The creation of the socket
+        // is enclosed by a begin/end for the listener socket to ensure that
+        // we check that the listener is open and also to prevent the I/O
+        // port from being closed as the new socket is registered.
+        WindowsAsynchronousSocketChannelImpl ch = null;
+        IOException ioe = null;
+        try {
+            begin();
+            ch = new WindowsAsynchronousSocketChannelImpl(iocp, false);
+        } catch (IOException x) {
+            ioe = x;
+        } finally {
+            end();
+        }
+        if (ioe != null) {
+            CompletedFuture<AsynchronousSocketChannel,A> result =
+                CompletedFuture.withFailure(this, ioe, attachment);
+            Invoker.invokeIndirectly(handler, result);
+            return result;
+        }
+
+        // need calling context when there is security manager as
+        // permission check may be done in a different thread without
+        // any application call frames on the stack
+        AccessControlContext acc = (System.getSecurityManager() == null) ?
+            null : AccessController.getContext();
+
+        PendingFuture<AsynchronousSocketChannel,A> result =
+            new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
+        AcceptTask task = new AcceptTask<A>(ch, acc, result);
+        result.setContext(task);
+
+        // check and set flag to prevent concurrent accepting
+        if (!accepting.compareAndSet(false, true))
+            throw new AcceptPendingException();
+
+        // initiate accept. As I/O operations are tied to the initiating thread
+        // then it will only be invoked direcly if this thread is in the thread
+        // pool. If this thread is not in the thread pool when a task is
+        // submitted to initiate the accept.
+        Invoker.invokeOnThreadInThreadPool(this, task);
+        return result;
+    }
+
+    // -- Native methods --
+
+    private static native void initIDs();
+
+    private static native int accept0(long listenSocket, long acceptSocket,
+        long overlapped, long dataBuffer) throws IOException;
+
+    private static native void updateAcceptContext(long listenSocket,
+        long acceptSocket) throws IOException;
+
+    private static native void closesocket0(long socket) throws IOException;
+
+    static {
+        Util.load();
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,911 @@
+/*
+ * Copyright 2007-2008 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 conne02110-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.ch;
+
+import java.nio.channels.*;
+import java.nio.ByteBuffer;
+import java.nio.BufferOverflowException;
+import java.net.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+/**
+ * Windows implementation of AsynchronousSocketChannel using overlapped I/O.
+ */
+
+class WindowsAsynchronousSocketChannelImpl
+    extends AsynchronousSocketChannelImpl implements Iocp.OverlappedChannel
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static int addressSize = unsafe.addressSize();
+
+    private static int dependsArch(int value32, int value64) {
+        return (addressSize == 4) ? value32 : value64;
+    }
+
+    /*
+     * typedef struct _WSABUF {
+     *     u_long      len;
+     *     char FAR *  buf;
+     * } WSABUF;
+     */
+    private static final int SIZEOF_WSABUF  = dependsArch(8, 16);
+    private static final int OFFSETOF_LEN   = 0;
+    private static final int OFFSETOF_BUF   = dependsArch(4, 8);
+
+    // maximum vector size for scatter/gather I/O
+    private static final int MAX_WSABUF     = 16;
+
+    private static final int SIZEOF_WSABUFARRAY = MAX_WSABUF * SIZEOF_WSABUF;
+
+
+    // socket handle. Use begin()/end() around each usage of this handle.
+    final long handle;
+
+    // I/O completion port that the socket is associated with
+    private final Iocp iocp;
+
+    // completion key to identify channel when I/O completes
+    private final int completionKey;
+
+    // Pending I/O operations are tied to an OVERLAPPED structure that can only
+    // be released when the I/O completion event is posted to the completion
+    // port. Where I/O operations complete immediately then it is possible
+    // there may be more than two OVERLAPPED structures in use.
+    private final PendingIoCache ioCache;
+
+    // per-channel arrays of WSABUF structures
+    private final long readBufferArray;
+    private final long writeBufferArray;
+
+
+    WindowsAsynchronousSocketChannelImpl(Iocp iocp, boolean failIfGroupShutdown)
+        throws IOException
+    {
+        super(iocp);
+
+        // associate socket with default completion port
+        long h = IOUtil.fdVal(fd);
+        int key = 0;
+        try {
+            key = iocp.associate(this, h);
+        } catch (ShutdownChannelGroupException x) {
+            if (failIfGroupShutdown) {
+                closesocket0(h);
+                throw x;
+            }
+        } catch (IOException x) {
+            closesocket0(h);
+            throw x;
+        }
+
+        this.handle = h;
+        this.iocp = iocp;
+        this.completionKey = key;
+        this.ioCache = new PendingIoCache();
+
+        // allocate WSABUF arrays
+        this.readBufferArray = unsafe.allocateMemory(SIZEOF_WSABUFARRAY);
+        this.writeBufferArray = unsafe.allocateMemory(SIZEOF_WSABUFARRAY);
+    }
+
+    WindowsAsynchronousSocketChannelImpl(Iocp iocp) throws IOException {
+        this(iocp, true);
+    }
+
+
+    public AsynchronousChannelGroupImpl group() {
+        return iocp;
+    }
+
+    /**
+     * Invoked by Iocp when an I/O operation competes.
+     */
+
+    public <V,A> PendingFuture<V,A> getByOverlapped(long overlapped) {
+        return ioCache.remove(overlapped);
+    }
+
+    // invoked by WindowsAsynchronousServerSocketChannelImpl
+    long handle() {
+        return handle;
+    }
+
+    // invoked by WindowsAsynchronousServerSocketChannelImpl when new connection
+    // accept
+    void setConnected(SocketAddress localAddress, SocketAddress remoteAddress) {
+        synchronized (stateLock) {
+            state = ST_CONNECTED;
+            this.localAddress = localAddress;
+            this.remoteAddress = remoteAddress;
+        }
+    }
+
+
+    void implClose() throws IOException {
+        // close socket (may cause outstanding async I/O operations to fail).
+        closesocket0(handle);
+
+        // waits until all I/O operations have completed
+        ioCache.close();
+
+        // release arrays of WSABUF structures
+        unsafe.freeMemory(readBufferArray);
+        unsafe.freeMemory(writeBufferArray);
+
+        // finally disassociate from the completion port (key can be 0 if
+        // channel created when group is shutdown)
+        if (completionKey != 0)
+            iocp.disassociate(completionKey);
+    }
+
+
+    public void onCancel(PendingFuture<?,?> task) {
+        if (task.getContext() instanceof ConnectTask)
+            killConnect();
+        if (task.getContext() instanceof ReadTask)
+            killReading();
+        if (task.getContext() instanceof WriteTask)
+            killWriting();
+    }
+
+    /**
+     * Implements the task to initiate a connection and the handler to
+     * consume the result when the connection is established (or fails).
+     */
+    private class ConnectTask<A> implements Runnable, Iocp.ResultHandler {
+        private final InetSocketAddress remote;
+        private final PendingFuture<Void,A> result;
+
+        ConnectTask(InetSocketAddress remote, PendingFuture<Void,A> result) {
+            this.remote = remote;
+            this.result = result;
+        }
+
+        private void closeChannel() {
+            try {
+                close();
+            } catch (IOException ignore) { }
+        }
+
+        private IOException toIOException(Throwable x) {
+            if (x instanceof IOException) {
+                if (x instanceof ClosedChannelException)
+                    x = new AsynchronousCloseException();
+                return (IOException)x;
+            }
+            return new IOException(x);
+        }
+
+        /**
+         * Invoke after a connection is successfully established.
+         */
+        private void afterConnect() throws IOException {
+            updateConnectContext(handle);
+            synchronized (stateLock) {
+                state = ST_CONNECTED;
+                remoteAddress = remote;
+            }
+        }
+
+        /**
+         * Task to initiate a connection.
+         */
+
+        public void run() {
+            long overlapped = 0L;
+            Throwable exc = null;
+            try {
+                begin();
+
+                // synchronize on result to allow this thread handle the case
+                // where the connection is established immediately.
+                synchronized (result) {
+                    overlapped = ioCache.add(result);
+                    // initiate the connection
+                    int n = connect0(handle, Net.isIPv6Available(), remote.getAddress(),
+                                     remote.getPort(), overlapped);
+                    if (n == IOStatus.UNAVAILABLE) {
+                        // connection is pending
+                        return;
+                    }
+
+                    // connection established immediately
+                    afterConnect();
+                    result.setResult(null);
+                }
+            } catch (Throwable x) {
+                exc = x;
+            } finally {
+                end();
+            }
+
+            if (exc != null) {
+                if (overlapped != 0L)
+                    ioCache.remove(overlapped);
+                closeChannel();
+                result.setFailure(toIOException(exc));
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Invoked by handler thread when connection established.
+         */
+
+        public void completed(int bytesTransferred) {
+            Throwable exc = null;
+            try {
+                begin();
+                afterConnect();
+                result.setResult(null);
+            } catch (Throwable x) {
+                // channel is closed or unable to finish connect
+                exc = x;
+            } finally {
+                end();
+            }
+
+            // can't close channel while in begin/end block
+            if (exc != null) {
+                closeChannel();
+                result.setFailure(toIOException(exc));
+            }
+
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Invoked by handler thread when failed to establish connection.
+         */
+
+        public void failed(int error, IOException x) {
+            if (isOpen()) {
+                closeChannel();
+                result.setFailure(x);
+            } else {
+                result.setFailure(new AsynchronousCloseException());
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+    }
+
+
+    public <A> Future<Void> connect(SocketAddress remote,
+                                    A attachment,
+                                    CompletionHandler<Void,? super A> handler)
+    {
+        if (!isOpen()) {
+            CompletedFuture<Void,A> result = CompletedFuture
+                .withFailure(this, new ClosedChannelException(), attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        InetSocketAddress isa = Net.checkAddress(remote);
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
+
+        // check and update state
+        // ConnectEx requires the socket to be bound to a local address
+        IOException bindException = null;
+        synchronized (stateLock) {
+            if (state == ST_CONNECTED)
+                throw new AlreadyConnectedException();
+            if (state == ST_PENDING)
+                throw new ConnectionPendingException();
+            if (localAddress == null) {
+                try {
+                    bind(new InetSocketAddress(0));
+                } catch (IOException x) {
+                    bindException = x;
+                }
+            }
+            if (bindException == null)
+                state = ST_PENDING;
+        }
+
+        // handle bind failure
+        if (bindException != null) {
+            try {
+                close();
+            } catch (IOException ignore) { }
+            CompletedFuture<Void,A> result = CompletedFuture
+                .withFailure(this, bindException, attachment);
+            Invoker.invoke(handler, result);
+            return result;
+        }
+
+        // setup task
+        PendingFuture<Void,A> result =
+            new PendingFuture<Void,A>(this, handler, attachment);
+        ConnectTask task = new ConnectTask<A>(isa, result);
+        result.setContext(task);
+
+        // initiate I/O (can only be done from thread in thread pool)
+        Invoker.invokeOnThreadInThreadPool(this, task);
+        return result;
+    }
+
+    /**
+     * Implements the task to initiate a read and the handler to consume the
+     * result when the read completes.
+     */
+    private class ReadTask<V,A> implements Runnable, Iocp.ResultHandler {
+        private final ByteBuffer[] bufs;
+        private final int numBufs;
+        private final boolean scatteringRead;
+        private final PendingFuture<V,A> result;
+
+        // set by run method
+        private ByteBuffer[] shadow;
+
+        ReadTask(ByteBuffer[] bufs,
+                 boolean scatteringRead,
+                 PendingFuture<V,A> result)
+        {
+            this.bufs = bufs;
+            this.numBufs = (bufs.length > MAX_WSABUF) ? MAX_WSABUF : bufs.length;
+            this.scatteringRead = scatteringRead;
+            this.result = result;
+        }
+
+        /**
+         * Invoked prior to read to prepare the WSABUF array. Where necessary,
+         * it substitutes non-direct buffers with direct buffers.
+         */
+        void prepareBuffers() {
+            shadow = new ByteBuffer[numBufs];
+            long address = readBufferArray;
+            for (int i=0; i<numBufs; i++) {
+                ByteBuffer dst = bufs[i];
+                int pos = dst.position();
+                int lim = dst.limit();
+                assert (pos <= lim);
+                int rem = (pos <= lim ? lim - pos : 0);
+                long a;
+                if (!(dst instanceof DirectBuffer)) {
+                    // substitute with direct buffer
+                    ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
+                    shadow[i] = bb;
+                    a = ((DirectBuffer)bb).address();
+                } else {
+                    shadow[i] = dst;
+                    a = ((DirectBuffer)dst).address() + pos;
+                }
+                unsafe.putAddress(address + OFFSETOF_BUF, a);
+                unsafe.putInt(address + OFFSETOF_LEN, rem);
+                address += SIZEOF_WSABUF;
+            }
+        }
+
+        /**
+         * Invoked after a read has completed to update the buffer positions
+         * and release any substituted buffers.
+         */
+        void updateBuffers(int bytesRead) {
+            for (int i=0; i<numBufs; i++) {
+                ByteBuffer nextBuffer = shadow[i];
+                int pos = nextBuffer.position();
+                int len = nextBuffer.remaining();
+                if (bytesRead >= len) {
+                    bytesRead -= len;
+                    int newPosition = pos + len;
+                    try {
+                        nextBuffer.position(newPosition);
+                    } catch (IllegalArgumentException x) {
+                        // position changed by another
+                    }
+                } else { // Buffers not completely filled
+                    if (bytesRead > 0) {
+                        assert(pos + bytesRead < (long)Integer.MAX_VALUE);
+                        int newPosition = pos + bytesRead;
+                        try {
+                            nextBuffer.position(newPosition);
+                        } catch (IllegalArgumentException x) {
+                            // position changed by another
+                        }
+                    }
+                    break;
+                }
+            }
+
+            // Put results from shadow into the slow buffers
+            for (int i=0; i<numBufs; i++) {
+                if (!(bufs[i] instanceof DirectBuffer)) {
+                    shadow[i].flip();
+                    try {
+                        bufs[i].put(shadow[i]);
+                    } catch (BufferOverflowException x) {
+                        // position changed by another
+                    }
+                }
+            }
+        }
+
+        void releaseBuffers() {
+            for (int i=0; i<numBufs; i++) {
+                if (!(bufs[i] instanceof DirectBuffer)) {
+                    Util.releaseTemporaryDirectBuffer(shadow[i]);
+                }
+            }
+        }
+
+
+        @SuppressWarnings("unchecked")
+        public void run() {
+            long overlapped = 0L;
+            boolean prepared = false;
+            boolean pending = false;
+
+            try {
+                begin();
+
+                // substitute non-direct buffers
+                prepareBuffers();
+                prepared = true;
+
+                // get an OVERLAPPED structure (from the cache or allocate)
+                overlapped = ioCache.add(result);
+
+                // synchronize on result to allow this thread handle the case
+                // where the read completes immediately.
+                synchronized (result) {
+                    int n = read0(handle, numBufs, readBufferArray, overlapped);
+                    if (n == IOStatus.UNAVAILABLE) {
+                        // I/O is pending
+                        pending = true;
+                        return;
+                    }
+                    // read completed immediately:
+                    // 1. update buffer position
+                    // 2. reset read flag
+                    // 3. release waiters
+                    if (n == 0) {
+                        n = -1;
+                    } else {
+                        updateBuffers(n);
+                    }
+                    enableReading();
+
+                    if (scatteringRead) {
+                        result.setResult((V)Long.valueOf(n));
+                    } else {
+                        result.setResult((V)Integer.valueOf(n));
+                    }
+                }
+            } catch (Throwable x) {
+                // failed to initiate read:
+                // 1. reset read flag
+                // 2. free resources
+                // 3. release waiters
+                enableReading();
+                if (overlapped != 0L)
+                    ioCache.remove(overlapped);
+                if (x instanceof ClosedChannelException)
+                    x = new AsynchronousCloseException();
+                if (!(x instanceof IOException))
+                    x = new IOException(x);
+                result.setFailure(x);
+            } finally {
+                if (prepared && !pending) {
+                    // return direct buffer(s) to cache if substituted
+                    releaseBuffers();
+                }
+                end();
+            }
+
+            // invoke completion handler
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Executed when the I/O has completed
+         */
+
+        @SuppressWarnings("unchecked")
+        public void completed(int bytesTransferred) {
+            if (bytesTransferred == 0) {
+                bytesTransferred = -1;  // EOF
+            } else {
+                updateBuffers(bytesTransferred);
+            }
+
+            // return direct buffer to cache if substituted
+            releaseBuffers();
+
+            // release waiters if not already released by timeout
+            synchronized (result) {
+                if (result.isDone())
+                    return;
+                enableReading();
+                if (scatteringRead) {
+                    result.setResult((V)Long.valueOf(bytesTransferred));
+                } else {
+                    result.setResult((V)Integer.valueOf(bytesTransferred));
+                }
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+
+
+        public void failed(int error, IOException x) {
+            // return direct buffer to cache if substituted
+            releaseBuffers();
+
+            // release waiters if not already released by timeout
+            if (!isOpen())
+                x = new AsynchronousCloseException();
+
+            synchronized (result) {
+                if (result.isDone())
+                    return;
+                enableReading();
+                result.setFailure(x);
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Invoked if timeout expires before it is cancelled
+         */
+        void timeout() {
+            // synchronize on result as the I/O could complete/fail
+            synchronized (result) {
+                if (result.isDone())
+                    return;
+
+                // kill further reading before releasing waiters
+                enableReading(true);
+                result.setFailure(new InterruptedByTimeoutException());
+            }
+
+            // invoke handler without any locks
+            Invoker.invoke(result.handler(), result);
+        }
+    }
+
+
+    <V extends Number,A> Future<V> readImpl(ByteBuffer[] bufs,
+                                            boolean scatteringRead,
+                                            long timeout,
+                                            TimeUnit unit,
+                                            A attachment,
+                                            CompletionHandler<V,? super A> handler)
+    {
+        // setup task
+        PendingFuture<V,A> result =
+            new PendingFuture<V,A>(this, handler, attachment);
+        final ReadTask readTask = new ReadTask<V,A>(bufs, scatteringRead, result);
+        result.setContext(readTask);
+
+        // schedule timeout
+        if (timeout > 0L) {
+            Future<?> timeoutTask = iocp.schedule(new Runnable() {
+                public void run() {
+                    readTask.timeout();
+                }
+            }, timeout, unit);
+            result.setTimeoutTask(timeoutTask);
+        }
+
+        // initiate I/O (can only be done from thread in thread pool)
+        Invoker.invokeOnThreadInThreadPool(this, readTask);
+        return result;
+    }
+
+    /**
+     * Implements the task to initiate a write and the handler to consume the
+     * result when the write completes.
+     */
+    private class WriteTask<V,A> implements Runnable, Iocp.ResultHandler {
+        private final ByteBuffer[] bufs;
+        private final int numBufs;
+        private final boolean gatheringWrite;
+        private final PendingFuture<V,A> result;
+
+        // set by run method
+        private ByteBuffer[] shadow;
+
+        WriteTask(ByteBuffer[] bufs,
+                  boolean gatheringWrite,
+                  PendingFuture<V,A> result)
+        {
+            this.bufs = bufs;
+            this.numBufs = (bufs.length > MAX_WSABUF) ? MAX_WSABUF : bufs.length;
+            this.gatheringWrite = gatheringWrite;
+            this.result = result;
+        }
+
+        /**
+         * Invoked prior to write to prepare the WSABUF array. Where necessary,
+         * it substitutes non-direct buffers with direct buffers.
+         */
+        void prepareBuffers() {
+            shadow = new ByteBuffer[numBufs];
+            long address = writeBufferArray;
+            for (int i=0; i<numBufs; i++) {
+                ByteBuffer src = bufs[i];
+                int pos = src.position();
+                int lim = src.limit();
+                assert (pos <= lim);
+                int rem = (pos <= lim ? lim - pos : 0);
+                long a;
+                if (!(src instanceof DirectBuffer)) {
+                    // substitute with direct buffer
+                    ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
+                    bb.put(src);
+                    bb.flip();
+                    src.position(pos);  // leave heap buffer untouched for now
+                    shadow[i] = bb;
+                    a = ((DirectBuffer)bb).address();
+                } else {
+                    shadow[i] = src;
+                    a = ((DirectBuffer)src).address() + pos;
+                }
+                unsafe.putAddress(address + OFFSETOF_BUF, a);
+                unsafe.putInt(address + OFFSETOF_LEN, rem);
+                address += SIZEOF_WSABUF;
+            }
+        }
+
+        /**
+         * Invoked after a write has completed to update the buffer positions
+         * and release any substituted buffers.
+         */
+        void updateBuffers(int bytesWritten) {
+            // Notify the buffers how many bytes were taken
+            for (int i=0; i<numBufs; i++) {
+                ByteBuffer nextBuffer = bufs[i];
+                int pos = nextBuffer.position();
+                int lim = nextBuffer.limit();
+                int len = (pos <= lim ? lim - pos : lim);
+                if (bytesWritten >= len) {
+                    bytesWritten -= len;
+                    int newPosition = pos + len;
+                    try {
+                        nextBuffer.position(newPosition);
+                    } catch (IllegalArgumentException x) {
+                        // position changed by someone else
+                    }
+                } else { // Buffers not completely filled
+                    if (bytesWritten > 0) {
+                        assert(pos + bytesWritten < (long)Integer.MAX_VALUE);
+                        int newPosition = pos + bytesWritten;
+                        try {
+                            nextBuffer.position(newPosition);
+                        } catch (IllegalArgumentException x) {
+                            // position changed by someone else
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+
+        void releaseBuffers() {
+            for (int i=0; i<numBufs; i++) {
+                if (!(bufs[i] instanceof DirectBuffer)) {
+                    Util.releaseTemporaryDirectBuffer(shadow[i]);
+                }
+            }
+        }
+
+
+        @SuppressWarnings("unchecked")
+        public void run() {
+            int n = -1;
+            long overlapped = 0L;
+            boolean prepared = false;
+            boolean pending = false;
+            boolean shutdown = false;
+
+            try {
+                begin();
+
+                // substitute non-direct buffers
+                prepareBuffers();
+                prepared = true;
+
+                // get an OVERLAPPED structure (from the cache or allocate)
+                overlapped = ioCache.add(result);
+
+                // synchronize on result to allow this thread handle the case
+                // where the read completes immediately.
+                synchronized (result) {
+                    n = write0(handle, numBufs, writeBufferArray, overlapped);
+                    if (n == IOStatus.UNAVAILABLE) {
+                        // I/O is pending
+                        pending = true;
+                        return;
+                    }
+
+                    enableWriting();
+
+                    if (n == IOStatus.EOF) {
+                        // special case for shutdown output
+                        shutdown = true;
+                        throw new ClosedChannelException();
+                    }
+
+                    // write completed immediately:
+                    // 1. enable writing
+                    // 2. update buffer position
+                    // 3. release waiters
+                    updateBuffers(n);
+
+                    // result is a Long or Integer
+                    if (gatheringWrite) {
+                        result.setResult((V)Long.valueOf(n));
+                    } else {
+                        result.setResult((V)Integer.valueOf(n));
+                    }
+                }
+            } catch (Throwable x) {
+                enableWriting();
+
+                // failed to initiate read:
+                if (!shutdown && (x instanceof ClosedChannelException))
+                    x = new AsynchronousCloseException();
+                if (!(x instanceof IOException))
+                    x = new IOException(x);
+                result.setFailure(x);
+
+                // release resources
+                if (overlapped != 0L)
+                    ioCache.remove(overlapped);
+
+            } finally {
+                if (prepared && !pending) {
+                    // return direct buffer(s) to cache if substituted
+                    releaseBuffers();
+                }
+                end();
+            }
+
+            // invoke completion handler
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Executed when the I/O has completed
+         */
+
+        @SuppressWarnings("unchecked")
+        public void completed(int bytesTransferred) {
+            updateBuffers(bytesTransferred);
+
+            // return direct buffer to cache if substituted
+            releaseBuffers();
+
+            // release waiters if not already released by timeout
+            synchronized (result) {
+                if (result.isDone())
+                    return;
+                enableWriting();
+                if (gatheringWrite) {
+                    result.setResult((V)Long.valueOf(bytesTransferred));
+                } else {
+                    result.setResult((V)Integer.valueOf(bytesTransferred));
+                }
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+
+
+        public void failed(int error, IOException x) {
+            // return direct buffer to cache if substituted
+            releaseBuffers();
+
+            // release waiters if not already released by timeout
+            if (!isOpen())
+                x = new AsynchronousCloseException();
+
+            synchronized (result) {
+                if (result.isDone())
+                    return;
+                enableWriting();
+                result.setFailure(x);
+            }
+            Invoker.invoke(result.handler(), result);
+        }
+
+        /**
+         * Invoked if timeout expires before it is cancelled
+         */
+        void timeout() {
+            // synchronize on result as the I/O could complete/fail
+            synchronized (result) {
+                if (result.isDone())
+                    return;
+
+                // kill further writing before releasing waiters
+                enableWriting(true);
+                result.setFailure(new InterruptedByTimeoutException());
+            }
+
+            // invoke handler without any locks
+            Invoker.invoke(result.handler(), result);
+        }
+    }
+
+
+    <V extends Number,A> Future<V> writeImpl(ByteBuffer[] bufs,
+                                             boolean gatheringWrite,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<V,? super A> handler)
+    {
+        // setup task
+        PendingFuture<V,A> result =
+            new PendingFuture<V,A>(this, handler, attachment);
+        final WriteTask writeTask = new WriteTask<V,A>(bufs, gatheringWrite, result);
+        result.setContext(writeTask);
+
+        // schedule timeout
+        if (timeout > 0L) {
+            Future<?> timeoutTask = iocp.schedule(new Runnable() {
+                public void run() {
+                    writeTask.timeout();
+                }
+            }, timeout, unit);
+            result.setTimeoutTask(timeoutTask);
+        }
+
+        // initiate I/O (can only be done from thread in thread pool)
+        Invoker.invokeOnThreadInThreadPool(this, writeTask);
+        return result;
+    }
+
+    // -- Native methods --
+
+    private static native void initIDs();
+
+    private static native int connect0(long socket, boolean preferIPv6,
+        InetAddress remote, int remotePort, long overlapped) throws IOException;
+
+    private static native void updateConnectContext(long socket) throws IOException;
+
+    private static native int read0(long socket, int count, long addres, long overlapped)
+        throws IOException;
+
+    private static native int write0(long socket, int count, long address,
+        long overlapped) throws IOException;
+
+    private static native void shutdown0(long socket, int how) throws IOException;
+
+    private static native void closesocket0(long socket) throws IOException;
+
+    static {
+        Util.load();
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007-2008 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.spi.FileSystemProvider;
+
+/**
+ * Creates default provider on Windows
+ */
+public class DefaultFileSystemProvider {
+    private DefaultFileSystemProvider() { }
+    public static FileSystemProvider create() {
+        return new WindowsFileSystemProvider();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2007-2008 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.spi.FileTypeDetector;
+
+public class DefaultFileTypeDetector {
+    private DefaultFileTypeDetector() { }
+
+    public static FileTypeDetector create() {
+        return new RegistryFileTypeDetector();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * File type detector that does lookup of file extension using Windows Registry.
+ */
+
+public class RegistryFileTypeDetector
+    extends AbstractFileTypeDetector
+{
+    public RegistryFileTypeDetector() {
+        super();
+    }
+
+
+    public String implProbeContentType(FileRef file) throws IOException {
+        if (!(file instanceof Path))
+            return null;
+
+        // get file extension
+        Path name = ((Path)file).getName();
+        if (name == null)
+            return null;
+        String filename = name.toString();
+        int dot = filename.lastIndexOf('.');
+        if ((dot < 0) || (dot == (filename.length()-1)))
+            return null;
+
+        // query HKEY_CLASSES_ROOT\<ext>
+        String key = filename.substring(dot);
+        NativeBuffer keyBuffer = WindowsNativeDispatcher.asNativeBuffer(key);
+        NativeBuffer nameBuffer = WindowsNativeDispatcher.asNativeBuffer("Content Type");
+        try {
+            return queryStringValue(keyBuffer.address(), nameBuffer.address());
+        } finally {
+            nameBuffer.release();
+            keyBuffer.release();
+        }
+    }
+
+    private static native String queryStringValue(long subKey, long name);
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+
+            public Void run() {
+                // nio.dll has dependency on net.dll
+                System.loadLibrary("net");
+                System.loadLibrary("nio");
+                return null;
+        }});
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2007-2008 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.ProviderMismatchException;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.io.IOException;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Windows implementation of AclFileAttributeView.
+ */
+
+class WindowsAclFileAttributeView
+    extends AbstractAclFileAttributeView
+{
+    /**
+     * typedef struct _SECURITY_DESCRIPTOR {
+     *     BYTE  Revision;
+     *     BYTE  Sbz1;
+     *     SECURITY_DESCRIPTOR_CONTROL Control;
+     *     PSID Owner;
+     *     PSID Group;
+     *     PACL Sacl;
+     *     PACL Dacl;
+     * } SECURITY_DESCRIPTOR;
+     */
+    private static final short SIZEOF_SECURITY_DESCRIPTOR   = 20;
+
+    private final WindowsPath file;
+    private final boolean followLinks;
+
+    WindowsAclFileAttributeView(WindowsPath file, boolean followLinks) {
+        this.file = file;
+        this.followLinks = followLinks;
+    }
+
+    // permision check
+    private void checkAccess(WindowsPath file,
+                             boolean checkRead,
+                             boolean checkWrite)
+    {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (checkRead)
+                sm.checkRead(file.getPathForPermissionCheck());
+            if (checkWrite)
+                sm.checkWrite(file.getPathForPermissionCheck());
+            sm.checkPermission(new RuntimePermission("accessUserInformation"));
+        }
+    }
+
+    // invokes GetFileSecurity to get requested security information
+    static NativeBuffer getFileSecurity(String path, int request)
+        throws IOException
+    {
+        // invoke get to buffer size
+        int size = 0;
+        try {
+            size = GetFileSecurity(path, request, 0L, 0);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(path);
+        }
+        assert size > 0;
+
+        // allocate buffer and re-invoke to get security information
+        NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
+        try {
+            for (;;) {
+                int newSize = GetFileSecurity(path, request, buffer.address(), size);
+                if (newSize <= size)
+                    return buffer;
+
+                // buffer was insufficient
+                buffer.release();
+                buffer = NativeBuffers.getNativeBuffer(newSize);
+                size = newSize;
+            }
+        } catch (WindowsException x) {
+            buffer.release();
+            x.rethrowAsIOException(path);
+            return null;
+        }
+    }
+
+
+    public UserPrincipal getOwner()
+        throws IOException
+    {
+        checkAccess(file, true, false);
+
+        // GetFileSecurity does not follow links so when following links we
+        // need the final target
+        String path = followLinks ? WindowsLinkSupport.getFinalPath(file) :
+                                    file.getPathForWin32Calls();
+        NativeBuffer buffer = getFileSecurity(path, OWNER_SECURITY_INFORMATION);
+        try {
+            // get the address of the SID
+            long sidAddress = GetSecurityDescriptorOwner(buffer.address());
+            if (sidAddress == 0L)
+                throw new IOException("no owner");
+            return WindowsUserPrincipals.fromSid(sidAddress);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+            return null;
+        } finally {
+            buffer.release();
+        }
+    }
+
+
+    public List<AclEntry> getAcl()
+        throws IOException
+    {
+        checkAccess(file, true, false);
+
+        // GetFileSecurity does not follow links so when following links we
+        // need the final target
+        String path = followLinks ? WindowsLinkSupport.getFinalPath(file) :
+                                    file.getPathForWin32Calls();
+
+        // ALLOW and DENY entries in DACL;
+        // AUDIT entries in SACL (ignore for now as it requires privileges)
+        NativeBuffer buffer = getFileSecurity(path, DACL_SECURITY_INFORMATION);
+        try {
+            return WindowsSecurityDescriptor.getAcl(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+
+
+    public void setOwner(UserPrincipal obj)
+        throws IOException
+    {
+        if (obj == null)
+            throw new NullPointerException("'owner' is null");
+        if (!(obj instanceof WindowsUserPrincipals.User))
+            throw new ProviderMismatchException();
+        WindowsUserPrincipals.User owner = (WindowsUserPrincipals.User)obj;
+
+        // permission check
+        checkAccess(file, false, true);
+
+        // SetFileSecurity does not follow links so when following links we
+        // need the final target
+        String path = followLinks ? WindowsLinkSupport.getFinalPath(file) :
+                                    file.getPathForWin32Calls();
+
+        // ConvertStringSidToSid allocates memory for SID so must invoke
+        // LocalFree to free it when we are done
+        long pOwner = 0L;
+        try {
+            pOwner = ConvertStringSidToSid(owner.sidString());
+        } catch (WindowsException x) {
+            throw new IOException("Failed to get SID for " + owner.getName()
+                + ": " + x.errorString());
+        }
+
+        // Allocate buffer for security descriptor, initialize it, set
+        // owner information and update the file.
+        try {
+            NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR);
+            try {
+                InitializeSecurityDescriptor(buffer.address());
+                SetSecurityDescriptorOwner(buffer.address(), pOwner);
+                // may need SeRestorePrivilege to set the owner
+                WindowsSecurity.Privilege priv =
+                    WindowsSecurity.enablePrivilege("SeRestorePrivilege");
+                try {
+                    SetFileSecurity(path,
+                                    OWNER_SECURITY_INFORMATION,
+                                    buffer.address());
+                } finally {
+                    priv.drop();
+                }
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(file);
+            } finally {
+                buffer.release();
+            }
+        } finally {
+            LocalFree(pOwner);
+        }
+    }
+
+
+    public void setAcl(List<AclEntry> acl) throws IOException {
+        checkAccess(file, false, true);
+
+        // SetFileSecurity does not follow links so when following links we
+        // need the final target
+        String path = followLinks ? WindowsLinkSupport.getFinalPath(file) :
+                                    file.getPathForWin32Calls();
+
+        WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.create(acl);
+        try {
+            SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd.address());
+        } catch (WindowsException x) {
+             x.rethrowAsIOException(file);
+        } finally {
+            sd.release();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2007 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 java.nio.channels.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.*;
+
+import com.sun.nio.file.ExtendedOpenOption;
+
+import sun.nio.ch.FileChannelImpl;
+import sun.nio.ch.ThreadPool;
+import sun.nio.ch.WindowsAsynchronousFileChannelImpl;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaIOFileDescriptorAccess;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Factory to create FileChannels and AsynchronousFileChannels.
+ */
+
+class WindowsChannelFactory {
+    private static final JavaIOFileDescriptorAccess fdAccess =
+        SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private WindowsChannelFactory() { }
+
+    /**
+     * Do not follow reparse points when opening an existing file. Do not fail
+     * if the file is a reparse point.
+     */
+    static final OpenOption NOFOLLOW_REPARSEPOINT = new OpenOption() { };
+
+    /**
+     * Open/creates file, returning FileChannel to access the file
+     *
+     * @param   pathForWindows
+     *          The path of the file to open/create
+     * @param   pathToCheck
+     *          The path used for permission checks (if security manager)
+     */
+    static FileChannel newFileChannel(String pathForWindows,
+                                      String pathToCheck,
+                                      Set<? extends OpenOption> options,
+                                      long pSecurityDescriptor)
+        throws WindowsException
+    {
+        boolean reading = false;
+        boolean writing = false;
+        boolean append = false;
+        boolean trunc = false;
+
+        // check for invalid flags
+        for (OpenOption flag: options) {
+            if (flag == StandardOpenOption.READ) {
+                reading = true; continue;
+            }
+            if (flag == StandardOpenOption.WRITE) {
+                writing = true; continue;
+            }
+            if (flag == StandardOpenOption.APPEND) {
+                append = true;
+                writing = true;
+                continue;
+            }
+            if (flag == StandardOpenOption.TRUNCATE_EXISTING) {
+                trunc = true; continue;
+            }
+            if (flag == null)
+                throw new NullPointerException();
+            if (!(flag instanceof StandardOpenOption) &&
+                !(flag instanceof ExtendedOpenOption))
+            {
+                throw new UnsupportedOperationException("Unsupported open option");
+            }
+        }
+
+        // default is reading
+        if (!reading && !writing) {
+            reading = true;
+        }
+
+        // check for invalid combinations
+        if (reading && append)
+            throw new IllegalArgumentException("READ + APPEND not allowed");
+        if (append && trunc)
+            throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
+
+        FileDescriptor fdObj = open(pathForWindows, pathToCheck, reading, writing,
+            append, false, options, pSecurityDescriptor);
+        return FileChannelImpl.open(fdObj, reading, writing, null);
+    }
+
+    /**
+     * Open/creates file, returning AsynchronousFileChannel to access the file
+     *
+     * @param   pathForWindows
+     *          The path of the file to open/create
+     * @param   pathToCheck
+     *          The path used for permission checks (if security manager)
+     * @param   pool
+     *          The thread pool that the channel is associated with
+     */
+    static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows,
+                                                              String pathToCheck,
+                                                              Set<? extends OpenOption> options,
+                                                              long pSecurityDescriptor,
+                                                              ThreadPool pool)
+        throws IOException
+    {
+        boolean reading = false;
+        boolean writing = false;
+
+        // check for invalid flags
+        for (OpenOption flag: options) {
+            if (flag == StandardOpenOption.READ) {
+                reading = true; continue;
+            }
+            if (flag == StandardOpenOption.WRITE) {
+                writing = true; continue;
+            }
+            if (flag == null)
+                throw new NullPointerException();
+            if (!(flag instanceof StandardOpenOption) &&
+                !(flag instanceof ExtendedOpenOption))
+            {
+                throw new UnsupportedOperationException("Unsupported open option");
+            }
+            if (flag == StandardOpenOption.APPEND)
+                throw new UnsupportedOperationException("'APPEND' not supported");
+        }
+
+        // default is reading
+        if (!reading && !writing) {
+            reading = true;
+        }
+
+        // open file for overlapped I/O
+        FileDescriptor fdObj;
+        try {
+            fdObj = open(pathForWindows, pathToCheck, reading, writing, false,
+                         true, options, pSecurityDescriptor);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(pathForWindows);
+            return null;
+        }
+
+        // create the AsynchronousFileChannel
+        try {
+            return WindowsAsynchronousFileChannelImpl.open(fdObj, reading, writing, pool);
+        } catch (IOException x) {
+            // IOException is thrown if the file handle cannot be associated
+            // with the completion port. All we can do is close the file.
+            long handle = fdAccess.getHandle(fdObj);
+            CloseHandle(handle);
+            throw x;
+        }
+    }
+
+    /**
+     * Opens file based on parameters and options, returning a FileDescriptor
+     * encapsulating the handle to the open file.
+     */
+    private static FileDescriptor open(String pathForWindows,
+                                       String pathToCheck,
+                                       boolean reading,
+                                       boolean writing,
+                                       boolean append,
+                                       boolean overlapped,
+                                       Set<? extends OpenOption> options,
+                                       long pSecurityDescriptor)
+        throws WindowsException
+    {
+        // set to true if file must be truncated after open
+        boolean truncateAfterOpen = false;
+
+        // map options
+        int dwDesiredAccess = 0;
+        if (reading)
+            dwDesiredAccess |= GENERIC_READ;
+        if (writing)
+            dwDesiredAccess |= (append) ? FILE_APPEND_DATA : GENERIC_WRITE;
+
+        int dwShareMode = 0;
+        if (!options.contains(ExtendedOpenOption.NOSHARE_READ))
+            dwShareMode |= FILE_SHARE_READ;
+        if (!options.contains(ExtendedOpenOption.NOSHARE_WRITE))
+            dwShareMode |= FILE_SHARE_WRITE;
+        if (!options.contains(ExtendedOpenOption.NOSHARE_DELETE))
+            dwShareMode |= FILE_SHARE_DELETE;
+
+        int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+        int dwCreationDisposition = OPEN_EXISTING;
+        if (writing) {
+            if (options.contains(StandardOpenOption.CREATE_NEW)) {
+                dwCreationDisposition = CREATE_NEW;
+                // force create to fail if file is orphaned reparse point
+                dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
+            } else {
+                if (options.contains(StandardOpenOption.CREATE))
+                    dwCreationDisposition = OPEN_ALWAYS;
+                if (options.contains(StandardOpenOption.TRUNCATE_EXISTING)) {
+                    // Windows doesn't have a creation disposition that exactly
+                    // corresponds to CREATE + TRUNCATE_EXISTING so we use
+                    // the OPEN_ALWAYS mode and then truncate the file.
+                    if (dwCreationDisposition == OPEN_ALWAYS) {
+                        truncateAfterOpen = true;
+                    } else {
+                        dwCreationDisposition = TRUNCATE_EXISTING;
+                    }
+                }
+            }
+        }
+
+        if (options.contains(StandardOpenOption.DSYNC) || options.contains(StandardOpenOption.SYNC))
+            dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
+        if (overlapped)
+            dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
+
+        boolean deleteOnClose = options.contains(StandardOpenOption.DELETE_ON_CLOSE);
+        if (deleteOnClose)
+            dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+
+        // NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point
+        boolean okayToFollowLinks = true;
+        if (dwCreationDisposition != CREATE_NEW &&
+            (options.contains(LinkOption.NOFOLLOW_LINKS) ||
+             options.contains(NOFOLLOW_REPARSEPOINT) ||
+             deleteOnClose))
+        {
+            if (options.contains(LinkOption.NOFOLLOW_LINKS))
+                okayToFollowLinks = false;
+            dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
+        }
+
+        // permission check
+        if (pathToCheck != null) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                if (reading)
+                    sm.checkRead(pathToCheck);
+                if (writing)
+                    sm.checkWrite(pathToCheck);
+                if (deleteOnClose)
+                    sm.checkDelete(pathToCheck);
+            }
+        }
+
+        // open file
+        long handle = CreateFile(pathForWindows,
+                                 dwDesiredAccess,
+                                 dwShareMode,
+                                 pSecurityDescriptor,
+                                 dwCreationDisposition,
+                                 dwFlagsAndAttributes);
+
+        // make sure this isn't a symbolic link.
+        if (!okayToFollowLinks) {
+            try {
+                // for security reasons we can only test here the file is a
+                // reparse point. To read the reparse point tag would require
+                // re-opening the file and this method is required to be atomic.
+                if (WindowsFileAttributes.readAttributes(handle).isReparsePoint()) {
+                    throw new WindowsException("File is reparse point");
+                }
+
+            } catch (WindowsException x) {
+                CloseHandle(handle);
+                throw x;
+            }
+        }
+
+        // truncate file (for CREATE + TRUNCATE_EXISTING case)
+        if (truncateAfterOpen) {
+            try {
+                SetEndOfFile(handle);
+            } catch (WindowsException x) {
+                CloseHandle(handle);
+                throw x;
+            }
+        }
+
+        // make the file sparse if needed
+        if (dwCreationDisposition == CREATE_NEW &&
+            options.contains(StandardOpenOption.SPARSE))
+        {
+            try {
+                DeviceIoControlSetSparse(handle);
+            } catch (WindowsException x) {
+                // ignore as sparse option is hint
+            }
+        }
+
+        // create FileDescriptor and return
+        FileDescriptor fdObj = new FileDescriptor();
+        fdAccess.setHandle(fdObj, handle);
+        return fdObj;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2007-2008 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;
+
+/**
+ * Win32 APIs constants.
+ */
+
+class WindowsConstants {
+    private WindowsConstants() { }
+
+    // general
+    public static final long INVALID_HANDLE_VALUE = -1L;
+
+    // generic rights
+    public static final int GENERIC_READ        = 0x80000000;
+    public static final int GENERIC_WRITE       = 0x40000000;
+
+    // share modes
+    public static final int FILE_SHARE_READ     = 0x00000001;
+    public static final int FILE_SHARE_WRITE    = 0x00000002;
+    public static final int FILE_SHARE_DELETE   = 0x00000004;
+
+    // creation modes
+    public static final int CREATE_NEW          = 1;
+    public static final int CREATE_ALWAYS       = 2;
+    public static final int OPEN_EXISTING       = 3;
+    public static final int OPEN_ALWAYS         = 4;
+    public static final int TRUNCATE_EXISTING   = 5;
+
+    // attributes and flags
+    public static final int FILE_ATTRIBUTE_READONLY         = 0x00000001;
+    public static final int FILE_ATTRIBUTE_HIDDEN           = 0x00000002;
+    public static final int FILE_ATTRIBUTE_SYSTEM           = 0x00000004;
+    public static final int FILE_ATTRIBUTE_DIRECTORY        = 0x00000010;
+    public static final int FILE_ATTRIBUTE_ARCHIVE          = 0x00000020;
+    public static final int FILE_ATTRIBUTE_DEVICE           = 0x00000040;
+    public static final int FILE_ATTRIBUTE_NORMAL           = 0x00000080;
+    public static final int FILE_ATTRIBUTE_REPARSE_POINT    = 0x400;
+    public static final int FILE_FLAG_OVERLAPPED            = 0x40000000;
+    public static final int FILE_FLAG_WRITE_THROUGH         = 0x80000000;
+    public static final int FILE_FLAG_BACKUP_SEMANTICS      = 0x02000000;
+    public static final int FILE_FLAG_DELETE_ON_CLOSE       = 0x04000000;
+    public static final int FILE_FLAG_OPEN_REPARSE_POINT    = 0x00200000;
+
+    // stream ids
+    public static final int BACKUP_ALTERNATE_DATA           = 0x00000004;
+    public static final int BACKUP_SPARSE_BLOCK             = 0x00000009;
+
+    // reparse point/symbolic link related constants
+    public static final int IO_REPARSE_TAG_SYMLINK              = 0xA000000C;
+    public static final int MAXIMUM_REPARSE_DATA_BUFFER_SIZE    = 16 * 1024;
+    public static final int SYMBOLIC_LINK_FLAG_DIRECTORY        = 0x1;
+
+    // volume flags
+    public static final int FILE_CASE_SENSITIVE_SEARCH      = 0x00000001;
+    public static final int FILE_CASE_PRESERVED_NAMES       = 0x00000002;
+    public static final int FILE_PERSISTENT_ACLS            = 0x00000008;
+    public static final int FILE_VOLUME_IS_COMPRESSED       = 0x00008000;
+    public static final int FILE_NAMED_STREAMS              = 0x00040000;
+    public static final int FILE_READ_ONLY_VOLUME           = 0x00080000;
+
+    // error codes
+    public static final int ERROR_FILE_NOT_FOUND        = 2;
+    public static final int ERROR_PATH_NOT_FOUND        = 3;
+    public static final int ERROR_ACCESS_DENIED         = 5;
+    public static final int ERROR_INVALID_HANDLE        = 6;
+    public static final int ERROR_INVALID_DATA          = 13;
+    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_DISK_FULL             = 112;
+    public static final int ERROR_INSUFFICIENT_BUFFER   = 122;
+    public static final int ERROR_INVALID_LEVEL         = 124;
+    public static final int ERROR_DIR_NOT_EMPTY         = 145;
+    public static final int ERROR_ALREADY_EXISTS        = 183;
+    public static final int ERROR_DIRECTORY             = 267;
+    public static final int ERROR_NOTIFY_ENUM_DIR       = 1022;
+    public static final int ERROR_NONE_MAPPED           = 1332;
+    public static final int ERROR_NOT_A_REPARSE_POINT   = 4390;
+    public static final int ERROR_INVALID_REPARSE_DATA  = 4392;
+
+    // notify filters
+    public static final int FILE_NOTIFY_CHANGE_FILE_NAME   = 0x00000001;
+    public static final int FILE_NOTIFY_CHANGE_DIR_NAME    = 0x00000002;
+    public static final int FILE_NOTIFY_CHANGE_ATTRIBUTES  = 0x00000004;
+    public static final int FILE_NOTIFY_CHANGE_SIZE        = 0x00000008;
+    public static final int FILE_NOTIFY_CHANGE_LAST_WRITE  = 0x00000010;
+    public static final int FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020;
+    public static final int FILE_NOTIFY_CHANGE_CREATION    = 0x00000040;
+    public static final int FILE_NOTIFY_CHANGE_SECURITY    = 0x00000100;
+
+    // notify actions
+    public final static int FILE_ACTION_ADDED              = 0x00000001;
+    public final static int FILE_ACTION_REMOVED            = 0x00000002;
+    public final static int FILE_ACTION_MODIFIED           = 0x00000003;
+    public final static int FILE_ACTION_RENAMED_OLD_NAME   = 0x00000004;
+    public final static int FILE_ACTION_RENAMED_NEW_NAME   = 0x00000005;
+
+    // copy flags
+    public static final int COPY_FILE_FAIL_IF_EXISTS       = 0x00000001;
+    public static final int COPY_FILE_COPY_SYMLINK         = 0x00000800;
+
+    // move flags
+    public static final int MOVEFILE_REPLACE_EXISTING       = 0x00000001;
+    public static final int MOVEFILE_COPY_ALLOWED           = 0x00000002;
+
+    // drive types
+    public static final int DRIVE_UNKNOWN                   = 0;
+    public static final int DRIVE_NO_ROOT_DIR               = 1;
+    public static final int DRIVE_REMOVABLE                 = 2;
+    public static final int DRIVE_FIXED                     = 3;
+    public static final int DRIVE_REMOTE                    = 4;
+    public static final int DRIVE_CDROM                     = 5;
+    public static final int DRIVE_RAMDISK                   = 6;
+
+    // file security
+    public static final int OWNER_SECURITY_INFORMATION      = 0x00000001;
+    public static final int GROUP_SECURITY_INFORMATION      = 0x00000002;
+    public static final int DACL_SECURITY_INFORMATION       = 0x00000004;
+    public static final int SACL_SECURITY_INFORMATION       = 0x00000008;
+
+    public static final int SidTypeUser = 1;
+    public static final int SidTypeGroup = 2;
+    public static final int SidTypeDomain = 3;
+    public static final int SidTypeAlias = 4;
+    public static final int SidTypeWellKnownGroup = 5;
+    public static final int SidTypeDeletedAccount = 6;
+    public static final int SidTypeInvalid = 7;
+    public static final int SidTypeUnknown = 8;
+    public static final int SidTypeComputer= 9;
+
+    public static final byte ACCESS_ALLOWED_ACE_TYPE         = 0x0;
+    public static final byte ACCESS_DENIED_ACE_TYPE          = 0x1;
+
+    public static final byte OBJECT_INHERIT_ACE              = 0x1;
+    public static final byte CONTAINER_INHERIT_ACE           = 0x2;
+    public static final byte NO_PROPAGATE_INHERIT_ACE        = 0x4;
+    public static final byte INHERIT_ONLY_ACE                = 0x8;
+
+    public static final int DELETE                      = 0x00010000;
+    public static final int READ_CONTROL                = 0x00020000;
+    public static final int WRITE_DAC                   = 0x00040000;
+    public static final int WRITE_OWNER                 = 0x00080000;
+    public static final int SYNCHRONIZE                 = 0x00100000;
+
+    public static final int FILE_LIST_DIRECTORY         = 0x0001;
+    public static final int FILE_READ_DATA              = 0x0001;
+    public static final int FILE_WRITE_DATA             = 0x0002;
+    public static final int FILE_APPEND_DATA            = 0x0004;
+    public static final int FILE_READ_EA                = 0x0008;
+    public static final int FILE_WRITE_EA               = 0x0010;
+    public static final int FILE_EXECUTE                = 0x0020;
+    public static final int FILE_DELETE_CHILD           = 0x0040;
+    public static final int FILE_READ_ATTRIBUTES        = 0x0080;
+    public static final int FILE_WRITE_ATTRIBUTES       = 0x0100;
+
+    // operating system security
+    public static final int TOKEN_DUPLICATE             = 0x0002;
+    public static final int TOKEN_IMPERSONATE           = 0x0004;
+    public static final int TOKEN_QUERY                 = 0x0008;
+    public static final int TOKEN_ADJUST_PRIVILEGES     = 0x0020;
+
+    public static final int SE_PRIVILEGE_ENABLED        = 0x00000002;
+
+    public static final int TokenUser                   = 1;
+    public static final int PROCESS_QUERY_INFORMATION   = 0x0400;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2007-2008 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 java.util.Iterator;
+import java.util.ConcurrentModificationException;
+import java.util.NoSuchElementException;
+import java.io.IOException;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Windows implementation of DirectoryStream
+ */
+
+class WindowsDirectoryStream
+    implements DirectoryStream<Path>
+{
+    private final WindowsPath dir;
+    private final DirectoryStream.Filter<? super Path> filter;
+
+    // handle to directory
+    private final long handle;
+    // first entry in the directory
+    private final String firstName;
+
+    private final Object closeLock = new Object();
+
+    // need closeLock to access these
+    private boolean isOpen = true;
+    private Iterator<Path> iterator;
+
+
+    WindowsDirectoryStream(WindowsPath dir, DirectoryStream.Filter<? super Path> filter)
+        throws IOException
+    {
+        this.dir = dir;
+        this.filter = filter;
+
+        // Need to append * or \* to match entries in directory.
+        String search = dir.getPathForWin32Calls();
+        char last = search.charAt(search.length() -1);
+        if (last == ':' || last == '\\') {
+            search += "*";
+        } else {
+            search += "\\*";
+        }
+
+        try {
+            FirstFile first = FindFirstFile(search);
+            this.handle = first.handle();
+            this.firstName = first.name();
+        } catch (WindowsException x) {
+            if (x.lastError() == ERROR_DIRECTORY) {
+                throw new NotDirectoryException(dir.getPathForExceptionMessage());
+            }
+            x.rethrowAsIOException(dir);
+
+            // keep compiler happy
+            throw new AssertionError();
+        }
+    }
+
+
+    public void close()
+        throws IOException
+    {
+        synchronized (closeLock) {
+            if (!isOpen)
+                return;
+            isOpen = false;
+        }
+        try {
+            FindClose(handle);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(dir);
+        }
+    }
+
+
+    public Iterator<Path> iterator() {
+        if (!isOpen) {
+            throw new IllegalStateException("Directory stream is closed");
+        }
+        synchronized (this) {
+            if (iterator != null)
+                throw new IllegalStateException("Iterator already obtained");
+            iterator = new WindowsDirectoryIterator();
+            return iterator;
+        }
+    }
+
+    private static void throwAsConcurrentModificationException(Throwable t) {
+        ConcurrentModificationException cme = new ConcurrentModificationException();
+        cme.initCause(t);
+        throw cme;
+    }
+
+    private class WindowsDirectoryIterator implements Iterator<Path> {
+        private boolean atEof;
+        private Path nextEntry;
+        private Path prevEntry;
+
+        WindowsDirectoryIterator() {
+            atEof = false;
+            if (firstName == null)
+                throw new AssertionError();
+            nextEntry = acceptEntry(firstName);
+        }
+
+        // applies filter and also ignores "." and ".."
+        private Path acceptEntry(String s) {
+            if (s.equals(".") || s.equals(".."))
+                return null;
+            Path entry = WindowsPath
+                .createFromNormalizedPath(dir.getFileSystem(), dir + "\\" + s);
+            if (filter.accept(entry)) {
+                return entry;
+            } else {
+                return null;
+            }
+        }
+
+        // reads next directory entry
+        private Path readNextEntry() {
+            String name = null;
+            for (;;) {
+                // synchronize on closeLock to prevent close while reading
+                synchronized (closeLock) {
+                    if (!isOpen)
+                        throwAsConcurrentModificationException(new
+                            IllegalStateException("Directory stream is closed"));
+                    try {
+                        name = FindNextFile(handle);
+                    } catch (WindowsException x) {
+                        try {
+                            x.rethrowAsIOException(dir);
+                        } catch (IOException ioe) {
+                            throwAsConcurrentModificationException(ioe);
+                        }
+                    }
+                }
+
+                // EOF
+                if (name == null)
+                    return null;
+
+                Path entry = acceptEntry(name);
+                if (entry != null)
+                    return entry;
+            }
+        }
+
+
+        public synchronized boolean hasNext() {
+            if (nextEntry == null && !atEof) {
+                nextEntry = readNextEntry();
+                atEof = (nextEntry == null);
+            }
+            return nextEntry != null;
+        }
+
+
+        public synchronized Path next() {
+            if (nextEntry == null) {
+                if (!atEof) {
+                    nextEntry = readNextEntry();
+                }
+                if (nextEntry == null) {
+                    atEof = true;
+                    throw new NoSuchElementException();
+                }
+            }
+            prevEntry = nextEntry;
+            nextEntry = null;
+            return prevEntry;
+        }
+
+
+        public void remove() {
+            if (!isOpen) {
+                throw new IllegalStateException("Directory stream is closed");
+            }
+            Path entry;
+            synchronized (this) {
+                if (prevEntry == null)
+                    throw new IllegalStateException("no last element");
+                entry = prevEntry;
+                prevEntry = null;
+            }
+            try {
+                entry.delete(true);
+            } catch (IOException ioe) {
+                throwAsConcurrentModificationException(ioe);
+            } catch (SecurityException se) {
+                throwAsConcurrentModificationException(se);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsException.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Internal exception thrown when a Win32 calls fails.
+ */
+
+class WindowsException extends Exception {
+    static final long serialVersionUID = 2765039493083748820L;
+
+    private int lastError;
+    private String msg;
+
+    WindowsException(int lastError) {
+        this.lastError = lastError;
+        this.msg = null;
+    }
+
+    WindowsException(String msg) {
+        this.lastError = 0;
+        this.msg = msg;
+    }
+
+    int lastError() {
+        return lastError;
+    }
+
+    String errorString() {
+        if (msg == null) {
+            msg = WindowsNativeDispatcher.FormatMessage(lastError);
+            if (msg == null) {
+                msg = "Unknown error: 0x" + Integer.toHexString(lastError);
+            }
+        }
+        return msg;
+    }
+
+
+    public String getMessage() {
+        return errorString();
+    }
+
+    private IOException translateToIOException(String file, String other) {
+        // not created with last error
+        if (lastError() == 0)
+            return new IOException(errorString());
+
+        // handle specific cases
+        if (lastError() == ERROR_FILE_NOT_FOUND || lastError() == ERROR_PATH_NOT_FOUND)
+            return new NoSuchFileException(file, other, null);
+        if (lastError() == ERROR_FILE_EXISTS || lastError() == ERROR_ALREADY_EXISTS)
+            return new FileAlreadyExistsException(file, other, null);
+        if (lastError() == ERROR_ACCESS_DENIED)
+            return new AccessDeniedException(file, other, null);
+
+        // fallback to the more general exception
+        return new FileSystemException(file, other, errorString());
+    }
+
+    void rethrowAsIOException(String file) throws IOException {
+        IOException x = translateToIOException(file, null);
+        throw x;
+    }
+
+    void rethrowAsIOException(WindowsPath file, WindowsPath other) throws IOException {
+        String a = (file == null) ? null : file.getPathForExceptionMessage();
+        String b = (other == null) ? null : other.getPathForExceptionMessage();
+        IOException x = translateToIOException(a, b);
+        throw x;
+    }
+
+    void rethrowAsIOException(WindowsPath file) throws IOException {
+        rethrowAsIOException(file, null);
+    }
+
+    IOException asIOException(WindowsPath file) {
+        return translateToIOException(file.getPathForExceptionMessage(), null);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.io.IOException;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+class WindowsFileAttributeViews {
+
+    private static class Basic extends AbstractBasicFileAttributeView {
+        final WindowsPath file;
+        final boolean followLinks;
+
+        Basic(WindowsPath file, boolean followLinks) {
+            this.file = file;
+            this.followLinks = followLinks;
+        }
+
+
+        public WindowsFileAttributes readAttributes() throws IOException {
+            try {
+                return WindowsFileAttributes.get(file, followLinks);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(file);
+                return null;    // keep compiler happy
+            }
+        }
+
+        /**
+         * Parameter values in Windows times.
+         */
+        void setFileTimes(long createTime, long lastAccessTime, long lastWriteTime)
+            throws IOException
+        {
+            long handle = -1L;
+            try {
+                int flags = FILE_FLAG_BACKUP_SEMANTICS;
+                if (!followLinks && file.getFileSystem().supportsLinks())
+                    flags |= FILE_FLAG_OPEN_REPARSE_POINT;
+
+                handle = CreateFile(file.getPathForWin32Calls(),
+                                    FILE_WRITE_ATTRIBUTES,
+                                    (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+                                    OPEN_EXISTING,
+                                    flags);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(file);
+            }
+
+            // update attributes
+            try {
+                SetFileTime(handle, createTime, lastAccessTime, lastWriteTime);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(file);
+            } finally {
+                CloseHandle(handle);
+            }
+        }
+
+
+        public void setTimes(Long lastModifiedTime,
+                             Long lastAccessTime,
+                             Long createTime,
+                             TimeUnit unit) throws IOException
+        {
+            file.checkWrite();
+
+            // if all null then do nothing
+            if (lastModifiedTime == null && lastAccessTime == null &&
+                createTime == null)
+            {
+                // no effect
+                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);
+            }
+
+            setFileTimes(crTime, accTime, modTime);
+        }
+    }
+
+    static class Dos extends Basic implements DosFileAttributeView {
+        private static final String READONLY_NAME = "readonly";
+        private static final String ARCHIVE_NAME = "archive";
+        private static final String SYSTEM_NAME = "system";
+        private static final String HIDDEN_NAME = "hidden";
+        private static final String ATTRIBUTES_NAME = "attributes";
+
+        Dos(WindowsPath file, boolean followLinks) {
+            super(file, followLinks);
+        }
+
+
+        public String name() {
+            return "dos";
+        }
+
+
+        public Object getAttribute(String attribute) throws IOException {
+            if (attribute.equals(READONLY_NAME))
+                return readAttributes().isReadOnly();
+            if (attribute.equals(ARCHIVE_NAME))
+                return readAttributes().isArchive();
+            if (attribute.equals(SYSTEM_NAME))
+                return readAttributes().isSystem();
+            if (attribute.equals(HIDDEN_NAME))
+                return readAttributes().isHidden();
+            // implementation specific
+            if (attribute.equals(ATTRIBUTES_NAME))
+                return readAttributes().attributes();
+            return super.getAttribute(attribute);
+        }
+
+
+        public void setAttribute(String attribute, Object value)
+            throws IOException
+        {
+            if (attribute.equals(READONLY_NAME)) {
+                setReadOnly((Boolean)value);
+                return;
+            }
+            if (attribute.equals(ARCHIVE_NAME)) {
+                setArchive((Boolean)value);
+                return;
+            }
+            if (attribute.equals(SYSTEM_NAME)) {
+                setSystem((Boolean)value);
+                return;
+            }
+            if (attribute.equals(HIDDEN_NAME)) {
+                setHidden((Boolean)value);
+                return;
+            }
+            super.setAttribute(attribute, value);
+        }
+
+
+        public Map<String,?> readAttributes(String first, String[] rest)
+            throws IOException
+        {
+            AttributesBuilder builder = AttributesBuilder.create(first, rest);
+            WindowsFileAttributes attrs = readAttributes();
+            addBasicAttributesToBuilder(attrs, builder);
+            if (builder.match(READONLY_NAME))
+                builder.add(READONLY_NAME, attrs.isReadOnly());
+            if (builder.match(ARCHIVE_NAME))
+                builder.add(ARCHIVE_NAME, attrs.isArchive());
+            if (builder.match(SYSTEM_NAME))
+                builder.add(SYSTEM_NAME, attrs.isSystem());
+            if (builder.match(HIDDEN_NAME))
+                builder.add(HIDDEN_NAME, attrs.isHidden());
+            if (builder.match(ATTRIBUTES_NAME))
+                builder.add(ATTRIBUTES_NAME, attrs.attributes());
+            return builder.unmodifiableMap();
+        }
+
+        /**
+         * Update DOS attributes
+         */
+        private void updateAttributes(int flag, boolean enable)
+            throws IOException
+        {
+            file.checkWrite();
+
+            // GetFileAttribtues & SetFileAttributes do not follow links so when
+            // following links we need the final target
+            String path = followLinks ? WindowsLinkSupport.getFinalPath(file) :
+                                        file.getPathForWin32Calls();
+
+            try {
+                int oldValue = GetFileAttributes(path);
+                int newValue = oldValue;
+                if (enable) {
+                    newValue |= flag;
+                } else {
+                    newValue &= ~flag;
+                }
+                if (newValue != oldValue) {
+                    SetFileAttributes(path, newValue);
+                }
+            } catch (WindowsException x) {
+                // don't reveal target in exception
+                x.rethrowAsIOException(file);
+            }
+        }
+
+
+        public void setReadOnly(boolean value) throws IOException {
+            updateAttributes(FILE_ATTRIBUTE_READONLY, value);
+        }
+
+
+        public void setHidden(boolean value) throws IOException {
+            updateAttributes(FILE_ATTRIBUTE_HIDDEN, value);
+        }
+
+
+        public void setArchive(boolean value) throws IOException {
+            updateAttributes(FILE_ATTRIBUTE_ARCHIVE, value);
+        }
+
+
+        public void setSystem(boolean value) throws IOException {
+            updateAttributes(FILE_ATTRIBUTE_SYSTEM, value);
+        }
+
+        // package-private
+        // Copy given attributes to the file.
+        void setAttributes(WindowsFileAttributes attrs)
+            throws IOException
+        {
+            // copy DOS attributes to target
+            int flags = 0;
+            if (attrs.isReadOnly()) flags |= FILE_ATTRIBUTE_READONLY;
+            if (attrs.isHidden()) flags |= FILE_ATTRIBUTE_HIDDEN;
+            if (attrs.isArchive()) flags |= FILE_ATTRIBUTE_ARCHIVE;
+            if (attrs.isSystem()) flags |= FILE_ATTRIBUTE_SYSTEM;
+            updateAttributes(flags, true);
+
+            // copy file times to target - must be done after updating FAT attributes
+            // as otherwise the last modified time may be wrong.
+            setFileTimes(
+                WindowsFileAttributes.toWindowsTime(attrs.creationTime()),
+                WindowsFileAttributes.toWindowsTime(attrs.lastModifiedTime()),
+                WindowsFileAttributes.toWindowsTime(attrs.lastAccessTime()));
+        }
+    }
+
+    static BasicFileAttributeView createBasicView(WindowsPath file, boolean followLinks) {
+        return new Basic(file, followLinks);
+    }
+
+    static WindowsFileAttributeViews.Dos createDosView(WindowsPath file, boolean followLinks) {
+        return new Dos(file, followLinks);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2007-2008 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.util.concurrent.TimeUnit;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+class WindowsFileAttributes
+    implements DosFileAttributes
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    /*
+     * typedef struct _BY_HANDLE_FILE_INFORMATION {
+     *     DWORD    dwFileAttributes;
+     *     FILETIME ftCreationTime;
+     *     FILETIME ftLastAccessTime;
+     *     FILETIME ftLastWriteTime;
+     *     DWORD    dwVolumeSerialNumber;
+     *     DWORD    nFileSizeHigh;
+     *     DWORD    nFileSizeLow;
+     *     DWORD    nNumberOfLinks;
+     *     DWORD    nFileIndexHigh;
+     *     DWORD    nFileIndexLow;
+     * } BY_HANDLE_FILE_INFORMATION;
+     */
+    private static final short SIZEOF_FILE_INFORMATION  = 52;
+    private static final short OFFSETOF_ATTRIBUTES      = 0;
+    private static final short OFFSETOF_CREATETIME      = 4;
+    private static final short OFFSETOF_LASTACCESSTIME  = 12;
+    private static final short OFFSETOF_LASTWRITETIME   = 20;
+    private static final short OFFSETOF_VOLSERIALNUM    = 28;
+    private static final short OFFSETOF_SIZEHIGH        = 32;
+    private static final short OFFSETOF_SIZELOW         = 36;
+    private static final short OFFSETOF_NUMLINKS        = 40;
+    private static final short OFFSETOF_INDEXHIGH       = 44;
+    private static final short OFFSETOF_INDEXLOW        = 48;
+
+    // attributes read from file system
+    private final int attrs;
+    private final long creationTime;
+    private final long lastAccessTime;
+    private final long lastWriteTime;
+    private final long size;
+    private final int linkCount;
+    private final int volSerialNumber;
+    private final int fileIndexHigh;
+    private final int fileIndexLow;
+
+    // used when the file is reparse point
+    private volatile boolean haveReparseTag;        // true if reparse tag read
+    private volatile int reparseTag;                // the tag value
+
+    /**
+     * Convert 64-bit value representing the number of 100-nanosecond intervals
+     * since January 1, 1601 to java time.
+     */
+    private static long toJavaTime(long time) {
+        time /= 10000L;
+        time -= 11644473600000L;
+        return time;
+    }
+
+    /**
+     * Convert java time 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;
+    }
+
+    /**
+     * Initialize a few instance of this class
+     */
+    private WindowsFileAttributes(long address) {
+        attrs = unsafe.getInt(address + OFFSETOF_ATTRIBUTES);
+        creationTime = toJavaTime(unsafe.getLong(address + OFFSETOF_CREATETIME));
+        lastAccessTime = toJavaTime(unsafe.getLong(address + OFFSETOF_LASTACCESSTIME));
+        lastWriteTime = toJavaTime(unsafe.getLong(address + OFFSETOF_LASTWRITETIME));
+        volSerialNumber = unsafe.getInt(address + OFFSETOF_VOLSERIALNUM);
+        size =  ((long)(unsafe.getInt(address + OFFSETOF_SIZEHIGH)) << 32)
+            + (unsafe.getInt(address + OFFSETOF_SIZELOW) & 0xFFFFFFFFL);
+        linkCount = unsafe.getInt(address + OFFSETOF_NUMLINKS);
+        fileIndexHigh = unsafe.getInt(address + OFFSETOF_INDEXHIGH);
+        fileIndexLow = unsafe.getInt(address + OFFSETOF_INDEXLOW);
+    }
+
+    /**
+     * Reads the attributes but does not process reparse points
+     */
+    static WindowsFileAttributes readAttributes(long handle)
+        throws WindowsException
+    {
+        NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_FILE_INFORMATION);
+        try {
+            GetFileInformationByHandle(handle, buffer.address());
+            return new WindowsFileAttributes(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+
+    /**
+     * If this object represents the attributes of a reparse point then read
+     * the reparse point tag. This method has effect if the attributes were
+     * read from a file that is not a reparse point.
+     */
+    WindowsFileAttributes finishRead(WindowsPath path)
+        throws WindowsException
+    {
+        if (isReparsePoint()) {
+            WindowsNativeDispatcher.FirstFile data =
+                FindFirstFile(path.getPathForWin32Calls());
+            reparseTag = data.reserved0();
+            haveReparseTag = true;
+            FindClose(data.handle());
+        }
+        return this;
+    }
+
+    /**
+     * Returns attributes of given file. If the file is a reparse point then its
+     * reparse tag is also read.
+     */
+    static WindowsFileAttributes get(WindowsPath path, boolean followLinks)
+        throws WindowsException
+    {
+        long handle = path.openForReadAttributeAccess(followLinks);
+        try {
+            return readAttributes(handle).finishRead(path);
+        } finally {
+            CloseHandle(handle);
+        }
+    }
+
+    /**
+     * Returns true if the attribtues are of the same file - both files must
+     * be open.
+     */
+    static boolean isSameFile(WindowsFileAttributes attrs1,
+                              WindowsFileAttributes attrs2)
+    {
+        // volume serial number and file index must be the same
+        if (attrs1.volSerialNumber != attrs2.volSerialNumber)
+            return false;
+        if (attrs1.fileIndexHigh != attrs2.fileIndexHigh)
+            return false;
+        if (attrs1.fileIndexLow != attrs2.fileIndexLow)
+            return false;
+        return true;
+    }
+
+    // package-private
+    int attributes() {
+        return attrs;
+    }
+
+    int volSerialNumber() {
+        return volSerialNumber;
+    }
+
+    int fileIndexHigh() {
+        return fileIndexHigh;
+    }
+
+    int fileIndexLow() {
+        return fileIndexLow;
+    }
+
+
+    public long size() {
+        return size;
+    }
+
+
+    public long lastModifiedTime() {
+        return (lastWriteTime >= 0L) ? lastWriteTime : 0L;
+    }
+
+
+    public long lastAccessTime() {
+        return (lastAccessTime >= 0L) ? lastAccessTime : 0L;
+    }
+
+
+    public long creationTime() {
+        return (creationTime >= 0L) ? creationTime : 0L;
+    }
+
+
+    public TimeUnit resolution() {
+        return TimeUnit.MILLISECONDS;
+    }
+
+
+    public int linkCount() {
+        return linkCount;
+    }
+
+
+    public Object fileKey() {
+        return null;
+    }
+
+    // package private
+    boolean isReparsePoint() {
+        return (attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+    }
+
+    boolean isDirectoryLink() {
+        return isSymbolicLink() && ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0);
+    }
+
+
+    public boolean isSymbolicLink() {
+        if (isReparsePoint()) {
+            if (!haveReparseTag)
+                throw new AssertionError("reparse tag not read");
+            return reparseTag == IO_REPARSE_TAG_SYMLINK;
+        } else {
+            return false;
+        }
+    }
+
+
+    public boolean isDirectory() {
+        // ignore FILE_ATTRIBUTE_DIRECTORY attribute if file is a sym link
+        if (isSymbolicLink())
+            return false;
+        return ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0);
+    }
+
+
+    public boolean isOther() {
+        if (isSymbolicLink())
+            return false;
+        // return true if device or reparse point
+        if ((attrs & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0)
+            return true;
+        return false;
+    }
+
+
+    public boolean isRegularFile() {
+        return !isSymbolicLink() && !isDirectory() && !isOther();
+    }
+
+
+    public boolean isReadOnly() {
+        return (attrs & FILE_ATTRIBUTE_READONLY) != 0;
+    }
+
+
+    public boolean isHidden() {
+        return (attrs & FILE_ATTRIBUTE_HIDDEN) != 0;
+    }
+
+
+    public boolean isArchive() {
+        return (attrs & FILE_ATTRIBUTE_ARCHIVE) != 0;
+    }
+
+
+    public boolean isSystem() {
+        return (attrs & FILE_ATTRIBUTE_SYSTEM) != 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,518 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import com.sun.nio.file.ExtendedCopyOption;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Utility methods for copying and moving files.
+ */
+
+class WindowsFileCopy {
+    private WindowsFileCopy() {
+    }
+
+    /**
+     * Copy file from source to target
+     */
+    static void copy(final WindowsPath source,
+                     final WindowsPath target,
+                     CopyOption... options)
+        throws IOException
+    {
+        // map options
+        boolean replaceExisting = false;
+        boolean copyAttributes = false;
+        boolean followLinks = true;
+        boolean interruptible = false;
+        for (CopyOption option: options) {
+            if (option == StandardCopyOption.REPLACE_EXISTING) {
+                replaceExisting = true;
+                continue;
+            }
+            if (option == LinkOption.NOFOLLOW_LINKS) {
+                followLinks = false;
+                continue;
+            }
+            if (option == StandardCopyOption.COPY_ATTRIBUTES) {
+                copyAttributes = true;
+                continue;
+            }
+            if (option == ExtendedCopyOption.INTERRUPTIBLE) {
+                interruptible = true;
+                continue;
+            }
+            if (option == null)
+                throw new NullPointerException();
+            throw new UnsupportedOperationException("Unsupported copy option");
+        }
+
+        // check permissions. If the source file is a symbolic link then
+        // later we must also check LinkPermission
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            source.checkRead();
+            target.checkWrite();
+        }
+
+        // get attributes of source file
+        // attempt to get attributes of target file
+        // if both files are the same there is nothing to do
+        // if target exists and !replace then throw exception
+
+        WindowsFileAttributes sourceAttrs = null;
+        WindowsFileAttributes targetAttrs = null;
+
+        long sourceHandle = 0L;
+        try {
+            sourceHandle = source.openForReadAttributeAccess(followLinks);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(source);
+        }
+        try {
+            // source attributes
+            try {
+                sourceAttrs = WindowsFileAttributes
+                    .readAttributes(sourceHandle)
+                    .finishRead(source);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(source);
+            }
+
+            // open target (don't follow links)
+            long targetHandle = 0L;
+            try {
+                targetHandle = target.openForReadAttributeAccess(false);
+                try {
+                    targetAttrs = WindowsFileAttributes
+                        .readAttributes(targetHandle)
+                        .finishRead(target);
+
+                    // if both files are the same then nothing to do
+                    if (WindowsFileAttributes.isSameFile(sourceAttrs, targetAttrs)) {
+                        return;
+                    }
+
+                    // can't replace file
+                    if (!replaceExisting) {
+                        throw new FileAlreadyExistsException(
+                            target.getPathForExceptionMessage());
+                    }
+
+                } finally {
+                    CloseHandle(targetHandle);
+                }
+            } catch (WindowsException x) {
+                // ignore
+            }
+
+        } finally {
+            CloseHandle(sourceHandle);
+        }
+
+        // if source file is a symbolic link then we must check for LinkPermission
+        if (sm != null && sourceAttrs.isSymbolicLink()) {
+            sm.checkPermission(new LinkPermission("symbolic"));
+        }
+
+        final String sourcePath = source.getPathForWin32Calls();
+        final String targetPath = target.getPathForWin32Calls();
+
+        // if target exists then delete it.
+        if (targetAttrs != null) {
+            try {
+                if (targetAttrs.isDirectory() || targetAttrs.isDirectoryLink()) {
+                    RemoveDirectory(targetPath);
+                } else {
+                    DeleteFile(targetPath);
+                }
+            } catch (WindowsException x) {
+                if (targetAttrs.isDirectory()) {
+                    // ERROR_ALREADY_EXISTS is returned when attempting to delete
+                    // non-empty directory on SAMBA servers.
+                    if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
+                        x.lastError() == ERROR_ALREADY_EXISTS)
+                    {
+                        throw new FileAlreadyExistsException(
+                            target.getPathForExceptionMessage());
+                    }
+                }
+                x.rethrowAsIOException(target);
+            }
+        }
+
+        // Use CopyFileEx if the file is not a directory or junction
+        if (!sourceAttrs.isDirectory() && !sourceAttrs.isDirectoryLink()) {
+            final int flags =
+                (source.getFileSystem().supportsLinks() && !followLinks) ?
+                COPY_FILE_COPY_SYMLINK : 0;
+
+            if (interruptible) {
+                // interruptible copy
+                Cancellable copyTask = new Cancellable() {
+
+                    public int cancelValue() {
+                        return 1;  // TRUE
+                    }
+
+                    public void implRun() throws IOException {
+                        try {
+                            CopyFileEx(sourcePath, targetPath, flags,
+                                       addressToPollForCancel());
+                        } catch (WindowsException x) {
+                            x.rethrowAsIOException(source, target);
+                        }
+                    }
+                };
+                try {
+                    Cancellable.runInterruptibly(copyTask);
+                } catch (ExecutionException e) {
+                    Throwable t = e.getCause();
+                    if (t instanceof IOException)
+                        throw (IOException)t;
+                    throw new IOException(t);
+                }
+            } else {
+                // non-interruptible copy
+                try {
+                    CopyFileEx(sourcePath, targetPath, flags, 0L);
+                } catch (WindowsException x) {
+                    x.rethrowAsIOException(source, target);
+                }
+            }
+            if (copyAttributes) {
+                // CopyFileEx does not copy security attributes
+                try {
+                    copySecurityAttributes(source, target, followLinks);
+                } catch (IOException x) {
+                    // ignore
+                }
+            }
+            return;
+        }
+
+        // copy directory or directory junction
+        try {
+            if (sourceAttrs.isDirectory()) {
+                CreateDirectory(targetPath, 0L);
+            } else {
+                String linkTarget = WindowsLinkSupport.readLink(source);
+                int flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
+                CreateSymbolicLink(targetPath,
+                                   addPrefixIfNeeded(linkTarget),
+                                   flags);
+            }
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(target);
+        }
+        if (copyAttributes) {
+            // copy DOS/timestamps attributes
+            WindowsFileAttributeViews.Dos view =
+                WindowsFileAttributeViews.createDosView(target, false);
+            try {
+                view.setAttributes(sourceAttrs);
+            } catch (IOException x) {
+                if (sourceAttrs.isDirectory()) {
+                    try {
+                        RemoveDirectory(targetPath);
+                    } catch (WindowsException ignore) { }
+                }
+            }
+
+            // copy security attributes. If this fail it doesn't cause the move
+            // to fail.
+            try {
+                copySecurityAttributes(source, target, followLinks);
+            } catch (IOException ignore) { }
+            }
+    }
+
+    /**
+     * Move file from source to target
+     */
+    static void move(WindowsPath source, WindowsPath target, CopyOption... options)
+        throws IOException
+    {
+        // map options
+        boolean atomicMove = false;
+        boolean replaceExisting = false;
+        for (CopyOption option: options) {
+            if (option == StandardCopyOption.ATOMIC_MOVE) {
+                atomicMove = true;
+                continue;
+            }
+            if (option == StandardCopyOption.REPLACE_EXISTING) {
+                replaceExisting = true;
+                continue;
+            }
+            if (option == LinkOption.NOFOLLOW_LINKS) {
+                // ignore
+                continue;
+            }
+            if (option == null) throw new NullPointerException();
+            throw new UnsupportedOperationException("Unsupported copy option");
+        }
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            source.checkWrite();
+            target.checkWrite();
+        }
+
+        String sourcePath = source.getPathForWin32Calls();
+        String targetPath = target.getPathForWin32Calls();
+
+        // atomic case
+        if (atomicMove) {
+            try {
+                MoveFileEx(sourcePath, targetPath, MOVEFILE_REPLACE_EXISTING);
+            } catch (WindowsException x) {
+                if (x.lastError() == ERROR_NOT_SAME_DEVICE) {
+                    throw new AtomicMoveNotSupportedException(
+                        source.getPathForExceptionMessage(),
+                        target.getPathForExceptionMessage(),
+                        x.errorString());
+                }
+                x.rethrowAsIOException(source, target);
+            }
+            return;
+        }
+
+        // get attributes of source file
+        // attempt to get attributes of target file
+        // if both files are the same there is nothing to do
+        // if target exists and !replace then throw exception
+
+        WindowsFileAttributes sourceAttrs = null;
+        WindowsFileAttributes targetAttrs = null;
+
+        long sourceHandle = 0L;
+        try {
+            sourceHandle = source.openForReadAttributeAccess(false);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(source);
+        }
+        try {
+            // source attributes
+            try {
+                sourceAttrs = WindowsFileAttributes
+                        .readAttributes(sourceHandle)
+                        .finishRead(source);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(source);
+            }
+
+            // open target (don't follow links)
+            long targetHandle = 0L;
+            try {
+                targetHandle = target.openForReadAttributeAccess(false);
+                try {
+                    targetAttrs = WindowsFileAttributes
+                        .readAttributes(targetHandle)
+                        .finishRead(target);
+
+                    // if both files are the same then nothing to do
+                    if (WindowsFileAttributes.isSameFile(sourceAttrs, targetAttrs)) {
+                        return;
+                    }
+
+                    // can't replace file
+                    if (!replaceExisting) {
+                        throw new FileAlreadyExistsException(
+                            target.getPathForExceptionMessage());
+                    }
+
+                } finally {
+                    CloseHandle(targetHandle);
+                }
+            } catch (WindowsException x) {
+                // ignore
+            }
+
+        } finally {
+            CloseHandle(sourceHandle);
+        }
+
+        // if target exists then delete it.
+        if (targetAttrs != null) {
+            try {
+                if (targetAttrs.isDirectory() || targetAttrs.isDirectoryLink()) {
+                    RemoveDirectory(targetPath);
+                } else {
+                    DeleteFile(targetPath);
+                }
+            } catch (WindowsException x) {
+                if (targetAttrs.isDirectory()) {
+                    // ERROR_ALREADY_EXISTS is returned when attempting to delete
+                    // non-empty directory on SAMBA servers.
+                    if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
+                        x.lastError() == ERROR_ALREADY_EXISTS)
+                    {
+                        throw new FileAlreadyExistsException(
+                            target.getPathForExceptionMessage());
+                    }
+                }
+                x.rethrowAsIOException(target);
+            }
+        }
+
+        // first try MoveFileEx (no options). If target is on same volume then
+        // all attributes (including security attributes) are preserved.
+        try {
+            MoveFileEx(sourcePath, targetPath, 0);
+            return;
+        } catch (WindowsException x) {
+            if (x.lastError() != ERROR_NOT_SAME_DEVICE)
+                x.rethrowAsIOException(source, target);
+        }
+
+        // target is on different volume so use MoveFileEx with copy option
+        if (!sourceAttrs.isDirectory() && !sourceAttrs.isDirectoryLink()) {
+            try {
+                MoveFileEx(sourcePath, targetPath, MOVEFILE_COPY_ALLOWED);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(source, target);
+            }
+            // MoveFileEx does not copy security attributes when moving
+            // across volumes.
+            try {
+                copySecurityAttributes(source, target, false);
+            } catch (IOException x) {
+                // ignore
+            }
+            return;
+        }
+
+        // moving directory or directory-link to another file system
+        assert sourceAttrs.isDirectory() || sourceAttrs.isDirectoryLink();
+
+        // create new directory or directory junction
+        try {
+            if (sourceAttrs.isDirectory()) {
+                CreateDirectory(targetPath, 0L);
+            } else {
+                String linkTarget = WindowsLinkSupport.readLink(source);
+                CreateSymbolicLink(targetPath,
+                                   addPrefixIfNeeded(linkTarget),
+                                   SYMBOLIC_LINK_FLAG_DIRECTORY);
+            }
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(target);
+        }
+
+        // copy timestamps/DOS attributes
+        WindowsFileAttributeViews.Dos view =
+                WindowsFileAttributeViews.createDosView(target, false);
+        try {
+            view.setAttributes(sourceAttrs);
+        } catch (IOException x) {
+            // rollback
+            try {
+                RemoveDirectory(targetPath);
+            } catch (WindowsException ignore) { }
+            throw x;
+        }
+
+        // copy security attributes. If this fails it doesn't cause the move
+        // to fail.
+        try {
+            copySecurityAttributes(source, target, false);
+        } catch (IOException ignore) { }
+
+        // delete source
+        try {
+            RemoveDirectory(sourcePath);
+        } catch (WindowsException x) {
+            // rollback
+            try {
+                RemoveDirectory(targetPath);
+            } catch (WindowsException ignore) { }
+            // ERROR_ALREADY_EXISTS is returned when attempting to delete
+            // non-empty directory on SAMBA servers.
+            if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
+                x.lastError() == ERROR_ALREADY_EXISTS)
+            {
+                throw new DirectoryNotEmptyException(
+                    target.getPathForExceptionMessage());
+            }
+            x.rethrowAsIOException(source);
+        }
+    }
+
+    /**
+     * Copy DACL/owner/group from source to target
+     */
+    private static void copySecurityAttributes(WindowsPath source,
+                                               WindowsPath target,
+                                               boolean followLinks)
+        throws IOException
+    {
+        String path = followLinks ?
+            WindowsLinkSupport.getFinalPath(source) : source.getPathForWin32Calls();
+
+        // may need SeRestorePrivilege to set file owner
+        WindowsSecurity.Privilege priv =
+            WindowsSecurity.enablePrivilege("SeRestorePrivilege");
+        try {
+            int request = (DACL_SECURITY_INFORMATION |
+                OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION);
+            NativeBuffer buffer =
+                WindowsAclFileAttributeView.getFileSecurity(path, request);
+            try {
+                try {
+                    SetFileSecurity(target.getPathForWin32Calls(), request,
+                        buffer.address());
+                } catch (WindowsException x) {
+                    x.rethrowAsIOException(target);
+                }
+            } finally {
+                buffer.release();
+            }
+        } finally {
+            priv.drop();
+        }
+    }
+
+    /**
+     * Add long path prefix to path if required
+     */
+    private static String addPrefixIfNeeded(String path) {
+        if (path.length() > 248) {
+            if (path.startsWith("\\\\")) {
+                path = "\\\\?\\UNC" + path.substring(1, path.length());
+            } else {
+                path = "\\\\?\\" + path;
+            }
+        }
+        return path;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.util.*;
+import java.io.IOException;
+
+import static sun.nio.fs.WindowsConstants.*;
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+
+/**
+ * Windows implementation of FileStore.
+ */
+
+class WindowsFileStore
+    extends FileStore
+{
+    private final String root;
+    private final String pathForPermissionCheck;
+    private final VolumeInformation info;
+    private final String displayName;   // returned by toString
+
+    private WindowsFileStore(String root, String pathForPermissionCheck)
+        throws WindowsException
+    {
+        assert root.charAt(root.length()-1) == '\\';
+        this.root = root;
+        this.pathForPermissionCheck = pathForPermissionCheck;
+        this.info = GetVolumeInformation(root);
+
+        // file store "display name" is the volume name if available
+        String vol = info.volumeName();
+        if (vol.length() > 0) {
+            this.displayName = vol;
+        } else {
+            // TBD - should we map all types? Does this need to be localized?
+            int type = GetDriveType(root);
+            this.displayName = (type == DRIVE_REMOVABLE) ? "Removable Disk" : "";
+        }
+    }
+
+    static WindowsFileStore create(String root, boolean ignoreNotReady)
+        throws IOException
+    {
+        try {
+            return new WindowsFileStore(root, root);
+        } catch (WindowsException x) {
+            if (ignoreNotReady && x.lastError() == ERROR_NOT_READY)
+                return null;
+            x.rethrowAsIOException(root);
+            return null; // keep compiler happy
+        }
+    }
+
+    static WindowsFileStore create(WindowsPath file) throws IOException {
+        try {
+            // if the file is a link then GetVolumePathName returns the
+            // volume that the link is on so we need to call it with the
+            // final target
+            String target;
+            if (file.getFileSystem().supportsLinks()) {
+                target = WindowsLinkSupport.getFinalPath(file);
+            } else {
+                // file must exist
+                WindowsFileAttributes.get(file, true);
+                target = file.toString();
+            }
+            String root = GetVolumePathName(target);
+            return new WindowsFileStore(root, file.getPathForPermissionCheck());
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+            return null; // keep compiler happy
+        }
+    }
+
+    VolumeInformation volumeInformation() {
+        return info;
+    }
+
+    void checkAttributeAccess() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkRead(pathForPermissionCheck);
+            sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
+        }
+    }
+
+
+    public String name() {
+        return info.volumeName();   // "SYSTEM", "DVD-RW", ...
+    }
+
+
+    public String type() {
+        return info.fileSystemName();  // "FAT", "NTFS", ...
+    }
+
+
+    public boolean isReadOnly() {
+        return ((info.flags() & FILE_READ_ONLY_VOLUME) != 0);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view) {
+        if (view == FileStoreSpaceAttributeView.class)
+            return (V) new WindowsFileStoreAttributeView(this);
+        return (V) null;
+    }
+
+
+    public FileStoreAttributeView getFileStoreAttributeView(String name) {
+        if (name.equals("space"))
+            return new WindowsFileStoreAttributeView(this);
+        if (name.equals("volume"))
+            return new VolumeFileStoreAttributeView(this);
+        return null;
+    }
+
+
+    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        if (type == BasicFileAttributeView.class)
+            return true;
+        if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class)
+            return ((info.flags() & FILE_PERSISTENT_ACLS) != 0);
+        if (type == NamedAttributeView.class)
+            return ((info.flags() & FILE_NAMED_STREAMS) != 0);
+        return false;
+    }
+
+
+    public boolean supportsFileAttributeView(String name) {
+        if (name.equals("basic") || name.equals("dos"))
+            return true;
+        if (name.equals("acl"))
+            return supportsFileAttributeView(AclFileAttributeView.class);
+        if (name.equals("owner"))
+            return supportsFileAttributeView(FileOwnerAttributeView.class);
+        if (name.equals("xattr"))
+            return supportsFileAttributeView(NamedAttributeView.class);
+        return false;
+    }
+
+
+    public boolean equals(Object ob) {
+        if (ob == this)
+            return true;
+        if (!(ob instanceof WindowsFileStore))
+            return false;
+        WindowsFileStore other = (WindowsFileStore)ob;
+        return this.info.volumeSerialNumber() == other.info.volumeSerialNumber();
+    }
+
+
+    public int hashCode() {
+        // reveals VSN without permission check - okay?
+        return info.volumeSerialNumber();
+    }
+
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(displayName);
+        if (sb.length() > 0)
+            sb.append(" ");
+        sb.append("(");
+        // drop trailing slash
+        sb.append(root.subSequence(0, root.length()-1));
+        sb.append(")");
+        return sb.toString();
+    }
+
+    static class WindowsFileStoreAttributeView
+        extends AbstractFileStoreSpaceAttributeView
+    {
+        private final WindowsFileStore fs;
+
+        WindowsFileStoreAttributeView(WindowsFileStore fs) {
+            this.fs = fs;
+        }
+
+
+        public FileStoreSpaceAttributes readAttributes()
+            throws IOException
+        {
+            fs.checkAttributeAccess();
+
+            // read the free space info
+            DiskFreeSpace info = null;
+            try {
+                info = GetDiskFreeSpaceEx(fs.root);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(fs.pathForPermissionCheck);
+            }
+
+            final DiskFreeSpace result = info;
+            return new FileStoreSpaceAttributes() {
+
+                public long totalSpace() {
+                    return result.totalNumberOfBytes();
+                }
+
+                public long usableSpace() {
+                    return result.freeBytesAvailable();
+                }
+
+                public long unallocatedSpace() {
+                    return result.totalNumberOfFreeBytes();
+                }
+            };
+        }
+    }
+
+    /**
+     * 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 final WindowsFileStore fs;
+
+        VolumeFileStoreAttributeView(WindowsFileStore fs) {
+            this.fs = fs;
+        }
+
+
+        public String name() {
+            return "volume";
+        }
+
+        private int vsn() {
+            fs.checkAttributeAccess();
+            return fs.volumeInformation().volumeSerialNumber();
+        }
+
+        private boolean isCompressed() {
+            fs.checkAttributeAccess();
+            return (fs.volumeInformation().flags() &
+                    FILE_VOLUME_IS_COMPRESSED) > 0;
+        }
+
+
+        public Object getAttribute(String attribute) throws IOException {
+            if (attribute.equals(VSN_NAME))
+                return vsn();
+            if (attribute.equals(COMPRESSED_NAME))
+                return isCompressed();
+            return null;
+        }
+
+
+        public void setAttribute(String attribute, Object value)
+            throws IOException
+        {
+            throw new UnsupportedOperationException();
+        }
+
+
+        public Map<String,?> readAttributes(String first, String... rest)
+            throws IOException
+        {
+            boolean vsn = false;
+            boolean compressed = false;
+
+            if (first.equals(VSN_NAME)) vsn = true;
+            else if (first.equals(COMPRESSED_NAME)) compressed = true;
+            else if (first.equals("*")) {
+                vsn = true;
+                compressed = true;
+            }
+            if (!vsn || !compressed) {
+                for (String attribute: rest) {
+                    if (attribute.equals("*")) {
+                        vsn = true;
+                        compressed = true;
+                        break;
+                    }
+                    if (attribute.equals(VSN_NAME)) {
+                        vsn = true;
+                        continue;
+                    }
+                    if (attribute.equals(COMPRESSED_NAME)) {
+                        compressed = true;
+                        continue;
+                    }
+                }
+            }
+
+            Map<String,Object> result = new HashMap<String,Object>();
+            if (vsn)
+                result.put(VSN_NAME, vsn());
+            if (compressed)
+                result.put(COMPRESSED_NAME, isCompressed());
+            return result;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.file.spi.*;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+
+class WindowsFileSystem
+    extends FileSystem
+{
+    private final WindowsFileSystemProvider provider;
+
+    // default directory (is absolute), and default root
+    private final String defaultDirectory;
+    private final String defaultRoot;
+
+    private final boolean supportsLinks;
+    private final boolean supportsStreamEnumeration;
+
+    // package-private
+    WindowsFileSystem(WindowsFileSystemProvider provider,
+                      String dir)
+    {
+        this.provider = provider;
+
+        // parse default directory and check it is absolute
+        WindowsPathParser.Result result = WindowsPathParser.parse(dir);
+
+        if (result.type() != WindowsPathType.ABSOLUTE)
+            throw new AssertionError("Default directory must be absolute/non-UNC");
+        this.defaultDirectory = result.path();
+        this.defaultRoot = result.root();
+
+        PrivilegedAction<String> pa = new GetPropertyAction("os.version");
+        String osversion = AccessController.doPrivileged(pa);
+        String[] vers = osversion.split("\\.", 0);
+        int major = Integer.parseInt(vers[0]);
+        int minor = Integer.parseInt(vers[1]);
+
+        // symbolic links available on Vista and newer
+        supportsLinks = (major >= 6);
+
+        // enumeration of data streams available on Windows Server 2003 and newer
+        supportsStreamEnumeration = (major >= 6) || (major == 5 && minor >= 2);
+    }
+
+    // package-private
+    String defaultDirectory() {
+        return defaultDirectory;
+    }
+
+    String defaultRoot() {
+        return defaultRoot;
+    }
+
+    boolean supportsLinks() {
+        return supportsLinks;
+    }
+
+    boolean supportsStreamEnumeration() {
+        return supportsStreamEnumeration;
+    }
+
+
+    public FileSystemProvider provider() {
+        return provider;
+    }
+
+
+    public String getSeparator() {
+        return "\\";
+    }
+
+
+    public boolean isOpen() {
+        return true;
+    }
+
+
+    public boolean isReadOnly() {
+        return false;
+    }
+
+
+    public void close() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    // return new iterator over root directories
+    private Iterator<Path> rootDirectoryIterator() {
+        int drives = 0;
+        try {
+            drives = WindowsNativeDispatcher.GetLogicalDrives();
+        } catch (WindowsException x) {
+            // shouldn't happen
+            throw new AssertionError(x.getMessage());
+        }
+
+        // iterate over roots, ignoring those that the security manager denies
+        ArrayList<Path> result = new ArrayList<Path>();
+        SecurityManager sm = System.getSecurityManager();
+        for (int i = 0; i <= 25; i++) {  // 0->A, 1->B, 2->C...
+            if ((drives & (1 << i)) != 0) {
+                StringBuilder sb = new StringBuilder(3);
+                sb.append((char)('A' + i));
+                sb.append(":\\");
+                String root = sb.toString();
+                if (sm != null) {
+                    try {
+                        sm.checkRead(root);
+                    } catch (SecurityException x) {
+                        continue;
+                    }
+                }
+                result.add(WindowsPath.createFromNormalizedPath(this, root));
+            }
+        }
+        return Collections.unmodifiableList(result).iterator();
+    }
+
+
+    public Iterable<Path> getRootDirectories() {
+        return new Iterable<Path>() {
+            public Iterator<Path> iterator() {
+                return rootDirectoryIterator();
+            }
+        };
+    }
+
+    /**
+     * Iterator returned by getFileStores method.
+     */
+    private class FileStoreIterator implements Iterator<FileStore> {
+        private final Iterator<Path> roots;
+        private FileStore next;
+
+        FileStoreIterator() {
+            this.roots = getRootDirectories().iterator();
+        }
+
+        private FileStore readNext() {
+            assert Thread.holdsLock(this);
+            for (;;) {
+                if (!roots.hasNext())
+                    return null;
+                WindowsPath root = (WindowsPath)roots.next();
+                // ignore if security manager denies access
+                try {
+                    root.checkRead();
+                } catch (SecurityException x) {
+                    continue;
+                }
+                try {
+                    FileStore fs = WindowsFileStore.create(root.toString(), true);
+                    if (fs != null)
+                        return fs;
+                } catch (IOException ioe) {
+                    // skip it
+                }
+            }
+        }
+
+
+        public synchronized boolean hasNext() {
+            if (next != null)
+                return true;
+            next = readNext();
+            return next != null;
+        }
+
+
+        public synchronized FileStore next() {
+            if (next == null)
+                next = readNext();
+            if (next == null) {
+                throw new NoSuchElementException();
+            } else {
+                FileStore result = next;
+                next = null;
+                return result;
+            }
+        }
+
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+
+    public Iterable<FileStore> getFileStores() {
+        return new Iterable<FileStore>() {
+            public Iterator<FileStore> iterator() {
+                return new FileStoreIterator();
+            }
+        };
+    }
+
+    // supported views
+    private static final Set<String> supportedFileAttributeViews = Collections
+        .unmodifiableSet(new HashSet<String>(Arrays.asList("basic", "dos", "acl", "owner", "xattr")));
+
+
+    public Set<String> supportedFileAttributeViews() {
+        return supportedFileAttributeViews;
+    }
+
+
+    public Path getPath(String path) {
+        WindowsPathParser.Result result = WindowsPathParser.parse(path);
+        return new WindowsPath(this, result.type(), result.root(), result.path());
+    }
+
+
+
+    public UserPrincipalLookupService getUserPrincipalLookupService() {
+        return theLookupService;
+    }
+
+    private static final UserPrincipalLookupService theLookupService =
+        new UserPrincipalLookupService() {
+
+            public UserPrincipal lookupPrincipalByName(String name)
+                throws IOException
+            {
+                return WindowsUserPrincipals.lookup(name);
+            }
+
+            public GroupPrincipal lookupPrincipalByGroupName(String group)
+                throws IOException
+            {
+                UserPrincipal user = WindowsUserPrincipals.lookup(group);
+                if (!(user instanceof GroupPrincipal))
+                    throw new UserPrincipalNotFoundException(group);
+                return (GroupPrincipal)user;
+            }
+        };
+
+
+    public PathMatcher getNameMatcher(String syntax, String input) {
+        String expr;
+        if (syntax.equals(GLOB_SYNTAX)) {
+            expr = Globs.toRegexPattern(input);
+        } else {
+            if (syntax.equals(REGEX_SYNTAX)) {
+                expr = input;
+            } else {
+                throw new UnsupportedOperationException("Syntax '" + syntax +
+                    "' not recognized");
+            }
+        }
+
+        // match in uppercase
+        StringBuilder sb = new StringBuilder(expr.length());
+        for (int i=0; i<expr.length(); i++) {
+            sb.append(Character.toUpperCase(expr.charAt(i)));
+        }
+        expr = sb.toString();
+
+        // return matcher
+        final Pattern pattern = Pattern.compile(expr);
+        return new PathMatcher() {
+
+            public boolean matches(Path path) {
+                // match on file name only
+                Path name = path.getName();
+                if (name == null)
+                    return false;
+                // match in uppercase
+                String s = name.toString();
+                StringBuilder sb = new StringBuilder(s.length());
+                for (int i=0; i<s.length(); i++) {
+                    sb.append( Character.toUpperCase(s.charAt(i)) );
+                }
+                return pattern.matcher(sb).matches();
+            }
+        };
+    }
+    private static final String GLOB_SYNTAX = "glob";
+    private static final String REGEX_SYNTAX = "regex";
+
+
+    public WatchService newWatchService()
+        throws IOException
+    {
+        return new WindowsWatchService(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.spi.*;
+import java.nio.file.attribute.*;
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+import java.net.URI;
+import java.util.concurrent.ExecutorService;
+import java.io.IOException;
+import java.util.*;
+
+import sun.nio.ch.ThreadPool;
+
+public class WindowsFileSystemProvider
+    extends FileSystemProvider
+{
+    private static final String USER_DIR = "user.dir";
+    private final WindowsFileSystem theFileSystem;
+
+    public WindowsFileSystemProvider() {
+        theFileSystem = new WindowsFileSystem(this, System.getProperty(USER_DIR));
+    }
+
+
+    public String getScheme() {
+        return "file";
+    }
+
+    private void checkUri(URI uri) {
+        if (!uri.getScheme().equalsIgnoreCase(getScheme()))
+            throw new IllegalArgumentException("URI does not match this provider");
+        if (uri.getAuthority() != null)
+            throw new IllegalArgumentException("Authority component present");
+        if (uri.getPath() == null)
+            throw new IllegalArgumentException("Path component is undefined");
+        if (!uri.getPath().equals("/"))
+            throw new IllegalArgumentException("Path component should be '/'");
+        if (uri.getQuery() != null)
+            throw new IllegalArgumentException("Query component present");
+        if (uri.getFragment() != null)
+            throw new IllegalArgumentException("Fragment component present");
+    }
+
+
+    public FileSystem newFileSystem(URI uri, Map<String,?> env)
+        throws IOException
+    {
+        checkUri(uri);
+        throw new FileSystemAlreadyExistsException();
+    }
+
+
+    public final FileSystem getFileSystem(URI uri) {
+        checkUri(uri);
+        return theFileSystem;
+    }
+
+
+    public Path getPath(URI uri) {
+        return WindowsUriSupport.fromUri(theFileSystem, uri);
+    }
+
+
+    public FileChannel newFileChannel(Path path,
+                                      Set<? extends OpenOption> options,
+                                      FileAttribute<?>... attrs)
+        throws IOException
+    {
+        if (path == null)
+            throw new NullPointerException();
+        if (!(path instanceof WindowsPath))
+            throw new ProviderMismatchException();
+        WindowsPath file = (WindowsPath)path;
+
+        WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs);
+        try {
+            return WindowsChannelFactory
+                .newFileChannel(file.getPathForWin32Calls(),
+                                file.getPathForPermissionCheck(),
+                                options,
+                                sd.address());
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+            return null;
+        } finally {
+            if (sd != null)
+                sd.release();
+        }
+    }
+
+
+    public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
+                                                              Set<? extends OpenOption> options,
+                                                              ExecutorService executor,
+                                                              FileAttribute<?>... attrs)
+        throws IOException
+    {
+        if (path == null)
+            throw new NullPointerException();
+        if (!(path instanceof WindowsPath))
+            throw new ProviderMismatchException();
+        WindowsPath file = (WindowsPath)path;
+        ThreadPool pool = (executor == null) ? null :
+            ThreadPool.create(ThreadPoolType.CACHED, executor, 0);
+        WindowsSecurityDescriptor sd =
+            WindowsSecurityDescriptor.fromAttribute(attrs);
+        try {
+            return WindowsChannelFactory
+                .newAsynchronousFileChannel(file.getPathForWin32Calls(),
+                                            file.getPathForPermissionCheck(),
+                                            options,
+                                            sd.address(),
+                                            pool);
+        } finally {
+            if (sd != null)
+                sd.release();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+import java.io.IOError;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Utility methods for symbolic link support on Windows Vista and newer.
+ */
+
+class WindowsLinkSupport {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private WindowsLinkSupport() {
+    }
+
+    /**
+     * Returns the target of a symbolic link
+     */
+    static String readLink(WindowsPath path) throws IOException {
+        long handle = 0L;
+        try {
+            handle = path.openForReadAttributeAccess(false); // don't follow links
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(path);
+        }
+        try {
+            return readLinkImpl(handle);
+        } finally {
+            CloseHandle(handle);
+        }
+    }
+
+    /**
+     * Returns the final path of a given path as a String. This should be used
+     * prior to calling Win32 system calls that do not follow links.
+     */
+    static String getFinalPath(WindowsPath input) throws IOException {
+        WindowsFileSystem fs = input.getFileSystem();
+        if (!fs.supportsLinks())
+            return input.getPathForWin32Calls();
+
+        // if the file is not a sym link then return the path to access the file
+        try {
+            if (!WindowsFileAttributes.get(input, false).isSymbolicLink()) {
+                return input.getPathForWin32Calls();
+            }
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(input);
+        }
+
+        // The file is a symbolic link so we open it and try to get the
+        // normalized path. This should succeed on NTFS but may fail if there
+        // is a link to a non-NFTS file system.
+        long h = 0;
+        try {
+            h = input.openForReadAttributeAccess(true);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(input);
+        }
+        try {
+            return stripPrefix(GetFinalPathNameByHandle(h));
+        } catch (WindowsException x) {
+            // ERROR_INVALID_LEVEL is the error returned when not supported by
+            // the file system
+            if (x.lastError() != ERROR_INVALID_LEVEL)
+                x.rethrowAsIOException(input);
+        } finally {
+            CloseHandle(h);
+        }
+
+        // Fallback: read target of link, resolve against parent, and repeat
+        // until file is not a link.
+        WindowsPath target = input;
+        int linkCount = 0;
+        do {
+            try {
+                h = target.openForReadAttributeAccess(false);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(target);
+            }
+            try {
+                try {
+                    WindowsFileAttributes attrs = WindowsFileAttributes
+                        .readAttributes(h)
+                        .finishRead(target);
+                    // non a link so we are done
+                    if (!attrs.isSymbolicLink()) {
+                        return target.getPathForWin32Calls();
+                    }
+                } catch (WindowsException x) {
+                    x.rethrowAsIOException(target);
+                }
+                WindowsPath link = WindowsPath
+                    .createFromNormalizedPath(fs, readLinkImpl(h));
+                WindowsPath parent = target.getParent();
+                if (parent == null) {
+                    // no parent so use parent of absolute path
+                    final WindowsPath t = target;
+                    target = AccessController
+                        .doPrivileged(new PrivilegedAction<WindowsPath>() {
+
+                            public WindowsPath run() {
+                                return t.toAbsolutePath();
+                            }});
+                    parent = target.getParent();
+                }
+                target = parent.resolve(link);
+            } finally {
+                CloseHandle(h);
+            }
+        } while (++linkCount < 32);
+
+        throw new FileSystemException(input.getPathForExceptionMessage(), null,
+            "Too many links");
+    }
+
+    /**
+     * Returns the actual path of a file, optionally resolving all symbolic
+     * links.
+     */
+    static String getRealPath(WindowsPath input, boolean resolveLinks)
+        throws IOException
+    {
+        WindowsFileSystem fs = input.getFileSystem();
+        if (!fs.supportsLinks())
+            resolveLinks = false;
+
+        // On Vista use GetFinalPathNameByHandle. This should succeed on NTFS
+        // but may fail if there is a link to a non-NFTS file system.
+        if (resolveLinks) {
+            long h = 0;
+            try {
+                h = input.openForReadAttributeAccess(true);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(input);
+            }
+            try {
+                return stripPrefix(GetFinalPathNameByHandle(h));
+            } catch (WindowsException x) {
+                if (x.lastError() != ERROR_INVALID_LEVEL)
+                    x.rethrowAsIOException(input);
+            } finally {
+                CloseHandle(h);
+            }
+        }
+
+        // Not resolving links or we are on Windows Vista (or newer) with a
+        // link to non-NFTS file system.
+
+        // Start with absolute path
+        String path = null;
+        try {
+            path = input.toAbsolutePath().toString();
+        } catch (IOError x) {
+            throw (IOException)(x.getCause());
+        }
+
+        // Collapse "." and ".."
+        try {
+            path = GetFullPathName(path);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(input);
+        }
+
+        // eliminate all symbolic links
+        if (resolveLinks) {
+            path = resolveAllLinks(WindowsPath.createFromNormalizedPath(fs, path));
+        }
+
+        // string builder to build up components of path
+        StringBuilder sb = new StringBuilder(path.length());
+
+        // Copy root component
+        int start;
+        char c0 = path.charAt(0);
+        char c1 = path.charAt(1);
+        if ((c0 <= 'z' && c0 >= 'a' || c0 <= 'Z' && c0 >= 'A') &&
+            c1 == ':' && path.charAt(2) == '\\') {
+            // Driver specifier
+            sb.append(Character.toUpperCase(c0));
+            sb.append(":\\");
+            start = 3;
+        } else if (c0 == '\\' && c1 == '\\') {
+            // UNC pathname, begins with "\\\\host\\share"
+            int last = path.length() - 1;
+            int pos = path.indexOf('\\', 2);
+            // skip both server and share names
+            if (pos == -1 || (pos == last)) {
+                // The UNC does not have a share name (collapsed by GetFullPathName)
+                throw new FileSystemException(input.getPathForExceptionMessage(),
+                    null, "UNC has invalid share");
+            }
+            pos = path.indexOf('\\', pos+1);
+            if (pos < 0) {
+                pos = last;
+                sb.append(path).append("\\");
+            } else {
+                sb.append(path, 0, pos+1);
+            }
+            start = pos + 1;
+        } else {
+            throw new AssertionError("path type not recognized");
+        }
+
+        // check root directory exists
+        try {
+            FirstFile fileData = FindFirstFile(sb.toString() + "*");
+            FindClose(fileData.handle());
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(path);
+        }
+
+        // iterate through each component to get its actual name in the
+        // directory
+        int curr = start;
+        while (curr < path.length()) {
+            int next = path.indexOf('\\', curr);
+            int end = (next == -1) ? path.length() : next;
+            String search = sb.toString() + path.substring(curr, end);
+            try {
+                FirstFile fileData = FindFirstFile(addLongPathPrefixIfNeeded(search));
+                try {
+                    sb.append(fileData.name());
+                    if (next != -1) {
+                        sb.append('\\');
+                    }
+                } finally {
+                    FindClose(fileData.handle());
+                }
+            } catch (WindowsException e) {
+                e.rethrowAsIOException(path);
+            }
+            curr = end + 1;
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Returns target of a symbolic link given the handle of an open file
+     * (that should be a link).
+     */
+    private static String readLinkImpl(long handle) throws IOException {
+        int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
+        NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
+        try {
+            try {
+                DeviceIoControlGetReparsePoint(handle, buffer.address(), size);
+            } catch (WindowsException x) {
+                // FIXME: exception doesn't have file name
+                if (x.lastError() == ERROR_NOT_A_REPARSE_POINT)
+                    throw new NotLinkException(null, null, x.errorString());
+                x.rethrowAsIOException((String)null);
+            }
+
+            /*
+             * typedef struct _REPARSE_DATA_BUFFER {
+             *     ULONG  ReparseTag;
+             *     USHORT  ReparseDataLength;
+             *     USHORT  Reserved;
+             *     union {
+             *         struct {
+             *             USHORT  SubstituteNameOffset;
+             *             USHORT  SubstituteNameLength;
+             *             USHORT  PrintNameOffset;
+             *             USHORT  PrintNameLength;
+             *             WCHAR  PathBuffer[1];
+             *         } SymbolicLinkReparseBuffer;
+             *         struct {
+             *             USHORT  SubstituteNameOffset;
+             *             USHORT  SubstituteNameLength;
+             *             USHORT  PrintNameOffset;
+             *             USHORT  PrintNameLength;
+             *             WCHAR  PathBuffer[1];
+             *         } MountPointReparseBuffer;
+             *         struct {
+             *             UCHAR  DataBuffer[1];
+             *         } GenericReparseBuffer;
+             *     };
+             * } REPARSE_DATA_BUFFER
+             */
+            final short OFFSETOF_REPARSETAG = 0;
+            final short OFFSETOF_PATHOFFSET = 8;
+            final short OFFSETOF_PATHLENGTH = 10;
+            final short OFFSETOF_PATHBUFFER = 16 + 4;   // check this
+
+            int tag = (int)unsafe.getLong(buffer.address() + OFFSETOF_REPARSETAG);
+            if (tag != IO_REPARSE_TAG_SYMLINK) {
+                // FIXME: exception doesn't have file name
+                throw new NotLinkException(null, null, "Reparse point is not a symbolic link");
+            }
+
+            // get offset and length of target
+            short nameOffset = unsafe.getShort(buffer.address() + OFFSETOF_PATHOFFSET);
+            short nameLengthInBytes = unsafe.getShort(buffer.address() + OFFSETOF_PATHLENGTH);
+            if ((nameLengthInBytes % 2) != 0)
+                throw new FileSystemException(null, null, "Symbolic link corrupted");
+
+            // copy into char array
+            char[] name = new char[nameLengthInBytes/2];
+            unsafe.copyMemory(null, buffer.address() + OFFSETOF_PATHBUFFER + nameOffset,
+                name, Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes);
+
+            // remove special prefix
+            String target = stripPrefix(new String(name));
+            if (target.length() == 0) {
+                throw new IOException("Symbolic link target is invalid");
+            }
+            return target;
+        } finally {
+            buffer.release();
+        }
+    }
+
+    /**
+     * Resolve all symbolic-links in a given absolute and normalized path
+     */
+    private static String resolveAllLinks(WindowsPath path)
+        throws IOException
+    {
+        assert path.isAbsolute();
+        WindowsFileSystem fs = path.getFileSystem();
+
+        // iterate through each name element of the path, resolving links as
+        // we go.
+        int linkCount = 0;
+        int elem = 0;
+        while (elem < path.getNameCount()) {
+            WindowsPath current = path.getRoot().resolve(path.subpath(0, elem+1));
+
+            long h = 0L;
+            try {
+                h = current.openForReadAttributeAccess(false);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(current);
+            }
+            try {
+                WindowsFileAttributes attrs = null;
+                try {
+                    attrs = WindowsFileAttributes.readAttributes(h)
+                        .finishRead(current);
+                } catch (WindowsException x) {
+                    x.rethrowAsIOException(current);
+                }
+                /**
+                 * If a symbolic link then we resolve it against the parent
+                 * of the current name element. We then resolve any remaining
+                 * part of the path against the result. The target of the link
+                 * may have "." and ".." components so re-normalize and restart
+                 * the process from the first element.
+                 */
+                if (attrs.isSymbolicLink()) {
+                    linkCount++;
+                    if (linkCount > 32)
+                        throw new IOException("Too many links");
+
+                    WindowsPath target = WindowsPath
+                        .createFromNormalizedPath(fs, readLinkImpl(h));
+                    WindowsPath remainder = null;
+                    int count = path.getNameCount();
+                    if ((elem+1) < count) {
+                        remainder = path.subpath(elem+1, count);
+                    }
+                    path = current.getParent().resolve(target);
+                    try {
+                        String full = GetFullPathName(path.toString());
+                        if (!full.equals(path.toString())) {
+                            path = WindowsPath.createFromNormalizedPath(fs, full);
+                        }
+                    } catch (WindowsException x) {
+                        x.rethrowAsIOException(path);
+                    }
+                    if (remainder != null) {
+                        path = path.resolve(remainder);
+                    }
+
+                    // reset
+                    elem = 0;
+                } else {
+                    // not a link
+                    elem++;
+                }
+            } finally {
+                CloseHandle(h);
+            }
+        }
+
+        return path.toString();
+    }
+
+    /**
+     * Add long path prefix to path if required.
+     */
+    private static String addLongPathPrefixIfNeeded(String path) {
+        if (path.length() > 248) {
+            if (path.startsWith("\\\\")) {
+                path = "\\\\?\\UNC" + path.substring(1, path.length());
+            } else {
+                path = "\\\\?\\" + path;
+            }
+        }
+        return path;
+    }
+
+    /**
+     * Strip long path or symbolic link prefix from path
+     */
+    private static String stripPrefix(String path) {
+        // prefix for resolved/long path
+        if (path.startsWith("\\\\?\\")) {
+            if (path.startsWith("\\\\?\\UNC\\")) {
+                path = "\\" + path.substring(7);
+            } else {
+                path = path.substring(4);
+            }
+            return path;
+        }
+
+        // prefix for target of symbolic link
+        if (path.startsWith("\\??\\")) {
+            if (path.startsWith("\\??\\UNC\\")) {
+                path = "\\" + path.substring(7);
+            } else {
+                path = path.substring(4);
+            }
+            return path;
+        }
+        return path;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2007-2008 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.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.io.IOException;
+import java.util.*;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Windows emulation of NamedAttributeView using Alternative Data Streams
+ */
+
+class WindowsNamedAttributeView
+    extends AbstractNamedAttributeView
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // syntax to address named streams
+    private String join(String file, String name) {
+        if (name == null)
+            throw new NullPointerException("'name' is null");
+        return file + ":" + name;
+    }
+    private String join(WindowsPath file, String name) {
+        return join(file.getPathForWin32Calls(), name);
+    }
+
+    private final WindowsPath file;
+    private final boolean followLinks;
+
+    WindowsNamedAttributeView(WindowsPath file, boolean followLinks) {
+        this.file = file;
+        this.followLinks = followLinks;
+    }
+
+    // enumerates the file streams using FindFirstStream/FindNextStream APIs.
+    private List<String> listUsingStreamEnumeration() throws IOException {
+        List<String> list = new ArrayList<String>();
+        try {
+            FirstStream first = FindFirstStream(file.getPathForWin32Calls());
+            if (first != null) {
+                long handle = first.handle();
+                try {
+                    // first stream is always ::$DATA for files
+                    String name = first.name();
+                    if (!name.equals("::$DATA")) {
+                        String[] segs = name.split(":");
+                        list.add(segs[1]);
+                    }
+                    while ((name = FindNextStream(handle)) != null) {
+                        String[] segs = name.split(":");
+                        list.add(segs[1]);
+                    }
+                } finally {
+                    FindClose(handle);
+                }
+            }
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+    // enumerates the file streams by reading the stream headers using
+    // BackupRead
+    private List<String> listUsingBackupRead() throws IOException {
+        long handle = -1L;
+        try {
+            int flags = FILE_FLAG_BACKUP_SEMANTICS;
+            if (!followLinks && file.getFileSystem().supportsLinks())
+                flags |= FILE_FLAG_OPEN_REPARSE_POINT;
+
+            handle = CreateFile(file.getPathForWin32Calls(),
+                                GENERIC_READ,
+                                FILE_SHARE_READ, // no write as we depend on file size
+                                OPEN_EXISTING,
+                                flags);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+        }
+
+        // buffer to read stream header and stream name.
+        final int BUFFER_SIZE = 4096;
+        NativeBuffer buffer = null;
+
+        // result with names of alternative data streams
+        final List<String> list = new ArrayList<String>();
+
+        try {
+            buffer = NativeBuffers.getNativeBuffer(BUFFER_SIZE);
+            long address = buffer.address();
+
+            /**
+             * typedef struct _WIN32_STREAM_ID {
+             *     DWORD dwStreamId;
+             *     DWORD dwStreamAttributes;
+             *     LARGE_INTEGER Size;
+             *     DWORD dwStreamNameSize;
+             *     WCHAR cStreamName[ANYSIZE_ARRAY];
+             * } WIN32_STREAM_ID;
+             */
+            final int SIZEOF_STREAM_HEADER      = 20;
+            final int OFFSETOF_STREAM_ID        = 0;
+            final int OFFSETOF_STREAM_SIZE      = 8;
+            final int OFFSETOF_STREAM_NAME_SIZE = 16;
+
+            long context = 0L;
+            try {
+                for (;;) {
+                    // read stream header
+                    BackupResult result = BackupRead(handle, address,
+                       SIZEOF_STREAM_HEADER, false, context);
+                    context = result.context();
+                    if (result.bytesTransferred() == 0)
+                        break;
+
+                    int streamId = unsafe.getInt(address + OFFSETOF_STREAM_ID);
+                    long streamSize = unsafe.getLong(address + OFFSETOF_STREAM_SIZE);
+                    int nameSize = unsafe.getInt(address + OFFSETOF_STREAM_NAME_SIZE);
+
+                    // read stream name
+                    if (nameSize > 0) {
+                        result = BackupRead(handle, address, nameSize, false, context);
+                        if (result.bytesTransferred() != nameSize)
+                            break;
+                    }
+
+                    // check for alternative data stream
+                    if (streamId == BACKUP_ALTERNATE_DATA) {
+                        char[] nameAsArray = new char[nameSize/2];
+                        unsafe.copyMemory(null, address, nameAsArray,
+                            Unsafe.ARRAY_CHAR_BASE_OFFSET, nameSize);
+
+                        String[] segs = new String(nameAsArray).split(":");
+                        if (segs.length == 3)
+                            list.add(segs[1]);
+                    }
+
+                    // sparse blocks not currently handled as documentation
+                    // is not sufficient on how the spase block can be skipped.
+                    if (streamId == BACKUP_SPARSE_BLOCK) {
+                        throw new IOException("Spare blocks not handled");
+                    }
+
+                    // seek to end of stream
+                    if (streamSize > 0L) {
+                        BackupSeek(handle, streamSize, context);
+                    }
+                }
+            } catch (WindowsException x) {
+                // failed to read or seek
+                throw new IOException(x.errorString());
+            } finally {
+                // release context
+                if (context != 0L) {
+                   try {
+                       BackupRead(handle, 0L, 0, true, context);
+                   } catch (WindowsException ignore) { }
+                }
+            }
+        } finally {
+            if (buffer != null)
+                buffer.release();
+            CloseHandle(handle);
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+
+    public List<String> list() throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+        // use stream APIs on Windwos Server 2003 and newer
+        if (file.getFileSystem().supportsStreamEnumeration()) {
+            return listUsingStreamEnumeration();
+        } else {
+            return listUsingBackupRead();
+        }
+    }
+
+
+    public int size(String name) throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        // wrap with channel
+        FileChannel fc = null;
+        try {
+            Set<OpenOption> opts = new HashSet<OpenOption>();
+            opts.add(READ);
+            if (!followLinks)
+                opts.add(WindowsChannelFactory.NOFOLLOW_REPARSEPOINT);
+            fc = WindowsChannelFactory
+                .newFileChannel(join(file, name), null, opts, 0L);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(join(file, name));
+        }
+        try {
+            long size = fc.size();
+            if (size > Integer.MAX_VALUE)
+                throw new ArithmeticException("Stream too large");
+            return (int)size;
+        } finally {
+            fc.close();
+        }
+    }
+
+
+    public int read(String name, ByteBuffer dst) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        // wrap with channel
+        FileChannel fc = null;
+        try {
+            Set<OpenOption> opts = new HashSet<OpenOption>();
+            opts.add(READ);
+            if (!followLinks)
+                opts.add(WindowsChannelFactory.NOFOLLOW_REPARSEPOINT);
+            fc = WindowsChannelFactory
+                .newFileChannel(join(file, name), null, opts, 0L);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(join(file, name));
+        }
+
+        // read to EOF (nothing we can do if I/O error occurs)
+        try {
+            if (fc.size() > dst.remaining())
+                throw new IOException("Stream too large");
+            int total = 0;
+            while (dst.hasRemaining()) {
+                int n = fc.read(dst);
+                if (n < 0)
+                    break;
+                total += n;
+            }
+            return total;
+        } finally {
+            fc.close();
+        }
+    }
+
+
+    public int write(String name, ByteBuffer src) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        /**
+         * Creating a named stream will cause the unnamed stream to be created
+         * if it doesn't already exist. To avoid this we open the unnamed stream
+         * for reading and hope it isn't deleted/moved while we create or
+         * replace the named stream. Opening the file without sharing options
+         * may cause sharing violations with other programs that are accessing
+         * the unnamed stream.
+         */
+        long handle = -1L;
+        try {
+            int flags = FILE_FLAG_BACKUP_SEMANTICS;
+            if (!followLinks)
+                flags |= FILE_FLAG_OPEN_REPARSE_POINT;
+
+            handle = CreateFile(file.getPathForWin32Calls(),
+                                GENERIC_READ,
+                                (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+                                OPEN_EXISTING,
+                                flags);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+        }
+        try {
+            Set<OpenOption> opts = new HashSet<OpenOption>();
+            if (!followLinks)
+                opts.add(WindowsChannelFactory.NOFOLLOW_REPARSEPOINT);
+            opts.add(CREATE);
+            opts.add(WRITE);
+            opts.add(StandardOpenOption.TRUNCATE_EXISTING);
+            FileChannel named = null;
+            try {
+                named = WindowsChannelFactory
+                    .newFileChannel(join(file, name), null, opts, 0L);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(join(file, name));
+            }
+            // write value (nothing we can do if I/O error occurs)
+            try {
+                int rem = src.remaining();
+                while (src.hasRemaining()) {
+                    named.write(src);
+                }
+                return rem;
+            } finally {
+                named.close();
+            }
+        } finally {
+            CloseHandle(handle);
+        }
+    }
+
+
+    public void delete(String name) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        String toDelete = followLinks ?
+            join(WindowsLinkSupport.getFinalPath(file), name) : join(file, name);
+        try {
+            DeleteFile(toDelete);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(toDelete);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1131 @@
+/*
+ * Copyright 2007-2008 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.security.AccessController;
+import java.security.PrivilegedAction;
+import java.lang.reflect.Field;
+import sun.misc.Unsafe;
+
+/**
+ * Win32 and library calls.
+ */
+
+class WindowsNativeDispatcher {
+    private WindowsNativeDispatcher() { }
+
+    /**
+     * HANDLE CreateFile(
+     *   LPCTSTR lpFileName,
+     *   DWORD dwDesiredAccess,
+     *   DWORD dwShareMode,
+     *   LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+     *   DWORD dwCreationDisposition,
+     *   DWORD dwFlagsAndAttributes,
+     *   HANDLE hTemplateFile
+     * )
+     */
+    static long CreateFile(String path,
+                           int dwDesiredAccess,
+                           int dwShareMode,
+                           long lpSecurityAttributes,
+                           int dwCreationDisposition,
+                           int dwFlagsAndAttributes)
+        throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            return CreateFile0(buffer.address(),
+                               dwDesiredAccess,
+                               dwShareMode,
+                               lpSecurityAttributes,
+                               dwCreationDisposition,
+                               dwFlagsAndAttributes);
+        } finally {
+            buffer.release();
+        }
+    }
+    static long CreateFile(String path,
+                           int dwDesiredAccess,
+                           int dwShareMode,
+                           int dwCreationDisposition,
+                           int dwFlagsAndAttributes)
+        throws WindowsException
+    {
+        return CreateFile(path, dwDesiredAccess, dwShareMode, 0L,
+                          dwCreationDisposition, dwFlagsAndAttributes);
+    }
+    private static native long CreateFile0(long lpFileName,
+                                           int dwDesiredAccess,
+                                           int dwShareMode,
+                                           long lpSecurityAttributes,
+                                           int dwCreationDisposition,
+                                           int dwFlagsAndAttributes)
+        throws WindowsException;
+
+    /**
+     * CloseHandle(
+     *   HANDLE hObject
+     * )
+     */
+    static native void CloseHandle(long handle);
+
+    /**
+     * DeleteFile(
+     *   LPCTSTR lpFileName
+     * )
+     */
+    static void DeleteFile(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            DeleteFile0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void DeleteFile0(long lpFileName)
+        throws WindowsException;
+
+    /**
+     * CreateDirectory(
+     *   LPCTSTR lpPathName,
+     *   LPSECURITY_ATTRIBUTES lpSecurityAttributes
+     * )
+     */
+    static void CreateDirectory(String path, long lpSecurityAttributes) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            CreateDirectory0(buffer.address(), lpSecurityAttributes);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void CreateDirectory0(long lpFileName, long lpSecurityAttributes)
+        throws WindowsException;
+
+    /**
+     * RemoveDirectory(
+     *   LPCTSTR lpPathName
+     * )
+     */
+    static void RemoveDirectory(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            RemoveDirectory0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void RemoveDirectory0(long lpFileName)
+        throws WindowsException;
+
+    /**
+     * Marks a file as a sparse file.
+     *
+     * DeviceIoControl(
+     *   FSCTL_SET_SPARSE
+     * )
+     */
+    static native void DeviceIoControlSetSparse(long handle)
+        throws WindowsException;
+
+    /**
+     * Retrieves the reparse point data associated with the file or directory.
+     *
+     * DeviceIoControl(
+     *   FSCTL_GET_REPARSE_POINT
+     * )
+     */
+    static native void DeviceIoControlGetReparsePoint(long handle,
+        long bufferAddress, int bufferSize) throws WindowsException;
+
+    /**
+     * HANDLE FindFirstFile(
+     *   LPCTSTR lpFileName,
+     *   LPWIN32_FIND_DATA lpFindFileData
+     * )
+     */
+    static FirstFile FindFirstFile(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            FirstFile data = new FirstFile();
+            FindFirstFile0(buffer.address(), data);
+            return data;
+        } finally {
+            buffer.release();
+        }
+    }
+    static class FirstFile {
+        private long handle;
+        private String name;
+        private int reserved0;
+
+        private FirstFile() { }
+        public long handle()    { return handle; }
+        public String name()    { return name; }
+        public int reserved0()  { return reserved0; }
+    }
+    private static native void FindFirstFile0(long lpFileName, FirstFile obj)
+        throws WindowsException;
+
+    /**
+     * FindNextFile(
+     *   HANDLE hFindFile,
+     *   LPWIN32_FIND_DATA lpFindFileData
+     * )
+     *
+     * @return  lpFindFileData->cFileName
+     */
+    static native String FindNextFile(long handle) throws WindowsException;
+
+    /**
+     * HANDLE FindFirstStreamW(
+     *   LPCWSTR lpFileName,
+     *   STREAM_INFO_LEVELS InfoLevel,
+     *   LPVOID lpFindStreamData,
+     *   DWORD dwFlags
+     * )
+     */
+    static FirstStream FindFirstStream(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            FirstStream data = new FirstStream();
+            FindFirstStream0(buffer.address(), data);
+            if (data.handle() == WindowsConstants.INVALID_HANDLE_VALUE)
+                return null;
+            return data;
+        } finally {
+            buffer.release();
+        }
+    }
+    static class FirstStream {
+        private long handle;
+        private String name;
+
+        private FirstStream() { }
+        public long handle()    { return handle; }
+        public String name()    { return name; }
+    }
+    private static native void FindFirstStream0(long lpFileName, FirstStream obj)
+        throws WindowsException;
+
+    /*
+     * FindNextStreamW(
+     *   HANDLE hFindStream,
+     *   LPVOID lpFindStreamData
+     * )
+     */
+    static native String FindNextStream(long handle) throws WindowsException;
+
+    /**
+     * FindClose(
+     *   HANDLE hFindFile
+     * )
+     */
+    static native void FindClose(long handle) throws WindowsException;
+
+    /**
+     * GetFileInformationByHandle(
+     *   HANDLE hFile,
+     *   LPBY_HANDLE_FILE_INFORMATION lpFileInformation
+     * )
+     */
+    static native void GetFileInformationByHandle(long handle, long address)
+        throws WindowsException;
+
+    /**
+     * CopyFileEx(
+     *   LPCWSTR lpExistingFileName
+     *   LPCWSTR lpNewFileName,
+     *   LPPROGRESS_ROUTINE lpProgressRoutine
+     *   LPVOID lpData,
+     *   LPBOOL pbCancel,
+     *   DWORD dwCopyFlags
+     * )
+     */
+    static void CopyFileEx(String source, String target, int flags,
+                           long addressToPollForCancel)
+        throws WindowsException
+    {
+        NativeBuffer sourceBuffer = asNativeBuffer(source);
+        NativeBuffer targetBuffer = asNativeBuffer(target);
+        try {
+            CopyFileEx0(sourceBuffer.address(), targetBuffer.address(), flags,
+                        addressToPollForCancel);
+        } finally {
+            targetBuffer.release();
+            sourceBuffer.release();
+        }
+    }
+    private static native void CopyFileEx0(long existingAddress, long newAddress,
+        int flags, long addressToPollForCancel) throws WindowsException;
+
+    /**
+     * MoveFileEx(
+     *   LPCTSTR lpExistingFileName,
+     *   LPCTSTR lpNewFileName,
+     *   DWORD dwFlags
+     * )
+     */
+    static void MoveFileEx(String source, String target, int flags)
+        throws WindowsException
+    {
+        NativeBuffer sourceBuffer = asNativeBuffer(source);
+        NativeBuffer targetBuffer = asNativeBuffer(target);
+        try {
+            MoveFileEx0(sourceBuffer.address(), targetBuffer.address(), flags);
+        } finally {
+            targetBuffer.release();
+            sourceBuffer.release();
+        }
+    }
+    private static native void MoveFileEx0(long existingAddress, long newAddress,
+        int flags) throws WindowsException;
+
+    /**
+     * DWORD GetFileAttributes(
+     *   LPCTSTR lpFileName
+     * )
+     */
+    static int GetFileAttributes(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            return GetFileAttributes0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int GetFileAttributes0(long lpFileName)
+        throws WindowsException;
+
+    /**
+     * SetFileAttributes(
+     *   LPCTSTR lpFileName,
+     *   DWORD dwFileAttributes
+     */
+    static void SetFileAttributes(String path, int dwFileAttributes)
+        throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            SetFileAttributes0(buffer.address(), dwFileAttributes);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void SetFileAttributes0(long lpFileName,
+        int dwFileAttributes) throws WindowsException;
+
+    /**
+     * SetFileTime(
+     *   HANDLE hFile,
+     *   CONST FILETIME *lpCreationTime,
+     *   CONST FILETIME *lpLastAccessTime,
+     *   CONST FILETIME *lpLastWriteTime
+     * )
+     */
+    static native void SetFileTime(long handle, long createTime,
+        long lastAccessTime, long lastWriteTime) throws WindowsException;
+
+    /**
+     * SetEndOfFile(
+     *   HANDLE hFile
+     * )
+     */
+    static native void SetEndOfFile(long handle) throws WindowsException;
+
+    /**
+     * DWORD GetLogicalDrives(VOID)
+     */
+    static native int GetLogicalDrives() throws WindowsException;
+
+    /**
+     * GetVolumeInformation(
+     *   LPCTSTR lpRootPathName,
+     *   LPTSTR lpVolumeNameBuffer,
+     *   DWORD nVolumeNameSize,
+     *   LPDWORD lpVolumeSerialNumber,
+     *   LPDWORD lpMaximumComponentLength,
+     *   LPDWORD lpFileSystemFlags,
+     *   LPTSTR lpFileSystemNameBuffer,
+     *   DWORD nFileSystemNameSize
+     * )
+     */
+    static VolumeInformation GetVolumeInformation(String root)
+        throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(root);
+        try {
+            VolumeInformation info = new VolumeInformation();
+            GetVolumeInformation0(buffer.address(), info);
+            return info;
+        } finally {
+            buffer.release();
+        }
+    }
+    static class VolumeInformation {
+        private String fileSystemName;
+        private String volumeName;
+        private int volumeSerialNumber;
+        private int flags;
+        private VolumeInformation() { }
+
+        public String fileSystemName()      { return fileSystemName; }
+        public String volumeName()          { return volumeName; }
+        public int volumeSerialNumber()     { return volumeSerialNumber; }
+        public int flags()                  { return flags; }
+    }
+    private static native void GetVolumeInformation0(long lpRoot,
+                                                     VolumeInformation obj)
+        throws WindowsException;
+
+    /**
+     * UINT GetDriveType(
+     *   LPCTSTR lpRootPathName
+     * )
+     */
+    static int GetDriveType(String root) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(root);
+        try {
+            return GetDriveType0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int GetDriveType0(long lpRoot) throws WindowsException;
+
+    /**
+     * GetDiskFreeSpaceEx(
+     *   LPCTSTR lpDirectoryName,
+     *   PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+     *   PULARGE_INTEGER lpTotalNumberOfBytes,
+     *   PULARGE_INTEGER lpTotalNumberOfFreeBytes
+     * )
+     */
+    static DiskFreeSpace GetDiskFreeSpaceEx(String path)
+        throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            DiskFreeSpace space = new DiskFreeSpace();
+            GetDiskFreeSpaceEx0(buffer.address(), space);
+            return space;
+        } finally {
+            buffer.release();
+        }
+    }
+    static class DiskFreeSpace {
+        private long freeBytesAvailable;
+        private long totalNumberOfBytes;
+        private long totalNumberOfFreeBytes;
+        private DiskFreeSpace() { }
+
+        public long freeBytesAvailable()      { return freeBytesAvailable; }
+        public long totalNumberOfBytes()      { return totalNumberOfBytes; }
+        public long totalNumberOfFreeBytes()  { return totalNumberOfFreeBytes; }
+    }
+    private static native void GetDiskFreeSpaceEx0(long lpDirectoryName,
+                                                   DiskFreeSpace obj)
+        throws WindowsException;
+
+
+    /**
+     * GetVolumePathName(
+     *   LPCTSTR lpszFileName,
+     *   LPTSTR lpszVolumePathName,
+     *   DWORD cchBufferLength
+     * )
+     *
+     * @return  lpFileName
+     */
+    static String GetVolumePathName(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            return GetVolumePathName0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native String GetVolumePathName0(long lpFileName)
+        throws WindowsException;
+
+
+    /**
+     * InitializeSecurityDescriptor(
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
+     *   DWORD dwRevision
+     * )
+     */
+    static native void InitializeSecurityDescriptor(long sdAddress)
+        throws WindowsException;
+
+    /**
+     * InitializeAcl(
+     *   PACL pAcl,
+     *   DWORD nAclLength,
+     *   DWORD dwAclRevision
+     * )
+     */
+    static native void InitializeAcl(long aclAddress, int size)
+         throws WindowsException;
+
+    /**
+     * GetFileSecurity(
+     *   LPCTSTR lpFileName,
+     *   SECURITY_INFORMATION RequestedInformation,
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
+     *   DWORD nLength,
+     *   LPDWORD lpnLengthNeeded
+     * )
+     */
+    static int GetFileSecurity(String path,
+                               int requestedInformation,
+                               long pSecurityDescriptor,
+                               int nLength) throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            return GetFileSecurity0(buffer.address(), requestedInformation,
+                pSecurityDescriptor, nLength);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int GetFileSecurity0(long lpFileName,
+                                               int requestedInformation,
+                                               long pSecurityDescriptor,
+                                               int nLength) throws WindowsException;
+
+    /**
+     * SetFileSecurity(
+     *   LPCTSTR lpFileName,
+     *   SECURITY_INFORMATION SecurityInformation,
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor
+     * )
+     */
+    static void SetFileSecurity(String path,
+                                int securityInformation,
+                                long pSecurityDescriptor)
+        throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            SetFileSecurity0(buffer.address(), securityInformation,
+                pSecurityDescriptor);
+        } finally {
+            buffer.release();
+        }
+    }
+    static native void SetFileSecurity0(long lpFileName, int securityInformation,
+        long pSecurityDescriptor) throws WindowsException;
+
+    /**
+     * GetSecurityDescriptorOwner(
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor
+     *   PSID *pOwner,
+     *   LPBOOL lpbOwnerDefaulted
+     * )
+     *
+     * @return  pOwner
+     */
+    static native long GetSecurityDescriptorOwner(long pSecurityDescriptor)
+        throws WindowsException;
+
+    /**
+     * SetSecurityDescriptorOwner(
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
+     *   PSID pOwner,
+     *   BOOL bOwnerDefaulted
+     * )
+     */
+    static native void SetSecurityDescriptorOwner(long pSecurityDescriptor,
+                                                  long pOwner)
+        throws WindowsException;
+
+    /**
+     * GetSecurityDescriptorDacl(
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
+     *   LPBOOL lpbDaclPresent,
+     *   PACL *pDacl,
+     *   LPBOOL lpbDaclDefaulted
+     * )
+     */
+    static native long GetSecurityDescriptorDacl(long pSecurityDescriptor);
+
+    /**
+     * SetSecurityDescriptorDacl(
+     *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
+     *   BOOL bDaclPresent,
+     *   PACL pDacl,
+     *   BOOL bDaclDefaulted
+     * )
+     */
+    static native void SetSecurityDescriptorDacl(long pSecurityDescriptor, long pAcl)
+        throws WindowsException;
+
+
+    /**
+     * GetAclInformation(
+     *   PACL pAcl,
+     *   LPVOID pAclInformation,
+     *   DWORD nAclInformationLength,
+     *   ACL_INFORMATION_CLASS dwAclInformationClass
+     * )
+     */
+    static AclInformation GetAclInformation(long aclAddress) {
+        AclInformation info = new AclInformation();
+        GetAclInformation0(aclAddress, info);
+        return info;
+    }
+    static class AclInformation {
+        private int aceCount;
+        private AclInformation() { }
+
+        public int aceCount()   { return aceCount; }
+    }
+    private static native void GetAclInformation0(long aclAddress,
+        AclInformation obj);
+
+    /**
+     * GetAce(
+     *   PACL pAcl,
+     *   DWORD dwAceIndex,
+     *   LPVOID *pAce
+     * )
+     */
+    static native long GetAce(long aclAddress, int aceIndex);
+
+    /**
+     * AddAccessAllowedAceEx(
+     *   PACL pAcl,
+     *   DWORD dwAceRevision,
+     *   DWORD AceFlags,
+     *   DWORD AccessMask,
+     *   PSID pSid
+     * )
+     */
+    static native void AddAccessAllowedAceEx(long aclAddress, int flags,
+        int mask, long sidAddress) throws WindowsException;
+
+    /**
+     * AddAccessDeniedAceEx(
+     *   PACL pAcl,
+     *   DWORD dwAceRevision,
+     *   DWORD AceFlags,
+     *   DWORD AccessMask,
+     *   PSID pSid
+     * )
+     */
+    static native void AddAccessDeniedAceEx(long aclAddress, int flags,
+        int mask, long sidAddress) throws WindowsException;
+
+    /**
+     * LookupAccountSid(
+     *   LPCTSTR lpSystemName,
+     *   PSID Sid,
+     *   LPTSTR Name,
+     *   LPDWORD cbName,
+     *   LPTSTR ReferencedDomainName,
+     *   LPDWORD cbReferencedDomainName,
+     *   PSID_NAME_USE peUse
+     * )
+     */
+    static Account LookupAccountSid(long sidAddress) throws WindowsException {
+        Account acc = new Account();
+        LookupAccountSid0(sidAddress, acc);
+        return acc;
+    }
+    static class Account {
+        private String domain;
+        private String name;
+        private int use;
+        private Account() { }
+
+        public String domain()  { return domain; }
+        public String name()    { return name; }
+        public int use()        { return use; }
+    }
+    private static native void LookupAccountSid0(long sidAddress, Account obj)
+        throws WindowsException;
+
+    /**
+     * LookupAccountName(
+     *   LPCTSTR lpSystemName,
+     *   LPCTSTR lpAccountName,
+     *   PSID Sid,
+     *   LPDWORD cbSid,
+     *   LPTSTR ReferencedDomainName,
+     *   LPDWORD cbReferencedDomainName,
+     *   PSID_NAME_USE peUse
+     * )
+     *
+     * @return  cbSid
+     */
+    static int LookupAccountName(String accountName,
+                                 long pSid,
+                                 int cbSid) throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(accountName);
+        try {
+            return LookupAccountName0(buffer.address(), pSid, cbSid);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int LookupAccountName0(long lpAccountName, long pSid,
+        int cbSid) throws WindowsException;
+
+    /**
+     * DWORD GetLengthSid(
+     *   PSID pSid
+     * )
+     */
+    static native int GetLengthSid(long sidAddress);
+
+    /**
+     * ConvertSidToStringSid(
+     *   PSID Sid,
+     *   LPTSTR* StringSid
+     * )
+     *
+     * @return  StringSid
+     */
+    static native String ConvertSidToStringSid(long sidAddress)
+        throws WindowsException;
+
+    /**
+     * ConvertStringSidToSid(
+     *   LPCTSTR StringSid,
+     *   PSID* pSid
+     * )
+     *
+     * @return  pSid
+     */
+    static long ConvertStringSidToSid(String sidString)
+        throws WindowsException
+    {
+        NativeBuffer buffer = asNativeBuffer(sidString);
+        try {
+            return ConvertStringSidToSid0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native long ConvertStringSidToSid0(long lpStringSid)
+        throws WindowsException;
+
+    /**
+     * HANDLE GetCurrentProcess(VOID)
+     */
+    static native long GetCurrentProcess();
+
+    /**
+     * HANDLE GetCurrentThread(VOID)
+     */
+    static native long GetCurrentThread();
+
+    /**
+     * OpenProcessToken(
+     *   HANDLE ProcessHandle,
+     *   DWORD DesiredAccess,
+     *   PHANDLE TokenHandle
+     * )
+     */
+    static native long OpenProcessToken(long hProcess, int desiredAccess)
+        throws WindowsException;
+
+    /**
+     * OpenThreadToken(
+     *   HANDLE ThreadHandle,
+     *   DWORD DesiredAccess,
+     *   BOOL OpenAsSelf,
+     *   PHANDLE TokenHandle
+     * )
+     */
+    static native long OpenThreadToken(long hThread, int desiredAccess,
+        boolean openAsSelf) throws WindowsException;
+
+    /**
+     */
+    static native long DuplicateTokenEx(long hThread, int desiredAccess)
+        throws WindowsException;
+
+    /**
+     * SetThreadToken(
+     *   PHANDLE Thread,
+     *   HANDLE Token
+     * )
+     */
+    static native void SetThreadToken(long thread, long hToken)
+        throws WindowsException;
+
+    /**
+     * GetTokenInformation(
+     *   HANDLE TokenHandle,
+     *   TOKEN_INFORMATION_CLASS TokenInformationClass,
+     *   LPVOID TokenInformation,
+     *   DWORD TokenInformationLength,
+     *   PDWORD ReturnLength
+     * )
+     */
+    static native int GetTokenInformation(long token, int tokenInfoClass,
+        long pTokenInfo, int tokenInfoLength) throws WindowsException;
+
+    /**
+     * AdjustTokenPrivileges(
+     *   HANDLE TokenHandle,
+     *   BOOL DisableAllPrivileges
+     *   PTOKEN_PRIVILEGES NewState
+     *   DWORD BufferLength
+     *   PTOKEN_PRIVILEGES
+     *   PDWORD ReturnLength
+     * )
+     */
+    static native void AdjustTokenPrivileges(long token, long luid, int attributes)
+        throws WindowsException;
+
+    /**
+     */
+    static long LookupPrivilegeValue(String name) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(name);
+        try {
+            return LookupPrivilegeValue0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native long LookupPrivilegeValue0(long lpName)
+        throws WindowsException;
+
+    /**
+     * BuildTrusteeWithSid(
+     *   PTRUSTEE pTrustee,
+     *   PSID pSid
+     * )
+     *
+     * @return  pTrustee
+     */
+    static native long BuildTrusteeWithSid(long pSid);
+
+    /**
+     * GetEffectiveRightsFromAcl(
+     *   PACL pacl,
+     *   PTRUSTEE pTrustee,
+     *   PACCESS_MASK pAccessRights
+     * )
+     *
+     * @return  AccessRights
+     */
+    static native int GetEffectiveRightsFromAcl(long pAcl, long pTrustee)
+        throws WindowsException;
+
+    /**
+     * CreateSymbolicLink(
+     *   LPCWSTR lpSymlinkFileName,
+     *   LPCWSTR lpTargetFileName,
+     *   DWORD dwFlags
+     * )
+     */
+    static void CreateSymbolicLink(String link, String target, int flags)
+        throws WindowsException
+    {
+        NativeBuffer linkBuffer = asNativeBuffer(link);
+        NativeBuffer targetBuffer = asNativeBuffer(target);
+        try {
+            CreateSymbolicLink0(linkBuffer.address(), targetBuffer.address(),
+                                flags);
+        } finally {
+            targetBuffer.release();
+            linkBuffer.release();
+        }
+    }
+    private static native void CreateSymbolicLink0(long linkAddress,
+        long targetAddress, int flags) throws WindowsException;
+
+    /**
+     * CreateHardLink(
+     *    LPCTSTR lpFileName,
+     *    LPCTSTR lpExistingFileName,
+     *    LPSECURITY_ATTRIBUTES lpSecurityAttributes
+     * )
+     */
+    static void CreateHardLink(String newFile, String existingFile)
+        throws WindowsException
+    {
+        NativeBuffer newFileBuffer = asNativeBuffer(newFile);
+        NativeBuffer existingFileBuffer = asNativeBuffer(existingFile);
+        try {
+            CreateHardLink0(newFileBuffer.address(), existingFileBuffer.address());
+        } finally {
+            existingFileBuffer.release();
+            newFileBuffer.release();
+        }
+    }
+    private static native void CreateHardLink0(long newFileBuffer,
+        long existingFiletBuffer) throws WindowsException;
+
+    /**
+     * GetFullPathName(
+     *   LPCTSTR lpFileName,
+     *   DWORD nBufferLength,
+     *   LPTSTR lpBuffer,
+     *   LPTSTR *lpFilePart
+     * )
+     */
+    static String GetFullPathName(String path) throws WindowsException {
+        NativeBuffer buffer = asNativeBuffer(path);
+        try {
+            return GetFullPathName0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native String GetFullPathName0(long pathAddress)
+        throws WindowsException;
+
+    /**
+     * GetFinalPathNameByHandle(
+     *   HANDLE hFile,
+     *   LPTSTR lpszFilePath,
+     *   DWORD cchFilePath,
+     *   DWORD dwFlags
+     * )
+     */
+    static native String GetFinalPathNameByHandle(long handle)
+        throws WindowsException;
+
+    /**
+     * FormatMessage(
+     *   DWORD dwFlags,
+     *   LPCVOID lpSource,
+     *   DWORD dwMessageId,
+     *   DWORD dwLanguageId,
+     *   LPTSTR lpBuffer,
+     *   DWORD nSize,
+     *   va_list *Arguments
+     * )
+     */
+    static native String FormatMessage(int errorCode);
+
+    /**
+     * LocalFree(
+     *   HLOCAL hMem
+     * )
+     */
+    static native void LocalFree(long address);
+
+    /**
+     * HANDLE CreateIoCompletionPort (
+     *   HANDLE FileHandle,
+     *   HANDLE ExistingCompletionPort,
+     *   DWORD CompletionKey,
+     *   DWORD NumberOfConcurrentThreads
+     * )
+     */
+    static native long CreateIoCompletionPort(long fileHandle, long existingPort,
+        int completionKey) throws WindowsException;
+
+
+    /**
+     * GetQueuedCompletionStatus(
+     *   HANDLE CompletionPort,
+     *   LPDWORD lpNumberOfBytesTransferred,
+     *   LPDWORD lpCompletionKey,
+     *   LPOVERLAPPED *lpOverlapped,
+     *   DWORD dwMilliseconds
+     */
+    static CompletionStatus GetQueuedCompletionStatus(long completionPort)
+        throws WindowsException
+    {
+        CompletionStatus status = new CompletionStatus();
+        GetQueuedCompletionStatus0(completionPort, status);
+        return status;
+    }
+    static class CompletionStatus {
+        private int error;
+        private int bytesTransferred;
+        private int completionKey;
+        private CompletionStatus() { }
+
+        int error() { return error; }
+        int bytesTransferred() { return bytesTransferred; }
+        int completionKey() { return completionKey; }
+    }
+    private static native void GetQueuedCompletionStatus0(long completionPort,
+        CompletionStatus status) throws WindowsException;
+
+    /**
+     * PostQueuedCompletionStatus(
+     *   HANDLE CompletionPort,
+     *   DWORD dwNumberOfBytesTransferred,
+     *   DWORD dwCompletionKey,
+     *   LPOVERLAPPED lpOverlapped
+     * )
+     */
+    static native void PostQueuedCompletionStatus(long completionPort,
+        int completionKey) throws WindowsException;
+
+    /**
+     * ReadDirectoryChangesW(
+     *   HANDLE hDirectory,
+     *   LPVOID lpBuffer,
+     *   DWORD nBufferLength,
+     *   BOOL bWatchSubtree,
+     *   DWORD dwNotifyFilter,
+     *   LPDWORD lpBytesReturned,
+     *   LPOVERLAPPED lpOverlapped,
+     *   LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
+     * )
+     */
+    static native void ReadDirectoryChangesW(long hDirectory,
+                                             long bufferAddress,
+                                             int bufferLength,
+                                             boolean watchSubTree,
+                                             int filter,
+                                             long bytesReturnedAddress,
+                                             long pOverlapped)
+        throws WindowsException;
+
+    /**
+     * BackupRead(
+     *   HANDLE hFile,
+     *   LPBYTE lpBuffer,
+     *   DWORD nNumberOfBytesToRead,
+     *   LPDWORD lpNumberOfBytesRead,
+     *   BOOL bAbort,
+     *   BOOL bProcessSecurity,
+     *   LPVOID* lpContext
+     * )
+     */
+    static BackupResult BackupRead(long hFile,
+                                   long bufferAddress,
+                                   int bufferSize,
+                                   boolean abort,
+                                   long context)
+        throws WindowsException
+    {
+        BackupResult result = new BackupResult();
+        BackupRead0(hFile, bufferAddress, bufferSize, abort, context, result);
+        return result;
+    }
+    static class BackupResult {
+        private int bytesTransferred;
+        private long context;
+        private BackupResult() { }
+
+        int bytesTransferred() { return bytesTransferred; }
+        long context() { return context; }
+    }
+    private static native void BackupRead0(long hFile, long bufferAddress,
+        int bufferSize, boolean abort, long context, BackupResult result)
+        throws WindowsException;
+
+    /**
+     * BackupSeek(
+     *   HANDLE hFile,
+     *   DWORD dwLowBytesToSeek,
+     *   DWORD dwHighBytesToSeek,
+     *   LPDWORD lpdwLowByteSeeked,
+     *   LPDWORD lpdwHighByteSeeked,
+     *   LPVOID* lpContext
+     * )
+     */
+    static native void BackupSeek(long hFile, long bytesToSeek, long context)
+        throws WindowsException;
+
+
+    // -- support for copying String with a NativeBuffer --
+
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private static volatile Field stringValueField;
+    private static volatile Field stringOffsetField;
+
+    private static char[] getValueField(String s) {
+        // FIXME - access via shared secrets?
+        if (stringValueField == null) {
+            stringValueField = Reflect.lookupField("java.lang.String", "value");
+        }
+        try {
+            return (char[]) stringValueField.get(s);
+        } catch (IllegalAccessException iae) {
+            throw new AssertionError(iae);
+        }
+    }
+
+    private static int getOffsetField(String s) {
+        // FIXME - access via shared secrets?
+        if (stringOffsetField == null) {
+            stringOffsetField = Reflect.lookupField("java.lang.String", "offset");
+        }
+        try {
+            return ((Integer)(stringOffsetField.get(s))).intValue();
+        } catch (IllegalAccessException iae) {
+            throw new AssertionError(iae);
+        }
+    }
+
+    static NativeBuffer asNativeBuffer(String s) {
+        int stringLengthInBytes = s.length() << 1;
+        int sizeInBytes = stringLengthInBytes + 2;  // char terminator
+
+        // get a native buffer of sufficient size
+        NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(sizeInBytes);
+        if (buffer == null) {
+            buffer = NativeBuffers.allocNativeBuffer(sizeInBytes);
+        } else {
+            // buffer already contains the string contents
+            if (buffer.owner() == s)
+                return buffer;
+        }
+
+        // copy into buffer and zero terminate
+        int stringOffsetInBytes = getOffsetField(s) << 1;
+        char[] stringValue = getValueField(s);
+        long offset = Unsafe.ARRAY_CHAR_BASE_OFFSET + stringOffsetInBytes;
+        unsafe.copyMemory(stringValue, offset, null, buffer.address(),
+            (long)stringLengthInBytes);
+        unsafe.putChar(buffer.address() + stringLengthInBytes, (char)0);
+        buffer.setOwner(s);
+        return buffer;
+    }
+
+    // -- native library initialization --
+
+    private static native void initIDs();
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                // nio.dll has dependency on net.dll
+                System.loadLibrary("net");
+                System.loadLibrary("nio");
+                return null;
+        }});
+        initIDs();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1294 @@
+/*
+ * Copyright 2007-2008 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 java.nio.file.attribute.*;
+import java.nio.file.spi.AbstractPath;
+import java.nio.channels.*;
+import java.io.*;
+import java.net.URI;
+import java.security.AccessController;
+import java.util.*;
+
+import com.sun.nio.file.ExtendedWatchEventModifier;
+
+import sun.security.util.SecurityConstants;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Windows implementation of Path
+ */
+
+class WindowsPath extends AbstractPath {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // FIXME - eliminate this reference to reduce space
+    private final WindowsFileSystem fs;
+
+    // path type
+    private final WindowsPathType type;
+    // root component (may be empty)
+    private final String root;
+    // normalized path
+    private final String path;
+
+    // offsets into name components (computed lazily)
+    private volatile Integer[] offsets;
+
+    // resolved against file system's default directory
+    private final String resolved;
+
+    // the path to use in calls to Windows (same as resolved path when less
+    // than 248 characters but differs for long paths)
+    private final String pathForWin32Calls;
+
+    // computed hash code (computed lazily, no need to be volatile)
+    private volatile int hash;
+
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    WindowsPath(WindowsFileSystem fs,
+                WindowsPathType type,
+                String root,
+                String path)
+    {
+        this.fs = fs;
+        this.type = type;
+        this.root = root;
+        this.path = path;
+
+        // resolve path against file system's default directory
+        switch (type) {
+            case ABSOLUTE :
+            case UNC :
+                this.resolved = path;
+                break;
+            case RELATIVE :
+                String defaultDirectory = getFileSystem().defaultDirectory();
+                if (defaultDirectory.endsWith("\\")) {
+                    this.resolved = defaultDirectory + path;
+                } else {
+                    this.resolved = defaultDirectory + "\\" + path;
+                }
+                break;
+            case DIRECTORY_RELATIVE:
+                String defaultRoot = getFileSystem().defaultRoot();
+                this.resolved = defaultRoot + path.substring(1);
+                break;
+            case DRIVE_RELATIVE:
+                // Need to postpone resolving these types of paths as they can
+                // change for the case of removable media devices when media
+                // is inserted or removed.
+                this.resolved = path;
+                break;
+            default:
+                throw new AssertionError();
+        }
+
+        // Long paths need to have "." and ".." removed and be prefixed with \\?\
+        // Note that it is okay to remove ".." even when it follows a link -
+        // for example, it is okay for foo/link/../bar to be changed to foo/bar.
+        // The reason is that Win32 APIs to access foo/link/../bar will access
+        // foo/bar anyway (which differs to Unix systems)
+        String ps = resolved;
+        if (ps.length() > 248) {
+            if (ps.length() > 32000) {
+                throw new InvalidPathException(ps,
+                    "Cannot access file with path exceeding 32000 characters");
+            }
+            try {
+                ps = GetFullPathName(ps);
+            } catch (WindowsException x) {
+                throw new AssertionError("GetFullPathName failed for '" + ps +
+                    "' " + x.getMessage());
+            }
+            ps = addPrefixIfNeeded(ps);
+        }
+
+        this.pathForWin32Calls = ps;
+    }
+
+    /**
+     * Creates a WindowsPath by parsing the given path.
+     */
+    static WindowsPath parse(WindowsFileSystem fs, String path) {
+        WindowsPathParser.Result result = WindowsPathParser.parse(path);
+        return new WindowsPath(fs, result.type(), result.root(), result.path());
+    }
+
+    /**
+     * Creates a WindowsPath from a given path that is known to be normalized.
+     */
+    static WindowsPath createFromNormalizedPath(WindowsFileSystem fs, String path) {
+        try {
+            WindowsPathParser.Result result =
+                WindowsPathParser.parseNormalizedPath(path);
+            return new WindowsPath(fs, result.type(), result.root(), result.path());
+        } catch (InvalidPathException x) {
+            throw new AssertionError(x.getMessage());
+        }
+    }
+
+    // use this message when throwing exceptions
+    String getPathForExceptionMessage() {
+        return path;
+    }
+
+    // use this path for permission checks
+    String getPathForPermissionCheck() {
+        return resolved;
+    }
+
+    // use this for calls into Windows (may have \\?\ or \\?\UNC prefix)
+    String getPathForWin32Calls() {
+        return pathForWin32Calls;
+    }
+
+    // Add long path prefix to path if required
+    private static String addPrefixIfNeeded(String path) {
+        if (path.length() > 248) {
+            if (path.startsWith("\\\\")) {
+                path = "\\\\?\\UNC" + path.substring(1, path.length());
+            } else {
+                path = "\\\\?\\" + path;
+            }
+        }
+        return path;
+    }
+
+
+    public WindowsFileSystem getFileSystem() {
+        return fs;
+    }
+
+    // -- Path operations --
+
+
+    public Path getName() {
+        // represents root component only
+        if (root.length() == path.length())
+            return null;
+        int off = path.lastIndexOf('\\');
+        if (off < root.length())
+            off = root.length();
+        else
+            off++;
+        return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", path.substring(off));
+    }
+
+
+    public WindowsPath getParent() {
+        // represents root component only
+        if (root.length() == path.length())
+            return null;
+        int off = path.lastIndexOf('\\');
+        if (off < root.length())
+            return getRoot();
+        else
+            return new WindowsPath(getFileSystem(),
+                                   type,
+                                   root,
+                                   path.substring(0, off));
+    }
+
+
+    public WindowsPath getRoot() {
+        if (root.length() == 0)
+            return null;
+        return new WindowsPath(getFileSystem(), type, root, root);
+    }
+
+    // package-private
+    boolean isUnc() {
+        return type == WindowsPathType.UNC;
+    }
+
+
+    public boolean isAbsolute() {
+        return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC;
+    }
+
+    private WindowsPath checkPath(FileRef path) {
+        if (path == null)
+            throw new NullPointerException();
+        if (!(path instanceof WindowsPath)) {
+            throw new ProviderMismatchException();
+        }
+        return (WindowsPath)path;
+    }
+
+
+    public WindowsPath relativize(Path obj) {
+        WindowsPath other = checkPath(obj);
+        if (this.equals(other))
+            return null;
+
+        // can only relativize paths of the same type
+        if (this.type != other.type)
+            throw new IllegalArgumentException("'other' is different type of Path");
+
+        // can only relativize paths if root component matches
+        if (!this.root.equalsIgnoreCase(other.root))
+            throw new IllegalArgumentException("'other' has different root");
+
+        int bn = this.getNameCount();
+        int cn = other.getNameCount();
+
+        // skip matching names
+        int n = (bn > cn) ? cn : bn;
+        int i = 0;
+        while (i < n) {
+            if (!this.getName(i).equals(other.getName(i)))
+                break;
+            i++;
+        }
+
+        // append ..\ for remaining names in the base
+        StringBuilder result = new StringBuilder();
+        for (int j=i; j<bn; j++) {
+            result.append("..\\");
+        }
+
+        // append remaining names in child
+        for (int j=i; j<cn; j++) {
+            result.append(other.getName(j).toString());
+            result.append("\\");
+        }
+
+        // drop trailing slash in result
+        result.setLength(result.length()-1);
+        return createFromNormalizedPath(getFileSystem(), result.toString());
+    }
+
+
+    public Path normalize() {
+        final int count = getNameCount();
+        if (count == 0)
+            return this;
+
+        boolean[] ignore = new boolean[count];      // true => ignore name
+        int remaining = count;                      // number of names remaining
+
+        // multiple passes to eliminate all occurences of "." and "name/.."
+        int prevRemaining;
+        do {
+            prevRemaining = remaining;
+            int prevName = -1;
+            for (int i=0; i<count; i++) {
+                if (ignore[i])
+                    continue;
+
+                String name = elementAsString(i);
+
+                // not "." or ".."
+                if (name.length() > 2) {
+                    prevName = i;
+                    continue;
+                }
+
+                // "." or something else
+                if (name.length() == 1) {
+                    // ignore "."
+                    if (name.charAt(0) == '.') {
+                        ignore[i] = true;
+                        remaining--;
+                    } else {
+                        prevName = i;
+                    }
+                    continue;
+                }
+
+                // not ".."
+                if (name.charAt(0) != '.' || name.charAt(1) != '.') {
+                    prevName = i;
+                    continue;
+                }
+
+                // ".." found
+                if (prevName >= 0) {
+                    // name/<ignored>/.. found so mark name and ".." to be
+                    // ignored
+                    ignore[prevName] = true;
+                    ignore[i] = true;
+                    remaining = remaining - 2;
+                    prevName = -1;
+                } else {
+                    // Cases:
+                    //    C:\<ignored>\..
+                    //    \\server\\share\<ignored>\..
+                    //    \<ignored>..
+                    if (isAbsolute() || type == WindowsPathType.DIRECTORY_RELATIVE) {
+                        boolean hasPrevious = false;
+                        for (int j=0; j<i; j++) {
+                            if (!ignore[j]) {
+                                hasPrevious = true;
+                                break;
+                            }
+                        }
+                        if (!hasPrevious) {
+                            // all proceeding names are ignored
+                            ignore[i] = true;
+                            remaining--;
+                        }
+                    }
+                }
+            }
+        } while (prevRemaining > remaining);
+
+        // no redundant names
+        if (remaining == count)
+            return this;
+
+        // corner case - all names removed
+        if (remaining == 0) {
+            return getRoot();
+        }
+
+        // re-constitute the path from the remaining names.
+        StringBuilder result = new StringBuilder();
+        if (root != null)
+            result.append(root);
+        for (int i=0; i<count; i++) {
+            if (!ignore[i]) {
+                result.append(getName(i).toString());
+                result.append("\\");
+            }
+        }
+
+        // drop trailing slash in result
+        result.setLength(result.length()-1);
+        return createFromNormalizedPath(getFileSystem(), result.toString());
+    }
+
+
+    public WindowsPath resolve(Path obj) {
+        if (obj == null)
+            return this;
+        WindowsPath other = checkPath(obj);
+        if (other.isAbsolute())
+            return other;
+
+        switch (other.type) {
+            case RELATIVE: {
+                String result;
+                if (path.endsWith("\\") || (root.length() == path.length())) {
+                    result = path + other.path;
+                } else {
+                    result = path + "\\" + other.path;
+                }
+                return new WindowsPath(getFileSystem(), type, root, result);
+            }
+
+            case DIRECTORY_RELATIVE: {
+                String result;
+                if (root.endsWith("\\")) {
+                    result = root + other.path.substring(1);
+                } else {
+                    result = root + other.path;
+                }
+                return createFromNormalizedPath(getFileSystem(), result);
+            }
+
+            case DRIVE_RELATIVE: {
+                if (!root.endsWith("\\"))
+                    return other;
+                // if different roots then return other
+                String thisRoot = root.substring(0, root.length()-1);
+                if (!thisRoot.equalsIgnoreCase(other.root))
+                    return other;
+                // same roots
+                String remaining = other.path.substring(other.root.length());
+                String result;
+                if (path.endsWith("\\")) {
+                    result = path + remaining;
+                } else {
+                    result = path + "\\" + remaining;
+                }
+                return createFromNormalizedPath(getFileSystem(), result);
+            }
+
+            default:
+                throw new AssertionError();
+        }
+    }
+
+
+    public WindowsPath resolve(String other) {
+        return resolve(getFileSystem().getPath(other));
+    }
+
+    // generate offset array
+    private void initOffsets() {
+        if (offsets == null) {
+            ArrayList<Integer> list = new ArrayList<Integer>();
+            int start = root.length();
+            int off = root.length();
+            while (off < path.length()) {
+                if (path.charAt(off) != '\\') {
+                    off++;
+                } else {
+                    list.add(start);
+                    start = ++off;
+                }
+            }
+            if (start != off)
+                list.add(start);
+            synchronized (this) {
+                if (offsets == null)
+                    offsets = list.toArray(new Integer[list.size()]);
+            }
+        }
+    }
+
+
+    public int getNameCount() {
+        initOffsets();
+        return offsets.length;
+    }
+
+    private String elementAsString(int i) {
+        initOffsets();
+        if (i == (offsets.length-1))
+            return path.substring(offsets[i]);
+        return path.substring(offsets[i], offsets[i+1]-1);
+    }
+
+
+    public WindowsPath getName(int index) {
+        initOffsets();
+        if (index < 0 || index >= offsets.length)
+            throw new IllegalArgumentException();
+        return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", elementAsString(index));
+    }
+
+
+    public WindowsPath subpath(int beginIndex, int endIndex) {
+        initOffsets();
+        if (beginIndex < 0)
+            throw new IllegalArgumentException();
+        if (beginIndex >= offsets.length)
+            throw new IllegalArgumentException();
+        if (endIndex > offsets.length)
+            throw new IllegalArgumentException();
+        if (beginIndex >= endIndex)
+            throw new IllegalArgumentException();
+
+        StringBuilder sb = new StringBuilder();
+        Integer[] nelems = new Integer[endIndex - beginIndex];
+        for (int i = beginIndex; i < endIndex; i++) {
+            nelems[i-beginIndex] = sb.length();
+            sb.append(elementAsString(i));
+            if (i != (endIndex-1))
+                sb.append("\\");
+        }
+        return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", sb.toString());
+    }
+
+
+    public boolean startsWith(Path obj) {
+        WindowsPath other = checkPath(obj);
+
+        // if this path has a root component the given path's root must match
+        if (!this.root.equalsIgnoreCase(other.root))
+            return false;
+
+        // roots match so compare elements
+        int thisCount = getNameCount();
+        int otherCount = other.getNameCount();
+        if (otherCount <= thisCount) {
+            while (--otherCount >= 0) {
+                String thisElement = this.elementAsString(otherCount);
+                String otherElement = other.elementAsString(otherCount);
+                // FIXME: should compare in uppercase
+                if (!thisElement.equalsIgnoreCase(otherElement))
+                    return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+
+    public boolean endsWith(Path obj) {
+        WindowsPath other = checkPath(obj);
+
+        // other path is longer
+        if (other.path.length() > path.length()) {
+            return false;
+        }
+
+        int thisCount = this.getNameCount();
+        int otherCount = other.getNameCount();
+
+        // given path has more elements that this path
+        if (otherCount > thisCount) {
+            return false;
+        }
+
+        // compare roots
+        if (other.root.length() > 0) {
+            if (otherCount < thisCount)
+                return false;
+            // FIXME: should compare in uppercase
+            if (!this.root.equalsIgnoreCase(other.root))
+                return false;
+        }
+
+        // match last 'otherCount' elements
+        int off = thisCount - otherCount;
+        while (--otherCount >= 0) {
+            String thisElement = this.elementAsString(off + otherCount);
+            String otherElement = other.elementAsString(otherCount);
+            // FIXME: should compare in uppercase
+            if (!thisElement.equalsIgnoreCase(otherElement))
+                return false;
+        }
+        return true;
+    }
+
+
+    public int compareTo(Path obj) {
+        if (obj == null)
+            throw new NullPointerException();
+        String s1 = path;
+        String s2 = ((WindowsPath)obj).path;
+        int n1 = s1.length();
+        int n2 = s2.length();
+        int min = Math.min(n1, n2);
+        for (int i = 0; i < min; i++) {
+            char c1 = s1.charAt(i);
+            char c2 = s2.charAt(i);
+             if (c1 != c2) {
+                 c1 = Character.toUpperCase(c1);
+                 c2 = Character.toUpperCase(c2);
+                 if (c1 != c2) {
+                     return c1 - c2;
+                 }
+             }
+        }
+        return n1 - n2;
+    }
+
+
+    public boolean equals(Object obj) {
+        if ((obj != null) && (obj instanceof WindowsPath)) {
+            return compareTo((Path)obj) == 0;
+        }
+        return false;
+    }
+
+
+    public int hashCode() {
+        // OK if two or more threads compute hash
+        int h = hash;
+        if (h == 0) {
+            for (int i = 0; i< path.length(); i++) {
+                h = 31*h + Character.toUpperCase(path.charAt(i));
+            }
+            hash = h;
+        }
+        return h;
+    }
+
+
+    public String toString() {
+        return path;
+    }
+
+
+    public Iterator<Path> iterator() {
+        return new Iterator<Path>() {
+            private int i = 0;
+
+            public boolean hasNext() {
+                return (i < getNameCount());
+            }
+
+            public Path next() {
+                if (i < getNameCount()) {
+                    Path result = getName(i);
+                    i++;
+                    return result;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    // -- file operations --
+
+    // package-private
+    long openForReadAttributeAccess(boolean followLinks)
+        throws WindowsException
+    {
+        int flags = FILE_FLAG_BACKUP_SEMANTICS;
+        if (!followLinks && getFileSystem().supportsLinks())
+            flags |= FILE_FLAG_OPEN_REPARSE_POINT;
+        return CreateFile(getPathForWin32Calls(),
+                          FILE_READ_ATTRIBUTES,
+                          (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+                          0L,
+                          OPEN_EXISTING,
+                          flags);
+    }
+
+    void checkRead() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkRead(getPathForPermissionCheck());
+        }
+    }
+
+    void checkWrite() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkWrite(getPathForPermissionCheck());
+        }
+    }
+
+    void checkDelete() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkDelete(getPathForPermissionCheck());
+        }
+    }
+
+
+    public FileStore getFileStore()
+        throws IOException
+    {
+        checkRead();
+        return WindowsFileStore.create(this);
+    }
+
+    /**
+     * Returns buffer with SID_AND_ATTRIBUTES structure representing the user
+     * associated with the current thread access token.
+     * FIXME - this should be cached.
+     */
+    private NativeBuffer getUserInfo() throws IOException {
+        try {
+            long hToken = WindowsSecurity.processTokenWithQueryAccess;
+            int size = GetTokenInformation(hToken, TokenUser, 0L, 0);
+            assert size > 0;
+
+            NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
+            try {
+                int newsize = GetTokenInformation(hToken, TokenUser,
+                                                  buffer.address(), size);
+                if (newsize != size)
+                    throw new AssertionError();
+                return buffer;
+            } catch (WindowsException x) {
+                buffer.release();
+                throw x;
+            }
+        } catch (WindowsException x) {
+            throw new IOException(x.getMessage());
+        }
+    }
+
+    /**
+     * Reads the file ACL and return the effective access as ACCESS_MASK
+     */
+    private int getEffectiveAccess() throws IOException {
+        // read security descriptor continaing ACL (symlinks are followed)
+        String fp = WindowsLinkSupport.getFinalPath(this);
+        NativeBuffer aclBuffer = WindowsAclFileAttributeView
+            .getFileSecurity(fp, DACL_SECURITY_INFORMATION);
+
+        // retrieves DACL from security descriptor
+        long pAcl = GetSecurityDescriptorDacl(aclBuffer.address());
+
+        // Use GetEffectiveRightsFromAcl to get effective access to file
+        try {
+            NativeBuffer userBuffer = getUserInfo();
+            try {
+                try {
+                    // SID_AND_ATTRIBUTES->pSid
+                    long pSid = unsafe.getAddress(userBuffer.address());
+                    long pTrustee = BuildTrusteeWithSid(pSid);
+                    try {
+                        return GetEffectiveRightsFromAcl(pAcl, pTrustee);
+                    } finally {
+                        LocalFree(pTrustee);
+                    }
+                } catch (WindowsException x) {
+                    throw new IOException("Unable to get effective rights from ACL: " +
+                        x.getMessage());
+                }
+            } finally {
+                userBuffer.release();
+            }
+        } finally {
+            aclBuffer.release();
+        }
+    }
+
+
+    public void checkAccess(AccessMode... modes) throws IOException {
+        // if no access modes then simply file attributes
+        if (modes.length == 0) {
+            checkRead();
+            try {
+                WindowsFileAttributes.get(this, true);
+            } catch (WindowsException exc) {
+                exc.rethrowAsIOException(this);
+            }
+            return;
+        }
+
+        boolean r = false;
+        boolean w = false;
+        boolean x = false;
+        for (AccessMode mode: modes) {
+            switch (mode) {
+                case READ : r = true; break;
+                case WRITE : w = true; break;
+                case EXECUTE : x = true; break;
+                default: throw new AssertionError("Should not get here");
+            }
+        }
+
+        int mask = 0;
+        if (r) {
+            checkRead();
+            mask |= FILE_READ_DATA;
+        }
+        if (w) {
+            checkWrite();
+            mask |= FILE_WRITE_DATA;
+        }
+        if (x) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null)
+                sm.checkExec(getPathForPermissionCheck());
+            mask |= FILE_EXECUTE;
+        }
+
+        if ((getEffectiveAccess() & mask) == 0)
+            throw new AccessDeniedException(
+                this.getPathForExceptionMessage(), null,
+                "Effective permissions does not allow requested access");
+
+        // for write access we neeed to check if the DOS readonly attribute
+        // and if the volume is read-only
+        if (w) {
+            try {
+                WindowsFileAttributes attrs = WindowsFileAttributes.get(this, true);
+                if (!attrs.isDirectory() && attrs.isReadOnly())
+                    throw new AccessDeniedException(
+                        this.getPathForExceptionMessage(), null,
+                        "DOS readonly attribute is set");
+            } catch (WindowsException exc) {
+                exc.rethrowAsIOException(this);
+            }
+
+            if (WindowsFileStore.create(this).isReadOnly()) {
+                throw new AccessDeniedException(
+                    this.getPathForExceptionMessage(), null, "Read-only file system");
+            }
+            return;
+        }
+    }
+
+
+    public void delete(boolean failIfNotExists) throws IOException {
+        checkDelete();
+
+        WindowsFileAttributes attrs = null;
+        try {
+             // need to know if file is a directory or junction
+             attrs = WindowsFileAttributes.get(this, false);
+             if (attrs.isDirectory() || attrs.isDirectoryLink()) {
+                RemoveDirectory(getPathForWin32Calls());
+             } else {
+                DeleteFile(getPathForWin32Calls());
+             }
+        } catch (WindowsException x) {
+
+            // no-op if file does not exist
+            if (!failIfNotExists &&
+                (x.lastError() == ERROR_FILE_NOT_FOUND ||
+                 x.lastError() == ERROR_PATH_NOT_FOUND)) return;
+
+            if (attrs != null && attrs.isDirectory()) {
+                // ERROR_ALREADY_EXISTS is returned when attempting to delete
+                // non-empty directory on SAMBA servers.
+                if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
+                    x.lastError() == ERROR_ALREADY_EXISTS)
+                {
+                    throw new DirectoryNotEmptyException(
+                        getPathForExceptionMessage());
+                }
+            }
+            x.rethrowAsIOException(this);
+        }
+    }
+
+
+    public DirectoryStream<Path> newDirectoryStream(DirectoryStream.Filter<? super Path> filter)
+        throws IOException
+    {
+        checkRead();
+        if (filter == null)
+            throw new NullPointerException();
+        return new WindowsDirectoryStream(this, filter);
+    }
+
+
+    public void implCopyTo(Path obj, CopyOption... options) throws IOException {
+        WindowsPath target = (WindowsPath)obj;
+        WindowsFileCopy.copy(this, target, options);
+    }
+
+
+    public void implMoveTo(Path obj, CopyOption... options) throws IOException {
+        WindowsPath target = (WindowsPath)obj;
+        WindowsFileCopy.move(this, target, options);
+    }
+
+    private boolean followLinks(LinkOption... options) {
+        boolean followLinks = true;
+        for (LinkOption option: options) {
+            if (option == LinkOption.NOFOLLOW_LINKS) {
+                followLinks = false;
+                continue;
+            }
+            throw new AssertionError("Should not get here");
+        }
+        return followLinks;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V
+        getFileAttributeView(Class<V> view, LinkOption... options)
+    {
+        if (view == null)
+            throw new NullPointerException();
+        boolean followLinks = followLinks(options);
+        if (view == BasicFileAttributeView.class)
+            return (V) WindowsFileAttributeViews.createBasicView(this, followLinks);
+        if (view == DosFileAttributeView.class)
+            return (V) WindowsFileAttributeViews.createDosView(this, followLinks);
+        if (view == AclFileAttributeView.class)
+            return (V) new WindowsAclFileAttributeView(this, followLinks);
+        if (view == FileOwnerAttributeView.class)
+            return (V) new FileOwnerAttributeViewImpl(
+                new WindowsAclFileAttributeView(this, followLinks));
+        if (view == NamedAttributeView.class)
+            return (V) new WindowsNamedAttributeView(this, followLinks);
+        return (V) null;
+    }
+
+
+    public FileAttributeView getFileAttributeView(String name, LinkOption... options) {
+        boolean followLinks = followLinks(options);
+        if (name.equals("basic"))
+            return WindowsFileAttributeViews.createBasicView(this, followLinks);
+        if (name.equals("dos"))
+            return WindowsFileAttributeViews.createDosView(this, followLinks);
+        if (name.equals("acl"))
+            return new WindowsAclFileAttributeView(this, followLinks);
+        if (name.equals("owner"))
+            return new FileOwnerAttributeViewImpl(
+                new WindowsAclFileAttributeView(this, followLinks));
+        if (name.equals("xattr"))
+            return new WindowsNamedAttributeView(this, followLinks);
+        return null;
+    }
+
+
+    public WindowsPath createDirectory(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkWrite();
+        WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs);
+        try {
+            CreateDirectory(getPathForWin32Calls(), sd.address());
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(this);
+        } finally {
+            sd.release();
+        }
+        return this;
+    }
+
+
+    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
+        }
+    }
+
+
+    public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+                                              FileAttribute<?>... attrs)
+         throws IOException
+    {
+        WindowsSecurityDescriptor sd =
+            WindowsSecurityDescriptor.fromAttribute(attrs);
+        try {
+            return WindowsChannelFactory
+                .newFileChannel(getPathForWin32Calls(),
+                                getPathForPermissionCheck(),
+                                options,
+                                sd.address());
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(this);
+            return null;  // keep compiler happy
+        } finally {
+            sd.release();
+        }
+    }
+
+
+    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();
+        }
+    }
+
+
+    public boolean isSameFile(FileRef obj) throws IOException {
+        if (this.equals(obj))
+            return true;
+        if (!(obj instanceof WindowsPath))  // includes null check
+            return false;
+        WindowsPath other = (WindowsPath)obj;
+
+        // check security manager access to both files
+        this.checkRead();
+        other.checkRead();
+
+        // open both files and see if they are the same
+        long h1 = 0L;
+        try {
+            h1 = this.openForReadAttributeAccess(true);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(this);
+        }
+        try {
+            WindowsFileAttributes attrs1 = null;
+            try {
+                attrs1 = WindowsFileAttributes.readAttributes(h1);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(this);
+            }
+            long h2 = 0L;
+            try {
+                h2 = other.openForReadAttributeAccess(true);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(other);
+            }
+            try {
+                WindowsFileAttributes attrs2 = null;
+                try {
+                    attrs2 = WindowsFileAttributes.readAttributes(h2);
+                } catch (WindowsException x) {
+                    x.rethrowAsIOException(other);
+                }
+                return WindowsFileAttributes.isSameFile(attrs1, attrs2);
+            } finally {
+                CloseHandle(h2);
+            }
+        } finally {
+            CloseHandle(h1);
+        }
+    }
+
+
+    public WindowsPath createSymbolicLink(Path obj, FileAttribute<?>... attrs)
+        throws IOException
+    {
+        if (!getFileSystem().supportsLinks()) {
+            throw new UnsupportedOperationException("Symbolic links not supported "
+                + "on this operating system");
+        }
+
+        WindowsPath target = checkPath(obj);
+
+        // no attributes allowed
+        if (attrs.length > 0) {
+            if (attrs[0] == null)
+                throw new NullPointerException();
+            throw new ProviderMismatchException();
+        }
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new LinkPermission("symbolic"));
+            this.checkWrite();
+        }
+
+        /**
+         * Throw I/O exception for the drive-relative case because Windows
+         * 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");
+        }
+
+        /*
+         * Windows treates symbolic links to directories differently than it
+         * does to other file types. For that reason we check if the exists and
+         * is a directory.
+         */
+        int flags = 0;
+        WindowsPath resolvedTarget =
+            WindowsPath.createFromNormalizedPath(getFileSystem(), resolve(target).path);
+        try {
+            if (WindowsFileAttributes.get(resolvedTarget, true).isDirectory())
+                flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
+        } catch (WindowsException x) {
+            // unable to access target so assume target is not a directory
+        }
+
+        // create the link
+        try {
+            CreateSymbolicLink(getPathForWin32Calls(),
+                               addPrefixIfNeeded(target.toString()),
+                               flags);
+        } catch (WindowsException x) {
+            if (x.lastError() == ERROR_INVALID_REPARSE_DATA) {
+                x.rethrowAsIOException(this, target);
+            } else {
+                x.rethrowAsIOException(this);
+            }
+        }
+        return this;
+    }
+
+
+    public Path createLink(Path obj) throws IOException {
+        WindowsPath existing = checkPath(obj);
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new LinkPermission("hard"));
+            this.checkWrite();
+            existing.checkWrite();
+        }
+
+        // create hard link
+        try {
+            CreateHardLink(this.getPathForWin32Calls(),
+                           existing.getPathForWin32Calls());
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(this, existing);
+        }
+
+        return this;
+    }
+
+
+    public WindowsPath readSymbolicLink() throws IOException {
+        if (!getFileSystem().supportsLinks()) {
+            throw new UnsupportedOperationException("symbolic links not supported");
+        }
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            FilePermission perm = new FilePermission(getPathForPermissionCheck(),
+                SecurityConstants.FILE_READLINK_ACTION);
+            AccessController.checkPermission(perm);
+        }
+
+        String target = WindowsLinkSupport.readLink(this);
+        return createFromNormalizedPath(getFileSystem(), target);
+    }
+
+
+    public URI toUri() {
+        return WindowsUriSupport.toUri(this);
+    }
+
+    // returns true if same drive letter
+    private static boolean isSameDrive(String root1, String root2) {
+        return Character.toUpperCase(root1.charAt(0)) ==
+               Character.toUpperCase(root2.charAt(0));
+    }
+
+
+    public WindowsPath toAbsolutePath() {
+        if (isAbsolute())
+            return this;
+
+        // permission check as per spec
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPropertyAccess("user.dir");
+        }
+
+        // result is the resolved path if the path is not drive-relative
+        if (type != WindowsPathType.DRIVE_RELATIVE)
+            return WindowsPath.createFromNormalizedPath(getFileSystem(), resolved);
+
+        // if the path is drive-relative and is relative to a drive other
+        // than the drive of the default directory then resolve against the
+        // working directory of that drive.
+        if (!isSameDrive(root, getFileSystem().defaultRoot())) {
+            try {
+                int dt = GetDriveType(root + "\\");
+                if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR)
+                    throw new WindowsException("");
+                String wd = GetFullPathName(root + ".");
+                String result = wd;
+                if (wd.endsWith("\\")) {
+                    result += path.substring(root.length());
+                } else {
+                    if (path.length() > root.length())
+                        result += "\\" + path.substring(root.length());
+                }
+                return WindowsPath.createFromNormalizedPath(getFileSystem(), result);
+            } catch (WindowsException x) {
+                IOException ioe = new IOException("Unable to get working " +
+                    "directory of drive '" +
+                    Character.toUpperCase(root.charAt(0)) + "'");
+                throw new java.io.IOError(ioe);
+            }
+        } else {
+            // relative to default directory
+            String remaining = path.substring(root.length());
+            String defaultDirectory = getFileSystem().defaultDirectory();
+            String result;
+            if (defaultDirectory.endsWith("\\")) {
+                result = defaultDirectory + remaining;
+            } else {
+                result = defaultDirectory + "\\" + remaining;
+            }
+            return createFromNormalizedPath(getFileSystem(), result);
+        }
+    }
+
+
+    public WindowsPath toRealPath(boolean resolveLinks) throws IOException {
+        checkRead();
+        String rp = WindowsLinkSupport.getRealPath(this, resolveLinks);
+        return createFromNormalizedPath(getFileSystem(), rp);
+    }
+
+
+    public boolean isHidden() throws IOException {
+        checkRead();
+        WindowsFileAttributes attrs = null;
+        try {
+            attrs = WindowsFileAttributes.get(this, true);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(this);
+        }
+        // DOS hidden attribute not meaningful when set on directories
+        if (attrs.isDirectory())
+            return false;
+        return attrs.isHidden();
+    }
+
+
+    public WatchKey register(WatchService watcher,
+                             WatchEvent.Kind<?>[] events,
+                             WatchEvent.Modifier... modifiers)
+        throws IOException
+    {
+        if (watcher == null)
+            throw new NullPointerException();
+        if (!(watcher instanceof WindowsWatchService))
+            throw new ProviderMismatchException();
+
+        // When a security manager is set then we need to make a defensive
+        // copy of the modifiers and check for the Windows specific FILE_TREE
+        // modifier. When the modifier is present then check that permission
+        // has been granted recursively.
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            boolean watchSubtree = false;
+            int ml = modifiers.length;
+            if (ml > 0) {
+                WatchEvent.Modifier[] copy = new WatchEvent.Modifier[ml];
+                System.arraycopy(modifiers, 0, copy, 0, ml);
+                modifiers = copy;
+                int i=0;
+                while (i < ml) {
+                    if (modifiers[i++] == ExtendedWatchEventModifier.FILE_TREE) {
+                        watchSubtree = true;
+                        break;
+                    }
+                }
+            }
+            String s = getPathForPermissionCheck();
+            sm.checkRead(s);
+            if (watchSubtree)
+                sm.checkRead(s + "\\-");
+        }
+
+        return ((WindowsWatchService)watcher).register(this, events, modifiers);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2007-2008 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.InvalidPathException;
+
+/**
+ * A parser of Windows path strings
+ */
+
+class WindowsPathParser {
+    private WindowsPathParser() { }
+
+    /**
+     * The result of a parse operation
+     */
+    static class Result {
+        private final WindowsPathType type;
+        private final String root;
+        private final String path;
+
+        Result(WindowsPathType type, String root, String path) {
+            this.type = type;
+            this.root = root;
+            this.path = path;
+        }
+
+        /**
+         * The path type
+         */
+        WindowsPathType type() {
+            return type;
+        }
+
+        /**
+         * The root component
+         */
+        String root() {
+            return root;
+        }
+
+        /**
+         * The normalized path (includes root)
+         */
+        String path() {
+            return path;
+        }
+    }
+
+    /**
+     * Parses the given input as a Windows path
+     */
+    static Result parse(String input) {
+        if (input == null || input.length() == 0)
+            throw new InvalidPathException(input, "Empty or null path");
+        return parse(input, true);
+    }
+
+    /**
+     * Parses the given input as a Windows path where it is known that the
+     * path is already normalized.
+     */
+    static Result parseNormalizedPath(String input) {
+        return parse(input, false);
+    }
+
+    /**
+     * Parses the given input as a Windows path.
+     *
+     * @param   requireToNormalize
+     *          Indicates if the path requires to be normalized
+     */
+    private static Result parse(String input, boolean requireToNormalize) {
+        String root = "";
+        WindowsPathType type = null;
+
+        int len = input.length();
+        int off = 0;
+        if (len > 1) {
+            char c0 = input.charAt(0);
+            char c1 = input.charAt(1);
+            char c = 0;
+            int next = 2;
+            if (isSlash(c0) && isSlash(c1)) {
+                // UNC: We keep the first two slash, collapse all the
+                // following, then take the hostname and share name out,
+                // meanwhile collapsing all the redundant slashes.
+                type = WindowsPathType.UNC;
+                off = nextNonSlash(input, next, len);
+                next = nextSlash(input, off, len);
+                if (off == next)
+                    throw new InvalidPathException(input, "UNC path is missing hostname");
+                String host = input.substring(off, next);  //host
+                off = nextNonSlash(input, next, len);
+                next = nextSlash(input, off, len);
+                if (off == next)
+                    throw new InvalidPathException(input, "UNC path is missing sharename");
+                root = "\\\\" + host + "\\" + input.substring(off, next) + "\\";
+                off = next;
+            } else {
+                if (isLetter(c0) && c1 == ':') {
+                    root = input.substring(0, 2);
+                    if (len > 2 && isSlash(input.charAt(2))) {
+                        off = 3;
+                        root += "\\";
+                        type = WindowsPathType.ABSOLUTE;
+                    } else {
+                        off = 2;
+                        type = WindowsPathType.DRIVE_RELATIVE;
+                    }
+                }
+            }
+        }
+        if (off == 0) {
+            if (isSlash(input.charAt(0))) {
+                type = WindowsPathType.DIRECTORY_RELATIVE;
+                root = "\\";
+            } else {
+                type = WindowsPathType.RELATIVE;
+            }
+        }
+
+        if (requireToNormalize) {
+            StringBuilder sb = new StringBuilder(input.length());
+            sb.append(root);
+            return new Result(type, root, normalize(sb, input, off));
+        } else {
+            return new Result(type, root, input);
+        }
+    }
+
+    /**
+     * Remove redundant slashes from the rest of the path, forcing all slashes
+     * into the preferred slash.
+    */
+    private static String normalize(StringBuilder sb, String path, int off) {
+        int len = path.length();
+        off = nextNonSlash(path, off, len);
+        int start = off;
+        char lastC = 0;
+        while (off < len) {
+            char c = path.charAt(off);
+            if (isSlash(c)) {
+                if (lastC == ' ')
+                    throw new InvalidPathException(path,
+                                                   "Trailing char <" + lastC + ">",
+                                                   off - 1);
+                sb.append(path, start, off);
+                off = nextNonSlash(path, off, len);
+                if (off != len)   //no slash at the end of normalized path
+                    sb.append('\\');
+                start = off;
+            } else {
+                if (isInvalidPathChar(c))
+                    throw new InvalidPathException(path,
+                                                   "Illegal char <" + c + ">",
+                                                   off);
+                lastC = c;
+                off++;
+            }
+        }
+        if (start != off) {
+            if (lastC == ' ')
+                throw new InvalidPathException(path,
+                                               "Trailing char <" + lastC + ">",
+                                               off - 1);
+            sb.append(path, start, off);
+        }
+        return sb.toString();
+    }
+
+    private static final boolean isSlash(char c) {
+        return (c == '\\') || (c == '/');
+    }
+
+    private static final int nextNonSlash(String path, int off, int end) {
+        while (off < end && isSlash(path.charAt(off))) { off++; }
+        return off;
+    }
+
+    private static final int nextSlash(String path, int off, int end) {
+        char c;
+        while (off < end && !isSlash(c=path.charAt(off))) {
+            if (isInvalidPathChar(c))
+                throw new InvalidPathException(path,
+                                               "Illegal character [" + c + "] in path",
+                                               off);
+            off++;
+        }
+        return off;
+    }
+
+    private static final boolean isLetter(char c) {
+        return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
+    }
+
+    // Reserved characters for window path name
+    private static final String reservedChars = "<>:\"|?*";
+    private static final boolean isInvalidPathChar(char ch) {
+        return ch < '\u0020' || reservedChars.indexOf(ch) != -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007-2008 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;
+
+/**
+ * A type safe enum of Windows path types.
+ */
+
+enum WindowsPathType {
+    ABSOLUTE,                   //  C:\foo
+    UNC,                        //  \\server\share\foo
+    RELATIVE,                   //  foo
+    DIRECTORY_RELATIVE,         //  \foo
+    DRIVE_RELATIVE              //  C:foo
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2007-2008 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 static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * Security related utility methods.
+ */
+
+class WindowsSecurity {
+    private WindowsSecurity() { }
+
+    // opens process token for given access
+    private static long openProcessToken(int access) {
+        try {
+            return OpenProcessToken(GetCurrentProcess(), access);
+        } catch (WindowsException x) {
+            return 0L;
+        }
+    }
+
+    /**
+     * Returns the access token for this process with TOKEN_DUPLICATE access
+     */
+    static final long processTokenWithDuplicateAccess =
+        openProcessToken(TOKEN_DUPLICATE);
+
+    /**
+     * Returns the access token for this process with TOKEN_QUERY access
+     */
+    static final long processTokenWithQueryAccess =
+        openProcessToken(TOKEN_QUERY);
+
+    /**
+     * Returned by enablePrivilege when code may require a given privilege.
+     * The drop method should be invoked after the operation completes so as
+     * to revert the privilege.
+     */
+    static interface Privilege {
+        void drop();
+    }
+
+    /**
+     * Attempts to enable the given privilege for this method.
+     */
+    static Privilege enablePrivilege(String priv) {
+        final long pLuid;
+        try {
+            pLuid = LookupPrivilegeValue(priv);
+        } catch (WindowsException x) {
+            // indicates bug in caller
+            throw new AssertionError(x);
+        }
+
+        long hToken = 0L;
+        boolean impersontating = false;
+        boolean elevated = false;
+        try {
+            hToken = OpenThreadToken(GetCurrentThread(),
+                                     TOKEN_ADJUST_PRIVILEGES, false);
+            if (hToken == 0L && processTokenWithDuplicateAccess != 0L) {
+                hToken = DuplicateTokenEx(processTokenWithDuplicateAccess,
+                    (TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE));
+                SetThreadToken(0L, hToken);
+                impersontating = true;
+            }
+
+            if (hToken != 0L) {
+                AdjustTokenPrivileges(hToken, pLuid, SE_PRIVILEGE_ENABLED);
+                elevated = true;
+            }
+        } catch (WindowsException x) {
+            // nothing to do, privilege not enabled
+        }
+
+        final long token = hToken;
+        final boolean stopImpersontating = impersontating;
+        final boolean needToRevert = elevated;
+
+        return new Privilege() {
+
+            public void drop() {
+                try {
+                    if (stopImpersontating) {
+                        SetThreadToken(0L, 0L);
+                    } else {
+                        if (needToRevert) {
+                            AdjustTokenPrivileges(token, pLuid, 0);
+                        }
+                    }
+                } catch (WindowsException x) {
+                    // should not happen
+                    throw new AssertionError(x);
+                }
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2007-2008 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.ProviderMismatchException;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/**
+ * A SecurityDescriptor for use when setting a file's ACL or creating a file
+ * with an initial ACL.
+ */
+
+class WindowsSecurityDescriptor {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    /**
+     * typedef struct _ACL {
+     *     BYTE  AclRevision;
+     *     BYTE  Sbz1;
+     *     WORD  AclSize;
+     *     WORD  AceCount;
+     *     WORD  Sbz2;
+     * } ACL;
+     *
+     * typedef struct _ACE_HEADER {
+     *     BYTE AceType;
+     *     BYTE AceFlags;
+     *     WORD AceSize;
+     * } ACE_HEADER;
+     *
+     * typedef struct _ACCESS_ALLOWED_ACE {
+     *     ACE_HEADER Header;
+     *     ACCESS_MASK Mask;
+     *     DWORD SidStart;
+     * } ACCESS_ALLOWED_ACE;
+     *
+     * typedef struct _ACCESS_DENIED_ACE {
+     *     ACE_HEADER Header;
+     *     ACCESS_MASK Mask;
+     *     DWORD SidStart;
+     * } ACCESS_DENIED_ACE;
+     *
+     * typedef struct _SECURITY_DESCRIPTOR {
+     *     BYTE  Revision;
+     *     BYTE  Sbz1;
+     *     SECURITY_DESCRIPTOR_CONTROL Control;
+     *     PSID Owner;
+     *     PSID Group;
+     *     PACL Sacl;
+     *     PACL Dacl;
+     * } SECURITY_DESCRIPTOR;
+     */
+    private static final short SIZEOF_ACL                   = 8;
+    private static final short SIZEOF_ACCESS_ALLOWED_ACE    = 12;
+    private static final short SIZEOF_ACCESS_DENIED_ACE     = 12;
+    private static final short SIZEOF_SECURITY_DESCRIPTOR   = 20;
+
+    private static final short OFFSETOF_TYPE                = 0;
+    private static final short OFFSETOF_FLAGS               = 1;
+    private static final short OFFSETOF_ACCESS_MASK         = 4;
+    private static final short OFFSETOF_SID                 = 8;
+
+    // null security descriptor
+    private static final WindowsSecurityDescriptor NULL_DESCRIPTOR =
+        new WindowsSecurityDescriptor();
+
+    // native resources
+    private final List<Long> sidList;
+    private final NativeBuffer aclBuffer, sdBuffer;
+
+    /**
+     * Creates the "null" SecurityDescriptor
+     */
+    private WindowsSecurityDescriptor() {
+        this.sidList = null;
+        this.aclBuffer = null;
+        this.sdBuffer = null;
+    }
+
+    /**
+     * Creates a SecurityDescriptor from the given ACL
+     */
+    private WindowsSecurityDescriptor(List<AclEntry> acl) throws IOException {
+        boolean initialized = false;
+
+        // SECURITY: need to copy list in case size changes during processing
+        acl = new ArrayList<AclEntry>(acl);
+
+        // list of SIDs
+        sidList = new ArrayList<Long>(acl.size());
+        try {
+            // initial size of ACL
+            int size = SIZEOF_ACL;
+
+            // get the SID for each entry
+            for (AclEntry entry: acl) {
+                UserPrincipal user = entry.principal();
+                if (!(user instanceof WindowsUserPrincipals.User))
+                    throw new ProviderMismatchException();
+                String sidString = ((WindowsUserPrincipals.User)user).sidString();
+                try {
+                    long pSid = ConvertStringSidToSid(sidString);
+                    sidList.add(pSid);
+
+                    // increase size to allow for entry
+                    size += GetLengthSid(pSid) +
+                        Math.max(SIZEOF_ACCESS_ALLOWED_ACE, SIZEOF_ACCESS_DENIED_ACE);
+
+                } catch (WindowsException x) {
+                    throw new IOException("Failed to get SID for " + user.getName()
+                        + ": " + x.errorString());
+                }
+            }
+
+            // allocate memory for the ACL
+            aclBuffer = NativeBuffers.getNativeBuffer(size);
+            sdBuffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR);
+
+            InitializeAcl(aclBuffer.address(), size);
+
+            // Add entry ACE to the ACL
+            int i = 0;
+            while (i < acl.size()) {
+                AclEntry entry = acl.get(i);
+                long pSid = sidList.get(i);
+                try {
+                    encode(entry, pSid, aclBuffer.address());
+                } catch (WindowsException x) {
+                    throw new IOException("Failed to encode ACE: " +
+                        x.errorString());
+                }
+                i++;
+            }
+
+            // initialize security descriptor and set DACL
+            InitializeSecurityDescriptor(sdBuffer.address());
+            SetSecurityDescriptorDacl(sdBuffer.address(), aclBuffer.address());
+            initialized = true;
+        } catch (WindowsException x) {
+            throw new IOException(x.getMessage());
+        } finally {
+            // release resources if not completely initialized
+            if (!initialized)
+                release();
+        }
+    }
+
+    /**
+     * Releases memory associated with SecurityDescriptor
+     */
+    void release() {
+        if (sdBuffer != null)
+            sdBuffer.release();
+        if (aclBuffer != null)
+            aclBuffer.release();
+        if (sidList != null) {
+            // release memory for SIDs
+            for (Long sid: sidList) {
+                LocalFree(sid);
+            }
+        }
+    }
+
+    /**
+     * Returns address of SecurityDescriptor
+     */
+    long address() {
+        return (sdBuffer == null) ? 0L : sdBuffer.address();
+    }
+
+    // decode Windows ACE to NFSv4 AclEntry
+    private static AclEntry decode(long aceAddress)
+        throws IOException
+    {
+        // map type
+        byte aceType = unsafe.getByte(aceAddress + OFFSETOF_TYPE);
+        if (aceType != ACCESS_ALLOWED_ACE_TYPE && aceType != ACCESS_DENIED_ACE_TYPE)
+            return null;
+        AclEntryType type;
+        if (aceType == ACCESS_ALLOWED_ACE_TYPE) {
+            type = AclEntryType.ALLOW;
+        } else {
+            type = AclEntryType.DENY;
+        }
+
+        // map flags
+        byte aceFlags = unsafe.getByte(aceAddress + OFFSETOF_FLAGS);
+        Set<AclEntryFlag> flags = new HashSet<AclEntryFlag>();
+        if ((aceFlags & OBJECT_INHERIT_ACE) != 0)
+            flags.add(AclEntryFlag.FILE_INHERIT);
+        if ((aceFlags & CONTAINER_INHERIT_ACE) != 0)
+            flags.add(AclEntryFlag.DIRECTORY_INHERIT);
+        if ((aceFlags & NO_PROPAGATE_INHERIT_ACE) != 0)
+            flags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
+        if ((aceFlags & INHERIT_ONLY_ACE) != 0)
+            flags.add(AclEntryFlag.INHERIT_ONLY);
+
+        // map access mask
+        int mask = unsafe.getInt(aceAddress + OFFSETOF_ACCESS_MASK);
+        Set<AclEntryPermission> perms = new HashSet<AclEntryPermission>();
+        if ((mask & FILE_READ_DATA) > 0)
+            perms.add(AclEntryPermission.READ_DATA);
+        if ((mask & FILE_WRITE_DATA) > 0)
+            perms.add(AclEntryPermission.WRITE_DATA);
+        if ((mask & FILE_APPEND_DATA ) > 0)
+            perms.add(AclEntryPermission.APPEND_DATA);
+        if ((mask & FILE_READ_EA) > 0)
+            perms.add(AclEntryPermission.READ_NAMED_ATTRS);
+        if ((mask & FILE_WRITE_EA) > 0)
+            perms.add(AclEntryPermission.WRITE_NAMED_ATTRS);
+        if ((mask & FILE_EXECUTE) > 0)
+            perms.add(AclEntryPermission.EXECUTE);
+        if ((mask & FILE_DELETE_CHILD ) > 0)
+            perms.add(AclEntryPermission.DELETE_CHILD);
+        if ((mask & FILE_READ_ATTRIBUTES) > 0)
+            perms.add(AclEntryPermission.READ_ATTRIBUTES);
+        if ((mask & FILE_WRITE_ATTRIBUTES) > 0)
+            perms.add(AclEntryPermission.WRITE_ATTRIBUTES);
+        if ((mask & DELETE) > 0)
+            perms.add(AclEntryPermission.DELETE);
+        if ((mask & READ_CONTROL) > 0)
+            perms.add(AclEntryPermission.READ_ACL);
+        if ((mask & WRITE_DAC) > 0)
+            perms.add(AclEntryPermission.WRITE_ACL);
+        if ((mask & WRITE_OWNER) > 0)
+            perms.add(AclEntryPermission.WRITE_OWNER);
+        if ((mask & SYNCHRONIZE) > 0)
+            perms.add(AclEntryPermission.SYNCHRONIZE);
+
+        // lookup SID to create UserPrincipal
+        long sidAddress = aceAddress + OFFSETOF_SID;
+        UserPrincipal user = WindowsUserPrincipals.fromSid(sidAddress);
+
+        return AclEntry.newBuilder()
+            .setType(type)
+            .setPrincipal(user)
+            .setFlags(flags).setPermissions(perms).build();
+    }
+
+    // encode NFSv4 AclEntry as Windows ACE to given ACL
+    private static void encode(AclEntry ace, long sidAddress, long aclAddress)
+        throws WindowsException
+    {
+        // ignore non-allow/deny entries for now
+        if (ace.type() != AclEntryType.ALLOW && ace.type() != AclEntryType.DENY)
+            return;
+        boolean allow = (ace.type() == AclEntryType.ALLOW);
+
+        // map access mask
+        Set<AclEntryPermission> aceMask = ace.permissions();
+        int mask = 0;
+        if (aceMask.contains(AclEntryPermission.READ_DATA))
+            mask |= FILE_READ_DATA;
+        if (aceMask.contains(AclEntryPermission.WRITE_DATA))
+            mask |= FILE_WRITE_DATA;
+        if (aceMask.contains(AclEntryPermission.APPEND_DATA))
+            mask |= FILE_APPEND_DATA;
+        if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS))
+            mask |= FILE_READ_EA;
+        if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS))
+            mask |= FILE_WRITE_EA;
+        if (aceMask.contains(AclEntryPermission.EXECUTE))
+            mask |= FILE_EXECUTE;
+        if (aceMask.contains(AclEntryPermission.DELETE_CHILD))
+            mask |= FILE_DELETE_CHILD;
+        if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES))
+            mask |= FILE_READ_ATTRIBUTES;
+        if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES))
+            mask |= FILE_WRITE_ATTRIBUTES;
+        if (aceMask.contains(AclEntryPermission.DELETE))
+            mask |= DELETE;
+        if (aceMask.contains(AclEntryPermission.READ_ACL))
+            mask |= READ_CONTROL;
+        if (aceMask.contains(AclEntryPermission.WRITE_ACL))
+            mask |= WRITE_DAC;
+        if (aceMask.contains(AclEntryPermission.WRITE_OWNER))
+            mask |= WRITE_OWNER;
+        if (aceMask.contains(AclEntryPermission.SYNCHRONIZE))
+            mask |= SYNCHRONIZE;
+
+        // map flags
+        Set<AclEntryFlag> aceFlags = ace.flags();
+        byte flags = 0;
+        if (aceFlags.contains(AclEntryFlag.FILE_INHERIT))
+            flags |= OBJECT_INHERIT_ACE;
+        if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT))
+            flags |= CONTAINER_INHERIT_ACE;
+        if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
+            flags |= NO_PROPAGATE_INHERIT_ACE;
+        if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY))
+            flags |= INHERIT_ONLY_ACE;
+
+        if (allow) {
+            AddAccessAllowedAceEx(aclAddress, flags, mask, sidAddress);
+        } else {
+            AddAccessDeniedAceEx(aclAddress, flags, mask, sidAddress);
+        }
+    }
+
+    /**
+     * Creates a security descriptor with a DACL representing the given ACL.
+     */
+    static WindowsSecurityDescriptor create(List<AclEntry> acl)
+        throws IOException
+    {
+        return new WindowsSecurityDescriptor(acl);
+    }
+
+    /**
+     * Processes the array of attributes looking for the attribute "acl:acl".
+     * Returns security descriptor representing the ACL or the "null" security
+     * descriptor if the attribute is not in the array.
+     */
+    @SuppressWarnings("unchecked")
+    static WindowsSecurityDescriptor fromAttribute(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        WindowsSecurityDescriptor sd = NULL_DESCRIPTOR;
+        for (FileAttribute<?> attr: attrs) {
+            // if more than one ACL specified then last one wins
+            if (sd != NULL_DESCRIPTOR)
+                sd.release();
+            if (attr == null)
+                throw new NullPointerException();
+            if (attr.name().equals("acl:acl")) {
+                List<AclEntry> acl = (List<AclEntry>)attr.value();
+                sd = new WindowsSecurityDescriptor(acl);
+            } else {
+                throw new UnsupportedOperationException("'" + attr.name() +
+                   "' not supported as initial attribute");
+            }
+        }
+        return sd;
+    }
+
+    /**
+     * Extracts DACL from security descriptor.
+     */
+    static List<AclEntry> getAcl(long pSecurityDescriptor) throws IOException {
+        // get address of DACL
+        long aclAddress = GetSecurityDescriptorDacl(pSecurityDescriptor);
+
+        // get ACE count
+        int aceCount = 0;
+        if (aclAddress == 0L) {
+            // no ACEs
+            aceCount = 0;
+        } else {
+            AclInformation aclInfo = GetAclInformation(aclAddress);
+            aceCount = aclInfo.aceCount();
+        }
+        ArrayList<AclEntry> result = new ArrayList<AclEntry>(aceCount);
+
+        // decode each of the ACEs to AclEntry objects
+        for (int i=0; i<aceCount; i++) {
+            long aceAddress = GetAce(aclAddress, i);
+            AclEntry entry = decode(aceAddress);
+            if (entry != null)
+                result.add(entry);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUriSupport.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2007-2008 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.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Utility methods to convert between Path and URIs.
+ */
+
+class WindowsUriSupport {
+    private WindowsUriSupport() {
+    }
+
+    // suffix for IPv6 literal address
+    private static final String IPV6_LITERAL_SUFFIX = ".ipv6-literal.net";
+
+    /**
+     * Returns URI to represent the given (absolute) path
+     */
+    private static URI toUri(String path, boolean isUnc, boolean addSlash) {
+        String uriHost;
+        String uriPath;
+
+        if (isUnc) {
+            int slash = path.indexOf('\\', 2);
+            uriHost = path.substring(2, slash);
+            uriPath = path.substring(slash).replace('\\', '/');
+
+            // handle IPv6 literal addresses
+            // 1. drop .ivp6-literal.net
+            // 2. replace "-" with ":"
+            // 3. replace "s" with "%" (zone/scopeID delimiter)
+            if (uriHost.endsWith(IPV6_LITERAL_SUFFIX)) {
+                uriHost = uriHost
+                    .substring(0, uriHost.length() - IPV6_LITERAL_SUFFIX.length())
+                    .replace('-', ':')
+                    .replace('s', '%');
+            }
+        } else {
+            uriHost = "";
+            uriPath = "/" + path.replace('\\', '/');
+        }
+
+        // append slash if known to be directory
+        if (addSlash)
+            uriPath += "/";
+
+        // return file:///C:/My%20Documents or file://server/share/foo
+        try {
+            return new URI("file", uriHost, uriPath, null);
+        } catch (URISyntaxException x) {
+            if (!isUnc)
+                throw new AssertionError(x);
+        }
+
+        // if we get here it means we've got a UNC with reserved characters
+        // in the server name. The authority component cannot contain escaped
+        // octets so fallback to encoding the server name into the URI path
+        // component.
+        uriPath = "//" + path.replace('\\', '/');
+        if (addSlash)
+            uriPath += "/";
+        try {
+            return new URI("file", null, uriPath, null);
+        } catch (URISyntaxException x) {
+            throw new AssertionError(x);
+        }
+    }
+
+    /**
+     * Converts given Path to a URI
+     */
+    static URI toUri(WindowsPath path) {
+        path = path.toAbsolutePath();
+        String s = path.toString();
+
+        // trailing slash will be added if file is a directory. Skip check if
+        // already have trailing space
+        boolean addSlash = false;
+        if (!s.endsWith("\\")) {
+            try {
+                 addSlash = WindowsFileAttributes.get(path, true).isDirectory();
+            } catch (WindowsException x) {
+            }
+        }
+
+        return toUri(s, path.isUnc(), addSlash);
+    }
+
+    /**
+     * Converts given URI to a Path
+     */
+    static WindowsPath fromUri(WindowsFileSystem fs, URI uri) {
+        if (!uri.isAbsolute())
+            throw new IllegalArgumentException("URI is not absolute");
+        if (uri.isOpaque())
+            throw new IllegalArgumentException("URI is not hierarchical");
+        String scheme = uri.getScheme();
+        if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
+            throw new IllegalArgumentException("URI scheme is not \"file\"");
+        if (uri.getFragment() != null)
+            throw new IllegalArgumentException("URI has a fragment component");
+        if (uri.getQuery() != null)
+            throw new IllegalArgumentException("URI has a query component");
+        String path = uri.getPath();
+        if (path.equals(""))
+            throw new IllegalArgumentException("URI path component is empty");
+
+        // UNC
+        String auth = uri.getAuthority();
+        if (auth != null && !auth.equals("")) {
+            String host = uri.getHost();
+            if (host == null)
+                throw new IllegalArgumentException("URI authority component has undefined host");
+            if (uri.getUserInfo() != null)
+                throw new IllegalArgumentException("URI authority component has user-info");
+            if (uri.getPort() != -1)
+                throw new IllegalArgumentException("URI authority component has port number");
+
+            // IPv6 literal
+            // 1. drop enclosing brackets
+            // 2. replace ":" with "-"
+            // 3. replace "%" with "s" (zone/scopeID delimiter)
+            // 4. Append .ivp6-literal.net
+            if (host.startsWith("[")) {
+                host = host.substring(1, host.length()-1)
+                           .replace(':', '-')
+                           .replace('%', 's');
+                host += IPV6_LITERAL_SUFFIX;
+            }
+
+            // reconstitute the UNC
+            path = "\\\\" + host + path;
+        } else {
+            if ((path.length() > 2) && (path.charAt(2) == ':')) {
+                // "/c:/foo" --> "c:/foo"
+                path = path.substring(1);
+            }
+        }
+        return WindowsPath.parse(fs, path);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2007-2008 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 static sun.nio.fs.WindowsConstants.*;
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+
+class WindowsUserPrincipals {
+    private WindowsUserPrincipals() { }
+
+    static class User implements UserPrincipal {
+        // String representation of SID
+        private final String sidString;
+
+        // SID type
+        private final int sidType;
+
+        // Account name (if available) or SID
+        private final String accountName;
+
+        User(String sidString, int sidType, String accountName) {
+            this.sidString = sidString;
+            this.sidType = sidType;
+            this.accountName = accountName;
+        }
+
+        // package-private
+        String sidString() {
+            return sidString;
+        }
+
+
+        public String getName() {
+            return accountName;
+        }
+
+
+        public String toString() {
+            String type;
+            switch (sidType) {
+                case SidTypeUser : type = "User"; break;
+                case SidTypeGroup : type = "Group"; break;
+                case SidTypeDomain : type = "Domain"; break;
+                case SidTypeAlias : type = "Alias"; break;
+                case SidTypeWellKnownGroup : type = "Well-known group"; break;
+                case SidTypeDeletedAccount : type = "Deleted"; break;
+                case SidTypeInvalid : type = "Invalid"; break;
+                case SidTypeComputer : type = "Computer"; break;
+                default: type = "Unknown";
+            }
+            return accountName + " (" + type + ")";
+        }
+
+
+        public boolean equals(Object obj) {
+            if (obj == this)
+                return true;
+            if (!(obj instanceof WindowsUserPrincipals.User))
+                return false;
+            WindowsUserPrincipals.User other = (WindowsUserPrincipals.User)obj;
+            return this.sidString.equals(other.sidString);
+        }
+
+
+        public int hashCode() {
+            return sidString.hashCode();
+        }
+    }
+
+    static class Group extends User implements GroupPrincipal {
+        Group(String sidString, int sidType, String accountName) {
+            super(sidString, sidType, accountName);
+        }
+    }
+
+    static UserPrincipal fromSid(long sidAddress) throws IOException {
+        String sidString;
+        try {
+            sidString = ConvertSidToStringSid(sidAddress);
+            if (sidString == null) {
+                // pre-Windows XP system?
+                throw new AssertionError();
+            }
+        } catch (WindowsException x) {
+            throw new IOException("Unable to convert SID to String: " +
+                x.errorString());
+        }
+
+        // lookup account; if not available then use the SID as the name
+        Account account = null;
+        String name;
+        try {
+            account = LookupAccountSid(sidAddress);
+            name = account.domain() + "\\" + account.name();
+        } catch (WindowsException x) {
+            name = sidString;
+        }
+
+        int sidType = (account == null) ? SidTypeUnknown : account.use();
+        if ((sidType == SidTypeGroup) ||
+            (sidType == SidTypeWellKnownGroup) ||
+            (sidType == SidTypeAlias)) // alias for local group
+        {
+            return new Group(sidString, sidType, name);
+        } else {
+            return new User(sidString, sidType, name);
+        }
+    }
+
+    static UserPrincipal lookup(String name) throws IOException {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("lookupUserInformation"));
+        }
+
+        // invoke LookupAccountName to get buffer size needed for SID
+        int size = 0;
+        try {
+            size = LookupAccountName(name, 0L, 0);
+        } catch (WindowsException x) {
+            if (x.lastError() == ERROR_NONE_MAPPED)
+                throw new UserPrincipalNotFoundException(name);
+            throw new IOException(name + ": " + x.errorString());
+        }
+        assert size > 0;
+
+        // allocate buffer and re-invoke LookupAccountName get SID
+        NativeBuffer sidBuffer = NativeBuffers.getNativeBuffer(size);
+        try {
+            int newSize = LookupAccountName(name, sidBuffer.address(), size);
+            if (newSize != size) {
+                // can this happen?
+                throw new AssertionError("SID change during lookup");
+            }
+
+            // return user principal
+            return fromSid(sidBuffer.address());
+        } catch (WindowsException x) {
+            throw new IOException(name + ": " + x.errorString());
+        } finally {
+            sidBuffer.release();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2007-2008 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 java.io.IOException;
+import java.util.*;
+import com.sun.nio.file.ExtendedWatchEventModifier;
+import sun.misc.Unsafe;
+
+import static sun.nio.fs.WindowsNativeDispatcher.*;
+import static sun.nio.fs.WindowsConstants.*;
+
+/*
+ * Win32 implementation of WatchService based on ReadDirectoryChangesW.
+ */
+
+class WindowsWatchService
+    extends AbstractWatchService
+{
+    private final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // background thread to service I/O completion port
+    private final Poller poller;
+
+    /**
+     * Creates an I/O completion port and a daemon thread to service it
+     */
+    WindowsWatchService(WindowsFileSystem fs) throws IOException {
+        // create I/O completion port
+        long port = 0L;
+        try {
+            port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0);
+        } catch (WindowsException x) {
+            throw new IOException(x.getMessage());
+        }
+
+        this.poller = new Poller(fs, this, port);
+        this.poller.start();
+    }
+
+
+    WatchKey register(Path path,
+                      WatchEvent.Kind<?>[] events,
+                      WatchEvent.Modifier... modifiers)
+         throws IOException
+    {
+        // delegate to poller
+        return poller.register(path, events, modifiers);
+    }
+
+
+    void implClose() throws IOException {
+        // delegate to poller
+        poller.close();
+    }
+
+    /**
+     * Windows implementation of WatchKey.
+     */
+    private class WindowsWatchKey extends AbstractWatchKey {
+        // file key (used to detect existing registrations)
+        private FileKey fileKey;
+
+        // handle to directory
+        private volatile long handle = INVALID_HANDLE_VALUE;
+
+        // interest events
+        private Set<? extends WatchEvent.Kind<?>> events;
+
+        // subtree
+        private boolean watchSubtree;
+
+        // buffer for change events
+        private NativeBuffer buffer;
+
+        // pointer to bytes returned (in buffer)
+        private long countAddress;
+
+        // pointer to overlapped structure (in buffer)
+        private long overlappedAddress;
+
+        // completion key (used to map I/O completion to WatchKey)
+        private int completionKey;
+
+        WindowsWatchKey(AbstractWatchService watcher, FileKey fileKey) {
+            super(watcher);
+            this.fileKey = fileKey;
+        }
+
+        WindowsWatchKey init(long handle,
+                             Set<? extends WatchEvent.Kind<?>> events,
+                             boolean watchSubtree,
+                             NativeBuffer buffer,
+                             long countAddress,
+                             long overlappedAddress,
+                             int completionKey)
+        {
+            this.handle = handle;
+            this.events = events;
+            this.watchSubtree = watchSubtree;
+            this.buffer = buffer;
+            this.countAddress = countAddress;
+            this.overlappedAddress = overlappedAddress;
+            this.completionKey = completionKey;
+            return this;
+        }
+
+        long handle() {
+            return handle;
+        }
+
+        Set<? extends WatchEvent.Kind<?>> events() {
+            return events;
+        }
+
+        void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
+            this.events = events;
+        }
+
+        boolean watchSubtree() {
+            return watchSubtree;
+        }
+
+        NativeBuffer buffer() {
+            return buffer;
+        }
+
+        long countAddress() {
+            return countAddress;
+        }
+
+        long overlappedAddress() {
+            return overlappedAddress;
+        }
+
+        FileKey fileKey() {
+            return fileKey;
+        }
+
+        int completionKey() {
+            return completionKey;
+        }
+
+        // close directory and release buffer
+        void releaseResources() {
+            CloseHandle(handle);
+            buffer.cleaner().clean();
+        }
+
+        // Invalidate key by closing directory and releasing buffer
+        void invalidate() {
+            releaseResources();
+            handle = INVALID_HANDLE_VALUE;
+            buffer = null;
+            countAddress = 0;
+            overlappedAddress = 0;
+        }
+
+
+        public boolean isValid() {
+            return handle != INVALID_HANDLE_VALUE;
+        }
+
+
+        public void cancel() {
+            if (isValid()) {
+                // delegate to poller
+                poller.cancel(this);
+            }
+        }
+    }
+
+    // file key to unique identify (open) directory
+    private static class FileKey {
+        private final int volSerialNumber;
+        private final int fileIndexHigh;
+        private final int fileIndexLow;
+
+        FileKey(int volSerialNumber, int fileIndexHigh, int fileIndexLow) {
+            this.volSerialNumber = volSerialNumber;
+            this.fileIndexHigh = fileIndexHigh;
+            this.fileIndexLow = fileIndexLow;
+        }
+
+
+        public int hashCode() {
+            return volSerialNumber ^ fileIndexHigh ^ fileIndexLow;
+        }
+
+
+        public boolean equals(Object obj) {
+            if (obj == this)
+                return true;
+            if (!(obj instanceof FileKey))
+                return false;
+            FileKey other = (FileKey)obj;
+            if (this.volSerialNumber != other.volSerialNumber) return false;
+            if (this.fileIndexHigh != other.fileIndexHigh) return false;
+            if (this.fileIndexLow != other.fileIndexLow) return false;
+            return true;
+        }
+    }
+
+    // all change events
+    private static final int ALL_FILE_NOTIFY_EVENTS =
+        FILE_NOTIFY_CHANGE_FILE_NAME |
+        FILE_NOTIFY_CHANGE_DIR_NAME |
+        FILE_NOTIFY_CHANGE_ATTRIBUTES  |
+        FILE_NOTIFY_CHANGE_SIZE |
+        FILE_NOTIFY_CHANGE_LAST_WRITE |
+        FILE_NOTIFY_CHANGE_CREATION |
+        FILE_NOTIFY_CHANGE_SECURITY;
+
+    /**
+     * Background thread to service I/O completion port.
+     */
+    private class Poller extends AbstractPoller {
+        /*
+         * typedef struct _OVERLAPPED {
+         *     DWORD  Internal;
+         *     DWORD  InternalHigh;
+         *     DWORD  Offset;
+         *     DWORD  OffsetHigh;
+         *     HANDLE hEvent;
+         * } OVERLAPPED;
+         */
+        private static final short SIZEOF_DWORD         = 4;
+        private static final short SIZEOF_OVERLAPPED    = 32; // 20 on 32-bit
+
+        /*
+         * typedef struct _FILE_NOTIFY_INFORMATION {
+         *     DWORD NextEntryOffset;
+         *     DWORD Action;
+         *     DWORD FileNameLength;
+         *     WCHAR FileName[1];
+         * } FileNameLength;
+         */
+        private static final short OFFSETOF_NEXTENTRYOFFSET = 0;
+        private static final short OFFSETOF_ACTION          = 4;
+        private static final short OFFSETOF_FILENAMELENGTH  = 8;
+        private static final short OFFSETOF_FILENAME        = 12;
+
+        // size of per-directory buffer for events (FIXME - make this configurable)
+        private static final int CHANGES_BUFFER_SIZE    = 16 * 1024;
+
+        private final WindowsFileSystem fs;
+        private final WindowsWatchService watcher;
+        private final long port;
+
+        // maps completion key to WatchKey
+        private final Map<Integer,WindowsWatchKey> int2key;
+
+        // maps file key to WatchKey
+        private final Map<FileKey,WindowsWatchKey> fk2key;
+
+        // unique completion key for each directory
+        private int lastCompletionKey;
+
+        Poller(WindowsFileSystem fs, WindowsWatchService watcher, long port) {
+            this.fs = fs;
+            this.watcher = watcher;
+            this.port = port;
+            this.int2key = new HashMap<Integer,WindowsWatchKey>();
+            this.fk2key = new HashMap<FileKey,WindowsWatchKey>();
+            this.lastCompletionKey = 0;
+        }
+
+
+        void wakeup() throws IOException {
+            try {
+                PostQueuedCompletionStatus(port, 0);
+            } catch (WindowsException x) {
+                throw new IOException(x.getMessage());
+            }
+        }
+
+        /**
+         * Register a directory for changes as follows:
+         *
+         * 1. Open directory
+         * 2. Read its attributes (and check it really is a directory)
+         * 3. Assign completion key and associated handle with completion port
+         * 4. Call ReadDirectoryChangesW to start (async) read of changes
+         * 5. Create or return existing key representing registration
+         */
+
+        Object implRegister(Path obj,
+                            Set<? extends WatchEvent.Kind<?>> events,
+                            WatchEvent.Modifier... modifiers)
+        {
+            WindowsPath dir = (WindowsPath)obj;
+            boolean watchSubtree = false;
+
+            // FILE_TREE modifier allowed
+            for (WatchEvent.Modifier modifier: modifiers) {
+                if (modifier == ExtendedWatchEventModifier.FILE_TREE) {
+                    watchSubtree = true;
+                    continue;
+                } else {
+                    return (modifier == null) ? new NullPointerException() :
+                        new UnsupportedOperationException("Modifier not supported: "
+                            + modifiers[0].name());
+                }
+            }
+
+            // open directory
+            long handle = -1L;
+            try {
+                handle = CreateFile(dir.getPathForWin32Calls(),
+                                    FILE_LIST_DIRECTORY,
+                                    (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+                                    OPEN_EXISTING,
+                                    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED);
+            } catch (WindowsException x) {
+                return x.asIOException(dir);
+            }
+
+            boolean registered = false;
+            try {
+                // read attributes and check file is a directory
+                WindowsFileAttributes attrs = null;
+                try {
+                    attrs = WindowsFileAttributes.readAttributes(handle);
+                } catch (WindowsException x) {
+                    return x.asIOException(dir);
+                }
+                if (!attrs.isDirectory()) {
+                    return new NotDirectoryException(dir.getPathForExceptionMessage());
+                }
+
+                // check if this directory is already registered
+                FileKey fk = new FileKey(attrs.volSerialNumber(),
+                                         attrs.fileIndexHigh(),
+                                         attrs.fileIndexLow());
+                WindowsWatchKey existing = fk2key.get(fk);
+
+                // if already registered and we're not changing the subtree
+                // modifier then simply update the event and return the key.
+                if (existing != null && watchSubtree == existing.watchSubtree()) {
+                    existing.setEvents(events);
+                    return existing;
+                }
+
+                // unique completion key (skip 0)
+                int completionKey = ++lastCompletionKey;
+                if (completionKey == 0)
+                    completionKey = ++lastCompletionKey;
+
+                // associate handle with completion port
+                try {
+                    CreateIoCompletionPort(handle, port, completionKey);
+                } catch (WindowsException x) {
+                    return new IOException(x.getMessage());
+                }
+
+                // allocate memory for events, including space for other structures
+                // needed to do overlapped I/O
+                int size = CHANGES_BUFFER_SIZE + SIZEOF_DWORD + SIZEOF_OVERLAPPED;
+                NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
+
+                long bufferAddress = buffer.address();
+                long overlappedAddress = bufferAddress + size - SIZEOF_OVERLAPPED;
+                long countAddress = overlappedAddress - SIZEOF_DWORD;
+
+                // start async read of changes to directory
+                try {
+                    ReadDirectoryChangesW(handle,
+                                          bufferAddress,
+                                          CHANGES_BUFFER_SIZE,
+                                          watchSubtree,
+                                          ALL_FILE_NOTIFY_EVENTS,
+                                          countAddress,
+                                          overlappedAddress);
+                } catch (WindowsException x) {
+                    buffer.release();
+                    return new IOException(x.getMessage());
+                }
+
+                WindowsWatchKey watchKey;
+                if (existing == null) {
+                    // not registered so create new watch key
+                    watchKey = new WindowsWatchKey(watcher, fk)
+                        .init(handle, events, watchSubtree, buffer, countAddress,
+                              overlappedAddress, completionKey);
+                    // map file key to watch key
+                    fk2key.put(fk, watchKey);
+                } else {
+                    // directory already registered so need to:
+                    // 1. remove mapping from old completion key to existing watch key
+                    // 2. release existing key's resources (handle/buffer)
+                    // 3. re-initialize key with new handle/buffer
+                    int2key.remove(existing.completionKey());
+                    existing.releaseResources();
+                    watchKey = existing.init(handle, events, watchSubtree, buffer,
+                        countAddress, overlappedAddress, completionKey);
+                }
+                // map completion map to watch key
+                int2key.put(completionKey, watchKey);
+
+                registered = true;
+                return watchKey;
+
+            } finally {
+                if (!registered) CloseHandle(handle);
+            }
+        }
+
+        // cancel single key
+
+        void implCancelKey(WatchKey obj) {
+            WindowsWatchKey key = (WindowsWatchKey)obj;
+            if (key.isValid()) {
+                fk2key.remove(key.fileKey());
+                int2key.remove(key.completionKey());
+                key.invalidate();
+            }
+        }
+
+        // close watch service
+
+        void implCloseAll() {
+            // cancel all keys
+            for (Integer completionKey: int2key.keySet()) {
+                WindowsWatchKey key = int2key.get(completionKey);
+                key.invalidate();
+            }
+            fk2key.clear();
+            int2key.clear();
+
+            // close I/O completion port
+            CloseHandle(port);
+        }
+
+        // Translate file change action into watch event
+        private WatchEvent.Kind<?> translateActionToEvent(int action)
+        {
+            switch (action) {
+                case FILE_ACTION_MODIFIED :
+                    return StandardWatchEventKind.ENTRY_MODIFY;
+
+                case FILE_ACTION_ADDED :
+                case FILE_ACTION_RENAMED_NEW_NAME :
+                    return StandardWatchEventKind.ENTRY_CREATE;
+
+                case FILE_ACTION_REMOVED :
+                case FILE_ACTION_RENAMED_OLD_NAME :
+                    return StandardWatchEventKind.ENTRY_DELETE;
+
+                default :
+                    return null;  // action not recognized
+            }
+        }
+
+        // process events (list of FILE_NOTIFY_INFORMATION structures)
+        private void processEvents(WindowsWatchKey key, int size) {
+            long address = key.buffer().address();
+
+            int nextOffset;
+            do {
+                int action = unsafe.getInt(address + OFFSETOF_ACTION);
+
+                // map action to event
+                WatchEvent.Kind<?> kind = translateActionToEvent(action);
+                if (key.events().contains(kind)) {
+                    // copy the name
+                    int nameLengthInBytes = unsafe.getInt(address + OFFSETOF_FILENAMELENGTH);
+                    if ((nameLengthInBytes % 2) != 0) {
+                        throw new AssertionError("FileNameLength.FileNameLength is not a multiple of 2");
+                    }
+                    char[] nameAsArray = new char[nameLengthInBytes/2];
+                    unsafe.copyMemory(null, address + OFFSETOF_FILENAME, nameAsArray,
+                        Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes);
+
+                    // create FileName and queue event
+                    WindowsPath name = WindowsPath
+                        .createFromNormalizedPath(fs, new String(nameAsArray));
+                    key.signalEvent(kind, name);
+                }
+
+                // next event
+                nextOffset = unsafe.getInt(address + OFFSETOF_NEXTENTRYOFFSET);
+                address += (long)nextOffset;
+            } while (nextOffset != 0);
+        }
+
+        /**
+         * Poller main loop
+         */
+
+        public void run() {
+            for (;;) {
+                CompletionStatus info = null;
+                try {
+                    info = GetQueuedCompletionStatus(port);
+                } catch (WindowsException x) {
+                    // this should not happen
+                    x.printStackTrace();
+                    return;
+                }
+
+                // wakeup
+                if (info.completionKey() == 0) {
+                    boolean shutdown = processRequests();
+                    if (shutdown) {
+                        return;
+                    }
+                    continue;
+                }
+
+                // map completionKey to get WatchKey
+                WindowsWatchKey key = int2key.get(info.completionKey());
+                if (key == null) {
+                    // We get here when a registration is changed. In that case
+                    // the directory is closed which causes an event with the
+                    // old completion key.
+                    continue;
+                }
+
+                // ReadDirectoryChangesW failed
+                if (info.error() != 0) {
+                    // buffer overflow
+                    if (info.error() == ERROR_NOTIFY_ENUM_DIR) {
+                        key.signalEvent(StandardWatchEventKind.OVERFLOW, null);
+                    } else {
+                        // other error so cancel key
+                        implCancelKey(key);
+                        key.signal();
+                    }
+                    continue;
+                }
+
+                // process the events
+                if (info.bytesTransferred() > 0) {
+                    processEvents(key, info.bytesTransferred());
+                } else {
+                    // insufficient buffer size
+                    key.signalEvent(StandardWatchEventKind.OVERFLOW, null);
+                }
+
+                // start read for next batch of changes
+                try {
+                    ReadDirectoryChangesW(key.handle(),
+                                          key.buffer().address(),
+                                          CHANGES_BUFFER_SIZE,
+                                          key.watchSubtree(),
+                                          ALL_FILE_NOTIFY_EVENTS,
+                                          key.countAddress(),
+                                          key.overlappedAddress());
+                } catch (WindowsException x) {
+                    // no choice but to cancel key
+                    implCancelKey(key);
+                    key.signal();
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/Iocp.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <windows.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+
+#include "sun_nio_ch_Iocp.h"
+
+
+static jfieldID completionStatus_error;
+static jfieldID completionStatus_bytesTransferred;
+static jfieldID completionStatus_completionKey;
+static jfieldID completionStatus_overlapped;
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_Iocp_initIDs(JNIEnv* env, jclass this)
+{
+    jclass clazz;
+
+    clazz = (*env)->FindClass(env, "sun/nio/ch/Iocp$CompletionStatus");
+    if (clazz == NULL) {
+        return;
+    }
+    completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
+    completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
+    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
+    completionStatus_overlapped = (*env)->GetFieldID(env, clazz, "overlapped", "J");
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this,
+    jlong handle, jlong existingPort, jint completionKey, jint concurrency)
+{
+    HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(handle),
+                                         (HANDLE)jlong_to_ptr(existingPort),
+                                         (DWORD)completionKey,
+                                         (DWORD)concurrency);
+    if (port == NULL) {
+        JNU_ThrowIOExceptionWithLastError(env, "CreateIoCompletionPort failed");
+    }
+    return ptr_to_jlong(port);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_Iocp_close0(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    CloseHandle(h);
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_Iocp_getQueuedCompletionStatus(JNIEnv* env, jclass this,
+    jlong completionPort, jobject obj)
+{
+    DWORD bytesTransferred;
+    DWORD completionKey;
+    OVERLAPPED *lpOverlapped;
+    BOOL res;
+
+    res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
+                                  &bytesTransferred,
+                                  &completionKey,
+                                  &lpOverlapped,
+                                  INFINITE);
+    if (res == 0 && lpOverlapped == NULL) {
+        JNU_ThrowIOExceptionWithLastError(env, "GetQueuedCompletionStatus failed");
+    } else {
+        DWORD ioResult = (res == 0) ? GetLastError() : 0;
+        (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
+        (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
+            (jint)bytesTransferred);
+        (*env)->SetIntField(env, obj, completionStatus_completionKey,
+            (jint)completionKey);
+        (*env)->SetLongField(env, obj, completionStatus_overlapped,
+            ptr_to_jlong(lpOverlapped));
+
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_Iocp_postQueuedCompletionStatus(JNIEnv* env, jclass this,
+    jlong completionPort, jint completionKey)
+{
+    BOOL res;
+
+    res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
+                                     (DWORD)0, // FIXME
+                                     (DWORD)completionKey,
+                                     NULL); // FIXME
+    if (res == 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "PostQueuedCompletionStatus");
+    }
+}
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_ch_Iocp_getErrorMessage(JNIEnv* env, jclass this, jint errorCode)
+{
+    WCHAR message[255];
+
+    DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
+                               NULL,
+                               (DWORD)errorCode,
+                               0,
+                               &message[0],
+                               255,
+                               NULL);
+
+
+    if (len == 0) {
+        return NULL;
+    } else {
+        return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <windows.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+
+#include "sun_nio_ch_WindowsAsynchronousFileChannelImpl.h"
+
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_readFile(JNIEnv* env, jclass this,
+    jlong handle, jlong address, jint len, jlong offset, jlong ov)
+{
+    BOOL res;
+    DWORD nread = 0;
+
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov);
+    lpOverlapped->Offset = (DWORD)offset;
+    lpOverlapped->OffsetHigh = (DWORD)((long)(offset >> 32));
+    lpOverlapped->hEvent = NULL;
+
+    res = ReadFile((HANDLE) jlong_to_ptr(handle),
+                   (LPVOID) jlong_to_ptr(address),
+                   (DWORD)len,
+                   &nread,
+                   lpOverlapped);
+
+    if (res == 0) {
+        int error = GetLastError();
+        if (error == ERROR_IO_PENDING)
+            return IOS_UNAVAILABLE;
+        if (error == ERROR_HANDLE_EOF)
+            return IOS_EOF;
+        JNU_ThrowIOExceptionWithLastError(env, "ReadFile failed");
+        return IOS_THROWN;
+    }
+
+    return (jint)nread;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_writeFile(JNIEnv* env, jclass this,
+    jlong handle, jlong address, jint len, jlong offset, jlong ov)
+{
+    BOOL res;
+    DWORD nwritten = 0;
+
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov);
+    lpOverlapped->Offset = (DWORD)offset;
+    lpOverlapped->OffsetHigh = (DWORD)((long)(offset >> 32));
+    lpOverlapped->hEvent = NULL;
+
+    res = WriteFile((HANDLE)jlong_to_ptr(handle),
+                   (LPVOID) jlong_to_ptr(address),
+                   (DWORD)len,
+                   &nwritten,
+                   lpOverlapped);
+
+    if (res == 0) {
+        int error = GetLastError();
+        if (error == ERROR_IO_PENDING) {
+            return IOS_UNAVAILABLE;
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "WriteFile failed");
+        return IOS_THROWN;
+    }
+    return (jint)nwritten;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_lockFile(JNIEnv *env, jobject this, jlong handle,
+                                                            jlong pos, jlong size, jboolean shared, jlong ov)
+{
+    BOOL res;
+    HANDLE h = jlong_to_ptr(handle);
+    DWORD lowPos = (DWORD)pos;
+    long highPos = (long)(pos >> 32);
+    DWORD lowNumBytes = (DWORD)size;
+    DWORD highNumBytes = (DWORD)(size >> 32);
+    DWORD flags = (shared == JNI_TRUE) ? 0 : LOCKFILE_EXCLUSIVE_LOCK;
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov);
+
+    lpOverlapped->Offset = lowPos;
+    lpOverlapped->OffsetHigh = highPos;
+    lpOverlapped->hEvent = NULL;
+
+    res = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, lpOverlapped);
+    if (res == 0) {
+        int error = GetLastError();
+        if (error == ERROR_IO_PENDING) {
+            return IOS_UNAVAILABLE;
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "WriteFile failed");
+        return IOS_THROWN;
+    }
+    return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_close0(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    CloseHandle(h);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <windows.h>
+#include <winsock2.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "net_util.h"
+
+#include "sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl.h"
+
+
+#ifndef WSAID_ACCEPTEX
+#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
+#endif
+
+#ifndef SO_UPDATE_ACCEPT_CONTEXT
+#define SO_UPDATE_ACCEPT_CONTEXT 0x700B
+#endif
+
+
+typedef BOOL (*AcceptEx_t)
+(
+    SOCKET sListenSocket,
+    SOCKET sAcceptSocket,
+    PVOID lpOutputBuffer,
+    DWORD dwReceiveDataLength,
+    DWORD dwLocalAddressLength,
+    DWORD dwRemoteAddressLength,
+    LPDWORD lpdwBytesReceived,
+    LPOVERLAPPED lpOverlapped
+);
+
+
+static AcceptEx_t AcceptEx_func;
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env, jclass this) {
+    GUID GuidAcceptEx = WSAID_ACCEPTEX;
+    SOCKET s;
+    int rv;
+    DWORD dwBytes;
+
+    s = socket(AF_INET, SOCK_STREAM, 0);
+    if (s == INVALID_SOCKET) {
+        JNU_ThrowIOExceptionWithLastError(env, "socket failed");
+        return;
+    }
+    rv = WSAIoctl(s,
+                  SIO_GET_EXTENSION_FUNCTION_POINTER,
+                  (LPVOID)&GuidAcceptEx,
+                  sizeof(GuidAcceptEx),
+                  &AcceptEx_func,
+                  sizeof(AcceptEx_func),
+                  &dwBytes,
+                  NULL,
+                  NULL);
+    if (rv != 0)
+        JNU_ThrowIOExceptionWithLastError(env, "WSAIoctl failed");
+    closesocket(s);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_accept0(JNIEnv* env, jclass this,
+    jlong listenSocket, jlong acceptSocket, jlong ov, jlong buf)
+{
+    BOOL res;
+    SOCKET s1 = (SOCKET)jlong_to_ptr(listenSocket);
+    SOCKET s2 = (SOCKET)jlong_to_ptr(acceptSocket);
+    PVOID outputBuffer = (PVOID)jlong_to_ptr(buf);
+
+    DWORD nread = 0;
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov);
+    ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
+
+    res = (*AcceptEx_func)(s1,
+                           s2,
+                           outputBuffer,
+                           0,
+                           sizeof(SOCKETADDRESS)+16,
+                           sizeof(SOCKETADDRESS)+16,
+                           &nread,
+                           lpOverlapped);
+    if (res == 0) {
+        int error = WSAGetLastError();
+        if (error == ERROR_IO_PENDING) {
+            return IOS_UNAVAILABLE;
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "AcceptEx failed");
+        return IOS_THROWN;
+    }
+
+    return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_updateAcceptContext(JNIEnv* env, jclass this,
+    jlong listenSocket, jlong acceptSocket)
+{
+    SOCKET s1 = (SOCKET)jlong_to_ptr(listenSocket);
+    SOCKET s2 = (SOCKET)jlong_to_ptr(acceptSocket);
+
+    setsockopt(s2, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&s1, sizeof(s1));
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_closesocket0(JNIEnv* env, jclass this,
+    jlong socket)
+{
+    SOCKET s = (SOCKET)jlong_to_ptr(socket);
+
+    if (closesocket(s) == SOCKET_ERROR)
+        JNU_ThrowIOExceptionWithLastError(env, "closesocket failed");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <windows.h>
+#include <winsock2.h>
+#include <stddef.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "net_util.h"
+
+#include "sun_nio_ch_WindowsAsynchronousSocketChannelImpl.h"
+
+#ifndef WSAID_CONNECTEX
+#define WSAID_CONNECTEX {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
+#endif
+
+#ifndef SO_UPDATE_CONNECT_CONTEXT
+#define SO_UPDATE_CONNECT_CONTEXT 0x7010
+#endif
+
+typedef BOOL (*ConnectEx_t)
+(
+    SOCKET s,
+    const struct sockaddr* name,
+    int namelen,
+    PVOID lpSendBuffer,
+    DWORD dwSendDataLength,
+    LPDWORD lpdwBytesSent,
+    LPOVERLAPPED lpOverlapped
+);
+
+static ConnectEx_t ConnectEx_func;
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_initIDs(JNIEnv* env, jclass this) {
+    GUID GuidConnectEx = WSAID_CONNECTEX;
+    SOCKET s;
+    int rv;
+    DWORD dwBytes;
+
+    s = socket(AF_INET, SOCK_STREAM, 0);
+    if (s == INVALID_SOCKET) {
+        JNU_ThrowIOExceptionWithLastError(env, "socket failed");
+        return;
+    }
+    rv = WSAIoctl(s,
+                  SIO_GET_EXTENSION_FUNCTION_POINTER,
+                  (LPVOID)&GuidConnectEx,
+                  sizeof(GuidConnectEx),
+                  &ConnectEx_func,
+                  sizeof(ConnectEx_func),
+                  &dwBytes,
+                  NULL,
+                  NULL);
+    if (rv != 0)
+        JNU_ThrowIOExceptionWithLastError(env, "WSAIoctl failed");
+    closesocket(s);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_connect0(JNIEnv* env, jclass this,
+    jlong socket, jboolean preferIPv6, jobject iao, jint port, jlong ov)
+{
+    SOCKET s = (SOCKET) jlong_to_ptr(socket);
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
+
+    SOCKETADDRESS sa;
+    int sa_len;
+    BOOL res;
+
+    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
+        return IOS_THROWN;
+    }
+
+    ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
+
+    res = (*ConnectEx_func)(s,
+                            (struct sockaddr *)&sa,
+                            sa_len,
+                            NULL,
+                            0,
+                            NULL,
+                            lpOverlapped);
+    if (res == 0) {
+        int error = GetLastError();
+        if (error == ERROR_IO_PENDING) {
+            return IOS_UNAVAILABLE;
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "ConnectEx failed");
+        return IOS_THROWN;
+    }
+    return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_updateConnectContext(JNIEnv* env, jclass this,
+    jlong socket)
+{
+    SOCKET s = (SOCKET)jlong_to_ptr(socket);
+    setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_shutdown0(JNIEnv *env, jclass cl,
+    jlong socket, jint how)
+{
+    SOCKET s =(SOCKET) jlong_to_ptr(socket);
+    if (shutdown(s, how) == SOCKET_ERROR) {
+        JNU_ThrowIOExceptionWithLastError(env, "shutdown failed");
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_closesocket0(JNIEnv* env, jclass this,
+    jlong socket)
+{
+    SOCKET s = (SOCKET)jlong_to_ptr(socket);
+    if (closesocket(s) == SOCKET_ERROR)
+        JNU_ThrowIOExceptionWithLastError(env, "closesocket failed");
+}
+
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_read0(JNIEnv* env, jclass this,
+    jlong socket, jint count, jlong address, jlong ov)
+{
+    SOCKET s = (SOCKET) jlong_to_ptr(socket);
+    WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address);
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
+    BOOL res;
+    DWORD nread = 0;
+    DWORD flags = 0;
+
+    ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
+    res = WSARecv(s,
+                  lpWsaBuf,
+                  (DWORD)count,
+                  &nread,
+                  &flags,
+                  lpOverlapped,
+                  NULL);
+
+    if (res == SOCKET_ERROR) {
+        int error = WSAGetLastError();
+        if (error == WSA_IO_PENDING) {
+            return IOS_UNAVAILABLE;
+        }
+        if (error == WSAESHUTDOWN) {
+            return 0;       // input shutdown
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "WSARecv failed");
+        return IOS_THROWN;
+    }
+    if (nread == 0) {
+        // Handle graceful close or bytes not yet available cases
+        // via completion port notification.
+        return IOS_UNAVAILABLE;
+    }
+    return (jint)nread;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_write0(JNIEnv* env, jclass this,
+    jlong socket, jint count, jlong address, jlong ov)
+{
+    SOCKET s = (SOCKET) jlong_to_ptr(socket);
+    WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address);
+    OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
+    BOOL res;
+    DWORD nwritten;
+
+    ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
+    res = WSASend(s,
+                  lpWsaBuf,
+                  (DWORD)count,
+                  &nwritten,
+                  0,
+                  lpOverlapped,
+                  NULL);
+
+    if (res == SOCKET_ERROR) {
+        int error = WSAGetLastError();
+        if (error == WSA_IO_PENDING) {
+            return IOS_UNAVAILABLE;
+        }
+        if (error == WSAESHUTDOWN) {
+            return IOS_EOF;     // output shutdown
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "WSASend failed");
+        return IOS_THROWN;
+    }
+    return (jint)nwritten;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <windows.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+
+#include "sun_nio_fs_RegistryFileTypeDetector.h"
+
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_RegistryFileTypeDetector_queryStringValue(JNIEnv* env, jclass this,
+    jlong keyAddress, jlong nameAddress)
+{
+    LPCWSTR lpSubKey= (LPCWSTR)jlong_to_ptr(keyAddress);
+    LPWSTR lpValueName = (LPWSTR)jlong_to_ptr(nameAddress);
+    LONG res;
+    HKEY hKey;
+    jstring result = NULL;
+
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, lpSubKey, 0, KEY_READ, &hKey);
+    if (res == ERROR_SUCCESS) {
+        DWORD type;
+        BYTE data[255];
+        DWORD size = sizeof(data);
+
+        res = RegQueryValueExW(hKey, lpValueName, NULL, &type, (LPBYTE)&data, &size);
+        if (res == ERROR_SUCCESS) {
+            if (type == REG_SZ) {
+                jsize len = wcslen((WCHAR*)data);
+                result = (*env)->NewString(env, (const jchar*)&data, len);
+            }
+        }
+
+        RegCloseKey(hKey);
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1328 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <direct.h>
+#include <malloc.h>
+#include <io.h>
+#include <windows.h>
+#include <aclapi.h>
+#include <winioctl.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+
+#include "sun_nio_fs_WindowsNativeDispatcher.h"
+
+/**
+ * jfieldIDs
+ */
+static jfieldID findFirst_handle;
+static jfieldID findFirst_name;
+static jfieldID findFirst_reserved0;
+
+static jfieldID findStream_handle;
+static jfieldID findStream_name;
+
+static jfieldID volumeInfo_fsName;
+static jfieldID volumeInfo_volName;
+static jfieldID volumeInfo_volSN;
+static jfieldID volumeInfo_flags;
+
+static jfieldID diskSpace_bytesAvailable;
+static jfieldID diskSpace_totalBytes;
+static jfieldID diskSpace_totalFree;
+
+static jfieldID account_domain;
+static jfieldID account_name;
+static jfieldID account_use;
+
+static jfieldID aclInfo_aceCount;
+
+static jfieldID completionStatus_error;
+static jfieldID completionStatus_bytesTransferred;
+static jfieldID completionStatus_completionKey;
+
+static jfieldID backupResult_bytesTransferred;
+static jfieldID backupResult_context;
+
+
+/**
+ * Win32 APIs not defined in Visual Studio 2003 header files
+ */
+
+typedef enum {
+  FindStreamInfoStandard
+} MY_STREAM_INFO_LEVELS;
+
+typedef struct _MY_WIN32_FIND_STREAM_DATA {
+  LARGE_INTEGER StreamSize;
+  WCHAR cStreamName[MAX_PATH + 36];
+} MY_WIN32_FIND_STREAM_DATA;
+
+typedef HANDLE (WINAPI* FindFirstStream_Proc)(LPCWSTR, MY_STREAM_INFO_LEVELS, LPVOID, DWORD);
+typedef BOOL (WINAPI* FindNextStream_Proc)(HANDLE, LPVOID);
+
+typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD);
+typedef BOOL (WINAPI* CreateHardLinkProc) (LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
+typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
+
+typedef BOOL (WINAPI* ConvertSidToStringSidProc) (PSID, LPWSTR*);
+typedef BOOL (WINAPI* ConvertStringSidToSidProc) (LPWSTR, PSID*);
+typedef DWORD (WINAPI* GetLengthSidProc) (PSID);
+
+static FindFirstStream_Proc FindFirstStream_func;
+static FindNextStream_Proc FindNextStream_func;
+
+static CreateSymbolicLinkProc CreateSymbolicLink_func;
+static CreateHardLinkProc CreateHardLink_func;
+static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
+
+static ConvertSidToStringSidProc ConvertSidToStringSid_func;
+static ConvertStringSidToSidProc ConvertStringSidToSid_func;
+static GetLengthSidProc GetLengthSid_func;
+
+static void throwWindowsException(JNIEnv* env, DWORD lastError) {
+    jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException",
+        "(I)V", lastError);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+/**
+ * Initializes jfieldIDs and get address of Win32 calls that are located
+ * at runtime.
+ */
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
+{
+    jclass clazz;
+    HMODULE h;
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile");
+    if (clazz == NULL) {
+        return;
+    }
+    findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
+    findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
+    findFirst_reserved0 = (*env)->GetFieldID(env, clazz, "reserved0", "I");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream");
+    if (clazz == NULL) {
+        return;
+    }
+    findStream_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
+    findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation");
+    if (clazz == NULL) {
+        return;
+    }
+    volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;");
+    volumeInfo_volName = (*env)->GetFieldID(env, clazz, "volumeName", "Ljava/lang/String;");
+    volumeInfo_volSN = (*env)->GetFieldID(env, clazz, "volumeSerialNumber", "I");
+    volumeInfo_flags = (*env)->GetFieldID(env, clazz, "flags", "I");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace");
+    if (clazz == NULL) {
+        return;
+    }
+    diskSpace_bytesAvailable = (*env)->GetFieldID(env, clazz, "freeBytesAvailable", "J");
+    diskSpace_totalBytes = (*env)->GetFieldID(env, clazz, "totalNumberOfBytes", "J");
+    diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account");
+    if (clazz == NULL) {
+        return;
+    }
+    account_domain = (*env)->GetFieldID(env, clazz, "domain", "Ljava/lang/String;");
+    account_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
+    account_use = (*env)->GetFieldID(env, clazz, "use", "I");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$AclInformation");
+    if (clazz == NULL) {
+        return;
+    }
+    aclInfo_aceCount = (*env)->GetFieldID(env, clazz, "aceCount", "I");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$CompletionStatus");
+    if (clazz == NULL) {
+        return;
+    }
+    completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
+    completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
+    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult");
+    if (clazz == NULL) {
+        return;
+    }
+    backupResult_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
+    backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J");
+
+
+    h = LoadLibrary("kernel32");
+    if (h != INVALID_HANDLE_VALUE) {
+        FindFirstStream_func =
+            (FindFirstStream_Proc)GetProcAddress(h, "FindFirstStreamW");
+        FindNextStream_func =
+            (FindNextStream_Proc)GetProcAddress(h, "FindNextStreamW");
+        CreateSymbolicLink_func =
+            (CreateSymbolicLinkProc)GetProcAddress(h, "CreateSymbolicLinkW");
+        CreateHardLink_func =
+            (CreateHardLinkProc)GetProcAddress(h, "CreateHardLinkW");
+        GetFinalPathNameByHandle_func =
+            (GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW");
+        FreeLibrary(h);
+    }
+
+    h = LoadLibrary("advapi32");
+    if (h != INVALID_HANDLE_VALUE) {
+        ConvertSidToStringSid_func =
+            (ConvertSidToStringSidProc)GetProcAddress(h, "ConvertSidToStringSidW");
+        ConvertStringSidToSid_func =
+            (ConvertStringSidToSidProc)GetProcAddress(h, "ConvertStringSidToSidW");
+        GetLengthSid_func =
+            (GetLengthSidProc)GetProcAddress(h, "GetLengthSid");
+        FreeLibrary(h);
+    }
+
+}
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_FormatMessage(JNIEnv* env, jclass this, jint errorCode) {
+    WCHAR message[255];
+
+    DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
+                               NULL,
+                               (DWORD)errorCode,
+                               0,
+                               &message[0],
+                               255,
+                               NULL);
+
+
+    if (len == 0) {
+        return NULL;
+    } else {
+        return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message));
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_LocalFree(JNIEnv* env, jclass this, jlong address)
+{
+    HLOCAL hMem = (HLOCAL)jlong_to_ptr(address);
+    LocalFree(hMem);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CreateFile0(JNIEnv* env, jclass this,
+    jlong address, jint dwDesiredAccess, jint dwShareMode, jlong sdAddress,
+    jint dwCreationDisposition, jint dwFlagsAndAttributes)
+{
+    HANDLE handle;
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+
+    SECURITY_ATTRIBUTES securityAttributes;
+    LPSECURITY_ATTRIBUTES lpSecurityAttributes;
+    PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
+
+
+    if (lpSecurityDescriptor == NULL) {
+        lpSecurityAttributes = NULL;
+    } else {
+        securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+        securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
+        securityAttributes.bInheritHandle = FALSE;
+        lpSecurityAttributes = &securityAttributes;
+    }
+
+    handle = CreateFileW(lpFileName,
+                        (DWORD)dwDesiredAccess,
+                        (DWORD)dwShareMode,
+                        lpSecurityAttributes,
+                        (DWORD)dwCreationDisposition,
+                        (DWORD)dwFlagsAndAttributes,
+                        NULL);
+    if (handle == INVALID_HANDLE_VALUE) {
+        throwWindowsException(env, GetLastError());
+    }
+    return ptr_to_jlong(handle);
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlSetSparse(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    DWORD bytesReturned;
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    if (DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesReturned, NULL) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlGetReparsePoint(JNIEnv* env, jclass this,
+    jlong handle, jlong bufferAddress, jint bufferSize)
+{
+    DWORD bytesReturned;
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    LPVOID outBuffer = (LPVOID)jlong_to_ptr(bufferAddress);
+
+    if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, outBuffer, (DWORD)bufferSize,
+                        &bytesReturned, NULL) == 0)
+    {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_DeleteFile0(JNIEnv* env, jclass this, jlong address)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    if (DeleteFileW(lpFileName) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CreateDirectory0(JNIEnv* env, jclass this,
+    jlong address, jlong sdAddress)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+
+    SECURITY_ATTRIBUTES securityAttributes;
+    LPSECURITY_ATTRIBUTES lpSecurityAttributes;
+    PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
+
+
+    if (lpSecurityDescriptor == NULL) {
+        lpSecurityAttributes = NULL;
+    } else {
+        securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+        securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
+        securityAttributes.bInheritHandle = FALSE;
+        lpSecurityAttributes = &securityAttributes;
+    }
+
+    if (CreateDirectoryW(lpFileName, lpSecurityAttributes) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_RemoveDirectory0(JNIEnv* env, jclass this, jlong address)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    if (RemoveDirectoryW(lpFileName) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CloseHandle(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    CloseHandle(h);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this,
+    jlong address, jobject obj)
+{
+    WIN32_FIND_DATAW data;
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+
+
+    HANDLE handle = FindFirstFileW(lpFileName, &data);
+    if (handle != INVALID_HANDLE_VALUE) {
+        jstring name = (*env)->NewString(env, data.cFileName, wcslen(data.cFileName));
+        if (name == NULL)
+            return;
+
+        (*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle));
+        (*env)->SetObjectField(env, obj, findFirst_name, name);
+        (*env)->SetIntField(env, obj, findFirst_reserved0, data.dwReserved0);
+
+    } else {
+        throwWindowsException(env, GetLastError());
+    }
+
+}
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    WIN32_FIND_DATAW data;
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+
+    if (FindNextFileW(h, &data) != 0) {
+        return (*env)->NewString(env, data.cFileName, wcslen(data.cFileName));
+    } else {
+        if (GetLastError() != ERROR_NO_MORE_FILES)
+            throwWindowsException(env, GetLastError());
+        return NULL;
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass this,
+    jlong address, jobject obj)
+{
+    MY_WIN32_FIND_STREAM_DATA data;
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    HANDLE handle;
+
+    if (FindFirstStream_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return;
+    }
+
+    handle = (*FindFirstStream_func)(lpFileName, FindStreamInfoStandard, &data, 0);
+    if (handle != INVALID_HANDLE_VALUE) {
+        jstring name = (*env)->NewString(env, data.cStreamName, wcslen(data.cStreamName));
+        if (name == NULL)
+            return;
+        (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
+        (*env)->SetObjectField(env, obj, findStream_name, name);
+    } else {
+        if (GetLastError() == ERROR_HANDLE_EOF) {
+             (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
+        } else {
+            throwWindowsException(env, GetLastError());
+        }
+    }
+
+}
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    MY_WIN32_FIND_STREAM_DATA data;
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+
+    if (FindNextStream_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return NULL;
+    }
+
+    if ((*FindNextStream_func)(h, &data) != 0) {
+        return (*env)->NewString(env, data.cStreamName, wcslen(data.cStreamName));
+    } else {
+        if (GetLastError() != ERROR_HANDLE_EOF)
+            throwWindowsException(env, GetLastError());
+        return NULL;
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_FindClose(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    if (FindClose(h) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle(JNIEnv* env, jclass this,
+    jlong handle, jlong address)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    BY_HANDLE_FILE_INFORMATION* info =
+        (BY_HANDLE_FILE_INFORMATION*)jlong_to_ptr(address);
+    if (GetFileInformationByHandle(h, info) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CopyFileEx0(JNIEnv* env, jclass this,
+    jlong existingAddress, jlong newAddress, jint flags, jlong cancelAddress)
+{
+    LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
+    LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
+    LPBOOL cancel = (LPBOOL)jlong_to_ptr(cancelAddress);
+    if (CopyFileExW(lpExistingFileName, lpNewFileName, NULL, NULL, cancel,
+                    (DWORD)flags) == 0)
+    {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_MoveFileEx0(JNIEnv* env, jclass this,
+    jlong existingAddress, jlong newAddress, jint flags)
+{
+    LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
+    LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
+    if (MoveFileExW(lpExistingFileName, lpNewFileName, (DWORD)flags) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetLogicalDrives(JNIEnv* env, jclass this)
+{
+    DWORD res = GetLogicalDrives();
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+    return (jint)res;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributes0(JNIEnv* env, jclass this,
+    jlong address)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    DWORD value = GetFileAttributesW(lpFileName);
+
+    if (value == INVALID_FILE_ATTRIBUTES) {
+        throwWindowsException(env, GetLastError());
+    }
+    return (jint)value;
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetFileAttributes0(JNIEnv* env, jclass this,
+    jlong address, jint value)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    if (SetFileAttributesW(lpFileName, (DWORD)value) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this,
+    jlong handle, jlong createTime, jlong lastAccessTime, jlong lastWriteTime)
+{
+    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)
+    {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetEndOfFile(JNIEnv* env, jclass this,
+    jlong handle)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+
+    if (SetEndOfFile(h) == 0)
+        throwWindowsException(env, GetLastError());
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumeInformation0(JNIEnv* env, jclass this,
+    jlong address, jobject obj)
+{
+    WCHAR volumeName[MAX_PATH+1];
+    DWORD volumeSerialNumber;
+    DWORD maxComponentLength;
+    DWORD flags;
+    WCHAR fileSystemName[MAX_PATH+1];
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    jstring str;
+
+    BOOL res = GetVolumeInformationW(lpFileName,
+                                     &volumeName[0],
+                                     MAX_PATH+1,
+                                     &volumeSerialNumber,
+                                     &maxComponentLength,
+                                     &flags,
+                                     &fileSystemName[0],
+                                     MAX_PATH+1);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+        return;
+    }
+
+    str = (*env)->NewString(env, (const jchar *)fileSystemName, (jsize)wcslen(fileSystemName));
+    if (str == NULL) return;
+    (*env)->SetObjectField(env, obj, volumeInfo_fsName, str);
+
+    str = (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
+    if (str == NULL) return;
+    (*env)->SetObjectField(env, obj, volumeInfo_volName, str);
+
+    (*env)->SetIntField(env, obj, volumeInfo_volSN, (jint)volumeSerialNumber);
+    (*env)->SetIntField(env, obj, volumeInfo_flags, (jint)flags);
+}
+
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetDriveType0(JNIEnv* env, jclass this, jlong address) {
+    LPCWSTR lpRootPathName = jlong_to_ptr(address);
+    return (jint)GetDriveTypeW(lpRootPathName);
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpaceEx0(JNIEnv* env, jclass this,
+    jlong address, jobject obj)
+{
+    ULARGE_INTEGER freeBytesAvailable;
+    ULARGE_INTEGER totalNumberOfBytes;
+    ULARGE_INTEGER totalNumberOfFreeBytes;
+    LPCWSTR lpDirName = jlong_to_ptr(address);
+
+
+    BOOL res = GetDiskFreeSpaceExW(lpDirName,
+                                   &freeBytesAvailable,
+                                   &totalNumberOfBytes,
+                                   &totalNumberOfFreeBytes);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+        return;
+    }
+
+    (*env)->SetLongField(env, obj, diskSpace_bytesAvailable,
+        long_to_jlong(freeBytesAvailable.QuadPart));
+    (*env)->SetLongField(env, obj, diskSpace_totalBytes,
+        long_to_jlong(totalNumberOfBytes.QuadPart));
+    (*env)->SetLongField(env, obj, diskSpace_totalFree,
+        long_to_jlong(totalNumberOfFreeBytes.QuadPart));
+}
+
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumePathName0(JNIEnv* env, jclass this,
+    jlong address)
+{
+    WCHAR volumeName[MAX_PATH+1];
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+
+
+    BOOL res = GetVolumePathNameW(lpFileName,
+                                  &volumeName[0],
+                                  MAX_PATH+1);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+        return NULL;
+    } else {
+        return (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_InitializeSecurityDescriptor(JNIEnv* env, jclass this,
+    jlong address)
+{
+    PSECURITY_DESCRIPTOR pSecurityDescriptor =
+        (PSECURITY_DESCRIPTOR)jlong_to_ptr(address);
+
+    if (InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_InitializeAcl(JNIEnv* env, jclass this,
+    jlong address, jint size)
+{
+    PACL pAcl = (PACL)jlong_to_ptr(address);
+
+    if (InitializeAcl(pAcl, (DWORD)size, ACL_REVISION) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetFileSecurity0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint requestedInformation, jlong descAddress)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
+    PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
+    DWORD lengthNeeded = 0;
+
+    BOOL res = SetFileSecurityW(lpFileName,
+                                (SECURITY_INFORMATION)requestedInformation,
+                                pSecurityDescriptor);
+
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetFileSecurity0(JNIEnv* env, jclass this,
+    jlong pathAddress, jint requestedInformation, jlong descAddress, jint nLength)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
+    PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
+    DWORD lengthNeeded = 0;
+
+    BOOL res = GetFileSecurityW(lpFileName,
+                                (SECURITY_INFORMATION)requestedInformation,
+                                pSecurityDescriptor,
+                                (DWORD)nLength,
+                                &lengthNeeded);
+
+    if (res == 0) {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+            return (jint)lengthNeeded;
+        } else {
+            throwWindowsException(env, GetLastError());
+            return 0;
+        }
+    } else {
+        return (jint)nLength;
+    }
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorOwner(JNIEnv* env,
+    jclass this, jlong address)
+{
+    PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
+    PSID pOwner;
+    BOOL bOwnerDefaulted;
+
+
+    if (GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwner, &bOwnerDefaulted) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+    return ptr_to_jlong(pOwner);
+
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorOwner(JNIEnv* env,
+    jclass this, jlong descAddress, jlong ownerAddress)
+{
+    PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
+    PSID pOwner = jlong_to_ptr(ownerAddress);
+
+    if (SetSecurityDescriptorOwner(pSecurityDescriptor, pOwner, FALSE) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorDacl(JNIEnv* env,
+    jclass this, jlong address)
+{
+    PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
+    BOOL bDaclPresent;
+    PACL pDacl;
+    BOOL bDaclDefaulted;
+
+    if (GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) == 0) {
+        throwWindowsException(env, GetLastError());
+        return (jlong)0;
+    } else {
+        return (bDaclPresent) ? ptr_to_jlong(pDacl) : (jlong)0;
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorDacl(JNIEnv* env,
+    jclass this, jlong descAddress, jlong aclAddress)
+{
+    PSECURITY_DESCRIPTOR pSecurityDescriptor = (PSECURITY_DESCRIPTOR)jlong_to_ptr(descAddress);
+    PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
+
+    if (SetSecurityDescriptorDacl(pSecurityDescriptor, TRUE, pAcl, FALSE) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetAclInformation0(JNIEnv* env,
+    jclass this, jlong address, jobject obj)
+{
+    PACL pAcl = (PACL)jlong_to_ptr(address);
+    ACL_SIZE_INFORMATION acl_size_info;
+
+    if (GetAclInformation(pAcl, (void *) &acl_size_info, sizeof(acl_size_info), AclSizeInformation) == 0) {
+        throwWindowsException(env, GetLastError());
+    } else {
+        (*env)->SetIntField(env, obj, aclInfo_aceCount, (jint)acl_size_info.AceCount);
+    }
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetAce(JNIEnv* env, jclass this, jlong address,
+    jint aceIndex)
+{
+    PACL pAcl = (PACL)jlong_to_ptr(address);
+    LPVOID pAce;
+
+    if (GetAce(pAcl, (DWORD)aceIndex, &pAce) == 0) {
+        throwWindowsException(env, GetLastError());
+        return (jlong)0;
+    } else {
+        return ptr_to_jlong(pAce);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessAllowedAceEx(JNIEnv* env,
+    jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
+{
+    PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
+    PSID pSid = (PSID)jlong_to_ptr(sidAddress);
+
+    if (AddAccessAllowedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessDeniedAceEx(JNIEnv* env,
+    jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
+{
+    PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
+    PSID pSid = (PSID)jlong_to_ptr(sidAddress);
+
+    if (AddAccessDeniedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountSid0(JNIEnv* env,
+    jclass this, jlong address, jobject obj)
+{
+    WCHAR domain[255];
+    WCHAR name[255];
+    DWORD domainLen = sizeof(domain);
+    DWORD nameLen = sizeof(name);
+    SID_NAME_USE use;
+    PSID sid = jlong_to_ptr(address);
+    jstring s;
+
+    if (LookupAccountSidW(NULL, sid, &name[0], &nameLen, &domain[0], &domainLen, &use) == 0) {
+        throwWindowsException(env, GetLastError());
+        return;
+    }
+
+    s = (*env)->NewString(env, (const jchar *)domain, (jsize)wcslen(domain));
+    if (s == NULL)
+        return;
+    (*env)->SetObjectField(env, obj, account_domain, s);
+
+    s = (*env)->NewString(env, (const jchar *)name, (jsize)wcslen(name));
+    if (s == NULL)
+        return;
+    (*env)->SetObjectField(env, obj, account_name, s);
+    (*env)->SetIntField(env, obj, account_use, (jint)use);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountName0(JNIEnv* env,
+    jclass this, jlong nameAddress, jlong sidAddress, jint cbSid)
+{
+
+    LPCWSTR accountName = jlong_to_ptr(nameAddress);
+    PSID sid = jlong_to_ptr(sidAddress);
+    WCHAR domain[255];
+    DWORD domainLen = sizeof(domain);
+    SID_NAME_USE use;
+
+    if (LookupAccountNameW(NULL, accountName, sid, (LPDWORD)&cbSid,
+                           &domain[0], &domainLen, &use) == 0)
+    {
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+            throwWindowsException(env, GetLastError());
+        }
+    }
+
+    return cbSid;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetLengthSid(JNIEnv* env,
+    jclass this, jlong address)
+{
+    PSID sid = jlong_to_ptr(address);
+
+    if (GetLengthSid_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return 0;
+    }
+    return (jint)(*GetLengthSid_func)(sid);
+}
+
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_ConvertSidToStringSid(JNIEnv* env,
+    jclass this, jlong address)
+{
+    PSID sid = jlong_to_ptr(address);
+    LPWSTR string;
+
+    if (ConvertSidToStringSid_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return NULL;
+    }
+
+    if ((*ConvertSidToStringSid_func)(sid, &string) == 0) {
+        throwWindowsException(env, GetLastError());
+        return NULL;
+    } else {
+        jstring s = (*env)->NewString(env, (const jchar *)string,
+            (jsize)wcslen(string));
+        LocalFree(string);
+        return s;
+    }
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_ConvertStringSidToSid0(JNIEnv* env,
+    jclass this, jlong address)
+{
+    LPWSTR lpStringSid = jlong_to_ptr(address);
+    PSID pSid;
+
+    if (ConvertStringSidToSid_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return (jlong)0;
+    }
+
+    if ((*ConvertStringSidToSid_func)(lpStringSid, &pSid) == 0)
+        throwWindowsException(env, GetLastError());
+
+    return ptr_to_jlong(pSid);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentProcess(JNIEnv* env, jclass this) {
+    HANDLE hProcess = GetCurrentProcess();
+    return ptr_to_jlong(hProcess);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentThread(JNIEnv* env, jclass this) {
+    HANDLE hThread = GetCurrentThread();
+    return ptr_to_jlong(hThread);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_OpenProcessToken(JNIEnv* env,
+    jclass this, jlong process, jint desiredAccess)
+{
+    HANDLE hProcess = (HANDLE)jlong_to_ptr(process);
+    HANDLE hToken;
+
+    if (OpenProcessToken(hProcess, (DWORD)desiredAccess, &hToken) == 0)
+        throwWindowsException(env, GetLastError());
+    return ptr_to_jlong(hToken);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_OpenThreadToken(JNIEnv* env,
+    jclass this, jlong thread, jint desiredAccess, jboolean openAsSelf)
+{
+    HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
+    HANDLE hToken;
+    BOOL bOpenAsSelf = (openAsSelf == JNI_TRUE) ? TRUE : FALSE;
+
+    if (OpenThreadToken(hThread, (DWORD)desiredAccess, bOpenAsSelf, &hToken) == 0) {
+        if (GetLastError() == ERROR_NO_TOKEN)
+            return (jlong)0;
+        throwWindowsException(env, GetLastError());
+    }
+    return ptr_to_jlong(hToken);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_DuplicateTokenEx(JNIEnv* env,
+    jclass this, jlong token, jint desiredAccess)
+{
+    HANDLE hToken = (HANDLE)jlong_to_ptr(token);
+    HANDLE resultToken;
+    BOOL res;
+
+    res = DuplicateTokenEx(hToken,
+                           (DWORD)desiredAccess,
+                           NULL,
+                           SecurityImpersonation,
+                           TokenImpersonation,
+                           &resultToken);
+    if (res == 0)
+        throwWindowsException(env, GetLastError());
+    return ptr_to_jlong(resultToken);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_SetThreadToken(JNIEnv* env,
+    jclass this, jlong thread, jlong token)
+{
+    HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
+    HANDLE hToken = (HANDLE)jlong_to_ptr(token);
+
+    if (SetThreadToken(hThread, hToken) == 0)
+        throwWindowsException(env, GetLastError());
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetTokenInformation(JNIEnv* env,
+    jclass this, jlong token, jint tokenInfoClass, jlong tokenInfo, jint tokenInfoLength)
+{
+    BOOL res;
+    DWORD lengthNeeded;
+    HANDLE hToken = (HANDLE)jlong_to_ptr(token);
+    LPVOID result = (LPVOID)jlong_to_ptr(tokenInfo);
+
+    res = GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)tokenInfoClass, (LPVOID)result,
+                              tokenInfoLength, &lengthNeeded);
+    if (res == 0) {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+            return (jint)lengthNeeded;
+        } else {
+            throwWindowsException(env, GetLastError());
+            return 0;
+        }
+    } else {
+        return tokenInfoLength;
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_AdjustTokenPrivileges(JNIEnv* env,
+    jclass this, jlong token, jlong luid, jint attributes)
+{
+    TOKEN_PRIVILEGES privs[1];
+    HANDLE hToken = (HANDLE)jlong_to_ptr(token);
+    PLUID pLuid = (PLUID)jlong_to_ptr(luid);
+
+    privs[0].PrivilegeCount = 1;
+    privs[0].Privileges[0].Luid = *pLuid;
+    privs[0].Privileges[0].Attributes = (DWORD)attributes;
+
+    if (AdjustTokenPrivileges(hToken, FALSE, &privs[0], 1, NULL, NULL) == 0)
+        throwWindowsException(env, GetLastError());
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_LookupPrivilegeValue0(JNIEnv* env,
+    jclass this, jlong name)
+{
+    LPCWSTR lpName = (LPCWSTR)jlong_to_ptr(name);
+    PLUID pLuid = LocalAlloc(0, sizeof(LUID));
+
+    if (pLuid == NULL) {
+        JNU_ThrowInternalError(env, "Unable to allocate LUID structure");
+    } else {
+        if (LookupPrivilegeValueW(NULL, lpName, pLuid) == 0)
+            throwWindowsException(env, GetLastError());
+    }
+    return ptr_to_jlong(pLuid);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_BuildTrusteeWithSid(JNIEnv* env,
+    jclass this, jlong sid)
+{
+    PSID pSid = (HANDLE)jlong_to_ptr(sid);
+    PTRUSTEE_W pTrustee = LocalAlloc(0, sizeof(TRUSTEE_W));
+
+    if (pTrustee == NULL) {
+        JNU_ThrowInternalError(env, "Unable to allocate TRUSTEE_W structure");
+    } else {
+        BuildTrusteeWithSidW(pTrustee, pSid);
+    }
+    return ptr_to_jlong(pTrustee);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetEffectiveRightsFromAcl(JNIEnv* env,
+    jclass this, jlong acl, jlong trustee)
+{
+    ACCESS_MASK access;
+    PACL pAcl = (PACL)jlong_to_ptr(acl);
+    PTRUSTEE pTrustee = (PTRUSTEE)jlong_to_ptr(trustee);
+
+    if (GetEffectiveRightsFromAcl(pAcl, pTrustee, &access) != ERROR_SUCCESS) {
+        throwWindowsException(env, GetLastError());
+    }
+    return (jint)access;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env,
+    jclass this, jlong linkAddress, jlong targetAddress, jint flags)
+{
+    LPCWSTR link = jlong_to_ptr(linkAddress);
+    LPCWSTR target = jlong_to_ptr(targetAddress);
+
+    if (CreateSymbolicLink_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return;
+    }
+
+    /* On Windows 64-bit this appears to succeed even when there is insufficient privileges */
+    if ((*CreateSymbolicLink_func)(link, target, (DWORD)flags) == 0)
+        throwWindowsException(env, GetLastError());
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CreateHardLink0(JNIEnv* env,
+    jclass this, jlong newFileAddress, jlong existingFileAddress)
+{
+    LPCWSTR newFile = jlong_to_ptr(newFileAddress);
+    LPCWSTR existingFile = jlong_to_ptr(existingFileAddress);
+
+    if (CreateHardLink_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return;
+    }
+    if ((*CreateHardLink_func)(newFile, existingFile, NULL) == 0)
+        throwWindowsException(env, GetLastError());
+}
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetFullPathName0(JNIEnv *env,
+                                                         jclass clz,
+                                                         jlong pathAddress)
+{
+    jstring rv = NULL;
+    WCHAR *lpBuf = NULL;
+    WCHAR buf[MAX_PATH];
+    DWORD len;
+    LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
+
+    len = GetFullPathNameW(lpFileName, MAX_PATH, buf, NULL);
+    if (len > 0) {
+        if (len < MAX_PATH) {
+            rv = (*env)->NewString(env, buf, len);
+        } else {
+            len += 1;  /* return length does not include terminator */
+            lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
+            if (lpBuf != NULL) {
+                len = GetFullPathNameW(lpFileName, len, lpBuf, NULL);
+                if (len > 0) {
+                    rv = (*env)->NewString(env, lpBuf, len);
+                } else {
+                    JNU_ThrowInternalError(env, "GetFullPathNameW failed");
+                }
+                free(lpBuf);
+            }
+        }
+    }
+    if (len == 0)
+        throwWindowsException(env, GetLastError());
+
+    return rv;
+}
+
+JNIEXPORT jstring JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
+    jclass this, jlong handle)
+{
+    jstring rv = NULL;
+    WCHAR *lpBuf = NULL;
+    WCHAR path[MAX_PATH];
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    DWORD len;
+
+    if (GetFinalPathNameByHandle_func == NULL) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return NULL;
+    }
+
+    len = (*GetFinalPathNameByHandle_func)(h, path, MAX_PATH, 0);
+    if (len > 0) {
+        if (len < MAX_PATH) {
+            rv = (*env)->NewString(env, (const jchar *)path, (jsize)len);
+        } else {
+            len += 1;  /* return length does not include terminator */
+            lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
+            if (lpBuf != NULL) {
+                len = (*GetFinalPathNameByHandle_func)(h, lpBuf, len, 0);
+                if (len > 0)  {
+                    rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len);
+                } else {
+                    JNU_ThrowInternalError(env, "GetFinalPathNameByHandleW failed");
+                }
+                free(lpBuf);
+            }
+        }
+    }
+
+    if (len == 0)
+        throwWindowsException(env, GetLastError());
+
+    return rv;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
+    jlong fileHandle, jlong existingPort, jint completionKey)
+{
+    HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
+                                         (HANDLE)jlong_to_ptr(existingPort),
+                                         (DWORD)completionKey,
+                                         0);
+    if (port == NULL) {
+        throwWindowsException(env, GetLastError());
+    }
+    return ptr_to_jlong(port);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env, jclass this,
+    jlong completionPort, jobject obj)
+{
+    DWORD bytesTransferred;
+    DWORD completionKey;
+    OVERLAPPED *lpOverlapped;
+    BOOL res;
+
+    res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
+                                  &bytesTransferred,
+                                  &completionKey,
+                                  &lpOverlapped,
+                                  INFINITE);
+    if (res == 0 && lpOverlapped == NULL) {
+        throwWindowsException(env, GetLastError());
+    } else {
+        DWORD ioResult = (res == 0) ? GetLastError() : 0;
+        (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
+        (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
+            (jint)bytesTransferred);
+        (*env)->SetIntField(env, obj, completionStatus_completionKey,
+            (jint)completionKey);
+
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
+    jlong completionPort, jint completionKey)
+{
+    BOOL res;
+
+    res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
+                                     (DWORD)0,  /* dwNumberOfBytesTransferred */
+                                     (DWORD)completionKey,
+                                     NULL);  /* lpOverlapped */
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this,
+    jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter,
+    jlong bytesReturnedAddress, jlong pOverlapped)
+{
+    BOOL res;
+    BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
+
+    ((LPOVERLAPPED)jlong_to_ptr(pOverlapped))->hEvent = NULL;
+    res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
+                                (LPVOID)jlong_to_ptr(bufferAddress),
+                                (DWORD)bufferLength,
+                                subtree,
+                                (DWORD)filter,
+                                (LPDWORD)jlong_to_ptr(bytesReturnedAddress),
+                                (LPOVERLAPPED)jlong_to_ptr(pOverlapped),
+                                NULL);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_BackupRead0(JNIEnv* env, jclass this,
+    jlong hFile, jlong bufferAddress, jint bufferSize, jboolean abort,
+    jlong context, jobject obj)
+{
+    BOOL res;
+    DWORD bytesTransferred;
+    BOOL a = (abort == JNI_TRUE) ? TRUE : FALSE;
+    VOID* pContext = (VOID*)jlong_to_ptr(context);
+
+    res = BackupRead((HANDLE)jlong_to_ptr(hFile),
+                     (LPBYTE)jlong_to_ptr(bufferAddress),
+                     (DWORD)bufferSize,
+                     &bytesTransferred,
+                     a,
+                     FALSE,
+                     &pContext);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    } else {
+        (*env)->SetIntField(env, obj, backupResult_bytesTransferred,
+            bytesTransferred);
+        (*env)->SetLongField(env, obj, backupResult_context,
+            ptr_to_jlong(pContext));
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_BackupSeek(JNIEnv* env, jclass this,
+    jlong hFile, jlong bytesToSeek, jlong context)
+{
+    BOOL res;
+    jint lowBytesToSeek = (jint)bytesToSeek;
+    jint highBytesToSeek = (jint)(bytesToSeek >> 32);
+    DWORD lowBytesSeeked;
+    DWORD highBytesSeeked;
+    VOID* pContext = jlong_to_ptr(context);
+
+    res = BackupSeek((HANDLE)jlong_to_ptr(hFile),
+                     (DWORD)lowBytesToSeek,
+                     (DWORD)highBytesToSeek,
+                     &lowBytesSeeked,
+                     &highBytesSeeked,
+                     &pContext);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/Sanity.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.util.*;
+import java.net.URI;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.FileVisitResult;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.Paths;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Sanity check zip provider by running a few simple tests.
+ */
+
+public class Sanity {
+    static int count;
+
+    public static void main(String[] args) throws Exception {
+        Path zipfile = Paths.get(args[0]);
+
+        // Test: zip should should be returned in provider list
+        boolean found = false;
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (provider.getScheme().equalsIgnoreCase("zip")) {
+                found = true;
+                break;
+            }
+        }
+        if (!found)
+            throw new RuntimeException("'zip' provider not installed");
+
+        // Test: FileSystems#newFileSystem(FileRef)
+        Map<String,?> env = new HashMap<String,Object>();
+        FileSystems.newFileSystem(zipfile, env, null).close();
+
+        // Test: FileSystems#newFileSystem(URI)
+        URI uri = URI.create("zip" + zipfile.toUri().toString().substring(4));
+        FileSystem fs = FileSystems.newFileSystem(uri, env, null);
+
+        // Test: exercise toUri method
+        String expected = uri.toString() + "#/foo";
+        String actual = fs.getPath("/foo").toUri().toString();
+        if (!actual.equals(expected)) {
+            throw new RuntimeException("toUri returned '" + actual +
+                "', expected '" + expected + "'");
+        }
+
+        // Test: exercise directory iterator and retrieval of basic attributes
+        Files.walkFileTree(fs.getPath("/"), new FileTreePrinter());
+
+        // Test: DirectoryStream with glob
+        count = 0;
+        Files.withDirectory(fs.getPath("/"), "M*-INF", new FileAction<Path>() {
+            public void invoke(Path file) {
+                if (file.toString().equals("META-INF"))
+                    throw new RuntimeException("Unexpected match: " + file);
+                count++;
+            }
+        });
+        if (count != 1)
+            throw new RuntimeException("Expected to match 1 file in directory");
+
+        // Test: copy file from zip file to current (scratch) directory
+        Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider");
+        if (source.exists()) {
+            Path target = Paths.get(source.getName().toString());
+            source.copyTo(target, StandardCopyOption.REPLACE_EXISTING);
+            try {
+                long s1 = Attributes.readBasicFileAttributes(source, true).size();
+                long s2 = Attributes.readBasicFileAttributes(target, true).size();
+                if (s2 != s1)
+                    throw new RuntimeException("target size != source size");
+            } finally {
+                target.delete(true);
+            }
+        }
+
+        // Test: readAttributes
+        Map<String,?> attrs = Attributes.readAttributes(source, true, "jar:*");
+        if (attrs.get("manifestAttributes") == null)
+            throw new RuntimeException("manifestAttributes missing");
+        long s1 = (Long)attrs.get("size");
+        long s2 = Attributes.readBasicFileAttributes(source, true).size();
+        if (s2 != s1)
+            throw new RuntimeException("size mis-match");
+
+        // Test: FileStore
+        FileStore store = fs.getPath("/").getFileStore();
+        if (!store.supportsFileAttributeView("basic"))
+            throw new RuntimeException("BasicFileAttributeView should be supported");
+
+        // Test: ClosedFileSystemException
+        fs.close();
+        if (fs.isOpen())
+            throw new RuntimeException("FileSystem should be closed");
+        try {
+            fs.getPath("/missing").checkAccess(AccessMode.READ);
+        } catch (ClosedFileSystemException x) { }
+    }
+
+    // FileVisitor that pretty prints a file tree
+    static class FileTreePrinter extends SimpleFileVisitor<Path> {
+        private int indent = 0;
+
+        private void indent() {
+            StringBuilder sb = new StringBuilder(indent);
+            for (int i=0; i<indent; i++) sb.append(" ");
+            System.out.print(sb);
+        }
+
+
+        public FileVisitResult preVisitDirectory(Path dir) {
+            if (dir.getName() != null) {
+                indent();
+                System.out.println(dir.getName() + "/");
+                indent++;
+            }
+            return FileVisitResult.CONTINUE;
+        }
+
+
+        public FileVisitResult visitFile(Path file,
+                                         BasicFileAttributes attrs)
+        {
+            indent();
+            System.out.print(file.getName());
+            if (attrs.isRegularFile())
+                System.out.format(" (%d)", attrs.size());
+            System.out.println();
+            return FileVisitResult.CONTINUE;
+        }
+
+
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+            if (exc != null)
+                super.postVisitDirectory(dir, exc);
+            if (dir.getName() != null)
+                indent--;
+            return FileVisitResult.CONTINUE;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/demo/nio/ZipFileSystem/sanity.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,71 @@
+#
+# Copyright 2007-2008 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 Sanity check ZipFileSystem demo
+# @build Sanity
+# @run shell sanity.sh
+
+if [ -z "${TESTJAVA}" ]; then
+    echo "Test must be run with jtreg"
+    exit 0
+fi
+
+ZIPFS="${TESTJAVA}/demo/nio/ZipFileSystem/ZipFileSystem.jar"
+if [ ! -r "${ZIPFS}" ]; then
+    echo "${ZIPFS} not found"
+    exit 0
+fi
+
+OS=`uname -s`
+case "$OS" in
+    Windows_* )
+        CLASSPATH="${TESTCLASSES};${ZIPFS}"
+        ;;
+    * )
+        CLASSPATH="${TESTCLASSES}:${ZIPFS}"
+        ;;
+esac
+export CLASSPATH
+
+failures=0
+
+go() {
+    echo ''
+    ${TESTJAVA}/bin/java $1 $2 $3 2>&1
+    if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+}
+
+# Run the tests
+
+go Sanity  "${ZIPFS}"
+
+#
+# Results
+#
+echo ''
+if [ $failures -gt 0 ];
+  then echo "$failures test(s) failed";
+  else echo "All test(s) passed"; fi
+exit $failures
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/io/Inputs/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2007-2008 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
+ * @summary Basic unit test for java.io.Inputs class
+ */
+
+import java.io.*;
+import java.util.*;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.MalformedInputException;
+
+import org.classpath.icedtea.java.io.Inputs;
+
+import org.classpath.icedtea.java.nio.file.Path;
+
+public class Basic {
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws IOException {
+        Path dir = createTempDir();
+        try {
+            testReadAllBytesMethods(dir);
+            testReadAllLinesMethods(dir);
+        } finally {
+            dir.delete();
+        }
+    }
+
+    static void testReadAllBytesMethods(Path dir) throws IOException {
+        // create file with random bytes
+        byte[] bytes = new byte[1 + rand.nextInt(64*1024)];
+        rand.nextBytes(bytes);
+        Path file = dir.resolve("foo");
+        Outputs.write(file, bytes);
+
+        try {
+            byte[] result;
+
+            // check all bytes are read
+            result = Inputs.readAllBytes(file);
+            if (!Arrays.equals(bytes, result))
+                throw new RuntimeException("Unexpected bytes");
+            result = Inputs.readAllBytes(new File(file.toString()));
+            if (!Arrays.equals(bytes, result))
+                throw new RuntimeException("Unexpected bytes");
+
+            // via URL connection
+            InputStream in = file.toUri().toURL().openConnection().getInputStream();
+            try {
+                result = Inputs.readAllBytes(in);
+            if (!Arrays.equals(bytes, result))
+                throw new RuntimeException("Unexpected bytes");
+            } finally {
+                in.close();
+            }
+
+            // test zero-length file
+            Outputs.write(file, new byte[0]);
+            if (Inputs.readAllBytes(file).length != 0)
+                throw new RuntimeException("Unexpected bytes");
+
+            // NullPointerException
+            try {
+                Inputs.readAllBytes((FileRef)null);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException npe) { }
+
+            try {
+                Inputs.readAllBytes((File)null);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException npe) { }
+
+            try {
+                Inputs.readAllBytes((InputStream)null);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException npe) { }
+
+        } finally {
+            file.delete();
+        }
+    }
+
+    static void testReadAllLinesMethods(Path dir) throws IOException {
+        String[] poem = { "I met a traveler from an antique land",
+                          "Who said: Two vast and trunkless legs of stone",
+                          "Stand in the desert. Near them, on the sand",
+                          "Half sunk, a shattered visage lies, whose frown,",
+                          "And wrinkled lip, and sneer of cold command,",
+                          "Tell that its sculptor well those passions read",
+                          "Which yet survive, stamped on these lifeless things,",
+                          "The hand that mocked them, and the heart that fed;",
+                          "And on the pedestal these words appear:",
+                          "My name is Ozymandias, king of kings:",
+                          "Look upon my works, ye Mighty, and despair!",
+                          "Nothing beside remains. Round the decay",
+                          "Of that colossal wreck, boundless and bare",
+                          "The lone and level sands stretch far away." };
+        List<String> poemAsList = Arrays.asList(poem);
+
+        Path file = dir.resolve("Shelley");
+        try {
+            Outputs.writeLines(file, poem);
+
+            checkEquals(poemAsList, Inputs.readAllLines(file));
+            checkEquals(poemAsList, Inputs.readAllLines(file, "UTF-8"));
+            checkEquals(poemAsList, Inputs.readAllLines(new File(file.toString())));
+            checkEquals(poemAsList,
+                Inputs.readAllLines(new File(file.toString()), "UTF-8"));
+            InputStream in = file.newInputStream();
+            try {
+                checkEquals(poemAsList, Inputs.readAllLines(in));
+            } finally {
+                in.close();
+            }
+            InputStreamReader reader = new InputStreamReader(file.newInputStream());
+            try {
+                checkEquals(poemAsList, Inputs.readAllLines(reader));
+            } finally {
+                reader.close();
+            }
+
+            // IOException
+            try {
+                Inputs.readAllLines(dir.resolve("doesNotExist"));
+                throw new RuntimeException("IOException expected");
+            } catch (IOException ignore) { }
+
+            // MalformedInputException
+            OutputStream out = file.newOutputStream();
+            try {
+                out.write((byte)0xC2);  // malformed 2-byte sequence
+                out.write((byte)0x00);
+            } finally {
+                out.close();
+            }
+            try {
+                Inputs.readAllLines(file, "UTF-8");
+                throw new RuntimeException("MalformedInputException expected");
+            } catch (MalformedInputException ignore) { }
+
+            // UnsupportedCharsetException
+            try {
+                Inputs.readAllLines(file, "BAD-CHARSET");
+                throw new RuntimeException("UnsupportedCharsetException expected");
+            } catch (UnsupportedCharsetException ignore) { }
+
+            try {
+                Inputs.readAllLines(new File(file.toString()), "BAD-CHARSET");
+                throw new RuntimeException("UnsupportedCharsetException expected");
+            } catch (UnsupportedCharsetException ignore) { }
+            in = file.newInputStream();
+            try {
+                try {
+                    Inputs.readAllLines(in, "BAD-CHARSET");
+                    throw new RuntimeException("UnsupportedCharsetException expected");
+                } catch (UnsupportedCharsetException ignore) { }
+            } finally {
+                in.close();
+            }
+
+            // NulPointerException
+            try {
+                Inputs.readAllLines((FileRef)null);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException npe) { }
+            try {
+                Inputs.readAllLines((FileRef)null, "UTF-8");
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException npe) { }
+
+            try {
+                Inputs.readAllLines(file, null);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException npe) { }
+
+        } finally {
+            file.delete();
+        }
+    }
+
+    static void checkEquals(List<String> expected, List<String> actual) {
+        if (!actual.equals(expected))
+            throw new RuntimeException();
+    }
+
+
+    static Path createTempDir() throws IOException {
+        Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+        Random r = new Random();
+
+        Path dir;
+        do {
+            dir = tmpdir.resolve("name" + r.nextInt());
+        } while (dir.exists());
+        return dir.createDirectory();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.util.concurrent.*;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup;
+
+/**
+ * Test that arbitrary tasks can be submitted to a channel group's thread pool.
+ */
+
+public class AsExecutor {
+
+    public static void main(String[] args) throws Exception {
+        // create channel groups
+        ThreadFactory factory = new PrivilegedThreadFactory();
+        int nThreads = 5;
+        ExecutorService pool = Executors.newFixedThreadPool(5, factory);
+        AsynchronousChannelGroup group1 = AsynchronousChannelGroup
+            .withFixedThreadPool(pool, nThreads);
+        AsynchronousChannelGroup group2 = AsynchronousChannelGroup
+            .withCachedThreadPool(Executors.newCachedThreadPool(factory), 0);
+
+        try {
+            // execute simple tasks
+            testSimpleTask(group1);
+            testSimpleTask(group2);
+
+            // install security manager and test again
+            System.setSecurityManager( new SecurityManager() );
+            testSimpleTask(group1);
+            testSimpleTask(group2);
+
+            // attempt to execute tasks that run with only frames from boot
+            // class loader on the stack.
+            testAttackingTask(group1);
+            testAttackingTask(group2);
+        } finally {
+            group1.shutdown();
+            group2.shutdown();
+        }
+    }
+
+    static void testSimpleTask(AsynchronousChannelGroup group) throws Exception {
+        Executor executor = (Executor)group;
+        final CountDownLatch latch = new CountDownLatch(1);
+        executor.execute(new Runnable() {
+            public void run() {
+                latch.countDown();
+            }
+        });
+        latch.await();
+    }
+
+    static void testAttackingTask(AsynchronousChannelGroup group) throws Exception {
+        Executor executor = (Executor)group;
+        Attack task = new Attack();
+        executor.execute(task);
+        task.waitUntilDone();
+        if (!task.failedDueToSecurityException())
+            throw new RuntimeException("SecurityException expected");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Attack.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.net.*;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A task that attempts to attack the current host.
+ */
+
+public class Attack implements Runnable {
+    private final CountDownLatch latch = new CountDownLatch(1);
+    private volatile boolean failedDueToSecurityException;
+
+    public void Attack() {
+        // check class is on boot class path
+        if (Attack.class.getClassLoader() != null)
+            throw new RuntimeException("Attack class not on boot class path");
+    }
+
+
+    public void run() {
+        try {
+            new Socket("127.0.0.1", 9999).close();
+            throw new RuntimeException("Connected (not expected)");
+        } catch (IOException e) {
+            throw new RuntimeException("IOException (not expected)");
+        } catch (SecurityException e) {
+            failedDueToSecurityException = true;
+        } finally {
+            latch.countDown();
+        }
+    }
+
+    public void waitUntilDone() throws InterruptedException {
+        latch.await();
+    }
+
+    public boolean failedDueToSecurityException() {
+        return failedDueToSecurityException;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousChannelGroup
+ * @build Basic
+ * @run main/othervm -XX:-UseVMInterruptibleIO Basic
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup;
+
+public class Basic {
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+        shutdownTests();
+        shutdownNowTests();
+        afterShutdownTests();
+        miscTests();
+    }
+
+    static void shutdownTests() throws Exception {
+        System.out.println("-- test shutdown --");
+
+        // test shutdown with no channels in groups
+        for (int i=0; i<500; i++) {
+            ExecutorService pool;
+            AsynchronousChannelGroup group;
+            if (rand.nextBoolean()) {
+                pool = Executors.newCachedThreadPool();
+                group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
+            } else {
+                int nThreads = 1 + rand.nextInt(8);
+                pool = Executors.newFixedThreadPool(nThreads);
+                group = AsynchronousChannelGroup.withFixedThreadPool(pool, nThreads);
+            }
+            group.shutdown();
+            if (!group.isShutdown())
+                throw new RuntimeException("Group should be shutdown");
+            // group should terminate quickly
+            boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+            if (!terminated)
+                throw new RuntimeException("Group should have terminated");
+            if (!pool.isTerminated())
+                throw new RuntimeException("Executor should have terminated");
+        }
+
+        // shutdown with channel in group
+        for (int i=0; i<500; i++) {
+            ExecutorService pool;
+            AsynchronousChannelGroup group;
+            if (rand.nextBoolean()) {
+                pool = Executors.newCachedThreadPool();
+                group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(10));
+            } else {
+                int nThreads = 1 + rand.nextInt(8);
+                pool = Executors.newFixedThreadPool(nThreads);
+                group = AsynchronousChannelGroup.withFixedThreadPool(pool, nThreads);
+            }
+            // create channel that is bound to group
+            AsynchronousChannel ch;
+            switch (rand.nextInt(3)) {
+                case 0 : ch = AsynchronousSocketChannel.open(group); break;
+                case 1 : ch = AsynchronousServerSocketChannel.open(group); break;
+                case 2 : ch = AsynchronousDatagramChannel.open(null, group); break;
+                default : throw new AssertionError();
+            }
+            group.shutdown();
+            if (!group.isShutdown())
+                throw new RuntimeException("Group should be shutdown");
+
+            // last channel so should terminate after this channel is closed
+            ch.close();
+
+            // group should terminate quickly
+            boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+            if (!terminated)
+                throw new RuntimeException("Group should have terminated");
+            if (!pool.isTerminated())
+                throw new RuntimeException("Executor should have terminated");
+        }
+    }
+
+    static void shutdownNowTests() throws Exception {
+        System.out.println("-- test shutdownNow --");
+
+        for (int i=0; i< 10; i++) {
+            ExecutorService pool;
+            AsynchronousChannelGroup group;
+            if (rand.nextBoolean()) {
+                pool = Executors.newCachedThreadPool();
+                group = AsynchronousChannelGroup
+                    .withCachedThreadPool(pool, rand.nextInt(5));
+            } else {
+                int nThreads = 1 + rand.nextInt(8);
+                pool = Executors.newFixedThreadPool(nThreads);
+                group = AsynchronousChannelGroup.withFixedThreadPool(pool, nThreads);
+            }
+
+            // I/O in progress
+            AsynchronousChannel ch;
+            if (rand.nextBoolean()) {
+                AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel
+                    .open(group).bind(new InetSocketAddress(0));
+                listener.accept();
+                ch = listener;
+            } else {
+                AsynchronousDatagramChannel adc =
+                    AsynchronousDatagramChannel.open(null, group);
+                adc.receive(ByteBuffer.allocate(100));
+                ch = adc;
+            }
+
+            // forceful shutdown
+            group.shutdownNow();
+
+            // shutdownNow is required to close all channels
+            if (ch.isOpen())
+                throw new RuntimeException("Channel should be closed");
+
+            boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+            if (!terminated)
+                throw new RuntimeException("Group should have terminated");
+            if (!pool.isTerminated())
+                throw new RuntimeException("Executor should have terminated");
+        }
+    }
+
+    // test creating channels in group after group is shutdown
+    static void afterShutdownTests() throws Exception {
+        System.out.println("-- test operations after group is shutdown  --");
+        ExecutorService pool = Executors.newFixedThreadPool(1);
+        AsynchronousChannelGroup group =
+            AsynchronousChannelGroup.withFixedThreadPool(pool, 1);
+
+        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+        AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(group);
+
+        // initiate accept
+        listener.bind(new InetSocketAddress(0));
+        Future<AsynchronousSocketChannel> result = listener.accept();
+
+        // shutdown group
+        group.shutdown();
+        if (!group.isShutdown())
+            throw new RuntimeException("Group should be shutdown");
+
+        // attempt to create another channel
+        try {
+            AsynchronousSocketChannel.open(group);
+            throw new RuntimeException("ShutdownChannelGroupException expected");
+        } catch (ShutdownChannelGroupException x) {
+        }
+        try {
+            AsynchronousServerSocketChannel.open(group);
+            throw new RuntimeException("ShutdownChannelGroupException expected");
+        } catch (ShutdownChannelGroupException x) {
+        }
+
+        // attempt to create another channel by connecting. This should cause
+        // the accept operation to fail.
+        InetAddress lh = InetAddress.getLocalHost();
+        int port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
+        InetSocketAddress isa = new InetSocketAddress(lh, port);
+        ch.connect(isa).get();
+        try {
+            result.get();
+            throw new RuntimeException("Connection was accepted");
+        } catch (ExecutionException x) {
+            Throwable cause = x.getCause();
+            if (!(cause instanceof IOException))
+                throw new RuntimeException("Cause should be IOException");
+            cause = cause.getCause();
+            if (!(cause instanceof ShutdownChannelGroupException))
+                throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
+        }
+
+        // initiate another accept even though channel group is shutdown.
+        Future<AsynchronousSocketChannel> res = listener.accept();
+        try {
+            res.get(3, TimeUnit.SECONDS);
+            throw new RuntimeException("TimeoutException expected");
+        } catch (TimeoutException x) {
+        }
+        // connect to the listener which should cause the accept to complete
+        AsynchronousSocketChannel.open().connect(isa);
+        try {
+            res.get();
+            throw new RuntimeException("Connection was accepted");
+        } catch (ExecutionException x) {
+            Throwable cause = x.getCause();
+            if (!(cause instanceof IOException))
+                throw new RuntimeException("Cause should be IOException");
+            cause = cause.getCause();
+            if (!(cause instanceof ShutdownChannelGroupException))
+                throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
+        }
+
+        // group should *not* terminate as channels are open
+        boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+        if (terminated)
+            throw new RuntimeException("Group should not have terminated");
+
+        // close channel; group should terminate quickly
+        ch.close();
+        listener.close();
+        terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+        if (!terminated)
+            throw new RuntimeException("Group should have terminated");
+    }
+
+    static void miscTests() throws Exception {
+        System.out.println("-- miscellenous tests --");
+        try {
+            AsynchronousChannelGroup.withFixedThreadPool(null, 1);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) {
+        }
+        ExecutorService pool = Executors.newCachedThreadPool();
+        try {
+            AsynchronousChannelGroup.withFixedThreadPool(pool, 0);
+            throw new RuntimeException("IAE expected");
+        } catch (IllegalArgumentException e) {
+        } finally {
+            pool.shutdown();
+        }
+        try {
+            AsynchronousChannelGroup.withCachedThreadPool(null, 0);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousChannelGroup
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+
+/**
+ * This test verifies that a channel or channel group can be closed from a
+ * completion handler when there are no threads available to handle I/O events.
+ */
+
+public class GroupOfOne {
+
+    public static void main(String[] args) throws Exception {
+        // create listener to accept connections
+        final AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open()
+                .bind(new InetSocketAddress(0));
+        listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+            public void completed(AsynchronousSocketChannel ch, Void att) {
+                listener.accept(null, this);
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+        SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
+
+        test(sa, true, false);
+        test(sa, false, true);
+        test(sa, true, true);
+    }
+
+    static void test(SocketAddress sa,
+                     final boolean closeChannel,
+                     final boolean shutdownGroup)
+        throws Exception
+    {
+        // group with 1 thread
+        ExecutorService pool = Executors.newFixedThreadPool(1);
+        final AsynchronousChannelGroup group =
+            AsynchronousChannelGroup.withFixedThreadPool(pool, 1);
+        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+
+        // the latch counts down when:
+        // 1. The read operation fails (expected)
+        // 2. the close/shutdown completes
+        final CountDownLatch latch = new CountDownLatch(2);
+
+        ch.connect(sa, null, new CompletionHandler<Void,Void>() {
+            public void completed(Void result, Void att)  {
+                System.out.println("Connected");
+
+                // initiate I/O operation that does not complete (successfully)
+                ByteBuffer buf = ByteBuffer.allocate(100);
+                ch.read(buf, null, new CompletionHandler<Integer,Void>() {
+                    public void completed(Integer bytesRead, Void att)  {
+                        throw new RuntimeException();
+                    }
+                    public void failed(Throwable exc, Void att) {
+                        if (!(exc instanceof AsynchronousCloseException))
+                            throw new RuntimeException(exc);
+                        System.out.println("Read failed (expected)");
+                        latch.countDown();
+                    }
+                    public void cancelled(Void att) {
+                        throw new RuntimeException();
+                    }
+                });
+
+                // close channel or shutdown group
+                try {
+                    if (closeChannel) {
+                        System.out.print("Close channel ...");
+                        ch.close();
+                        System.out.println(" done.");
+                    }
+                    if (shutdownGroup) {
+                        System.out.print("Shutdown group ...");
+                        group.shutdownNow();
+                        System.out.println(" done.");
+                    }
+                    latch.countDown();
+                } catch (IOException e) {
+                    throw new RuntimeException();
+                }
+            }
+            public void failed(Throwable exc, Void att) {
+                throw new RuntimeException(exc);
+            }
+            public void cancelled(Void att) {
+                throw new RuntimeException();
+            }
+        });
+
+        latch.await();
+
+        // clean-up
+        group.shutdown();
+        boolean terminated = group.awaitTermination(5, TimeUnit.SECONDS);
+        if (!terminated)
+            throw new RuntimeException("Group did not terminate");
+
+        System.out.println("TEST OKAY");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Identity.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousChannelGroup
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * Tests that the completion handler is invoked by a thread with
+ * the expected identity.
+ */
+
+public class Identity {
+    static final Random rand = new Random();
+    static final CountDownLatch done = new CountDownLatch(1);
+    static final AtomicBoolean failed = new AtomicBoolean(false);
+
+    static void fail(String msg) {
+        failed.set(true);
+        done.countDown();
+        throw new RuntimeException(msg);
+    }
+
+    // thread-local identifies the thread
+    private static final ThreadLocal<Integer> myGroup =
+        new ThreadLocal<Integer>() {
+ protected Integer initialValue() {
+                return Integer.valueOf(-1);
+            }
+        };
+
+    // creates a ThreadFactory that constructs groups with the given identity
+    static final ThreadFactory createThreadFactory(final int groupId) {
+        return new ThreadFactory() {
+
+            public Thread newThread(final Runnable r) {
+                Thread t = new Thread(new Runnable() {
+                    public void run() {
+                        myGroup.set(groupId);
+                        r.run();
+                    }});
+                t.setDaemon(true);
+                return t;
+            }
+        };
+    }
+
+    public static void main(String[] args) throws Exception {
+        // create listener to accept connections
+        final AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open()
+                .bind(new InetSocketAddress(0));
+        listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+            public void completed(final AsynchronousSocketChannel ch, Void att) {
+                listener.accept(null, this);
+
+                final ByteBuffer buf = ByteBuffer.allocate(100);
+                ch.read(buf, null, new CompletionHandler<Integer,Void>() {
+                    public void completed(Integer bytesRead, Void att) {
+                        buf.clear();
+                        ch.read(buf, null, this);
+                    }
+                    public void failed(Throwable exc, Void att) {
+                    }
+                    public void cancelled(Void att) {
+                    }
+                });
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+        SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
+
+        // create 3-10 channels, each in its own group
+        final int groupCount = 3 + rand.nextInt(8);
+        final AsynchronousSocketChannel[] channel = new AsynchronousSocketChannel[groupCount];
+        for (int i=0; i<groupCount; i++) {
+            ThreadFactory factory = createThreadFactory(i);
+            AsynchronousChannelGroup group;
+            if (rand.nextBoolean()) {
+                int nThreads = 1 + rand.nextInt(10);
+                ExecutorService pool = Executors.newFixedThreadPool(nThreads, factory);
+                group = AsynchronousChannelGroup.withFixedThreadPool(pool, nThreads);
+            } else {
+                ExecutorService pool = Executors.newCachedThreadPool(factory);
+                group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
+            }
+
+            // create channel in group and connect it to the server
+            AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+            ch.connect(sa).get();
+            channel[i] = ch;
+        }
+
+        // randomly write to each channel, ensuring that the completion handler
+        // is always invoked by a thread with the right identity.
+        final AtomicInteger writeCount = new AtomicInteger(100);
+        channel[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
+            public void completed(Integer bytesWritten, Integer groupId) {
+                if (bytesWritten != 1)
+                    fail("Expected 1 byte to be written");
+                if (!myGroup.get().equals(groupId))
+                    fail("Handler invoked by thread with the wrong identity");
+                if (writeCount.decrementAndGet() > 0) {
+                    int id = rand.nextInt(groupCount);
+                    channel[id].write(getBuffer(), id, this);
+                } else {
+                    done.countDown();
+                }
+            }
+            public void failed(Throwable exc, Integer groupId) {
+                fail(exc.getMessage());
+            }
+            public void cancelled(Integer groupId) {
+                fail("I/O operation was cancelled");
+            }
+        });
+
+        // wait until
+        done.await();
+        if (failed.get())
+            throw new RuntimeException("Test failed - see log for details");
+    }
+
+    static ByteBuffer getBuffer() {
+        ByteBuffer buf;
+        if (rand.nextBoolean()) {
+            buf = ByteBuffer.allocateDirect(1);
+        } else {
+            buf = ByteBuffer.allocate(1);
+        }
+        buf.put((byte)0);
+        buf.flip();
+        return buf;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.util.concurrent.ThreadFactory;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * The "privileged" ThreadFactory used by the AsExecutor test.
+ */
+
+public class PrivilegedThreadFactory implements ThreadFactory {
+    public void PrivilegedThreadPoolFactory() {
+        // check class is on boot class path
+        if (PrivilegedThreadFactory.class.getClassLoader() != null)
+            throw new RuntimeException("PrivilegedThreadFactory class not on boot class path");
+    }
+
+
+    public Thread newThread(final Runnable r) {
+        return AccessController.doPrivileged(new PrivilegedAction<Thread>() {
+
+            public Thread run() {
+                Thread t = new Thread(r);
+                t.setDaemon(true);
+                return t;
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Restart.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousChannelGroup
+ * @build Restart
+ * @run main/othervm -XX:-UseVMInterruptibleIO Restart
+ */
+
+import java.nio.channels.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.io.IOException;
+
+/**
+ * Exercise replacement of threads in the thread pool when completion handlers
+ * terminate due to errors or runtime exceptions.
+ */
+
+public class Restart {
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+        // thread group for thread pools
+        final ThreadGroup tg = new ThreadGroup("test");
+
+        // keep track of the number of threads that terminate
+        final AtomicInteger exceptionCount = new AtomicInteger(0);
+        final Thread.UncaughtExceptionHandler ueh =
+            new Thread.UncaughtExceptionHandler() {
+                public void uncaughtException(Thread t, Throwable e) {
+                    exceptionCount.incrementAndGet();
+                }
+            };
+        ThreadFactory factory = new ThreadFactory() {
+
+            public Thread newThread(Runnable r) {
+                Thread t = new Thread(tg, r);
+                t.setUncaughtExceptionHandler(ueh);
+                return t;
+            }
+        };
+
+        // group with fixed thread pool
+        int nThreads = 1 + rand.nextInt(4);
+        ExecutorService pool = Executors.newFixedThreadPool(nThreads, factory);
+        AsynchronousChannelGroup group =
+            AsynchronousChannelGroup.withFixedThreadPool(pool, nThreads);
+        testRestart(group, 100);
+        group.shutdown();
+
+        // group with thread pool created automatically
+        pool = Executors.newCachedThreadPool(factory);
+        group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
+        testRestart(group, 100);
+        group.shutdown();
+
+        // give time for threads to terminate
+        Thread.sleep(3000);
+        int actual = exceptionCount.get();
+        if (actual != 200)
+            throw new RuntimeException(actual + " exceptions, expected: " + 200);
+    }
+
+    static void testRestart(AsynchronousChannelGroup group, int count)
+        throws Exception
+    {
+        AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open(group)
+                .bind(new InetSocketAddress(0));
+
+        for (int i=0; i<count; i++) {
+            final CountDownLatch latch = new CountDownLatch(1);
+
+            listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+                public void completed(AsynchronousSocketChannel ch, Void att) {
+                    try {
+                        ch.close();
+                    } catch (IOException ignore) { }
+
+                    latch.countDown();
+
+                    // throw error or runtime exception
+                    if (rand.nextBoolean()) {
+                        throw new Error();
+                    } else {
+                        throw new RuntimeException();
+                    }
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+                public void cancelled(Void att) {
+                }
+            });
+
+            // establish loopback connection which should cause completion
+            // handler to be invoked.
+            int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+            AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+            InetAddress lh = InetAddress.getLocalHost();
+            ch.connect(new InetSocketAddress(lh, port)).get();
+            ch.close();
+
+            // wait for handler to be invoked
+            latch.await();
+        }
+
+        // clean-up
+        listener.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Unbounded.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousChannelGroup
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+
+public class Unbounded {
+    // number of concurrent completion handlers
+    static final int CONCURRENCY_COUNT = 512;
+
+    public static void main(String[] args) throws Exception {
+        // all accepted connections are added to a queue
+        final ArrayBlockingQueue<AsynchronousSocketChannel> queue =
+            new ArrayBlockingQueue<AsynchronousSocketChannel>(CONCURRENCY_COUNT);
+
+        // create listener to accept connections
+        final AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open()
+                .bind(new InetSocketAddress(0));
+        listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+            public void completed(AsynchronousSocketChannel ch, Void att) {
+                queue.add(ch);
+                listener.accept(null, this);
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        System.out.println("Listener created.");
+
+        // establish lots of connections
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+        SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
+        AsynchronousSocketChannel[] channels =
+            new AsynchronousSocketChannel[CONCURRENCY_COUNT];
+        for (int i=0; i<CONCURRENCY_COUNT; i++) {
+            int attempts = 0;
+            for (;;) {
+                try {
+                    channels[i] = AsynchronousSocketChannel.open();
+                    channels[i].connect(sa).get();
+                    break;
+                } catch (IOException x) {
+                    // probably resource issue so back off and retry
+                    if (++attempts >= 3)
+                        throw x;
+                    Thread.sleep(50);
+                }
+            }
+        }
+        System.out.println("All connection established.");
+
+        // the barrier where all threads (plus the main thread) wait
+        final CyclicBarrier barrier = new CyclicBarrier(CONCURRENCY_COUNT+1);
+
+        // initiate a read operation on each channel.
+        for (int i=0; i<CONCURRENCY_COUNT; i++) {
+            ByteBuffer buf = ByteBuffer.allocateDirect(100);
+            channels[i].read( buf, channels[i],
+                new CompletionHandler<Integer,AsynchronousSocketChannel>() {
+                    public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
+                        try {
+                            ch.close();
+                            barrier.await();
+                        } catch (Exception x) {
+                            throw new AssertionError(x);
+                        }
+                    }
+                    public void failed(Throwable exc, AsynchronousSocketChannel ch) {
+                    }
+                    public void cancelled(AsynchronousSocketChannel ch) {
+                    }
+                });
+        }
+        System.out.println("All read operations outstanding.");
+
+        // write data to each of the accepted connections
+        int remaining = CONCURRENCY_COUNT;
+        while (remaining > 0) {
+            AsynchronousSocketChannel ch = queue.take();
+            ch.write(ByteBuffer.wrap("welcome".getBytes())).get();
+            ch.close();
+            remaining--;
+        }
+
+        // wait for all threads to reach the barrier
+        System.out.println("Waiting for all threads to reach barrier");
+        barrier.await();
+        listener.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,52 @@
+#
+# Copyright 2007-2008 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 4607272
+# @summary Unit test for AsynchronousChannelGrou#execute
+# @build AsExecutor PrivilegedThreadFactory Attack
+# @run shell run_any_task.sh
+
+# if TESTJAVA isn't set then we assume an interactive run.
+
+if [ -z "$TESTJAVA" ]; then
+    TESTSRC=.
+    TESTCLASSES=.
+    JAVA=java
+    JAR=jar
+else
+    JAVA="${TESTJAVA}/bin/java"
+    JAR="${TESTJAVA}/bin/jar"
+fi
+
+echo "Creating JAR file ..."
+$JAR -cf "${TESTCLASSES}/Privileged.jar" \
+    -C "${TESTCLASSES}" PrivilegedThreadFactory.class \
+    -C "${TESTCLASSES}" PrivilegedThreadFactory\$1.class \
+    -C "${TESTCLASSES}" Attack.class
+
+echo "Running test ..."
+$JAVA -XX:-UseVMInterruptibleIO \
+    -Xbootclasspath/a:"${TESTCLASSES}/Privileged.jar" \
+    -classpath "${TESTCLASSES}" \
+    AsExecutor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2007-2008 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 4527345
+ * @summary Unit test for AsynchronousDatagramChannel
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+public class Basic {
+
+    public static void main(String[] args) throws Exception {
+        doReceiveTests();
+        doReadTests();
+        doSendTests();
+        doWriteTests();
+        doMulticastTests();
+    }
+
+    // basic receive tests
+    static void doReceiveTests() throws Exception {
+        final byte[] msg = "hello".getBytes();
+
+        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
+            .bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
+        InetAddress rh = InetAddress.getLocalHost();
+        final SocketAddress sa = new InetSocketAddress(rh, port);
+
+        DatagramChannel sender = DatagramChannel.open();
+        ByteBuffer dst = ByteBuffer.allocateDirect(100);
+
+        // Test: datagram packet received immediately
+        sender.send(ByteBuffer.wrap(msg), sa);
+        dst.clear();
+        ch.receive(dst).get(1, TimeUnit.SECONDS);
+        if (dst.flip().remaining() != msg.length)
+            throw new RuntimeException("Unexpected number of bytes read");
+
+        // Test: datagram packet not received immediately
+        dst.clear();
+        final CountDownLatch latch = new CountDownLatch(1);
+        ch.receive(dst, null, new CompletionHandler<SocketAddress,Void>() {
+            public void completed(SocketAddress source, Void att) {
+                latch.countDown();
+            }
+            public void failed (Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        Thread.sleep(2000);
+        sender.send(ByteBuffer.wrap(msg), sa);
+        latch.await(2, TimeUnit.SECONDS);  // wait for completion handler
+
+        // Test: timeout
+        dst.clear();
+        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
+        ch.receive(dst, 2, TimeUnit.SECONDS, null, new CompletionHandler<SocketAddress,Void>() {
+            public void completed(SocketAddress source, Void att) {
+            }
+            public void failed (Throwable exc, Void att) {
+                exception.set(exc);
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        Throwable result;
+        while ((result = exception.get()) == null) {
+            Thread.sleep(100);
+        }
+        if (!(result instanceof InterruptedByTimeoutException))
+            throw new RuntimeException("InterruptedByTimeoutException expected");
+
+        // AsynchronousCloseException
+        dst = ByteBuffer.allocateDirect(100);
+        exception.set(null);
+        ch.receive(dst, null, new CompletionHandler<SocketAddress,Void>() {
+            public void completed(SocketAddress source, Void att) {
+            }
+            public void failed (Throwable exc, Void att) {
+                exception.set(exc);
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        ch.close();
+        while ((result = exception.get()) == null) {
+            Thread.sleep(100);
+        }
+        if (!(result instanceof AsynchronousCloseException))
+            throw new RuntimeException("AsynchronousCloseException expected");
+
+        // done
+        sender.close();
+    }
+
+    // basic read tests
+    static void doReadTests() throws Exception {
+        final byte[] msg = "hello".getBytes();
+
+        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
+            .bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
+        InetAddress lh = InetAddress.getLocalHost();
+        final SocketAddress sa = new InetSocketAddress(lh, port);
+
+        DatagramChannel sender = DatagramChannel.open();
+        ByteBuffer dst = ByteBuffer.allocateDirect(100);
+
+        // Test: not connected
+        try {
+            ch.read(dst);
+            throw new RuntimeException("NotYetConnectedException expected");
+        } catch (NotYetConnectedException e) {
+        }
+
+        // connect the channel
+        sender.bind(new InetSocketAddress(0));
+        ch.connect(new InetSocketAddress(lh,
+                ((InetSocketAddress)(sender.getLocalAddress())).getPort()));
+
+        // Test: datagram packet received immediately
+        sender.send(ByteBuffer.wrap(msg), sa);
+        dst.clear();
+        ch.read(dst).get(1, TimeUnit.SECONDS);
+        if (dst.flip().remaining() != msg.length)
+            throw new RuntimeException("Unexpected number of bytes read");
+
+        // Test: datagram packet not received immediately
+        dst.clear();
+        final CountDownLatch l1 = new CountDownLatch(1);
+        ch.read(dst, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer bytesRead, Void att) {
+                l1.countDown();
+            }
+            public void failed (Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        Thread.sleep(2000);
+        sender.send(ByteBuffer.wrap(msg), sa);
+        l1.await(2, TimeUnit.SECONDS);
+
+        // Test: timeout
+        dst.clear();
+        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
+        ch.read(dst, 2, TimeUnit.SECONDS, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer bytesRead, Void att) {
+            }
+            public void failed (Throwable exc, Void att) {
+                exception.set(exc);
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        Throwable result;
+        while ((result = exception.get()) == null) {
+            Thread.sleep(100);
+        }
+        if (!(result instanceof InterruptedByTimeoutException))
+            throw new RuntimeException("InterruptedByTimeoutException expected");
+
+        // AsynchronousCloseException
+        dst.clear();
+        exception.set(null);
+        ch.read(dst, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer bytesRead, Void att) {
+            }
+            public void failed (Throwable exc, Void att) {
+                exception.set(exc);
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        ch.close();
+        while ((result = exception.get()) == null) {
+            Thread.sleep(100);
+        }
+        if (!(result instanceof AsynchronousCloseException))
+            throw new RuntimeException("AsynchronousCloseException expected");
+
+        // done
+        sender.close();
+    }
+
+    // basic send tests
+    static void doSendTests() throws Exception {
+        final byte[] msg = "hello".getBytes();
+
+        DatagramChannel reader = DatagramChannel.open()
+            .bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
+        InetAddress rh = InetAddress.getLocalHost();
+        SocketAddress sa = new InetSocketAddress(rh, port);
+
+        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
+
+        // Test: send datagram packet to reader
+        int bytesSent = ch.send(ByteBuffer.wrap(msg), sa).get();
+        if (bytesSent != msg.length)
+            throw new RuntimeException("Unexpected number of bytes sent");
+
+        // check received
+        ByteBuffer dst = ByteBuffer.allocateDirect(100);
+        reader.receive(dst);
+        dst.flip();
+        if (dst.remaining() != msg.length)
+            throw new RuntimeException("Unexpected number of bytes received");
+
+        // Test: send datagram packet to reader and check completion handler
+        // is invoked
+        final CountDownLatch l2 = new CountDownLatch(1);
+        ch.send(ByteBuffer.wrap(msg), sa, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer bytesSent, Void att) {
+                if (bytesSent != msg.length)
+                    throw new RuntimeException("Unexpected number of bytes received");
+                l2.countDown();
+            }
+            public void failed (Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        l2.await(5, TimeUnit.SECONDS);
+
+        // check received
+        dst.clear();
+        reader.receive(dst);
+        dst.flip();
+        if (dst.remaining() != msg.length)
+            throw new RuntimeException("Unexpected number of bytes received");
+
+        // Test: check that failed method is invoked
+        ch.close();
+        final CountDownLatch l3 = new CountDownLatch(1);
+        ch.send(ByteBuffer.wrap(msg), sa, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer bytesSent, Void att) {
+                throw new RuntimeException("completed method invoked");
+            }
+            public void failed (Throwable exc, Void att) {
+                if (exc instanceof ClosedChannelException) {
+                    l3.countDown();
+                } else {
+                    throw new RuntimeException(exc);
+                }
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        l3.await(5, TimeUnit.SECONDS);
+
+        // done
+        reader.close();
+    }
+
+    // basic write tests
+    static void doWriteTests() throws Exception {
+        final byte[] msg = "hello".getBytes();
+
+        DatagramChannel reader = DatagramChannel.open()
+            .bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
+        InetAddress rh = InetAddress.getLocalHost();
+        SocketAddress sa = new InetSocketAddress(rh, port);
+
+        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
+
+        // Test: unconnected
+        try {
+            ch.write(ByteBuffer.wrap(msg)).get();
+            throw new RuntimeException("NotYetConnectedException expected");
+        } catch (NotYetConnectedException e) {
+        }
+
+        // Test: connect, and write datagram
+        ch.connect(sa);
+        int bytesSent = ch.write(ByteBuffer.wrap(msg)).get();
+        if (bytesSent != msg.length)
+            throw new RuntimeException("Unexpected number of bytes sent");
+
+        // check received
+        ByteBuffer dst = ByteBuffer.allocateDirect(100);
+        reader.receive(dst);
+        dst.flip();
+        if (dst.remaining() != msg.length)
+            throw new RuntimeException("Unexpected number of bytes received");
+
+        // Test: write datagram and check completion handler is invoked
+        final CountDownLatch l2 = new CountDownLatch(1);
+        ch.write(ByteBuffer.wrap(msg), null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer bytesSent, Void att) {
+                if (bytesSent != msg.length)
+                    throw new RuntimeException("Unexpected number of bytes received");
+                l2.countDown();
+            }
+            public void failed (Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        l2.await(5, TimeUnit.SECONDS);
+
+        // check received
+        dst.clear();
+        reader.receive(dst);
+        dst.flip();
+        if (dst.remaining() != msg.length)
+            throw new RuntimeException("Unexpected number of bytes received");
+
+        // done
+        ch.close();
+        reader.close();
+    }
+
+    // basic multicast test
+    static void doMulticastTests() throws Exception {
+        final byte[] msg = "hello".getBytes();
+
+        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel
+            .open(StandardProtocolFamily.INET, null)
+            .setOption(StandardSocketOption.SO_REUSEADDR, true)
+            .bind(new InetSocketAddress(0));
+
+        InetAddress lh = InetAddress.getLocalHost();
+        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
+
+        // join group
+        InetAddress group = InetAddress.getByName("225.4.5.6");
+        NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
+        MembershipKey key = ch.join(group, interf);
+
+        // check key
+        if (key.channel() != ch)
+            throw new RuntimeException("Not the expected channel");
+
+        // send message to group
+        DatagramChannel sender = DatagramChannel.open();
+        sender.send(ByteBuffer.wrap(msg), new InetSocketAddress(group, port));
+        sender.close();
+
+        // check message received
+        ByteBuffer dst = ByteBuffer.allocate(200);
+        SocketAddress source = ch.receive(dst).get(2, TimeUnit.SECONDS);
+        if (!((InetSocketAddress)source).getAddress().equals(lh))
+            throw new RuntimeException("Unexpected source");
+
+        // done
+        ch.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousFileChannel
+ */
+
+import java.nio.file.*;
+import java.nio.channels.*;
+import java.nio.ByteBuffer;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
+import static java.nio.file.StandardOpenOption.*;
+
+public class Basic {
+
+    private static final Random rand = new Random();
+
+    public static void main(String[] args) throws IOException {
+        // create temporary file
+        File blah = File.createTempFile("blah", null);
+        blah.deleteOnExit();
+
+        final AsynchronousFileChannel ch = AsynchronousFileChannel
+            .open(blah.toPath(), READ, WRITE);
+
+        // run tests
+        testUsingCompletionHandlers(ch);
+        testUsingWaitOnResult(ch);
+        testLocking(ch);
+        testInterruptHandlerThread(ch);
+
+        // close channel and invoke test that expects channel to be closed
+        ch.close();
+        testClosedChannel(ch);
+
+        // these tests open the file themselves
+        testCustomThreadPool(blah.toPath());
+        testAsynchronousClose(blah.toPath());
+        testCancel(blah.toPath());
+        testTruncate(blah.toPath());
+    }
+
+    /*
+     * Generate buffer with random contents
+     * Writes buffer to file using a CompletionHandler to consume the result
+     *    of each write operation
+     * Reads file to EOF to a new buffer using a CompletionHandler to consume
+     *    the result of each read operation
+     * Compares buffer contents
+     */
+    static void testUsingCompletionHandlers(AsynchronousFileChannel ch)
+        throws IOException
+    {
+        System.out.println("testUsingCompletionHandlers");
+
+        ch.truncate(0L);
+
+        // generate buffer with random elements and write it to file
+        ByteBuffer src = genBuffer();
+        writeFully(ch, src, 0L);
+
+        // read to EOF or buffer is full
+        ByteBuffer dst = (rand.nextBoolean()) ?
+            ByteBuffer.allocateDirect(src.capacity()) :
+            ByteBuffer.allocate(src.capacity());
+        readAll(ch, dst, 0L);
+
+        // check buffers are the same
+        src.flip();
+        dst.flip();
+        if (!src.equals(dst)) {
+            throw new RuntimeException("Contents differ");
+        }
+    }
+
+    /*
+     * Generate buffer with random contents
+     * Writes buffer to file, invoking the Future's get method to wait for
+     *    each write operation to complete
+     * Reads file to EOF to a new buffer, invoking the Future's get method to
+     *    wait for each write operation to complete
+     * Compares buffer contents
+     */
+    static void testUsingWaitOnResult(AsynchronousFileChannel ch)
+        throws IOException
+    {
+        System.out.println("testUsingWaitOnResult");
+
+        ch.truncate(0L);
+
+        // generate buffer
+        ByteBuffer src = genBuffer();
+
+        // write buffer completely to file
+        long position = 0L;
+        while (src.hasRemaining()) {
+            Future<Integer> result = ch.write(src, position);
+            try {
+                int n = result.get();
+                // update position
+                position += n;
+            } catch (ExecutionException x) {
+                throw new RuntimeException(x.getCause());
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);
+            }
+        }
+
+        // read file into new buffer
+        ByteBuffer dst = (rand.nextBoolean()) ?
+            ByteBuffer.allocateDirect(src.capacity()) :
+            ByteBuffer.allocate(src.capacity());
+        position = 0L;
+        int n;
+        do {
+            Future<Integer> result = ch.read(dst, position);
+            try {
+                n = result.get();
+
+                // update position
+                if (n > 0) position += n;
+            } catch (ExecutionException x) {
+                throw new RuntimeException(x.getCause());
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);
+            }
+        } while (n > 0);
+
+        // check buffers are the same
+        src.flip();
+        dst.flip();
+        if (!src.equals(dst)) {
+            throw new RuntimeException("Contents differ");
+        }
+    }
+
+    // exercise lock methods
+    static void testLocking(AsynchronousFileChannel ch)
+        throws IOException
+    {
+        System.out.println("testLocking");
+
+        // test 1 - acquire lock and check that tryLock throws
+        // OverlappingFileLockException
+        FileLock fl;
+        try {
+            fl = ch.lock().get();
+        } catch (ExecutionException x) {
+            throw new RuntimeException(x);
+        } catch (InterruptedException x) {
+            throw new RuntimeException("Should not be interrupted");
+        }
+        if (!fl.acquiredBy().equals(ch))
+            throw new RuntimeException("FileLock#acquiredBy returned incorrect channel");
+        try {
+            ch.tryLock();
+            throw new RuntimeException("OverlappingFileLockException expected");
+        } catch (OverlappingFileLockException x) {
+        }
+        fl.release();
+
+        // test 2 - acquire try and check that lock throws OverlappingFileLockException
+        fl = ch.tryLock();
+        if (fl == null)
+            throw new RuntimeException("Unable to acquire lock");
+        try {
+            ch.lock(null, new CompletionHandler<FileLock,Void> () {
+                public void completed(FileLock result, Void att) {
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+                public void cancelled(Void att) {
+                }
+            });
+            throw new RuntimeException("OverlappingFileLockException expected");
+        } catch (OverlappingFileLockException x) {
+        }
+        fl.release();
+    }
+
+    // interrupt should not close channel
+    static void testInterruptHandlerThread(final AsynchronousFileChannel ch) {
+        System.out.println("testInterruptHandlerThread");
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(100);
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        ch.read(buf, 0L, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer result, Void att) {
+                try {
+                    Thread.currentThread().interrupt();
+                    long size = ch.size();
+                    latch.countDown();
+                } catch (IOException x) {
+                    x.printStackTrace();
+                }
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+
+        // wait for handler to complete
+        await(latch);
+    }
+
+    // invoke method on closed channel
+    static void testClosedChannel(AsynchronousFileChannel ch) {
+        System.out.println("testClosedChannel");
+
+        if (ch.isOpen())
+            throw new RuntimeException("Channel should be closed");
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(100);
+
+        // check read fails with ClosedChannelException
+        try {
+            ch.read(buf, 0L).get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        } catch (InterruptedException x) {
+        }
+
+        // check write fails with ClosedChannelException
+        try {
+            ch.write(buf, 0L).get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        } catch (InterruptedException x) {
+        }
+
+        // check lock fails with ClosedChannelException
+        try {
+            ch.lock().get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        } catch (InterruptedException x) {
+        }
+    }
+
+
+    // exercise custom thread pool
+    static void testCustomThreadPool(Path file) throws IOException {
+        System.out.println("testCustomThreadPool");
+
+        // records threads that are created
+        final List<Thread> threads = new ArrayList<Thread>();
+
+        ThreadFactory threadFactory = new ThreadFactory() {
+
+             public Thread newThread(Runnable r) {
+                 Thread t = new Thread(r);
+                 t.setDaemon(true);
+                 synchronized (threads) {
+                     threads.add(t);
+                 }
+                 return t;
+             }
+        };
+
+        // exercise tests with varied number of threads
+        for (int nThreads=1; nThreads<=5; nThreads++) {
+            synchronized (threads) {
+                threads.clear();
+            }
+            ExecutorService executor = Executors.newFixedThreadPool(nThreads, threadFactory);
+            Set<StandardOpenOption> opts = EnumSet.of(WRITE);
+            AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, opts, executor);
+            try {
+                for (int i=0; i<10; i++) {
+                    // do I/O operation to see which thread invokes the completion handler
+                    final AtomicReference<Thread> invoker = new AtomicReference<Thread>();
+                    final CountDownLatch latch = new CountDownLatch(1);
+
+                    ch.write(genBuffer(), 0L, null, new CompletionHandler<Integer,Void>() {
+                        public void completed(Integer result, Void att) {
+                            invoker.set(Thread.currentThread());
+                            latch.countDown();
+                        }
+                        public void failed(Throwable exc, Void att) {
+                        }
+                        public void cancelled(Void att) {
+                        }
+                    });
+                    await(latch);
+
+                    // check invoker
+                    boolean found = false;
+                    synchronized (threads) {
+                        for (Thread t: threads) {
+                            if (t == invoker.get()) {
+                                found = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (!found)
+                        throw new RuntimeException("Invoker thread not found");
+                }
+            } finally {
+                ch.close();
+            }
+        }
+    }
+
+    // exercise asynchronous close
+    static void testAsynchronousClose(Path file) throws IOException {
+        System.out.println("testAsynchronousClose");
+
+        // create file
+        AsynchronousFileChannel ch = AsynchronousFileChannel
+            .open(file, WRITE, TRUNCATE_EXISTING);
+        long size = 0L;
+        do {
+            ByteBuffer buf = genBuffer();
+            int n = buf.remaining();
+            writeFully(ch, buf, size);
+            size += n;
+        } while (size < (50L * 1024L * 1024L));
+
+        ch.close();
+
+        ch = AsynchronousFileChannel.open(file, WRITE, SYNC);
+
+        // randomize number of writers, buffer size, and positions
+
+        int nwriters = 1 + rand.nextInt(8);
+        ByteBuffer[] buf = new ByteBuffer[nwriters];
+        long[] position = new long[nwriters];
+        for (int i=0; i<nwriters; i++) {
+            buf[i] = genBuffer();
+            position[i] = rand.nextInt((int)size);
+        }
+
+        // initiate I/O
+        Future[] result = new Future[nwriters];
+        for (int i=0; i<nwriters; i++) {
+            result[i] = ch.write(buf[i], position[i]);
+        }
+
+        // close file
+        ch.close();
+
+        // write operations should complete or fail with AsynchronousCloseException
+        for (int i=0; i<nwriters; i++) {
+            try {
+                result[i].get();
+            } catch (ExecutionException x) {
+                Throwable cause = x.getCause();
+                if (!(cause instanceof AsynchronousCloseException))
+                    throw new RuntimeException(cause);
+            } catch (CancellationException  x) {
+                throw new RuntimeException(x);   // should not happen
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);   // should not happen
+            }
+        }
+    }
+
+    // exercise cancel method
+    static void testCancel(Path file) throws IOException {
+        System.out.println("testCancel");
+
+        for (int i=0; i<2; i++) {
+            boolean mayInterruptIfRunning = (i == 0) ? false : true;
+
+            // open with SYNC option to improve chances that write will not
+            // complete immediately
+            AsynchronousFileChannel ch = AsynchronousFileChannel
+                .open(file, WRITE, SYNC);
+
+            // start write operation
+            final CountDownLatch latch = new CountDownLatch(1);
+            Future<Integer> res = ch.write(genBuffer(), 0L, null,
+                new CompletionHandler<Integer,Void>() {
+                    public void completed(Integer result, Void att) {
+                    }
+                    public void failed(Throwable exc, Void att) {
+                    }
+                    public void cancelled(Void att) {
+                        latch.countDown();
+                    }
+            });
+
+            // cancel operation
+            boolean cancelled = res.cancel(mayInterruptIfRunning);
+
+            // check post-conditions
+            if (!res.isDone())
+                throw new RuntimeException("isDone should return true");
+            if (res.isCancelled() != cancelled)
+                throw new RuntimeException("isCancelled not consistent");
+            try {
+                res.get();
+                if (!cancelled)
+                    throw new RuntimeException("CancellationException expected");
+            } catch (CancellationException x) {
+                // expected
+            } catch (ExecutionException x) {
+                throw new RuntimeException(x);
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);
+            }
+            try {
+                res.get(1, TimeUnit.SECONDS);
+                throw new RuntimeException("CancellationException expected");
+            } catch (CancellationException x) {
+                // expected
+            } catch (ExecutionException x) {
+                throw new RuntimeException(x);
+            } catch (TimeoutException x) {
+                throw new RuntimeException(x);
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);
+            }
+
+            // check that cancelled method is invoked
+            if (cancelled)
+                await(latch);
+
+            ch.close();
+        }
+    }
+
+    // exercise truncate method
+    static void testTruncate(Path file) throws IOException {
+        System.out.println("testTruncate");
+
+        // basic tests
+        AsynchronousFileChannel ch = AsynchronousFileChannel
+            .open(file, CREATE, WRITE, TRUNCATE_EXISTING);
+        try {
+            writeFully(ch, genBuffer(), 0L);
+            long size = ch.size();
+
+            // attempt to truncate to a size greater than the current size
+            if (ch.truncate(size + 1L).size() != size)
+                throw new RuntimeException("Unexpected size after truncation");
+
+            // truncate file
+            if (ch.truncate(size - 1L).size() != (size - 1L))
+                throw new RuntimeException("Unexpected size after truncation");
+
+            // invalid size
+            try {
+                ch.truncate(-1L);
+                throw new RuntimeException("IllegalArgumentException expected");
+            } catch (IllegalArgumentException e) { }
+
+        } finally {
+            ch.close();
+        }
+
+        // channel is closed
+        try {
+            ch.truncate(0L);
+            throw new RuntimeException("ClosedChannelException expected");
+        } catch (ClosedChannelException  e) { }
+
+        // channel is read-only
+        ch = AsynchronousFileChannel.open(file, READ);
+        try {
+            try {
+            ch.truncate(0L);
+                throw new RuntimeException("NonWritableChannelException expected");
+            } catch (NonWritableChannelException  e) { }
+        } finally {
+            ch.close();
+        }
+    }
+
+    // returns ByteBuffer with random bytes
+    static ByteBuffer genBuffer() {
+        int size = 1024 + rand.nextInt(16000);
+        byte[] buf = new byte[size];
+        boolean useDirect = rand.nextBoolean();
+        if (useDirect) {
+            ByteBuffer bb = ByteBuffer.allocateDirect(buf.length);
+            bb.put(buf);
+            bb.flip();
+            return bb;
+        } else {
+            return ByteBuffer.wrap(buf);
+        }
+    }
+
+    // writes all remaining bytes in the buffer to the given channel at the
+    // given position
+    static void writeFully(final AsynchronousFileChannel ch,
+                           final ByteBuffer src,
+                           long position)
+    {
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        // use position as attachment
+        ch.write(src, position, position, new CompletionHandler<Integer,Long>() {
+            public void completed(Integer result, Long position) {
+                int n = result;
+                if (src.hasRemaining()) {
+                    long p = position + n;
+                    ch.write(src, p, p, this);
+                } else {
+                    latch.countDown();
+                }
+            }
+            public void failed(Throwable exc, Long position) {
+            }
+            public void cancelled(Long position) {
+            }
+        });
+
+        // wait for writes to complete
+        await(latch);
+    }
+
+    static void readAll(final AsynchronousFileChannel ch,
+                        final ByteBuffer dst,
+                       long position)
+    {
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        // use position as attachment
+        ch.read(dst, position, position, new CompletionHandler<Integer,Long>() {
+            public void completed(Integer result, Long position) {
+                int n = result;
+                if (n > 0) {
+                    long p = position + n;
+                    ch.read(dst, p, p, this);
+                } else {
+                    latch.countDown();
+                }
+            }
+            public void failed(Throwable exc, Long position) {
+            }
+            public void cancelled(Long position) {
+            }
+        });
+
+        // wait for reads to complete
+        await(latch);
+    }
+
+    static void await(CountDownLatch latch) {
+        // wait until done
+        boolean done = false;
+        while (!done) {
+            try {
+                latch.await();
+                done = true;
+            } catch (InterruptedException x) { }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for java.nio.channels.AsynchronousFileChannel
+ * @build CustomThreadPool MyThreadFactory
+ * @run main/othervm -Djava.nio.channels.DefaultThreadPool.threadFactory=MyThreadFactory CustomThreadPool
+ */
+
+import java.io.File;
+import static java.nio.file.StandardOpenOption.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class CustomThreadPool {
+
+    public static void main(String[] args) throws Exception {
+        File blah = File.createTempFile("blah", null);
+        blah.deleteOnExit();
+        AsynchronousFileChannel ch =
+            AsynchronousFileChannel.open(blah.toPath(), READ, WRITE);
+        ByteBuffer src = ByteBuffer.wrap("Scooby Snacks".getBytes());
+
+        final AtomicReference<Thread> invoker = new AtomicReference<Thread>();
+        ch.write(src, 0, invoker,
+            new CompletionHandler<Integer,AtomicReference<Thread>>() {
+                public void completed(Integer result, AtomicReference<Thread> invoker) {
+                    invoker.set(Thread.currentThread());
+                }
+                public void failed(Throwable exc, AtomicReference<Thread> invoker) {
+                }
+                public void cancelled(AtomicReference<Thread> invoker) {
+                }
+            });
+        Thread t;
+        while ((t = invoker.get()) == null) {
+            Thread.sleep(100);
+        }
+        ch.close();
+
+        // check handler was run by known thread
+        if (!MyThreadFactory.created(t))
+            throw new RuntimeException("Handler invoked by unknown thread");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Lock.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousFileChannel#lock method
+ */
+
+import java.net.*;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.file.*;
+import static java.nio.file.StandardOpenOption.*;
+import java.nio.channels.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+import java.util.concurrent.*;
+
+public class Lock {
+
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+        if (args.length > 0 && args[0].equals("-lockslave")) {
+            int port = Integer.parseInt(args[1]);
+            runLockSlave(port);
+            System.exit(0);
+        }
+
+        LockSlaveMirror slave = startLockSlave();
+        try {
+
+             // create temporary file
+            File blah = File.createTempFile("blah", null);
+            blah.deleteOnExit();
+
+            testLockProtocol(blah, slave);
+            testAsyncClose(blah, slave);
+
+        } finally {
+            slave.shutdown();
+        }
+    }
+
+    // test locking protocol
+    static void testLockProtocol(File file, LockSlaveMirror slave)
+        throws Exception
+    {
+        FileLock fl;
+
+        // slave VM opens file and acquires exclusive lock
+        slave.open(file.getPath()).lock();
+
+        AsynchronousFileChannel ch = AsynchronousFileChannel
+            .open(file.toPath(), READ, WRITE);
+
+        // this VM tries to acquire lock
+        // (lock should not be acquire until released by slave VM)
+        Future<FileLock> result = ch.lock();
+        try {
+            result.get(2, TimeUnit.SECONDS);
+            throw new RuntimeException("Timeout expected");
+        } catch (TimeoutException x) {
+        }
+
+        // slave VM releases lock
+        slave.unlock();
+
+        // this VM should now acquire lock
+        fl = result.get();
+        fl.release();
+
+        // slave VM acquires lock on range
+        slave.lock(0, 10, false);
+
+        // this VM acquires lock on non-overlapping range
+        fl = ch.lock(10, 10, false, null, null).get();
+        fl.release();
+
+        // done
+        ch.close();
+        slave.close();
+    }
+
+    // test close of channel with outstanding lock operation
+    static void testAsyncClose(File file, LockSlaveMirror slave) throws Exception {
+        // slave VM opens file and acquires exclusive lock
+        slave.open(file.getPath()).lock();
+
+        for (int i=0; i<100; i++) {
+            AsynchronousFileChannel ch = AsynchronousFileChannel
+                .open(file.toPath(), READ, WRITE);
+
+            // try to lock file (should not complete because file is locked by slave)
+            Future<FileLock> result = ch.lock();
+            try {
+                result.get(rand.nextInt(100), TimeUnit.MILLISECONDS);
+                throw new RuntimeException("Timeout expected");
+            } catch (TimeoutException x) {
+            }
+
+            // close channel with lock operation outstanding
+            ch.close();
+
+            // operation should complete with AsynchronousCloseException
+            try {
+                result.get();
+                throw new RuntimeException("ExecutionException expected");
+            } catch (ExecutionException x) {
+                if (!(x.getCause() instanceof AsynchronousCloseException)) {
+                    x.getCause().printStackTrace();
+                    throw new RuntimeException("AsynchronousCloseException expected");
+                }
+            }
+        }
+
+        slave.close();
+    }
+
+    // starts a "lock slave" in another process, returning a mirror object to
+    // control the slave
+    static LockSlaveMirror startLockSlave() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open()
+            .bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
+
+        String sep = FileSystems.getDefault().getSeparator();
+
+        String command = System.getProperty("java.home") +
+            sep + "bin" + sep + "java Lock -lockslave " + port;
+        Process p = Runtime.getRuntime().exec(command);
+        IOHandler.handle(p.getInputStream());
+        IOHandler.handle(p.getErrorStream());
+
+        // wait for slave to connect
+        SocketChannel sc = ssc.accept();
+        return new LockSlaveMirror(sc);
+    }
+
+    // commands that the slave understands
+    static final String OPEN_CMD    = "open";
+    static final String CLOSE_CMD   = "close";
+    static final String LOCK_CMD    = "lock";
+    static final String UNLOCK_CMD  = "unlock";
+    static final char TERMINATOR    = ';';
+
+    // provides a proxy to a "lock slave"
+    static class LockSlaveMirror {
+        private final SocketChannel sc;
+
+        LockSlaveMirror(SocketChannel sc) {
+            this.sc = sc;
+        }
+
+        private void sendCommand(String cmd, String... params)
+            throws IOException
+        {
+            for (String s: params) {
+                cmd += " " + s;
+            }
+            cmd += TERMINATOR;
+
+            ByteBuffer buf = Charset.defaultCharset().encode(cmd);
+            while (buf.hasRemaining()) {
+                sc.write(buf);
+            }
+
+            // wait for ack
+            buf = ByteBuffer.allocate(1);
+            int n = sc.read(buf);
+            if (n != 1)
+                throw new RuntimeException("Reply expected");
+            if (buf.get(0) != TERMINATOR)
+                throw new RuntimeException("Terminated expected");
+        }
+
+        LockSlaveMirror open(String file) throws IOException {
+            sendCommand(OPEN_CMD, file);
+            return this;
+        }
+
+        void close() throws IOException {
+            sendCommand(CLOSE_CMD);
+        }
+
+        LockSlaveMirror lock() throws IOException {
+            sendCommand(LOCK_CMD);
+            return this;
+        }
+
+
+        LockSlaveMirror lock(long position, long size, boolean shared)
+            throws IOException
+        {
+            sendCommand(LOCK_CMD, position + "," + size + "," + shared);
+            return this;
+        }
+
+        LockSlaveMirror unlock() throws IOException {
+            sendCommand(UNLOCK_CMD);
+            return this;
+        }
+
+        void shutdown() throws IOException {
+            sc.close();
+        }
+    }
+
+    // Helper class to direct process output to the parent System.out
+    static class IOHandler implements Runnable {
+        private final InputStream in;
+
+        IOHandler(InputStream in) {
+            this.in = in;
+        }
+
+        static void handle(InputStream in) {
+            IOHandler handler = new IOHandler(in);
+            Thread thr = new Thread(handler);
+            thr.setDaemon(true);
+            thr.start();
+        }
+
+        public void run() {
+            try {
+                byte b[] = new byte[100];
+                for (;;) {
+                    int n = in.read(b);
+                    if (n < 0) return;
+                    for (int i=0; i<n; i++) {
+                        System.out.print((char)b[i]);
+                    }
+                }
+            } catch (IOException ioe) { }
+        }
+    }
+
+    // slave process that responds to simple commands a socket connection
+    static void runLockSlave(int port) throws Exception {
+
+        // establish connection to parent
+        SocketChannel sc = SocketChannel.open(new InetSocketAddress(port));
+        ByteBuffer buf = ByteBuffer.allocateDirect(1024);
+
+        FileChannel fc = null;
+        FileLock fl = null;
+        try {
+            for (;;) {
+
+                // read command (ends with ";")
+                buf.clear();
+                int n, last = 0;
+                do {
+                    n = sc.read(buf);
+                    if (n < 0)
+                        return;
+                    if (n == 0)
+                        throw new AssertionError();
+                    last += n;
+                } while (buf.get(last-1) != TERMINATOR);
+
+                // decode into command and optional parameter
+                buf.flip();
+                String s = Charset.defaultCharset().decode(buf).toString();
+                int sp = s.indexOf(" ");
+                String cmd = (sp < 0) ? s.substring(0, s.length()-1) :
+                    s.substring(0, sp);
+                String param = (sp < 0) ? "" : s.substring(sp+1, s.length()-1);
+
+                // execute
+                if (cmd.equals(OPEN_CMD)) {
+                    if (fc != null)
+                        throw new RuntimeException("File already open");
+                    fc = FileChannel.open(Paths.get(param),READ, WRITE);
+                }
+                if (cmd.equals(CLOSE_CMD)) {
+                    if (fc == null)
+                        throw new RuntimeException("No file open");
+                    fc.close();
+                    fc = null;
+                    fl = null;
+                }
+                if (cmd.equals(LOCK_CMD)) {
+                    if (fl != null)
+                        throw new RuntimeException("Already holding lock");
+
+                    if (param.length() == 0) {
+                        fl = fc.lock();
+                    } else {
+                        String[] values = param.split(",");
+                        if (values.length != 3)
+                            throw new RuntimeException("Lock parameter invalid");
+                        long position = Long.parseLong(values[0]);
+                        long size = Long.parseLong(values[1]);
+                        boolean shared = Boolean.parseBoolean(values[2]);
+                        fl = fc.lock(position, size, shared);
+                    }
+                }
+
+                if (cmd.equals(UNLOCK_CMD)) {
+                    if (fl == null)
+                        throw new RuntimeException("Not holding lock");
+                    fl.release();
+                    fl = null;
+                }
+
+                // send reply
+                byte[] reply = { TERMINATOR };
+                n = sc.write(ByteBuffer.wrap(reply));
+            }
+
+        } finally {
+            sc.close();
+            if (fc != null) fc.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/MyThreadFactory.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.util.concurrent.ThreadFactory;
+import java.util.*;
+
+public class MyThreadFactory implements ThreadFactory {
+
+    private static final Set<Thread> threads = new HashSet<Thread>();
+
+    static boolean created(Thread t) {
+        synchronized (threads) {
+            return threads.contains(t);
+        }
+    }
+
+    public MyThreadFactory() {
+    }
+
+
+    public Thread newThread(Runnable r) {
+        Thread t = new Thread(r);
+        t.setDaemon(true);
+        synchronized (threads) {
+            threads.add(t);
+        }
+        return t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousServerSocketChannel
+ * @run main/timeout=180 Basic
+ */
+
+import java.nio.channels.*;
+import java.net.*;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class Basic {
+
+    public static void main(String[] args) throws Exception {
+        testBind();
+        testAccept();
+    }
+
+    static void testBind() throws Exception {
+        System.out.println("-- bind --");
+
+        AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open();
+        if (ch.getLocalAddress() != null)
+            throw new RuntimeException("Local address should be 'null'");
+        ch.bind(new InetSocketAddress(0), 20);
+
+        // check local address after binding
+        InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress();
+        if (local.getPort() == 0)
+            throw new RuntimeException("Unexpected port");
+        if (!local.getAddress().isAnyLocalAddress())
+            throw new RuntimeException("Not bound to a wildcard address");
+
+        // try to re-bind
+        try {
+            ch.bind(new InetSocketAddress(0));
+            throw new RuntimeException("AlreadyBoundException expected");
+        } catch (AlreadyBoundException x) {
+        }
+        ch.close();
+
+        // check ClosedChannelException
+        ch = AsynchronousServerSocketChannel.open();
+        ch.close();
+        try {
+            ch.bind(new InetSocketAddress(0));
+            throw new RuntimeException("ClosedChannelException  expected");
+        } catch (ClosedChannelException  x) {
+        }
+    }
+
+    static void testAccept() throws Exception {
+        System.out.println("-- accept --");
+
+        final AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
+
+        InetAddress lh = InetAddress.getLocalHost();
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+        final InetSocketAddress isa = new InetSocketAddress(lh, port);
+
+        // establish a few loopback connections
+        for (int i=0; i<100; i++) {
+            SocketChannel sc = SocketChannel.open(isa);
+            AsynchronousSocketChannel ch = listener.accept().get();
+            sc.close();
+            ch.close();
+        }
+
+       final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
+
+        // start accepting
+        listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+            public void completed(AsynchronousSocketChannel ch, Void att) {
+                try {
+                    ch.close();
+                } catch (IOException ignore) { }
+            }
+            public void failed(Throwable exc, Void att) {
+                exception.set(exc);
+            }
+            public void cancelled(Void att) {
+            }
+        });
+
+        // check AcceptPendingException
+        try {
+            listener.accept();
+            throw new RuntimeException("AcceptPendingException expected");
+        } catch (AcceptPendingException x) {
+        }
+
+        // asynchronous close
+        listener.close();
+        while (exception.get() == null)
+            Thread.sleep(100);
+        if (!(exception.get() instanceof AsynchronousCloseException))
+            throw new RuntimeException("AsynchronousCloseException expected");
+
+        // once closed when a further attemt should throw ClosedChannelException
+        try {
+            listener.accept().get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        } catch (InterruptedException x) {
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008 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 4607272
+ * @summary Unit test for AsynchronousServerServerSocketChannel
+ * @build WithSecurityManager
+ * @run main/othervm WithSecurityManager allow
+ * @run main/othervm WithSecurityManager deny
+ */
+
+import java.nio.file.Paths;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.*;
+
+public class WithSecurityManager {
+    public static void main(String[] args) throws Exception {
+        boolean allow = false;
+        String policy = (args[0].equals("allow")) ? "java.policy.allow" :
+            "java.policy.deny";
+
+        String testSrc = System.getProperty("test.src");
+        if (testSrc == null)
+            testSrc = ".";
+
+        System.setProperty("java.security.policy",
+            Paths.get(testSrc).resolve(policy).toString());
+        System.setSecurityManager(new SecurityManager());
+
+        AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
+
+        InetAddress lh = InetAddress.getLocalHost();
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+
+        // establish and accept connection
+        SocketChannel sc = SocketChannel.open(new InetSocketAddress(lh, port));
+        Future<AsynchronousSocketChannel> result = listener.accept();
+
+        if (allow) {
+            // no security exception
+            result.get().close();
+        } else {
+            try {
+                result.get();
+            } catch (ExecutionException x) {
+                if (!(x.getCause() instanceof SecurityException))
+                    throw new RuntimeException("SecurityException expected");
+            }
+        }
+
+        sc.close();
+        listener.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,3 @@
+grant {
+    permission java.net.SocketPermission "*:1024-", "accept,connect,resolve";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,3 @@
+grant {
+    permission java.net.SocketPermission "*:1024-", "connect,resolve";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,805 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousSocketChannel
+ * @run main/timeout=600 Basic
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import static java.net.StandardSocketOption.*;
+import java.net.*;
+import java.util.Random;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.io.IOException;
+
+public class Basic {
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+        testBind();
+        testSocketOptions();
+        testConnect();
+        testCloseWhenPending();
+        testCancel();
+        testRead1();
+        testRead2();
+        testRead3();
+        testWrite1();
+        testWrite2();
+        testTimeout();
+        testShutdown();
+    }
+
+    static class Server {
+        private final ServerSocketChannel ssc;
+        private final InetSocketAddress address;
+
+        Server() throws IOException {
+            ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
+
+            InetAddress lh = InetAddress.getLocalHost();
+            int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
+            address = new InetSocketAddress(lh, port);
+        }
+
+        InetSocketAddress address() {
+            return address;
+        }
+
+        SocketChannel accept() throws IOException {
+            return ssc.accept();
+        }
+
+        void close() {
+            try {
+                ssc.close();
+            } catch (IOException ignore) { }
+        }
+
+    }
+
+    static void testBind() throws Exception {
+        System.out.println("-- bind --");
+
+        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        if (ch.getLocalAddress() != null)
+            throw new RuntimeException("Local address should be 'null'");
+        ch.bind(new InetSocketAddress(0));
+
+        // check local address after binding
+        InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress();
+        if (local.getPort() == 0)
+            throw new RuntimeException("Unexpected port");
+        if (!local.getAddress().isAnyLocalAddress())
+            throw new RuntimeException("Not bound to a wildcard address");
+
+        // try to re-bind
+        try {
+            ch.bind(new InetSocketAddress(0));
+            throw new RuntimeException("AlreadyBoundException expected");
+        } catch (AlreadyBoundException x) {
+        }
+        ch.close();
+
+        // check ClosedChannelException
+        ch = AsynchronousSocketChannel.open();
+        ch.close();
+        try {
+            ch.bind(new InetSocketAddress(0));
+            throw new RuntimeException("ClosedChannelException  expected");
+        } catch (ClosedChannelException  x) {
+        }
+    }
+
+    static void testSocketOptions() throws Exception {
+        System.out.println("-- socket options --");
+
+        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()
+            .setOption(SO_RCVBUF, 128*1024)
+            .setOption(SO_SNDBUF, 128*1024)
+            .setOption(SO_REUSEADDR, true)
+            .bind(new InetSocketAddress(0));
+
+        // default values
+        if ((Boolean)ch.getOption(SO_KEEPALIVE))
+            throw new RuntimeException("Default of SO_KEEPALIVE should be 'false'");
+        if ((Boolean)ch.getOption(TCP_NODELAY))
+            throw new RuntimeException("Default of TCP_NODELAY should be 'false'");
+
+        // set and check
+        if (!(Boolean)ch.setOption(SO_KEEPALIVE, true).getOption(SO_KEEPALIVE))
+            throw new RuntimeException("SO_KEEPALIVE did not change");
+        if (!(Boolean)ch.setOption(TCP_NODELAY, true).getOption(TCP_NODELAY))
+            throw new RuntimeException("SO_KEEPALIVE did not change");
+
+        // read others (can't check as actual value is implementation dependent)
+        ch.getOption(SO_RCVBUF);
+        ch.getOption(SO_SNDBUF);
+
+        ch.close();
+    }
+
+    static void testConnect() throws Exception {
+        System.out.println("-- connect --");
+
+        Server server = new Server();
+        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+
+        // check local address
+        if (ch.getLocalAddress() == null)
+            throw new RuntimeException("Not bound to local address");
+
+        // check remote address
+        InetSocketAddress remote = (InetSocketAddress)ch.getRemoteAddress();
+        if (remote.getPort() != server.address().getPort())
+            throw new RuntimeException("Connected to unexpected port");
+        if (!remote.getAddress().equals(server.address().getAddress()))
+            throw new RuntimeException("Connected to unexpected address");
+
+        // try to connect again
+        try {
+            ch.connect(server.address()).get();
+            throw new RuntimeException("AlreadyConnectedException expected");
+        } catch (AlreadyConnectedException x) {
+        }
+        ch.close();
+
+        // check that connect fails with ClosedChannelException)
+        ch = AsynchronousSocketChannel.open();
+        ch.close();
+        try {
+            ch.connect(server.address()).get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        }
+        final AtomicReference<Throwable> connectException =
+            new AtomicReference<Throwable>();
+        ch.connect(server.address(), null, new CompletionHandler<Void,Void>() {
+            public void completed(Void result, Void att) {
+            }
+            public void failed(Throwable exc, Void att) {
+                connectException.set(exc);
+            }
+            public void cancelled(Void att) {
+            }
+        });
+        while (connectException.get() == null) {
+            Thread.sleep(100);
+        }
+        if (!(connectException.get() instanceof ClosedChannelException))
+            throw new RuntimeException("ClosedChannelException expected");
+
+        System.out.println("-- connect to non-existent host --");
+
+        // test failure
+        InetAddress badHost = InetAddress.getByName("1.2.3.4");
+        if (!badHost.isReachable(10*1000)) {
+
+            ch = AsynchronousSocketChannel.open();
+            try {
+                ch.connect(new InetSocketAddress(badHost, 9876)).get();
+                throw new RuntimeException("Connection should not be established");
+            } catch (ExecutionException x) {
+            }
+            if (ch.isOpen())
+                throw new RuntimeException("Channel should be closed");
+        }
+
+        server.close();
+    }
+
+    static void testCloseWhenPending() throws Exception {
+        System.out.println("-- asynchronous close when connecting --");
+
+        AsynchronousSocketChannel ch;
+
+        // asynchronous close while connecting
+        InetAddress rh = InetAddress.getByName("1.2.3.4");
+        if (!rh.isReachable(3000)) {
+            InetSocketAddress isa = new InetSocketAddress(rh, 1234);
+
+            ch = AsynchronousSocketChannel.open();
+            Future<Void> result = ch.connect(isa);
+
+            // give time to initiate the connect (SYN)
+            Thread.sleep(50);
+
+            // close
+            ch.close();
+
+            // check that AsynchronousCloseException is thrown
+            try {
+                result.get();
+                throw new RuntimeException("Should not connect");
+            } catch (ExecutionException x) {
+                if (!(x.getCause() instanceof AsynchronousCloseException))
+                    throw new RuntimeException(x);
+            }
+        }
+
+        System.out.println("-- asynchronous close when reading --");
+
+        Server server = new Server();
+        ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+
+        ByteBuffer dst = ByteBuffer.allocateDirect(100);
+        Future<Integer> result = ch.read(dst);
+
+        // attempt a second read - should fail with ReadPendingException
+        ByteBuffer buf = ByteBuffer.allocateDirect(100);
+        try {
+            ch.read(buf);
+            throw new RuntimeException("ReadPendingException expected");
+        } catch (ReadPendingException x) {
+        }
+
+        // close channel (should cause initial read to complete)
+        ch.close();
+
+        // check that AsynchronousCloseException is thrown
+        try {
+            result.get();
+            throw new RuntimeException("Should not read");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof AsynchronousCloseException))
+                throw new RuntimeException(x);
+        }
+
+        System.out.println("-- asynchronous close when writing --");
+
+        ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+
+        final AtomicReference<Throwable> writeException =
+            new AtomicReference<Throwable>();
+
+        // write bytes to fill socket buffer
+        ch.write(genBuffer(), ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
+            public void completed(Integer result, AsynchronousSocketChannel ch) {
+                ch.write(genBuffer(), ch, this);
+            }
+            public void failed(Throwable x, AsynchronousSocketChannel ch) {
+                writeException.set(x);
+            }
+            public void cancelled(AsynchronousSocketChannel ch) {
+            }
+        });
+
+        // give time for socket buffer to fill up.
+        Thread.sleep(5*1000);
+
+        //  attempt a concurrent write - should fail with WritePendingException
+        try {
+            ch.write(genBuffer());
+            throw new RuntimeException("WritePendingException expected");
+        } catch (WritePendingException x) {
+        }
+
+        // close channel - should cause initial write to complete
+        ch.close();
+
+        // wait for exception
+        while (writeException.get() == null) {
+            Thread.sleep(100);
+        }
+        if (!(writeException.get() instanceof AsynchronousCloseException))
+            throw new RuntimeException("AsynchronousCloseException expected");
+
+        server.close();
+    }
+
+    static void testCancel() throws Exception {
+        System.out.println("-- cancel --");
+
+        Server server = new Server();
+
+        for (int i=0; i<2; i++) {
+            boolean mayInterruptIfRunning = (i == 0) ? false : true;
+
+            // establish loopback connection
+            AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+            ch.connect(server.address()).get();
+            SocketChannel peer = server.accept();
+
+            // start read operation
+            final CountDownLatch latch = new CountDownLatch(1);
+            ByteBuffer buf = ByteBuffer.allocate(1);
+            Future<Integer> res = ch.read(buf, null,
+                new CompletionHandler<Integer,Void>() {
+                    public void completed(Integer result, Void att) {
+                    }
+                    public void failed(Throwable exc, Void att) {
+                    }
+                    public void cancelled(Void att) {
+                        latch.countDown();
+                    }
+            });
+
+            // cancel operation
+            boolean cancelled = res.cancel(mayInterruptIfRunning);
+
+            // check post-conditions
+            if (!res.isDone())
+                throw new RuntimeException("isDone should return true");
+            if (res.isCancelled() != cancelled)
+                throw new RuntimeException("isCancelled not consistent");
+            try {
+                res.get();
+                throw new RuntimeException("CancellationException expected");
+            } catch (CancellationException x) {
+            }
+            try {
+                res.get(1, TimeUnit.SECONDS);
+                throw new RuntimeException("CancellationException expected");
+            } catch (CancellationException x) {
+            }
+
+            // check that completion handler executed.
+            latch.await();
+
+            ch.close();
+            peer.close();
+        }
+
+        server.close();
+    }
+
+    static void testRead1() throws Exception {
+        System.out.println("-- read (1) --");
+
+        Server server = new Server();
+        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+
+        // read with 0 bytes remaining should complete immediately
+        ByteBuffer buf = ByteBuffer.allocate(1);
+        buf.put((byte)0);
+        int n = ch.read(buf).get();
+        if (n != 0)
+            throw new RuntimeException("0 expected");
+
+        // write bytes and close connection
+        SocketChannel sc = server.accept();
+        ByteBuffer src = genBuffer();
+        sc.setOption(StandardSocketOption.SO_SNDBUF, src.remaining());
+        while (src.hasRemaining())
+            sc.write(src);
+        sc.close();
+
+        // reads should complete immediately
+        final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100);
+        final CountDownLatch latch = new CountDownLatch(1);
+        ch.read(dst, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer result, Void att) {
+                int n = result;
+                if (n > 0) {
+                    ch.read(dst, null, this);
+                } else {
+                    latch.countDown();
+                }
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+
+        latch.await();
+
+        // check buffers
+        src.flip();
+        dst.flip();
+        if (!src.equals(dst)) {
+            throw new RuntimeException("Contents differ");
+        }
+
+        // close channel
+        ch.close();
+
+        // check read fails with ClosedChannelException
+        try {
+            ch.read(dst).get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        }
+
+        server.close();
+    }
+
+    static void testRead2() throws Exception {
+        System.out.println("-- read (2) --");
+
+        Server server = new Server();
+
+        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+        SocketChannel sc = server.accept();
+
+        ByteBuffer src = genBuffer();
+
+        // read until the buffer is full
+        final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity());
+        final CountDownLatch latch = new CountDownLatch(1);
+        ch.read(dst, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer result, Void att) {
+                if (dst.hasRemaining()) {
+                    ch.read(dst, null, this);
+                } else {
+                    latch.countDown();
+                }
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+
+        // trickle the writing
+        do {
+            int rem = src.remaining();
+            int size = (rem <= 100) ? rem : 50 + rand.nextInt(rem - 100);
+            ByteBuffer buf = ByteBuffer.allocate(size);
+            for (int i=0; i<size; i++)
+                buf.put(src.get());
+            buf.flip();
+            Thread.sleep(50 + rand.nextInt(1500));
+            while (buf.hasRemaining())
+                sc.write(buf);
+        } while (src.hasRemaining());
+
+        // wait until ascynrhonous reading has completed
+        latch.await();
+
+        // check buffers
+        src.flip();
+        dst.flip();
+        if (!src.equals(dst)) {
+           throw new RuntimeException("Contents differ");
+        }
+
+        sc.close();
+        ch.close();
+        server.close();
+    }
+
+    // exercise scattering read
+    static void testRead3() throws Exception {
+        System.out.println("-- read (3) --");
+
+        Server server = new Server();
+        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+        SocketChannel sc = server.accept();
+
+        ByteBuffer[] dsts = new ByteBuffer[3];
+        for (int i=0; i<dsts.length; i++) {
+            dsts[i] = ByteBuffer.allocateDirect(100);
+        }
+
+        // scattering read that completes ascynhronously
+        final CountDownLatch latch = new CountDownLatch(1);
+        ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, null,
+            new CompletionHandler<Long,Void>() {
+                public void completed(Long result, Void att) {
+                    long n = result;
+                    if (n <= 0)
+                        throw new RuntimeException("No bytes read");
+                    latch.countDown();
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+                public void cancelled(Void att) {
+                }
+        });
+
+        // write some bytes
+        sc.write(genBuffer());
+
+        // read should now complete
+        latch.await();
+
+        // write more bytes
+        sc.write(genBuffer());
+
+        // read should complete immediately
+        for (int i=0; i<dsts.length; i++) {
+            dsts[i].rewind();
+        }
+        long n = ch
+            .read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, null, null).get();
+        if (n <= 0)
+            throw new RuntimeException("No bytes read");
+
+        ch.close();
+        sc.close();
+        server.close();
+    }
+
+    static void testWrite1() throws Exception {
+        System.out.println("-- write (1) --");
+
+        Server server = new Server();
+        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+        SocketChannel sc = server.accept();
+
+        // write with 0 bytes remaining should complete immediately
+        ByteBuffer buf = ByteBuffer.allocate(1);
+        buf.put((byte)0);
+        int n = ch.write(buf).get();
+        if (n != 0)
+            throw new RuntimeException("0 expected");
+
+        // write all bytes and close connection when done
+        final ByteBuffer src = genBuffer();
+        ch.write(src, null, new CompletionHandler<Integer,Void>() {
+            public void completed(Integer result, Void att) {
+                if (src.hasRemaining()) {
+                    ch.write(src, null, this);
+                } else {
+                    try {
+                        ch.close();
+                    } catch (IOException ignore) { }
+                }
+            }
+            public void failed(Throwable exc, Void att) {
+            }
+            public void cancelled(Void att) {
+            }
+        });
+
+        // read to EOF or buffer full
+        ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100);
+        do {
+            n = sc.read(dst);
+        } while (n > 0);
+        sc.close();
+
+        // check buffers
+        src.flip();
+        dst.flip();
+        if (!src.equals(dst)) {
+            throw new RuntimeException("Contents differ");
+        }
+
+        // check write fails with ClosedChannelException
+        try {
+            ch.read(dst).get();
+            throw new RuntimeException("ExecutionException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("Cause of ClosedChannelException expected");
+        }
+
+        server.close();
+    }
+
+    // exercise gathering write
+    static void testWrite2() throws Exception {
+        System.out.println("-- write (2) --");
+
+        Server server = new Server();
+        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+        SocketChannel sc = server.accept();
+
+        // write buffers (should complete immediately)
+        ByteBuffer[] srcs = genBuffers(1);
+        long n = ch
+            .write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, null, null).get();
+        if (n <= 0)
+            throw new RuntimeException("No bytes written");
+
+        // set to true to signal that no more buffers should be written
+        final AtomicBoolean continueWriting = new AtomicBoolean(true);
+
+        // number of bytes written
+        final AtomicLong bytesWritten = new AtomicLong(n);
+
+        // write until socket buffer is full so as to create the conditions
+        // for when a write does not complete immediately
+        srcs = genBuffers(1);
+        ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, null,
+            new CompletionHandler<Long,Void>() {
+                public void completed(Long result, Void att) {
+                    long n = result;
+                    if (n <= 0)
+                        throw new RuntimeException("No bytes written");
+                    bytesWritten.addAndGet(n);
+                    if (continueWriting.get()) {
+                        ByteBuffer[] srcs = genBuffers(8);
+                        ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS,
+                            null, this);
+                    }
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+                public void cancelled(Void att) {
+                }
+        });
+
+        // give time for socket buffer to fill up.
+        Thread.sleep(5*1000);
+
+        // signal handler to stop further writing
+        continueWriting.set(false);
+
+        // read until done
+        ByteBuffer buf = ByteBuffer.allocateDirect(4096);
+        long total = 0L;
+        do {
+            n = sc.read(buf);
+            if (n <= 0)
+                throw new RuntimeException("No bytes read");
+            buf.rewind();
+            total += n;
+        } while (total < bytesWritten.get());
+
+        ch.close();
+        sc.close();
+        server.close();
+    }
+
+    static void testShutdown() throws Exception {
+        System.out.println("-- shutdown--");
+
+        Server server = new Server();
+        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+        SocketChannel sc = server.accept();
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(1000);
+        int n;
+
+        // check read
+        ch.shutdownInput();
+        n = ch.read(buf).get();
+        if (n != -1)
+            throw new RuntimeException("-1 expected");
+        // check full with full buffer
+        buf.put(new byte[100]);
+        n = ch.read(buf).get();
+        if (n != -1)
+            throw new RuntimeException("-1 expected");
+
+        // check write
+        ch.shutdownOutput();
+        try {
+            ch.write(buf).get();
+            throw new RuntimeException("ClosedChannelException expected");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof ClosedChannelException))
+                throw new RuntimeException("ClosedChannelException expected");
+        }
+
+        sc.close();
+        ch.close();
+        server.close();
+    }
+
+    static void testTimeout() throws Exception {
+        Server server = new Server();
+        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
+        ch.connect(server.address()).get();
+
+        System.out.println("-- timeout when reading --");
+
+        // this read should timeout
+        ByteBuffer dst = ByteBuffer.allocate(512);
+        try {
+            ch.read(dst, 3, TimeUnit.SECONDS, null, null).get();
+            throw new RuntimeException("Read did not timeout");
+        } catch (ExecutionException x) {
+            if (!(x.getCause() instanceof InterruptedByTimeoutException))
+                throw new RuntimeException("InterruptedByTimeoutException expected");
+        }
+
+        // after a timeout then further reading should throw unspecified runtime exception
+        boolean exceptionThrown = false;
+        try {
+            ch.read(dst);
+        } catch (RuntimeException x) {
+            exceptionThrown = true;
+        }
+        if (!exceptionThrown)
+            throw new RuntimeException("RuntimeException expected after timeout.");
+
+
+        System.out.println("-- timeout when writing --");
+
+        final AtomicReference<Throwable> writeException = new AtomicReference<Throwable>();
+
+        final long timeout = 5;
+        final TimeUnit unit = TimeUnit.SECONDS;
+
+        // write bytes to fill socket buffer
+        ch.write(genBuffer(), timeout, unit, ch,
+            new CompletionHandler<Integer,AsynchronousSocketChannel>()
+        {
+            public void completed(Integer result, AsynchronousSocketChannel ch) {
+                ch.write(genBuffer(), timeout, unit, ch, this);
+            }
+            public void failed(Throwable exc, AsynchronousSocketChannel ch) {
+                writeException.set(exc);
+            }
+            public void cancelled(AsynchronousSocketChannel ch) {
+            }
+        });
+
+        // wait for exception
+        while (writeException.get() == null) {
+            Thread.sleep(100);
+        }
+        if (!(writeException.get() instanceof InterruptedByTimeoutException))
+            throw new RuntimeException("InterruptedByTimeoutException expected");
+
+        // after a timeout then further writing should throw unspecified runtime exception
+        exceptionThrown = false;
+        try {
+            ch.write(genBuffer());
+        } catch (RuntimeException x) {
+            exceptionThrown = true;
+        }
+        if (!exceptionThrown)
+            throw new RuntimeException("RuntimeException expected after timeout.");
+
+        ch.close();
+    }
+
+   // returns ByteBuffer with random bytes
+   static ByteBuffer genBuffer() {
+       int size = 1024 + rand.nextInt(16000);
+       byte[] buf = new byte[size];
+       rand.nextBytes(buf);
+       boolean useDirect = rand.nextBoolean();
+       if (useDirect) {
+           ByteBuffer bb = ByteBuffer.allocateDirect(buf.length);
+           bb.put(buf);
+           bb.flip();
+           return bb;
+       } else {
+           return ByteBuffer.wrap(buf);
+       }
+   }
+
+   // return ByteBuffer[] with random bytes
+   static ByteBuffer[] genBuffers(int max) {
+       int len = 1;
+       if (max > 1)
+           len += rand.nextInt(max);
+       ByteBuffer[] bufs = new ByteBuffer[len];
+       for (int i=0; i<len; i++)
+           bufs[i] = genBuffer();
+       return bufs;
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Leaky.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Unit test for AsynchronousSocketChannel
+ * @run main/othervm -XX:+DisableExplicitGC -mx64m Leaky
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.Future;
+
+/**
+ * Heap buffers must be substituted with direct buffers when doing I/O. This
+ * test creates a scenario on Windows that challenges the per-thread buffer
+ * cache and quickly leads to an OutOfMemoryError if temporary buffers are
+ * not returned to the native heap.
+ */
+
+public class Leaky {
+
+    static final int K = 1024;
+
+    static class Connection {
+        private final AsynchronousSocketChannel client;
+        private final SocketChannel peer;
+        private final ByteBuffer dst;
+        private Future<Integer> readResult;
+
+        Connection() throws Exception {
+            ServerSocketChannel ssc =
+                ServerSocketChannel.open().bind(new InetSocketAddress(0));
+            InetAddress lh = InetAddress.getLocalHost();
+            int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
+            SocketAddress remote = new InetSocketAddress(lh, port);
+            client = AsynchronousSocketChannel.open();
+            client.connect(remote).get();
+            peer = ssc.accept();
+            ssc.close();
+            dst = ByteBuffer.allocate(K*K);
+        }
+
+        void startRead() {
+            dst.clear();
+            readResult = client.read(dst);
+        }
+
+        void write() throws Exception {
+            peer.write(ByteBuffer.wrap("X".getBytes()));
+        }
+
+        void finishRead() throws Exception {
+            readResult.get();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        final int CONNECTION_COUNT = 10;
+        Connection[] connections = new Connection[CONNECTION_COUNT];
+        for (int i=0; i<CONNECTION_COUNT; i++) {
+            connections[i] = new Connection();
+        }
+
+        for (int i=0; i<1024; i++) {
+            // initiate reads
+            for (Connection conn: connections) {
+                conn.startRead();
+            }
+
+            // write data so that the read can complete
+            for (Connection conn: connections) {
+                conn.write();
+            }
+
+            // complete read
+            for (Connection conn: connections) {
+                conn.finishRead();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/Channels/Basic2.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2007-2008 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 4607272
+ * @summary Test Channels methods for interoperability between streams and
+ *     asynchronous byte channels
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Random;
+
+public class Basic2 {
+
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+        // establish loopback connection
+        AsynchronousServerSocketChannel listener =
+            AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+        InetSocketAddress isa =
+            new InetSocketAddress(InetAddress.getLocalHost(), port);
+        AsynchronousSocketChannel ch1 = AsynchronousSocketChannel.open();
+        ch1.connect(isa).get();
+        AsynchronousSocketChannel ch2 = listener.accept().get();
+
+        // start thread to write to stream
+        Writer writer = new Writer(Channels.newOutputStream(ch1));
+        Thread writerThread = new Thread(writer);
+        writerThread.start();
+
+        // start thread to read from stream
+        Reader reader = new Reader(Channels.newInputStream(ch2));
+        Thread readerThread = new Thread(reader);
+        readerThread.start();
+
+        // wait for threads to complete
+        writerThread.join();
+        readerThread.join();
+
+        // check that reader received what we expected
+        if (reader.total() != writer.total())
+            throw new RuntimeException("Unexpected number of bytes read");
+        if (reader.hash() != writer.hash())
+            throw new RuntimeException("Hash incorrect for bytes read");
+
+        // channels should be closed
+        if (ch1.isOpen() || ch2.isOpen())
+            throw new RuntimeException("Channels should be closed");
+    }
+
+    static class Reader implements Runnable {
+        private final InputStream in;
+        private volatile int total;
+        private volatile int hash;
+
+        Reader(InputStream in) {
+            this.in = in;
+        }
+
+        public void run() {
+            try {
+                int n;
+                do {
+                    // random offset/len
+                    byte[] buf = new byte[128 + rand.nextInt(128)];
+                    int len, off;
+                    if (rand.nextBoolean()) {
+                        len = buf.length;
+                        off = 0;
+                        n = in.read(buf);
+                    } else {
+                        len = 1 + rand.nextInt(64);
+                        off = rand.nextInt(64);
+                        n = in.read(buf, off, len);
+                    }
+                    if (n > len)
+                        throw new RuntimeException("Too many bytes read");
+                    if (n > 0) {
+                        total += n;
+                        for (int i=0; i<n; i++) {
+                            int value = buf[off + i];
+                            hash = hash ^ value;
+                        }
+                    }
+                } while (n > 0);
+                in.close();
+
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+        }
+
+        int total() { return total; }
+        int hash() { return hash; }
+    }
+
+    static class Writer implements Runnable {
+        private final OutputStream out;
+        private final int total;
+        private volatile int hash;
+
+        Writer(OutputStream out) {
+            this.out = out;
+            this.total = 50*1000 + rand.nextInt(50*1000);
+        }
+
+        public void run() {
+            hash = 0;
+            int rem = total;
+            try {
+                do {
+                    byte[] buf = new byte[1 + rand.nextInt(rem)];
+                    int off, len;
+
+                    // write random bytes
+                    if (rand.nextBoolean()) {
+                        off = 0;
+                        len = buf.length;
+                    } else {
+                        off = rand.nextInt(buf.length);
+                        int r = buf.length - off;
+                        len = (r <= 1) ? 1 : (1 + rand.nextInt(r));
+                    }
+                    for (int i=0; i<len; i++) {
+                        byte value = (byte)rand.nextInt(256);
+                        buf[off + i] = value;
+                        hash = hash ^ value;
+                    }
+                    if ((off == 0) && (len == buf.length)) {
+                        out.write(buf);
+                    } else {
+                        out.write(buf, off, len);
+                    }
+                    rem -= len;
+                } while (rem > 0);
+
+                // close stream when done
+                out.close();
+
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+        }
+
+        int total() { return total; }
+        int hash() { return hash; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 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.
+ */
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+
+public class CheckProvider {
+    public static void main(String[] args) {
+        Class<?> c = AsynchronousChannelProvider.provider().getClass();
+
+        String expected = args[0];
+        String actual = c.getName();
+
+        if (!actual.equals(expected))
+            throw new RuntimeException("Provider is of type '" + actual +
+                "', expected '" + expected + "'");
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1 @@
+Provider1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 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.
+ */
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+import java.nio.channels.*;
+import java.net.ProtocolFamily;
+import java.util.concurrent.ExecutorService;
+import java.io.IOException;
+
+public class Provider1 extends AsynchronousChannelProvider {
+    public Provider1() {
+    }
+
+
+    public AsynchronousChannelGroup openAsynchronousChannelGroup
+        (ThreadPoolType poolType, ExecutorService executor, int n) throws IOException
+    {
+        throw new RuntimeException();
+    }
+
+
+    public AsynchronousSocketChannel openAsynchronousSocketChannel
+        (AsynchronousChannelGroup group) throws IOException
+    {
+        throw new RuntimeException();
+    }
+
+
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel
+        (AsynchronousChannelGroup group) throws IOException
+    {
+        throw new RuntimeException();
+    }
+
+
+    public AsynchronousDatagramChannel openAsynchronousDatagramChannel
+        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException
+    {
+        throw new RuntimeException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 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.
+ */
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+import java.nio.channels.*;
+import java.net.ProtocolFamily;
+import java.util.concurrent.ExecutorService;
+import java.io.IOException;
+
+public class Provider2 extends AsynchronousChannelProvider {
+    public Provider2() {
+    }
+
+
+    public AsynchronousChannelGroup openAsynchronousChannelGroup
+        (ThreadPoolType poolType, ExecutorService executor, int n) throws IOException
+    {
+        throw new RuntimeException();
+    }
+
+
+    public AsynchronousSocketChannel openAsynchronousSocketChannel
+        (AsynchronousChannelGroup group) throws IOException
+    {
+        throw new RuntimeException();
+    }
+
+
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel
+        (AsynchronousChannelGroup group) throws IOException
+    {
+        throw new RuntimeException();
+    }
+
+
+    public AsynchronousDatagramChannel openAsynchronousDatagramChannel
+        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException
+    {
+        throw new RuntimeException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,71 @@
+#
+# Copyright 2008 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
+# @summary Unit test for java.nio.channels.spi.AsynchronousChannelProvider
+# @build Provider1 Provider2 CheckProvider
+# @run shell custom_provider.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 tests
+
+go CheckProvider Provider1
+go -Djava.nio.channels.spi.AsynchronousChannelProvider=Provider2 CheckProvider \
+  Provider2
+
+#
+# Results
+#
+echo ''
+if [ $failures -gt 0 ];
+  then echo "$failures test(s) failed";
+  else echo "All test(s) passed"; fi
+exit $failures
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2007-2008 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.DirectoryStream
+ * @library ..
+ */
+
+import java.nio.file.*;
+import java.util.*;
+import java.io.IOException;
+
+public class Basic {
+    static boolean found;
+
+    static void doTest(final Path dir) throws IOException {
+        // test that directory is empty
+        Files.withDirectory(dir, new FileAction<FileRef>() {
+            public void invoke(FileRef entry) {
+                throw new RuntimeException("directory not empty");
+            }
+        });
+
+        // create file in directory
+        final Path foo = Paths.get("foo");
+        dir.resolve(foo).createFile();
+
+        // iterate over directory and check there is one entry
+        found = false;
+        Files.withDirectory(dir, new FileAction<Path>() {
+            public void invoke(Path entry) {
+                if (entry.getName().equals(foo)) {
+                    if (found)
+                        throw new RuntimeException("entry already found");
+                    found = true;
+                } else {
+                    throw new RuntimeException("entry " + entry.getName() +
+                        " not expected");
+                }
+            }
+        });
+        if (!found)
+            throw new RuntimeException("entry not found");
+
+        // check filtering: f* should match foo
+        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
+            private PathMatcher matcher =
+                dir.getFileSystem().getNameMatcher("glob", "f*");
+            public boolean accept(Path file) {
+                return matcher.matches(file);
+            }
+        };
+        Files.withDirectory(dir, filter, new FileAction<Path>() {
+            public void invoke(Path entry) {
+                if (!entry.getName().equals(foo))
+                    throw new RuntimeException("entry not expected");
+            }
+        });
+
+        // check filtering: z* should not match any files
+        filter = new DirectoryStream.Filter<Path>() {
+            private PathMatcher matcher =
+                dir.getFileSystem().getNameMatcher("glob", "z*");
+            public boolean accept(Path file) {
+                return matcher.matches(file);
+            }
+        };
+        Files.withDirectory(dir, filter, new FileAction<FileRef>() {
+            public void invoke(FileRef entry) {
+                throw new RuntimeException("no matching entries expected");
+            }
+        });
+
+        // test NotDirectoryException
+        try {
+            dir.resolve(foo).newDirectoryStream();
+            throw new RuntimeException("NotDirectoryException not thrown");
+        } catch (NotDirectoryException x) {
+        }
+
+        // test iterator remove method
+        DirectoryStream<Path> stream = dir.newDirectoryStream();
+        Iterator<Path> i = stream.iterator();
+        while (i.hasNext()) {
+            Path entry = i.next();
+            if (!entry.getName().equals(foo))
+                throw new RuntimeException("entry not expected");
+            i.remove();
+        }
+        stream.close();
+
+        // test IllegalStateException
+        stream =  dir.newDirectoryStream();
+        i = stream.iterator();
+        try {
+            stream.iterator();
+            throw new RuntimeException("IllegalStateException not thrown as expected");
+        } catch (IllegalStateException x) {
+        }
+        stream.close();
+        try {
+            stream.iterator();
+            throw new RuntimeException("IllegalStateException not thrown as expected");
+        } catch (IllegalStateException x) {
+        }
+        try {
+            i.hasNext();
+            throw new RuntimeException("ConcurrentModificationException not thrown as expected");
+        } catch (ConcurrentModificationException x) {
+            Throwable t = x.getCause();
+            if (!(t instanceof IllegalStateException))
+                throw new RuntimeException("Cause is not IllegalStateException as expected");
+        }
+        try {
+            i.next();
+            throw new RuntimeException("IllegalStateException not thrown as expected");
+        } catch (ConcurrentModificationException x) {
+            Throwable t = x.getCause();
+            if (!(t instanceof IllegalStateException))
+                throw new RuntimeException("Cause is not IllegalStateException as expected");
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            doTest(dir);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Filters.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2007-2008 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().getNameMatcher("glob", glob);
+            public boolean accept(Path file) {
+                return matcher.matches(file);
+            }
+        };
+    }
+
+    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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/SecureDS.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2007-2008 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.SecureDirectoryStream
+ * @library ..
+ */
+
+import java.nio.file.*;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.LinkOption.*;
+import java.nio.file.attribute.*;
+import java.nio.channels.*;
+import java.io.IOException;
+import java.util.*;
+
+public class SecureDS {
+    static boolean supportsLinks;
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            DirectoryStream stream = dir.newDirectoryStream();
+            stream.close();
+            if (!(stream instanceof SecureDirectoryStream)) {
+                System.out.println("SecureDirectoryStream not supported.");
+                return;
+            }
+
+            supportsLinks = TestUtil.supportsLinks(dir);
+
+            // run tests
+            doBasicTests(dir);
+            doMoveTests(dir);
+            miscTests(dir);
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+
+    // Exercise each of SecureDirectoryStream's method (except move)
+    static void doBasicTests(Path dir) throws IOException {
+        Path dir1 = dir.resolve("dir1").createDirectory();
+        Path dir2 = dir.resolve("dir2");
+
+        // create a file, directory, and two sym links in the directory
+        Path fileEntry = Paths.get("myfile");
+        dir1.resolve(fileEntry).createFile();
+        Path dirEntry = Paths.get("mydir");
+        dir1.resolve(dirEntry).createDirectory();
+        // myfilelink -> myfile
+        Path link1Entry = Paths.get("myfilelink");
+        if (supportsLinks)
+            dir1.resolve(link1Entry).createSymbolicLink(fileEntry);
+        // mydirlink -> mydir
+        Path link2Entry = Paths.get("mydirlink");
+        if (supportsLinks)
+            dir1.resolve(link2Entry).createSymbolicLink(dirEntry);
+
+        // open directory and then move it so that it is no longer accessible
+        // via its original path.
+        SecureDirectoryStream stream =
+            (SecureDirectoryStream)dir1.newDirectoryStream();
+        dir1.moveTo(dir2);
+
+        // Test: iterate over all entries
+        int count = 0;
+        for (Path entry: stream) { count++; }
+        assertTrue(count == (supportsLinks ? 4 : 2));
+
+        // Test: getFileAttributeView to access directory's attributes
+        assertTrue(stream
+            .getFileAttributeView(BasicFileAttributeView.class)
+                .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)
+                .readAttributes()
+                    .isRegularFile());
+        assertTrue(stream
+            .getFileAttributeView(fileEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
+                .readAttributes()
+                    .isRegularFile());
+        assertTrue(stream
+            .getFileAttributeView(dirEntry, BasicFileAttributeView.class)
+                .readAttributes()
+                    .isDirectory());
+        assertTrue(stream
+            .getFileAttributeView(dirEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
+                .readAttributes()
+                    .isDirectory());
+        if (supportsLinks) {
+            assertTrue(stream
+                .getFileAttributeView(link1Entry, BasicFileAttributeView.class)
+                    .readAttributes()
+                        .isRegularFile());
+            assertTrue(stream
+                .getFileAttributeView(link1Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
+                    .readAttributes()
+                        .isSymbolicLink());
+            assertTrue(stream
+                .getFileAttributeView(link2Entry, BasicFileAttributeView.class)
+                    .readAttributes()
+                        .isDirectory());
+            assertTrue(stream
+                .getFileAttributeView(link2Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
+                    .readAttributes()
+                        .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();
+        if (supportsLinks) {
+            stream.newByteChannel(link1Entry, opts).close();
+            try {
+                Set<OpenOption> mixed = new HashSet<OpenOption>();
+                mixed.add(READ);
+                mixed.add(NOFOLLOW_LINKS);
+                stream.newByteChannel(link1Entry, mixed).close();
+                shouldNotGetHere();
+            } catch (IOException x) { }
+        }
+
+        // Test: newDirectoryStream
+        stream.newDirectoryStream(dirEntry, true, null).close();
+        stream.newDirectoryStream(dirEntry, false, null).close();
+        if (supportsLinks) {
+            stream.newDirectoryStream(link2Entry, true, null).close();
+            try {
+                stream.newDirectoryStream(link2Entry, false, null).close();
+                shouldNotGetHere();
+            } catch (IOException x) { }
+        }
+
+        // Test: delete
+        if (supportsLinks) {
+            stream.deleteFile(link1Entry);
+            stream.deleteFile(link2Entry);
+        }
+        stream.deleteDirectory(dirEntry);
+        stream.deleteFile(fileEntry);
+
+        // Test: remove
+        // (requires resetting environment to get new iterator)
+        stream.close();
+        dir2.moveTo(dir1);
+        dir1.resolve(fileEntry).createFile();
+        stream = (SecureDirectoryStream)dir1.newDirectoryStream();
+        dir1.moveTo(dir2);
+        Iterator<Path> iter = stream.iterator();
+        int removed = 0;
+        while (iter.hasNext()) {
+            iter.next();
+            iter.remove();
+            removed++;
+        }
+        assertTrue(removed == 1);
+
+        // clean-up
+        stream.close();
+        dir2.delete();
+    }
+
+    // Exercise SecureDirectoryStream's move method
+    static void doMoveTests(Path dir) throws IOException {
+        Path dir1 = dir.resolve("dir1").createDirectory();
+        Path dir2 = dir.resolve("dir2").createDirectory();
+
+        // create dir1/myfile, dir1/mydir, dir1/mylink
+        Path fileEntry = Paths.get("myfile");
+        dir1.resolve(fileEntry).createFile();
+        Path dirEntry = Paths.get("mydir");
+        dir1.resolve(dirEntry).createDirectory();
+        Path linkEntry = Paths.get("mylink");
+        if (supportsLinks)
+            dir1.resolve(linkEntry).createSymbolicLink(Paths.get("missing"));
+
+        // target name
+        Path target = Paths.get("newfile");
+
+        // open stream to both directories
+        SecureDirectoryStream stream1 =
+            (SecureDirectoryStream)dir1.newDirectoryStream();
+        SecureDirectoryStream stream2 =
+            (SecureDirectoryStream)dir2.newDirectoryStream();
+
+        // Test: move dir1/myfile -> dir2/newfile
+        stream1.move(fileEntry, stream2, target);
+        assertTrue(dir1.resolve(fileEntry).notExists());
+        assertTrue(dir2.resolve(target).exists());
+        stream2.deleteFile(target);
+
+        // Test: move dir1/mydir -> dir2/newfile
+        stream1.move(dirEntry, stream2, target);
+        assertTrue(dir1.resolve(dirEntry).notExists());
+        assertTrue(dir2.resolve(target).exists());
+        stream2.deleteDirectory(target);
+
+        // Test: move dir1/mylink -> dir2/newfile
+        if (supportsLinks) {
+            stream1.move(linkEntry, stream2, target);
+            assertTrue(dir2.resolve(target)
+                .getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS)
+                .readAttributes()
+                .isSymbolicLink());
+            stream2.deleteFile(target);
+        }
+
+        // Test: move between devices
+        String testDirAsString = System.getProperty("test.dir");
+        if (testDirAsString != null) {
+            Path testDir = Paths.get(testDirAsString);
+            if (!dir1.getFileStore().equals(testDir.getFileStore())) {
+                SecureDirectoryStream ts =
+                    (SecureDirectoryStream)testDir.newDirectoryStream();
+                dir1.resolve(fileEntry).createFile();
+                try {
+                    stream1.move(fileEntry, ts, target);
+                    shouldNotGetHere();
+                } catch (AtomicMoveNotSupportedException x) { }
+                ts.close();
+                stream1.deleteFile(fileEntry);
+            }
+        }
+
+        // clean-up
+        dir1.delete();
+        dir2.delete();
+    }
+
+    // null and ClosedDirectoryStreamException
+    static void miscTests(Path dir) throws IOException {
+        Path file = Paths.get("file");
+        dir.resolve(file).createFile();
+
+        SecureDirectoryStream stream =
+            (SecureDirectoryStream)dir.newDirectoryStream();
+
+        // NullPointerException
+        try {
+            stream.getFileAttributeView(null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.getFileAttributeView(null, BasicFileAttributeView.class);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.getFileAttributeView(file, null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.newByteChannel(null, EnumSet.of(CREATE,WRITE));
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.newByteChannel(null, EnumSet.of(CREATE,WRITE,null));
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.newByteChannel(file, null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.move(null, stream, file);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.move(file, null, file);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.move(file, stream, null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.newDirectoryStream(null, true, null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.deleteFile(null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+        try {
+            stream.deleteDirectory(null);
+            shouldNotGetHere();
+        } catch (NullPointerException x) { }
+
+        // close stream
+        stream.close();
+        stream.close();     // should be no-op
+
+        // ClosedDirectoryStreamException
+        try {
+            stream.newDirectoryStream(file, true, null);
+            shouldNotGetHere();
+        } catch (ClosedDirectoryStreamException x) { }
+        try {
+            stream.newByteChannel(file, EnumSet.of(READ));
+            shouldNotGetHere();
+        } catch (ClosedDirectoryStreamException x) { }
+        try {
+            stream.move(file, stream, file);
+            shouldNotGetHere();
+        } catch (ClosedDirectoryStreamException x) { }
+        try {
+            stream.deleteFile(file);
+            shouldNotGetHere();
+        } catch (ClosedDirectoryStreamException x) { }
+
+        // clean-up
+        dir.resolve(file).delete();
+    }
+
+    static void assertTrue(boolean b) {
+        if (!b) throw new RuntimeException("Assertion failed");
+    }
+
+    static void shouldNotGetHere() {
+        assertTrue(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileStore/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2007-2008 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.FileStore
+ * @library ..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+
+public class Basic {
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            doTests(dir);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+
+    static void assertTrue(boolean okay) {
+        if (!okay)
+            throw new RuntimeException("Assertion failed");
+    }
+
+    static void doTests(Path dir) throws IOException {
+        /**
+         * Test: Directory should be on FileStore that is writable
+         */
+        assertTrue(!dir.getFileStore().isReadOnly());
+
+        /**
+         * Test: Two files should have the same FileStore
+         */
+        FileStore store1 = dir.resolve("foo").createFile().getFileStore();
+        FileStore store2 = dir.resolve("bar").createFile().getFileStore();
+        assertTrue(store1.equals(store2));
+        assertTrue(store2.equals(store1));
+        assertTrue(store1.hashCode() == store2.hashCode());
+
+        /**
+         * Test: File and FileStore attributes
+         */
+        assertTrue(store1.supportsFileAttributeView("basic"));
+
+        /**
+         * Test: Enumerate all FileStores
+         */
+        for (FileStore store: FileSystems.getDefault().getFileStores()) {
+            System.out.format("%s (name=%s type=%s)\n", store, store.name(),
+                store.type());
+            Attributes.readFileStoreSpaceAttributes(store);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileSystem/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2007-2008 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.FileSystem
+ * @library ..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+
+/**
+ * Simple santity checks for java.nio.file.FileSystem
+ */
+public class Basic {
+
+    static void check(boolean okay, String msg) {
+        if (!okay)
+            throw new RuntimeException(msg);
+    }
+
+    static void checkSupported(FileSystem fs, String... views) {
+        for (String view: views) {
+            check(fs.supportedFileAttributeViews().contains(view),
+                "support for '" + view + "' expected");
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        FileSystem fs = FileSystems.getDefault();
+
+        // close should throw UOE
+        try {
+            fs.close();
+            throw new RuntimeException("UnsupportedOperationException expected");
+        } catch (UnsupportedOperationException e) { }
+        check(fs.isOpen(), "should be open");
+
+        check(!fs.isReadOnly(), "should provide read-write access");
+
+        check(fs.provider().getScheme().equals("file"),
+            "should use 'file' scheme");
+
+        // santity check method - need to re-visit this in future as I/O errors
+        // are possible
+        for (FileStore store: fs.getFileStores()) {
+            System.out.println(store);
+        }
+
+        // sanity check supportedFileAttributeViews
+        checkSupported(fs, "basic");
+        String os = System.getProperty("os.name");
+        if (os.equals("SunOS"))
+            checkSupported(fs, "posix", "unix", "owner", "acl", "xattr");
+        if (os.equals("Linux"))
+            checkSupported(fs, "posix", "unix", "owner", "dos", "xattr");
+        if (os.equals("Windows"))
+            checkSupported(fs, "owner", "dos", "acl", "xattr");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ContentType.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.io.*;
+
+/**
+ * Uses Files.probeContentType to probe html file and custom file type.
+ */
+
+public class ContentType {
+
+    static FileRef createHtmlFile() throws IOException {
+        Path file = File.createTempFile("foo", ".html").toPath();
+        OutputStream out = file.newOutputStream();
+        try {
+            out.write("<html><body>foo</body></html>".getBytes());
+        } finally {
+            out.close();
+        }
+
+        return file;
+    }
+
+    static FileRef createUnknownFile() throws IOException {
+        return File.createTempFile("unknown", "unknown-file-type-789").toPath();
+    }
+
+    static FileRef 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();
+        try {
+            String type = Files.probeContentType(file);
+            if (type == null) {
+                System.err.println("Content type cannot be determined - test skipped");
+            } else {
+                if (!type.equals("text/html"))
+                    throw new RuntimeException("Unexpected type: " + type);
+            }
+        } finally {
+            file.delete();
+        }
+        file = createUnknownFile();
+        try {
+            String type = Files.probeContentType(file);
+            if (type != null)
+                 throw new RuntimeException(file + " should not be recognized as:" +
+                     type);
+        } finally {
+            file.delete();
+        }
+
+        // exercise custom file type detector
+        file = createGrapeFile();
+        try {
+            String type = Files.probeContentType(file);
+            if (type == null)
+                throw new RuntimeException("Custom file type detector not installed?");
+            if (!type.equals("grape/unknown"))
+                throw new RuntimeException("Unexpected type: " + type);
+        } finally {
+            file.delete();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/CreateFileTree.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Creates a file tree with possible cycles caused by symbolic links
+ * to ancestor directories.
+ */
+
+public class CreateFileTree {
+
+    static final Random rand = new Random();
+
+    public static Path createTemporaryDirectory() throws IOException {
+        Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+        Path dir;
+        do {
+            dir = tmpdir.resolve("name" + rand.nextInt());
+        } while (dir.exists());
+        dir.createDirectory();
+        return dir;
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path top = createTemporaryDirectory();
+        if (!top.isAbsolute())
+            top = top.toAbsolutePath();
+
+        List<Path> dirs = new ArrayList<Path>();
+
+        // create tree
+        Queue<Path> queue = new ArrayDeque<Path>();
+        queue.add(top);
+        int total = 1 + rand.nextInt(20);
+        int n = 0;
+        Path dir;
+        while (((dir = queue.poll()) != null) && (n < total)) {
+            int r = Math.min((total-n), (1+rand.nextInt(3)));
+            for (int i=0; i<r; i++) {
+                String name = "dir" + (++n);
+                Path subdir = dir.resolve(name).createDirectory();
+                queue.offer(subdir);
+                dirs.add(subdir);
+            }
+        }
+        assert dirs.size() >= 2;
+
+        // create a few regular files in the file tree
+        int files = dirs.size() * 3;
+        for (int i=0; i<files; i++) {
+            String name = "file" + (i+1);
+            int x = rand.nextInt(dirs.size());
+            dirs.get(x).resolve(name).createFile();
+        }
+
+        // create a few sym links in the file tree so as to create cycles
+        int links = 1 + rand.nextInt(5);
+        for (int i=0; i<links; i++) {
+            int x = rand.nextInt(dirs.size());
+            int y;
+            do {
+                y = rand.nextInt(dirs.size());
+            } while (y != x);
+            String name = "link" + (i+1);
+            Path link = dirs.get(x).resolve(name);
+            Path target = dirs.get(y);
+            link.createSymbolicLink(target);
+        }
+
+        // done
+        System.out.println(top);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ForceLoad.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007-2008 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 Test library dependencies by invoking Files.probeContentType
+ *     before other methods that would cause nio.dll to be loaded.
+ */
+
+import java.nio.file.*;
+import java.io.IOException;
+
+public class ForceLoad {
+
+    public static void main(String[] args) throws IOException {
+        Files.probeContentType(Paths.get("."));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,1 @@
+SimpleFileTypeDetector
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/Misc.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007-2008 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.Files for miscellenous cases not
+ *   covered by other tests
+ * @library ..
+ */
+
+import java.nio.file.*;
+import java.io.IOException;
+import java.util.*;
+
+public class Misc {
+
+    static void npeExpected() {
+        throw new RuntimeException("NullPointerException expected");
+    }
+
+    public static void main(String[] args) throws IOException {
+        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);
+            Files.walkFileTree(Paths.get("."), opts, Integer.MAX_VALUE,
+                new SimpleFileVisitor<Path>(){});
+            npeExpected();
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class),
+                Integer.MAX_VALUE, null);
+            npeExpected();
+        } catch (NullPointerException e) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/PrintFileTree.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Invokes Files.walkFileTree to traverse a file tree and prints
+ * each of the directories and files. The -L option causes symbolic
+ * links to be followed.
+ */
+
+public class PrintFileTree {
+
+    public static void main(String[] args) throws Exception {
+        boolean followLinks = false;
+        Path dir;
+
+        if (args[0].equals("-L")) {
+            followLinks = true;
+            dir = Paths.get(args[1]);
+        } else {
+            dir = Paths.get(args[0]);
+        }
+
+        Set<FileVisitOption> options = new HashSet<FileVisitOption>();
+        if (followLinks)
+            options.add(FileVisitOption.FOLLOW_LINKS);
+
+        Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor<FileRef>() {
+            public FileVisitResult preVisitDirectory(FileRef dir) {
+                System.out.println(dir);
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) {
+                exc.printStackTrace();
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
+                System.out.println(file);
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) {
+                if (exc != null) {
+                    exc.printStackTrace();
+                    return FileVisitResult.TERMINATE;
+                }
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult visitFileFailed(FileRef file, IOException exc) {
+                exc.printStackTrace();
+                return FileVisitResult.TERMINATE;
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SimpleFileTypeDetector.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.nio.file.spi.FileTypeDetector;
+import java.io.*;
+
+
+public class SimpleFileTypeDetector extends FileTypeDetector {
+    public SimpleFileTypeDetector() {
+    }
+
+    public String probeContentType(FileRef file) throws IOException {
+
+        System.out.println("probe " + file + "...");
+
+        if (file instanceof Path) {
+            String name = ((Path)file).toString();
+            if (name.endsWith(".grape")) {
+                return "grape/unknown";
+            }
+        }
+
+        // unknown
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SkipSiblings.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Unit test for Files.walkFileTree to test SKIP_SIBLINGS return value.
+ */
+
+public class SkipSiblings {
+
+    static final Random rand = new Random();
+    static final Set<Path> skipped = new HashSet<Path>();
+
+    // check if this path's directory has been skipped
+    static void check(Path path) {
+        if (skipped.contains(path.getParent()))
+            throw new RuntimeException(path + " should not have been visited");
+    }
+
+    // indicates if the siblings of this path should be skipped
+    static boolean skip(Path path) {
+        Path parent = path.getParent();
+        if (parent != null && rand.nextBoolean()) {
+            skipped.add(parent);
+            return true;
+        }
+        return false;
+    }
+
+    public static void main(String[] args) throws Exception {
+        Path dir = Paths.get(args[0]);
+
+        Files.walkFileTree(dir, new FileVisitor<Path>() {
+            public FileVisitResult preVisitDirectory(Path dir) {
+                check(dir);
+                if (skip(dir))
+                    return FileVisitResult.SKIP_SIBLINGS;
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
+                throw new RuntimeException(exc);
+            }
+
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                check(file);
+                if (skip(file))
+                    return FileVisitResult.SKIP_SIBLINGS;
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult postVisitDirectory(Path dir, IOException x) {
+                if (x != null)
+                    throw new RuntimeException(x);
+                check(dir);
+                return FileVisitResult.CONTINUE;
+            }
+            public FileVisitResult visitFileFailed(Path file, IOException x) {
+                throw new RuntimeException(x);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/TerminateWalk.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Unit test for Files.walkFileTree to test TERMINATE return value
+ */
+
+public class TerminateWalk {
+
+    static final Random rand = new Random();
+    static boolean terminated;
+
+    static FileVisitResult maybeTerminate() {
+        if (terminated)
+            throw new RuntimeException("FileVisitor invoked after termination");
+        if (rand.nextInt(10) == 0) {
+            terminated = true;
+            return FileVisitResult.TERMINATE;
+        } else {
+            return FileVisitResult.CONTINUE;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Path dir = Paths.get(args[0]);
+
+        Files.walkFileTree(dir, new FileVisitor<Path>() {
+            public FileVisitResult preVisitDirectory(Path dir) {
+                return maybeTerminate();
+            }
+            public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
+                return maybeTerminate();
+            }
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                return maybeTerminate();
+            }
+            public FileVisitResult postVisitDirectory(Path dir, IOException x) {
+                return maybeTerminate();
+            }
+            public FileVisitResult visitFileFailed(Path file, IOException x) {
+                return maybeTerminate();
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/content_type.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,70 @@
+#
+# Copyright 2007-2008 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
+# @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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/walk_file_tree.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,86 @@
+#
+# Copyright 2007-2008 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 walkFileTree method
+# @build CreateFileTree PrintFileTree SkipSiblings TerminateWalk
+# @run shell walk_file_tree.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_* )
+        echo "This test does not run on Windows" 
+        exit 0
+        ;;
+    * )
+        CLASSPATH=${TESTCLASSES}:${TESTSRC}
+        ;;
+esac
+export CLASSPATH
+
+# create the file tree
+ROOT=`$JAVA CreateFileTree`
+if [ $? != 0 ]; then exit 1; fi
+
+failures=0
+
+# print the file tree and compare output with find(1)
+$JAVA PrintFileTree "$ROOT" > out1
+find "$ROOT" > out2
+diff out1 out2
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
+# repeat test following links (use -follow instead of -L
+# to allow running on older systems)
+$JAVA PrintFileTree -L "$ROOT" > out1
+find "$ROOT" -follow > out2
+diff out1 out2
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
+# test SKIP_SIBLINGS
+$JAVA SkipSiblings "$ROOT"
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
+# test TERMINATE
+$JAVA TerminateWalk "$ROOT"
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
+# clean-up
+rm -r "$ROOT"
+
+echo ''
+if [ $failures -gt 0 ];
+  then echo "$failures test(s) failed";
+  else echo "Test passed"; fi
+exit $failures
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/CopyAndMove.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,983 @@
+/*
+ * Copyright 2007-2008 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.Path copyTo/moveTo methods
+ * @library ..
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.file.*;
+import static java.nio.file.StandardCopyOption.*;
+import static java.nio.file.LinkOption.*;
+import java.nio.file.attribute.*;
+import java.io.*;
+import java.util.*;
+
+public class CopyAndMove {
+    static final Random rand = new Random();
+    static boolean heads() { return rand.nextBoolean(); }
+    static boolean supportsLinks;
+
+    public static void main(String[] args) throws Exception {
+        Path dir1 = TestUtil.createTemporaryDirectory();
+        try {
+            supportsLinks = TestUtil.supportsLinks(dir1);
+
+            // Exercise copyTo
+            doCopyTests(dir1);
+
+            // Exercise moveTo
+            // if test.dir differs to temporary file system then can test
+            // moving between devices
+            String testDir = System.getProperty("test.dir");
+            Path dir2 = (testDir != null) ? Paths.get(testDir) : dir1;
+            doMoveTests(dir1, dir2);
+
+        } finally {
+            TestUtil.removeAll(dir1);
+        }
+    }
+
+    static void checkBasicAttributes(BasicFileAttributes attrs1,
+                                     BasicFileAttributes attrs2)
+    {
+        // check file type
+        assertTrue(attrs1.isRegularFile() == attrs2.isRegularFile());
+        assertTrue(attrs1.isDirectory() == attrs2.isDirectory());
+        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());
+        assertTrue(time1 == time2);
+
+        // check size
+        if (attrs1.isRegularFile())
+            assertTrue(attrs1.size() == attrs2.size());
+    }
+
+    static void checkPosixAttributes(PosixFileAttributes attrs1,
+                                     PosixFileAttributes attrs2)
+    {
+        assertTrue(attrs1.permissions().equals(attrs2.permissions()));
+        assertTrue(attrs1.owner().equals(attrs2.owner()));
+        assertTrue(attrs1.group().equals(attrs2.group()));
+    }
+
+    static void checkDosAttributes(DosFileAttributes attrs1,
+                                   DosFileAttributes attrs2)
+    {
+        assertTrue(attrs1.isReadOnly() == attrs2.isReadOnly());
+        assertTrue(attrs1.isHidden() == attrs2.isHidden());
+        assertTrue(attrs1.isArchive() == attrs2.isArchive());
+        assertTrue(attrs1.isSystem() == attrs2.isSystem());
+    }
+
+    static void checkNamedAttributes(Map<String,ByteBuffer> attrs1,
+                                     Map<String,ByteBuffer> attrs2)
+    {
+        assert attrs1.size() == attrs2.size();
+        for (String name: attrs1.keySet()) {
+            ByteBuffer bb1 = attrs1.get(name);
+            ByteBuffer bb2 = attrs2.get(name);
+            assertTrue(bb2 != null);
+            assertTrue(bb1.equals(bb2));
+        }
+    }
+
+    static Map<String,ByteBuffer> readNamedAttributes(Path file)
+        throws IOException
+    {
+        NamedAttributeView view = file
+            .getFileAttributeView(NamedAttributeView.class);
+        Map<String,ByteBuffer> result = new HashMap<String,ByteBuffer>();
+        for (String name: view.list()) {
+            int size = view.size(name);
+            ByteBuffer bb = ByteBuffer.allocate(size);
+            int n = view.read(name, bb);
+            assertTrue(n == size);
+            bb.flip();
+            result.put(name, bb);
+        }
+        return result;
+    }
+
+    // move source to target with verification
+    static void moveAndVerify(Path source, Path target, CopyOption... options)
+        throws IOException
+    {
+        // read attributes before file is moved
+        BasicFileAttributes basicAttributes = null;
+        PosixFileAttributes posixAttributes = null;
+        DosFileAttributes dosAttributes = null;
+        Map<String,ByteBuffer> namedAttributes = null;
+
+        // get file attributes of source file
+        String os = System.getProperty("os.name");
+        if (os.equals("SunOS") || os.equals("Linux")) {
+            posixAttributes = Attributes.readPosixFileAttributes(source, NOFOLLOW_LINKS);
+            basicAttributes = posixAttributes;
+        }
+        if (os.startsWith("Windows")) {
+            dosAttributes = Attributes.readDosFileAttributes(source, NOFOLLOW_LINKS);
+            basicAttributes = dosAttributes;
+        }
+        if (basicAttributes == null)
+            basicAttributes = Attributes.readBasicFileAttributes(source, NOFOLLOW_LINKS);
+
+        // hash file contents if regular file
+        int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0;
+
+        // record link target if symbolic link
+        Path linkTarget = null;
+        if (basicAttributes.isSymbolicLink())
+            linkTarget = source.readSymbolicLink();
+
+        // read named attributes if available (and file is not a sym link)
+        if (!basicAttributes.isSymbolicLink() &&
+            source.getFileStore().supportsFileAttributeView("xattr"))
+        {
+            namedAttributes = readNamedAttributes(source);
+        }
+
+        // move file
+        source.moveTo(target, options);
+
+        // verify source does not exist
+        assertTrue(source.notExists());
+
+        // verify file contents
+        if (basicAttributes.isRegularFile()) {
+            if (computeHash(target) != hash)
+                throw new RuntimeException("Failed to verify move of regular file");
+        }
+
+        // verify link target
+        if (basicAttributes.isSymbolicLink()) {
+            if (!target.readSymbolicLink().equals(linkTarget))
+                throw new RuntimeException("Failed to verify move of symbolic link");
+        }
+
+        // verify basic attributes
+        checkBasicAttributes(basicAttributes,
+            Attributes.readBasicFileAttributes(target, NOFOLLOW_LINKS));
+
+        // verify POSIX attributes
+        if (posixAttributes != null && !basicAttributes.isSymbolicLink()) {
+            checkPosixAttributes(posixAttributes,
+                Attributes.readPosixFileAttributes(target, NOFOLLOW_LINKS));
+        }
+
+        // verify DOS attributes
+        if (dosAttributes != null && !basicAttributes.isSymbolicLink()) {
+            checkDosAttributes(dosAttributes,
+                Attributes.readDosFileAttributes(target, NOFOLLOW_LINKS));
+        }
+
+        // verify named attributes
+        if (namedAttributes != null &&
+            target.getFileStore().supportsFileAttributeView("xattr"))
+        {
+            checkNamedAttributes(namedAttributes, readNamedAttributes(target));
+        }
+    }
+
+    /**
+     * Tests all possible ways to invoke moveTo
+     */
+    static void doMoveTests(Path dir1, Path dir2) throws IOException {
+        Path source, target, entry;
+
+        boolean sameDevice = dir1.getFileStore().equals(dir2.getFileStore());
+
+        // -- regular file --
+
+        /**
+         * Test: move regular file, target does not exist
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target);
+        target.delete();
+
+        /**
+         * Test: move regular file, target exists
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1).createFile();
+        try {
+            moveAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        target.delete();
+        target.createDirectory();
+        try {
+            moveAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: move regular file, target does not exist
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target, REPLACE_EXISTING);
+        target.delete();
+
+        /**
+         * Test: move regular file, target exists
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1).createFile();
+        moveAndVerify(source, target, REPLACE_EXISTING);
+        target.delete();
+
+        /**
+         * Test: move regular file, target exists and is empty directory
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1).createDirectory();
+        moveAndVerify(source, target, REPLACE_EXISTING);
+        target.delete();
+
+        /**
+         * Test: move regular file, target exists and is non-empty directory
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1).createDirectory();
+        entry = target.resolve("foo").createFile();
+        try {
+            moveAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        entry.delete();
+        source.delete();
+        target.delete();
+
+        /**
+         * Test atomic move of regular file (same file store)
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target, ATOMIC_MOVE);
+        target.delete();
+
+        /**
+         * Test atomic move of regular file (different file store)
+         */
+        if (!sameDevice) {
+            source = createSourceFile(dir1);
+            target = getTargetFile(dir2);
+            try {
+                moveAndVerify(source, target, ATOMIC_MOVE);
+                throw new RuntimeException("AtomicMoveNotSupportedException expected");
+            } catch (AtomicMoveNotSupportedException x) {
+            }
+            source.delete();
+        }
+
+        // -- directories --
+
+        /*
+         * Test: move empty directory, target does not exist
+         */
+        source = createSourceDirectory(dir1);
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target);
+        target.delete();
+
+        /**
+         * Test: move empty directory, target exists
+         */
+        source = createSourceDirectory(dir1);
+        target = getTargetFile(dir1).createFile();
+        try {
+            moveAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        target.delete();
+        target.createDirectory();
+        try {
+            moveAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: move empty directory, target does not exist
+         */
+        source = createSourceDirectory(dir1);
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target, REPLACE_EXISTING);
+        target.delete();
+
+        /**
+         * Test: move empty directory, target exists
+         */
+        source = createSourceDirectory(dir1);
+        target = getTargetFile(dir1).createFile();
+        moveAndVerify(source, target, REPLACE_EXISTING);
+        target.delete();
+
+        /**
+         * Test: move empty, target exists and is empty directory
+         */
+        source = createSourceDirectory(dir1);
+        target = getTargetFile(dir1).createDirectory();
+        moveAndVerify(source, target, REPLACE_EXISTING);
+        target.delete();
+
+        /**
+         * Test: move empty directory, target exists and is non-empty directory
+         */
+        source = createSourceDirectory(dir1);
+        target = getTargetFile(dir1).createDirectory();
+        entry = target.resolve("foo").createFile();
+        try {
+            moveAndVerify(source, target, REPLACE_EXISTING);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        entry.delete();
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: move non-empty directory (same file system)
+         */
+        source = createSourceDirectory(dir1);
+        source.resolve("foo").createFile();
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target);
+        target.resolve("foo").delete();
+        target.delete();
+
+        /**
+         * Test: move non-empty directory (different file store)
+         */
+        if (!sameDevice) {
+            source = createSourceDirectory(dir1);
+            source.resolve("foo").createFile();
+            target = getTargetFile(dir2);
+            try {
+                moveAndVerify(source, target);
+                throw new RuntimeException("IOException expected");
+            } catch (IOException x) {
+            }
+            source.resolve("foo").delete();
+            source.delete();
+        }
+
+        /**
+         * Test atomic move of directory (same file store)
+         */
+        source = createSourceDirectory(dir1);
+        source.resolve("foo").createFile();
+        target = getTargetFile(dir1);
+        moveAndVerify(source, target, ATOMIC_MOVE);
+        target.resolve("foo").delete();
+        target.delete();
+
+        // -- symbolic links --
+
+        /**
+         * Test: Move symbolic link to file, target does not exist
+         */
+        if (supportsLinks) {
+            Path tmp = createSourceFile(dir1);
+            source = dir1.resolve("link").createSymbolicLink(tmp);
+            target = getTargetFile(dir1);
+            moveAndVerify(source, target);
+            target.delete();
+            tmp.delete();
+        }
+
+        /**
+         * Test: Move symbolic link to directory, target does not exist
+         */
+        if (supportsLinks) {
+            source = dir1.resolve("link").createSymbolicLink(dir2);
+            target = getTargetFile(dir1);
+            moveAndVerify(source, target);
+            target.delete();
+        }
+
+        /**
+         * Test: Move broken symbolic link, target does not exists
+         */
+        if (supportsLinks) {
+            Path tmp = Paths.get("doesnotexist");
+            source = dir1.resolve("link").createSymbolicLink(tmp);
+            target = getTargetFile(dir1);
+            moveAndVerify(source, target);
+            target.delete();
+        }
+
+        /**
+         * Test: Move symbolic link, target exists
+         */
+        if (supportsLinks) {
+            source = dir1.resolve("link").createSymbolicLink(dir2);
+            target = getTargetFile(dir1).createFile();
+            try {
+                moveAndVerify(source, target);
+                throw new RuntimeException("FileAlreadyExistsException expected");
+            } catch (FileAlreadyExistsException x) {
+            }
+            source.delete();
+            target.delete();
+        }
+
+        /**
+         * Test: Move regular file, target exists
+         */
+        if (supportsLinks) {
+            source = dir1.resolve("link").createSymbolicLink(dir2);
+            target = getTargetFile(dir1).createFile();
+            moveAndVerify(source, target, REPLACE_EXISTING);
+            target.delete();
+        }
+
+        /**
+         * Test: move symbolic link, target exists and is empty directory
+         */
+        if (supportsLinks) {
+            source = dir1.resolve("link").createSymbolicLink(dir2);
+            target = getTargetFile(dir1).createDirectory();
+            moveAndVerify(source, target, REPLACE_EXISTING);
+            target.delete();
+        }
+
+        /**
+         * Test: symbolic link, target exists and is non-empty directory
+         */
+        if (supportsLinks) {
+            source = dir1.resolve("link").createSymbolicLink(dir2);
+            target = getTargetFile(dir1).createDirectory();
+            entry = target.resolve("foo").createFile();
+            try {
+                moveAndVerify(source, target);
+                throw new RuntimeException("FileAlreadyExistsException expected");
+            } catch (FileAlreadyExistsException x) {
+            }
+            entry.delete();
+            source.delete();
+            target.delete();
+        }
+
+        /**
+         * Test atomic move of symbolic link (same file store)
+         */
+        if (supportsLinks) {
+            source = dir1.resolve("link").createSymbolicLink(dir1);
+            target = getTargetFile(dir1).createFile();
+            moveAndVerify(source, target, REPLACE_EXISTING);
+            target.delete();
+        }
+
+        // -- misc. tests --
+
+        /**
+         * Test nulls
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1);
+        try {
+            source.moveTo(null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+        try {
+            source.moveTo(target, (CopyOption[])null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+        try {
+            CopyOption[] opts = { REPLACE_EXISTING, null };
+            source.moveTo(target, opts);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+        source.delete();
+
+        /**
+         * Test UOE
+         */
+        source = createSourceFile(dir1);
+        target = getTargetFile(dir1);
+        try {
+            source.moveTo(target, new CopyOption() { });
+        } catch (UnsupportedOperationException x) { }
+        try {
+            source.moveTo(target, REPLACE_EXISTING,  new CopyOption() { });
+        } catch (UnsupportedOperationException x) { }
+        source.delete();
+    }
+
+    // copy source to target with verification
+    static void copyAndVerify(Path source, Path target, CopyOption... options)
+        throws IOException
+    {
+        source.copyTo(target, options);
+
+        // get attributes of source and target file to verify copy
+        boolean followLinks = true;
+        LinkOption[] linkOptions = new LinkOption[0];
+        boolean copyAttributes = false;
+        for (CopyOption opt : options) {
+            if (opt == NOFOLLOW_LINKS) {
+                followLinks = false;
+                linkOptions = new LinkOption[] { NOFOLLOW_LINKS };
+            }
+            if (opt == COPY_ATTRIBUTES)
+                copyAttributes = true;
+        }
+        BasicFileAttributes basicAttributes = Attributes
+            .readBasicFileAttributes(source, linkOptions);
+
+        // check hash if regular file
+        if (basicAttributes.isRegularFile())
+            assertTrue(computeHash(source) == computeHash(target));
+
+        // check link target if symbolic link
+        if (basicAttributes.isSymbolicLink())
+            assert( source.readSymbolicLink().equals(target.readSymbolicLink()));
+
+        // check that attributes are copied
+        if (copyAttributes && followLinks) {
+            checkBasicAttributes(basicAttributes,
+                Attributes.readBasicFileAttributes(source, linkOptions));
+
+            // check POSIX attributes are copied
+            String os = System.getProperty("os.name");
+            if (os.equals("SunOS") || os.equals("Linux")) {
+                checkPosixAttributes(
+                    Attributes.readPosixFileAttributes(source, linkOptions),
+                    Attributes.readPosixFileAttributes(target, linkOptions));
+            }
+
+            // check DOS attributes are copied
+            if (os.startsWith("Windows")) {
+                checkDosAttributes(
+                    Attributes.readDosFileAttributes(source, linkOptions),
+                    Attributes.readDosFileAttributes(target, linkOptions));
+            }
+
+            // check named attributes are copied
+            if (followLinks &&
+                source.getFileStore().supportsFileAttributeView("xattr") &&
+                target.getFileStore().supportsFileAttributeView("xattr"))
+            {
+                checkNamedAttributes(readNamedAttributes(source),
+                                     readNamedAttributes(target));
+            }
+        }
+    }
+
+    /**
+     * Tests all possible ways to invoke copyTo
+     */
+    static void doCopyTests(Path dir) throws IOException {
+        Path source, target, link, entry;
+
+        // -- regular file --
+
+        /**
+         * Test: move regular file, target does not exist
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir);
+        copyAndVerify(source, target);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy regular file, target exists
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir).createFile();
+        try {
+            copyAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        target.delete();
+        target.createDirectory();
+        try {
+            copyAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy regular file, target does not exist
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir);
+        copyAndVerify(source, target, REPLACE_EXISTING);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy regular file, target exists
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir).createFile();
+        copyAndVerify(source, target, REPLACE_EXISTING);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy regular file, target exists and is empty directory
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir).createDirectory();
+        copyAndVerify(source, target, REPLACE_EXISTING);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy regular file, target exists and is non-empty directory
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir).createDirectory();
+        entry = target.resolve("foo").createFile();
+        try {
+            copyAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        entry.delete();
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy regular file + attributes
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir);
+        copyAndVerify(source, target, COPY_ATTRIBUTES);
+        source.delete();
+        target.delete();
+
+
+        // -- directory --
+
+        /*
+         * Test: copy directory, target does not exist
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir);
+        copyAndVerify(source, target);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy directory, target exists
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir).createFile();
+        try {
+            copyAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        target.delete();
+        target.createDirectory();
+        try {
+            copyAndVerify(source, target);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy directory, target does not exist
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir);
+        copyAndVerify(source, target, REPLACE_EXISTING);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy directory, target exists
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir).createFile();
+        copyAndVerify(source, target, REPLACE_EXISTING);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy directory, target exists and is empty directory
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir).createDirectory();
+        copyAndVerify(source, target, REPLACE_EXISTING);
+        source.delete();
+        target.delete();
+
+        /**
+         * Test: copy directory, target exists and is non-empty directory
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir).createDirectory();
+        entry = target.resolve("foo").createFile();
+        try {
+            copyAndVerify(source, target, REPLACE_EXISTING);
+            throw new RuntimeException("FileAlreadyExistsException expected");
+        } catch (FileAlreadyExistsException x) {
+        }
+        entry.delete();
+        source.delete();
+        target.delete();
+
+        /*
+         * Test: copy directory + attributes
+         */
+        source = createSourceDirectory(dir);
+        target = getTargetFile(dir);
+        copyAndVerify(source, target, COPY_ATTRIBUTES);
+        source.delete();
+        target.delete();
+
+        // -- symbolic links --
+
+        /**
+         * Test: Follow link
+         */
+        if (supportsLinks) {
+            source = createSourceFile(dir);
+            link = dir.resolve("link").createSymbolicLink(source);
+            target = getTargetFile(dir);
+            copyAndVerify(link, target);
+            link.delete();
+            source.delete();
+        }
+
+        /**
+         * Test: Copy link (to file)
+         */
+        if (supportsLinks) {
+            source = createSourceFile(dir);
+            link = dir.resolve("link").createSymbolicLink(source);
+            target = getTargetFile(dir);
+            copyAndVerify(link, target, NOFOLLOW_LINKS);
+            link.delete();
+            source.delete();
+        }
+
+        /**
+         * Test: Copy link (to directory)
+         */
+        if (supportsLinks) {
+            source = dir.resolve("mydir").createDirectory();
+            link = dir.resolve("link").createSymbolicLink(source);
+            target = getTargetFile(dir);
+            copyAndVerify(link, target, NOFOLLOW_LINKS);
+            link.delete();
+            source.delete();
+        }
+
+        /**
+         * Test: Copy broken link
+         */
+        if (supportsLinks) {
+            assertTrue(source.notExists());
+            link = dir.resolve("link").createSymbolicLink(source);
+            target = getTargetFile(dir);
+            copyAndVerify(link, target, NOFOLLOW_LINKS);
+            link.delete();
+        }
+
+        /**
+         * Test: Copy link to UNC (Windows only)
+         */
+        if (supportsLinks &&
+            System.getProperty("os.name").startsWith("Windows"))
+        {
+            Path unc = Paths.get("\\\\rialto\\share\\file");
+            link = dir.resolve("link").createSymbolicLink(unc);
+            target = getTargetFile(dir);
+            copyAndVerify(link, target, NOFOLLOW_LINKS);
+            link.delete();
+        }
+
+        // -- misc. tests --
+
+        /**
+         * Test nulls
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir);
+        try {
+            source.copyTo(null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+        try {
+            source.copyTo(target, (CopyOption[])null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+        try {
+            CopyOption[] opts = { REPLACE_EXISTING, null };
+            source.copyTo(target, opts);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+        source.delete();
+
+        /**
+         * Test UOE
+         */
+        source = createSourceFile(dir);
+        target = getTargetFile(dir);
+        try {
+            source.copyTo(target, new CopyOption() { });
+        } catch (UnsupportedOperationException x) { }
+        try {
+            source.copyTo(target, REPLACE_EXISTING,  new CopyOption() { });
+        } catch (UnsupportedOperationException x) { }
+        source.delete();
+    }
+
+
+    static void assertTrue(boolean value) {
+        if (!value)
+            throw new RuntimeException("Assertion failed");
+    }
+
+    // computes simple hash of the given file
+    static int computeHash(Path file) throws IOException {
+        int h = 0;
+
+        InputStream in = file.newInputStream();
+        try {
+            byte[] buf = new byte[1024];
+            int n;
+            do {
+                n = in.read(buf);
+                for (int i=0; i<n; i++) {
+                    h = 31*h + (buf[i] & 0xff);
+                }
+            } while (n > 0);
+        } finally {
+            in.close();
+        }
+        return h;
+    }
+
+    // create file of random size in given directory
+    static Path createSourceFile(Path dir) throws IOException {
+        String name = "source" + Integer.toString(rand.nextInt());
+        Path file = dir.resolve(name).createFile();
+        byte[] bytes = new byte[rand.nextInt(128*1024)];
+        rand.nextBytes(bytes);
+        OutputStream out = file.newOutputStream();
+        try {
+            out.write(bytes);
+        } finally {
+            out.close();
+        }
+        randomizeAttributes(file);
+        return file;
+    }
+
+    // create directory in the given directory
+    static Path createSourceDirectory(Path dir) throws IOException {
+        String name = "sourcedir" + Integer.toString(rand.nextInt());
+        Path subdir = dir.resolve(name).createDirectory();
+        randomizeAttributes(subdir);
+        return subdir;
+    }
+
+    // "randomize" the file attributes of the given file.
+    static void randomizeAttributes(Path file) throws IOException {
+        String os = System.getProperty("os.name");
+        boolean isWindows = os.startsWith("Windows");
+        boolean isUnix = os.equals("SunOS") || os.equals("Linux");
+        boolean isDirectory = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS)
+            .isDirectory();
+
+        if (isUnix) {
+            Set<PosixFilePermission> perms = Attributes
+                .readPosixFileAttributes(file, NOFOLLOW_LINKS).permissions();
+            PosixFilePermission[] toChange = {
+                PosixFilePermission.GROUP_READ,
+                PosixFilePermission.GROUP_WRITE,
+                PosixFilePermission.GROUP_EXECUTE,
+                PosixFilePermission.OTHERS_READ,
+                PosixFilePermission.OTHERS_WRITE,
+                PosixFilePermission.OTHERS_EXECUTE
+            };
+            for (PosixFilePermission perm: toChange) {
+                if (heads()) {
+                    perms.add(perm);
+                } else {
+                    perms.remove(perm);
+                }
+            }
+            Attributes.setPosixFilePermissions(file, perms);
+        }
+
+        if (isWindows) {
+            DosFileAttributeView view = file
+                .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS);
+            // only set or unset the hidden attribute
+            view.setHidden(heads());
+        }
+
+        boolean addNamedAttributes = heads() &&
+            file.getFileStore().supportsFileAttributeView("xattr");
+
+        // remove this when copying a direcory copies its named streams
+        if (isWindows && isDirectory) addNamedAttributes = false;
+
+        if (addNamedAttributes) {
+            NamedAttributeView view = file
+                .getFileAttributeView(NamedAttributeView.class);
+            int n = rand.nextInt(16);
+            while (n > 0) {
+                byte[] value = new byte[1 + rand.nextInt(100)];
+                view.write("user." + Integer.toString(n), ByteBuffer.wrap(value));
+                n--;
+            }
+        }
+    }
+
+    // create name for file in given directory
+    static Path getTargetFile(Path dir) throws IOException {
+        String name = "target" + Integer.toString(rand.nextInt());
+        return dir.resolve(name);
+    }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/DeleteOnClose.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import static java.nio.file.StandardOpenOption.*;
+import java.io.*;
+import java.util.*;
+
+public class DeleteOnClose {
+
+    public static void main(String[] args) throws IOException {
+        // open file but do not close it. Its existance will be checked by
+        // the calling script.
+        Paths.get(args[0]).newByteChannel(READ, WRITE, DELETE_ON_CLOSE);
+
+        // check temporary file has been deleted after closing it
+        Path file = File.createTempFile("blah", "tmp").toPath();
+        file.newByteChannel(READ, WRITE, DELETE_ON_CLOSE).close();
+        if (file.exists())
+            throw new RuntimeException("Temporary file was not deleted");
+
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            // check that DELETE_ON_CLOSE fails when file is a sym link
+            if (TestUtil.supportsLinks(dir)) {
+                file = dir.resolve("foo").createFile();
+                Path link = dir.resolve("link").createSymbolicLink(file);
+                try {
+                    link.newByteChannel(READ, WRITE, DELETE_ON_CLOSE);
+                    throw new RuntimeException("IOException expected");
+                } catch (IOException ignore) { }
+            }
+
+            // check that DELETE_ON_CLOSE works with files created via open
+            // directories
+            DirectoryStream stream = dir.newDirectoryStream();
+            try {
+                if (stream instanceof SecureDirectoryStream) {
+                    SecureDirectoryStream secure = (SecureDirectoryStream)stream;
+                    file = Paths.get("foo");
+
+                    Set<OpenOption> opts = new HashSet<OpenOption>();
+                    opts.add(WRITE);
+                    opts.add(DELETE_ON_CLOSE);
+                    secure.newByteChannel(file, opts).close();
+
+                    if (dir.resolve(file).exists())
+                        throw new RuntimeException("File not deleted");
+                }
+            } finally {
+                stream.close();
+            }
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-2008 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 Sun-specific ExtendedCopyOption.INTERRUPTIBLE option
+ * @library ..
+ * @run main/othervm -XX:-UseVMInterruptibleIO InterruptCopy
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.Attributes;
+import java.io.*;
+import java.util.concurrent.*;
+import com.sun.nio.file.ExtendedCopyOption;
+
+public class InterruptCopy {
+
+    private static final long FILE_SIZE_TO_COPY = 512 * 1024 * 1024;
+    private static final int DELAY_IN_MS = 500;
+
+    public static void main(String[] args) throws Exception {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            FileStore store = dir.getFileStore();
+            System.out.format("Checking space (%s)\n", store);
+            long usableSpace = Attributes
+                .readFileStoreSpaceAttributes(store).usableSpace();
+            if (usableSpace < 2*FILE_SIZE_TO_COPY) {
+                System.out.println("Insufficient disk space to run test.");
+                return;
+            }
+            doTest(dir);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+
+    static void doTest(Path dir) throws Exception {
+        final Path source = dir.resolve("foo");
+        final Path target = dir.resolve("bar");
+
+        // create source file (don't create it as sparse file because we
+        // require the copy to take a long time)
+        System.out.println("Creating source file...");
+        byte[] buf = new byte[32*1024];
+        long total = 0;
+        OutputStream out = source.newOutputStream();
+        try {
+            do {
+                out.write(buf);
+                total += buf.length;
+            } while (total < FILE_SIZE_TO_COPY);
+        } finally {
+            out.close();
+        }
+        System.out.println("Source file created.");
+
+        ScheduledExecutorService pool =
+            Executors.newSingleThreadScheduledExecutor();
+        try {
+            // copy source to target in main thread, interrupting it after a delay
+            final Thread me = Thread.currentThread();
+            pool.schedule(new Runnable() {
+                public void run() {
+                    me.interrupt();
+                }}, DELAY_IN_MS, TimeUnit.MILLISECONDS);
+            System.out.println("Copying file...");
+            try {
+                source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE);
+                throw new RuntimeException("Copy completed (this is not expected)");
+            } catch (IOException e) {
+                System.out.println("Copy failed (this is expected)");
+                e.printStackTrace();
+            }
+
+            // copy source to target via task in thread pool, interrupting it after
+            // a delay using cancel(true)
+            Future<Void> result = pool.submit(new Callable<Void>() {
+                public Void call() throws IOException {
+                    System.out.println("Copying file...");
+                    source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE,
+                        StandardCopyOption.REPLACE_EXISTING);
+                    return null;
+                }
+            });
+            Thread.sleep(DELAY_IN_MS);
+            boolean cancelled = result.cancel(true);
+            if (!cancelled)
+                result.get();
+            System.out.println("Copy cancelled.");
+        } finally {
+            pool.shutdown();
+            pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Links.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2007-2008 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.Path createSymbolicLink,
+ *     readSymbolicLink, and createLink methods
+ * @library ..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.*;
+import java.util.*;
+
+public class Links {
+
+    static final boolean isWindows =
+        System.getProperty("os.name").startsWith("Windows");
+
+    static void assertTrue(boolean okay) {
+        if (!okay)
+            throw new RuntimeException("Assertion failed");
+    }
+
+    /**
+     * Exercise createSymbolicLink and readLink methods
+     */
+    static void testSymLinks(Path dir) throws IOException {
+        Path link = dir.resolve("link");
+
+        // Check if sym links are supported
+        try {
+            link.createSymbolicLink(Paths.get("foo"));
+            link.delete();
+        } catch (UnsupportedOperationException x) {
+            // sym links not supported
+            return;
+        } catch (IOException x) {
+            // probably insufficient privileges to create sym links (Windows)
+            return;
+        }
+
+        // Test links to various targets
+        String[] windowsTargets =
+            { "foo", "C:\\foo", "\\foo", "\\\\server\\share\\foo" };
+        String[] otherTargets = { "relative", "/absolute" };
+
+        String[] targets = (isWindows) ? windowsTargets : otherTargets;
+        for (String s: targets) {
+            Path target = Paths.get(s);
+            link.createSymbolicLink(target);
+            try {
+                assertTrue(link.readSymbolicLink().equals(target));
+            } finally {
+                link.delete();
+            }
+        }
+    }
+
+    /**
+     * Exercise createLink method
+     */
+    static void testHardLinks(Path dir) throws IOException {
+        Path foo = dir.resolve("foo").createFile();
+        try {
+            Path bar;
+            try {
+                bar = dir.resolve("bar").createLink(foo);
+            } catch (UnsupportedOperationException x) {
+                return;
+            } catch (IOException x) {
+                // probably insufficient privileges (Windows)
+                return;
+            }
+            try {
+                Object key1 = Attributes
+                    .readBasicFileAttributes(foo).fileKey();
+                Object key2 = Attributes
+                    .readBasicFileAttributes(bar).fileKey();
+                assertTrue((key1 == null) || (key1.equals(key2)));
+
+                assertTrue(Attributes
+                    .readBasicFileAttributes(foo).linkCount() >= 2);
+                assertTrue(Attributes
+                    .readBasicFileAttributes(bar).linkCount() >= 2);
+
+            } finally {
+                bar.delete();
+            }
+
+
+        } finally {
+            foo.delete();
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            testSymLinks(dir);
+            testHardLinks(dir);
+
+            // repeat tests on Windows with long path
+            if (isWindows) {
+                Path dirWithLongPath = null;
+                try {
+                    dirWithLongPath = TestUtil.createDirectoryWithLongPath(dir);
+                } catch (IOException x) {
+                    System.out.println("Unable to create long path: " + x);
+                }
+                if (dirWithLongPath != null) {
+                    System.out.println("");
+                    System.out.println("** REPEAT TESTS WITH LONG PATH **");
+                    testSymLinks(dirWithLongPath);
+                    testHardLinks(dirWithLongPath);
+                }
+            }
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Misc.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2007-2008 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.Path for miscellenous methods not
+ *   covered by other tests
+ * @library ..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.*;
+import java.util.*;
+
+public class Misc {
+    static final boolean isWindows =
+        System.getProperty("os.name").startsWith("Windows");
+    static boolean supportsLinks;
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            supportsLinks = TestUtil.supportsLinks(dir);
+
+            // equals and hashCode methods
+            equalsAndHashCode();
+
+            // checkAccess method
+            checkAccessTests(dir);
+
+            // toRealPath method
+            toRealPathTests(dir);
+
+            // isSameFile method
+            isSameFileTests(dir);
+
+            // isHidden method
+            isHiddenTests(dir);
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+
+    /**
+     * Exercise equals and hashCode methods
+     */
+    static void equalsAndHashCode() {
+
+        Path thisFile = Paths.get("this");
+        Path thatFile = Paths.get("that");
+
+        assertTrue(thisFile.equals(thisFile));
+        assertTrue(!thisFile.equals(thatFile));
+
+        assertTrue(!thisFile.equals(null));
+        assertTrue(!thisFile.equals(new Object()));
+
+        Path likeThis = Paths.get("This");
+        if (isWindows) {
+            // case insensitive
+            assertTrue(thisFile.equals(likeThis));
+            assertTrue(thisFile.hashCode() == likeThis.hashCode());
+        } else {
+            // case senstive
+            assertTrue(!thisFile.equals(likeThis));
+        }
+    }
+
+    /**
+     * Exercise checkAccess method
+     */
+    static void checkAccessTests(Path dir) throws IOException {
+        final Path file = dir.resolve("foo").createFile();
+
+        /**
+         * Test: This directory should readable and writable
+         */
+        dir.checkAccess();
+        dir.checkAccess(AccessMode.READ);
+        dir.checkAccess(AccessMode.WRITE);
+        dir.checkAccess(AccessMode.READ, AccessMode.WRITE);
+
+        /**
+         * Test: File does not exist
+         */
+        Path doesNotExist = dir.resolve("thisDoesNotExists");
+        try {
+            doesNotExist.checkAccess();
+            throw new RuntimeException("NoSuchFileException expected");
+        } catch (NoSuchFileException x) {
+        }
+        try {
+            doesNotExist.checkAccess(AccessMode.READ);
+            throw new RuntimeException("NoSuchFileException expected");
+        } catch (NoSuchFileException x) {
+        }
+        try {
+            doesNotExist.checkAccess(AccessMode.WRITE);
+            throw new RuntimeException("NoSuchFileException expected");
+        } catch (NoSuchFileException x) {
+        }
+        try {
+            doesNotExist.checkAccess(AccessMode.EXECUTE);
+            throw new RuntimeException("NoSuchFileException expected");
+        } catch (NoSuchFileException x) {
+        }
+
+        /**
+         * Test: Edit ACL to deny WRITE and EXECUTE
+         */
+        AclFileAttributeView view = file
+            .getFileAttributeView(AclFileAttributeView.class);
+        if (view != null &&
+            file.getFileStore().supportsFileAttributeView("acl"))
+        {
+            UserPrincipal owner = view.getOwner();
+            List<AclEntry> acl = view.getAcl();
+
+            // Insert entry to deny WRITE and EXECUTE
+            AclEntry entry = AclEntry.newBuilder()
+                .setType(AclEntryType.DENY)
+                .setPrincipal(owner)
+                .setPermissions(AclEntryPermission.WRITE_DATA,
+                    AclEntryPermission.EXECUTE)
+                .build();
+            acl.add(0, entry);
+            view.setAcl(acl);
+
+            try {
+                file.checkAccess(AccessMode.WRITE);
+                throw new RuntimeException("AccessDeniedException expected");
+            } catch (AccessDeniedException x) {
+            }
+
+            try {
+                file.checkAccess(AccessMode.EXECUTE);
+                throw new RuntimeException("AccessDeniedException expected");
+            } catch (AccessDeniedException x) {
+            }
+
+
+            // Restore ACL
+            acl.remove(0);
+            view.setAcl(acl);
+        }
+
+        /**
+         * Test: Windows DOS read-only attribute
+         */
+        if (isWindows) {
+            DosFileAttributeView dview =
+                file.getFileAttributeView(DosFileAttributeView.class);
+            dview.setReadOnly(true);
+            try {
+                file.checkAccess(AccessMode.WRITE);
+                throw new RuntimeException("AccessDeniedException expected");
+            } catch (AccessDeniedException x) {
+            }
+            dview.setReadOnly(false);
+
+            // Read-only attribute does not make direcory read-only
+            dview = dir.getFileAttributeView(DosFileAttributeView.class);
+            boolean save = dview.readAttributes().isReadOnly();
+            dview.setReadOnly(true);
+            dir.checkAccess(AccessMode.WRITE);
+            dview.setReadOnly(save);
+        }
+
+        /**
+         * Test: null
+         */
+        try {
+            file.checkAccess((AccessMode)null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException ignore) { }
+
+        // clean-up
+        file.delete();
+    }
+
+    /**
+     * Exercise toRealPath method
+     */
+    static void toRealPathTests(Path dir) throws IOException {
+        final Path file = dir.resolve("foo").createFile();
+        final Path link = dir.resolve("link");
+
+        /**
+         * Test: toRealPath(true) will access same file as toRealPath(false)
+         */
+        assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false)));
+
+        /**
+         * Test: toRealPath(true) should resolve links
+         */
+        if (supportsLinks) {
+            link.createSymbolicLink(file.toAbsolutePath());
+            assertTrue(link.toRealPath(true).equals(file.toRealPath(true)));
+            link.delete();
+        }
+
+
+        /**
+         * Test: toRealPath(false) should not resolve links
+         */
+        if (supportsLinks) {
+            link.createSymbolicLink(file.toAbsolutePath());
+            assertTrue(link.toRealPath(false).getName().equals(link.getName()));
+            link.delete();
+        }
+
+        /**
+         * Test: toRealPath should eliminate "."
+         */
+        assertTrue(dir.resolve(".").toRealPath(true).equals(dir.toRealPath(true)));
+        assertTrue(dir.resolve(".").toRealPath(false).equals(dir.toRealPath(false)));
+
+        /**
+         * Test: toRealPath should eliminate ".." when it doesn't follow a
+         *       symbolic link
+         */
+        Path subdir = dir.resolve("subdir").createDirectory();
+        assertTrue(subdir.resolve("..").toRealPath(true).equals(dir.toRealPath(true)));
+        assertTrue(subdir.resolve("..").toRealPath(false).equals(dir.toRealPath(false)));
+        subdir.delete();
+
+        // clean-up
+        file.delete();
+    }
+
+    /**
+     * Exercise isSameFile method
+     */
+    static void isSameFileTests(Path dir) throws IOException {
+        Path thisFile = dir.resolve("thisFile");
+        Path thatFile = dir.resolve("thatFile");
+
+        /**
+         * Test: isSameFile for self and null
+         */
+        assertTrue(thisFile.isSameFile(thisFile));
+        assertTrue(!thisFile.isSameFile(null));
+
+        /**
+         * Test: Neither files exist
+         */
+        try {
+            thisFile.isSameFile(thatFile);
+            throw new RuntimeException("IOException not thrown");
+        } catch (IOException x) {
+        }
+        try {
+            thatFile.isSameFile(thisFile);
+            throw new RuntimeException("IOException not thrown");
+        } catch (IOException x) {
+        }
+
+        thisFile.createFile();
+        try {
+            /**
+             * Test: One file exists
+             */
+            try {
+                thisFile.isSameFile(thatFile);
+                throw new RuntimeException("IOException not thrown");
+            } catch (IOException x) {
+            }
+            try {
+                thatFile.isSameFile(thisFile);
+                throw new RuntimeException("IOException not thrown");
+            } catch (IOException x) {
+            }
+
+            thatFile.createFile();
+
+            /**
+             * Test: Both file exists
+             */
+            try {
+                assertTrue(!thisFile.isSameFile(thatFile));
+                assertTrue(!thatFile.isSameFile(thisFile));
+            } finally {
+                thatFile.delete(false);
+            }
+
+            /**
+             * Test: Symbolic links
+             */
+            if (supportsLinks) {
+                thatFile.createSymbolicLink(thisFile);
+                try {
+                    assertTrue(thisFile.isSameFile(thatFile));
+                    assertTrue(thatFile.isSameFile(thisFile));
+                } finally {
+                    thatFile.delete(false);
+                }
+            }
+        } finally {
+            thisFile.delete(false);
+        }
+    }
+
+    /**
+     * Exercise isHidden method
+     */
+    static void isHiddenTests(Path dir) throws IOException {
+        assertTrue(!dir.isHidden());
+
+        Path file = dir.resolve(".foo");
+        if (isWindows) {
+            file.createFile();
+            try {
+                Attributes.setAttribute(file, "dos:hidden", true);
+                assertTrue(file.isHidden());
+            } finally {
+                file.delete();
+            }
+        } else {
+            assertTrue(file.isHidden());
+        }
+    }
+
+    static void assertTrue(boolean okay) {
+        if (!okay)
+            throw new RuntimeException("Assertion Failed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/PathOps.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,646 @@
+/*
+ * Copyright 2007-2008 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.Path path operations
+ */
+
+import java.nio.file.*;
+
+public class PathOps {
+
+    static final java.io.PrintStream out = System.out;
+
+    private String input;
+    private Path path;
+    private Exception exc;
+
+    private PathOps(String s) {
+        out.println();
+        input = s;
+        try {
+            path = FileSystems.getDefault().getPath(s);
+            out.format("%s -> %s", s, path);
+        } catch (Exception x) {
+            exc = x;
+            out.format("%s -> %s", s, x);
+        }
+        out.println();
+    }
+
+    Path path() {
+        return path;
+    }
+
+    void fail() {
+        throw new RuntimeException("PathOps failed");
+    }
+
+    void checkPath() {
+        if (path == null) {
+            throw new InternalError("path is null");
+        }
+    }
+
+    void check(Object result, String expected) {
+        out.format("\tExpected: %s\n", expected);
+        out.format("\tActual: %s\n",  result);
+        if (result == null) {
+            if (expected == null) return;
+        } else {
+            // compare string representations
+            if (expected != null && result.toString().equals(expected.toString()))
+                return;
+        }
+        fail();
+    }
+
+    void check(Object result, boolean expected) {
+        check(result, Boolean.toString(expected));
+    }
+
+    PathOps root(String expected) {
+        out.println("check root");
+        checkPath();
+        check(path.getRoot(), expected);
+        return this;
+    }
+
+    PathOps parent(String expected) {
+        out.println("check parent");
+        checkPath();
+        check(path.getParent(), expected);
+        return this;
+    }
+
+    PathOps name(String expected) {
+        out.println("check name");
+        checkPath();
+        check(path.getName(), expected);
+        return this;
+    }
+
+    PathOps element(int index, String expected) {
+        out.format("check element %d\n", index);
+        checkPath();
+        check(path.getName(index), expected);
+        return this;
+    }
+
+    PathOps subpath(int startIndex, int endIndex, String expected) {
+        out.format("test subpath(%d,%d)\n", startIndex, endIndex);
+        checkPath();
+        check(path.subpath(startIndex, endIndex), expected);
+        return this;
+    }
+
+    PathOps starts(String prefix) {
+        out.format("test startsWith with %s\n", prefix);
+        checkPath();
+        Path s = FileSystems.getDefault().getPath(prefix);
+        check(path.startsWith(s), true);
+        return this;
+    }
+
+    PathOps notStarts(String prefix) {
+        out.format("test not startsWith with %s\n", prefix);
+        checkPath();
+        Path s = FileSystems.getDefault().getPath(prefix);
+        check(path.startsWith(s), false);
+        return this;
+    }
+
+    PathOps ends(String suffix) {
+        out.format("test endsWith %s\n", suffix);
+        checkPath();
+        Path s = FileSystems.getDefault().getPath(suffix);
+        check(path.endsWith(s), true);
+        return this;
+    }
+
+    PathOps notEnds(String suffix) {
+        out.format("test not endsWith %s\n", suffix);
+        checkPath();
+        Path s = FileSystems.getDefault().getPath(suffix);
+        check(path.endsWith(s), false);
+        return this;
+    }
+
+    PathOps absolute() {
+        out.println("check path is absolute");
+        checkPath();
+        check(path.isAbsolute(), true);
+        return this;
+    }
+
+    PathOps notAbsolute() {
+        out.println("check path is not absolute");
+        checkPath();
+        check(path.isAbsolute(), false);
+        return this;
+    }
+
+    PathOps resolve(String other, String expected) {
+        out.format("test resolve %s\n", other);
+        checkPath();
+        check(path.resolve(other), expected);
+        return this;
+    }
+
+    PathOps relativize(String other, String expected) {
+        out.format("test relativize %s\n", other);
+        checkPath();
+        Path that = FileSystems.getDefault().getPath(other);
+        check(path.relativize(that), expected);
+        return this;
+    }
+
+    PathOps normalize(String expected) {
+        out.println("check normalized path");
+        checkPath();
+        check(path.normalize(), expected);
+        return this;
+    }
+
+    PathOps string(String expected) {
+        out.println("check string representation");
+        checkPath();
+        check(path, expected);
+        return this;
+    }
+
+    PathOps invalid() {
+        if (!(exc instanceof InvalidPathException)) {
+            out.println("InvalidPathException not thrown as expected");
+            fail();
+        }
+        return this;
+    }
+
+    static PathOps test(String s) {
+        return new PathOps(s);
+    }
+
+    // -- PathOpss --
+
+    static void header(String s) {
+        out.println();
+        out.println();
+        out.println("-- " + s + " --");
+    }
+
+    static void doWindowsTests() {
+        header("Windows specific tests");
+
+        // all components present
+        test("C:\\a\\b\\c")
+            .root("C:\\")
+            .parent("C:\\a\\b")
+            .name("c");
+        test("C:a\\b\\c")
+            .root("C:")
+            .parent("C:a\\b")
+            .name("c");
+        test("\\\\server\\share\\a")
+            .root("\\\\server\\share\\")
+            .parent("\\\\server\\share\\")
+            .name("a");
+
+        // root component only
+        test("C:\\")
+            .root("C:\\")
+            .parent(null)
+            .name(null);
+        test("C:")
+            .root("C:")
+            .parent(null)
+            .name(null);
+        test("\\\\server\\share\\")
+            .root("\\\\server\\share\\")
+            .parent(null)
+            .name(null);
+
+        // no root component
+        test("a\\b")
+            .root(null)
+            .parent("a")
+            .name("b");
+
+        // name component only
+        test("foo")
+            .root(null)
+            .parent(null)
+            .name("foo");
+
+        // startsWith and endsWith
+        test("C:\\foo\\bar")
+            .starts("C:\\")
+            .starts("C:\\foo")
+            .starts("C:\\foo\\bar")
+            .notStarts("C:\\f")
+            .notStarts("C:foo")
+            .notStarts("D:")
+            .notStarts("\\foo\\bar")
+            .ends("bar")
+            .ends("foo\\bar")
+            .ends("C:\\foo\\bar")
+            .notEnds("r")
+            .notEnds("C:foo\\bar")
+            .notEnds("o\\bar");
+
+        // elements
+        test("C:\\a\\b\\c")
+            .element(0, "a")
+            .element(1, "b")
+            .element(2, "c");
+        test("foo.bar\\gus.alice")
+            .element(0, "foo.bar")
+            .element(1, "gus.alice");
+
+        // subpath
+        test("C:\\foo")
+            .subpath(0, 1, "foo");
+        test("C:foo")
+            .subpath(0, 1, "foo");
+        test("foo")
+            .subpath(0, 1, "foo");
+        test("C:\\foo\\bar\\gus")
+            .subpath(0, 1, "foo")
+            .subpath(0, 2, "foo\\bar")
+            .subpath(0, 3, "foo\\bar\\gus")
+            .subpath(1, 2, "bar")
+            .subpath(1, 3, "bar\\gus")
+            .subpath(2, 3, "gus");
+        test("\\\\server\\share\\foo")
+            .subpath(0, 1, "foo");
+
+        // isAbsolute
+        test("foo").notAbsolute();
+        test("C:").notAbsolute();
+        test("C:\\").absolute();
+        test("C:\\abc").absolute();
+        test("\\\\server\\share\\").absolute();
+
+        // resolve
+        test("C:\\")
+            .resolve("foo", "C:\\foo")
+            .resolve("D:\\bar", "D:\\bar")
+            .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
+            .resolve("C:foo", "C:\\foo")
+            .resolve("D:foo", "D:foo");
+        test("\\")
+            .resolve("foo", "\\foo")
+            .resolve("D:bar", "D:bar")
+            .resolve("C:\\bar", "C:\\bar")
+            .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
+            .resolve("\\foo", "\\foo");
+        test("\\foo")
+            .resolve("bar", "\\foo\\bar")
+            .resolve("D:bar", "D:bar")
+            .resolve("C:\\bar", "C:\\bar")
+            .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
+            .resolve("\\bar", "\\bar");
+        test("foo")
+            .resolve("bar", "foo\\bar")
+            .resolve("D:\\bar", "D:\\bar")
+            .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
+            .resolve("C:bar", "C:bar")
+            .resolve("D:foo", "D:foo");
+        test("C:")
+            .resolve("foo", "C:foo");
+        test("\\\\server\\share\\foo")
+            .resolve("bar", "\\\\server\\share\\foo\\bar")
+            .resolve("\\bar", "\\\\server\\share\\bar")
+            .resolve("D:\\bar", "D:\\bar")
+            .resolve("\\\\other\\share\\bar", "\\\\other\\share\\bar")
+            .resolve("D:bar", "D:bar");
+
+        // relativize
+        test("foo\\bar")
+            .relativize("foo\\bar", null)
+            .relativize("foo", "..");
+        test("C:\\a\\b\\c")
+            .relativize("C:\\a", "..\\..");
+        test("\\\\server\\share\\foo")
+            .relativize("\\\\server\\share\\bar", "..\\bar");
+
+        // normalize
+        test("C:\\")
+            .normalize("C:\\");
+        test("C:\\.")
+            .normalize("C:\\");
+        test("C:\\..")
+            .normalize("C:\\");
+        test("\\\\server\\share")
+            .normalize("\\\\server\\share\\");
+        test("\\\\server\\share\\.")
+            .normalize("\\\\server\\share\\");
+        test("\\\\server\\share\\..")
+            .normalize("\\\\server\\share\\");
+        test("C:")
+            .normalize("C:");
+        test("C:.")
+            .normalize("C:");
+        test("C:..")
+            .normalize("C:..");
+        test("\\")
+            .normalize("\\");
+        test("\\.")
+            .normalize("\\");
+        test("\\..")
+            .normalize("\\");
+        test("foo")
+            .normalize("foo");
+        test("foo\\.")
+            .normalize("foo");
+        test("foo\\..")
+            .normalize(null);
+        test("C:\\foo")
+            .normalize("C:\\foo");
+        test("C:\\foo\\.")
+            .normalize("C:\\foo");
+        test("C:\\.\\foo")
+            .normalize("C:\\foo");
+        test("C:\\foo\\..")
+            .normalize("C:\\");
+        test("C:\\..\\foo")
+            .normalize("C:\\foo");
+        test("\\\\server\\share\\foo")
+            .normalize("\\\\server\\share\\foo");
+        test("\\\\server\\share\\foo\\.")
+            .normalize("\\\\server\\share\\foo");
+        test("\\\\server\\share\\.\\foo")
+            .normalize("\\\\server\\share\\foo");
+        test("\\\\server\\share\\foo\\..")
+            .normalize("\\\\server\\share\\");
+        test("\\\\server\\share\\..\\foo")
+            .normalize("\\\\server\\share\\foo");
+        test("C:foo")
+            .normalize("C:foo");
+        test("C:foo\\.")
+            .normalize("C:foo");
+        test("C:.\\foo")
+            .normalize("C:foo");
+        test("C:foo\\..")
+            .normalize("C:");
+        test("C:..\\foo")
+            .normalize("C:..\\foo");
+        test("\\foo")
+            .normalize("\\foo");
+        test("\\foo\\.")
+            .normalize("\\foo");
+        test("\\.\\foo")
+            .normalize("\\foo");
+        test("\\foo\\..")
+            .normalize("\\");
+        test("\\..\\foo")
+            .normalize("\\foo");
+        test(".")
+            .normalize(null);
+        test("..")
+            .normalize("..");
+        test("\\..\\..")
+            .normalize("\\");
+        test("..\\..\\foo")
+            .normalize("..\\..\\foo");
+        test("foo\\bar\\..")
+            .normalize("foo");
+        test("foo\\bar\\.\\..")
+            .normalize("foo");
+        test("foo\\bar\\gus\\..\\..")
+            .normalize("foo");
+        test(".\\foo\\.\\bar\\.\\gus\\..\\.\\..")
+            .normalize("foo");
+
+        // UNC corner cases
+        test("\\\\server\\share\\")
+            .root("\\\\server\\share\\")
+            .parent(null)
+            .name(null);
+        test("\\\\server")
+            .invalid();
+        test("\\\\server\\")
+            .invalid();
+        test("\\\\server\\share")
+            .root("\\\\server\\share\\")
+            .parent(null)
+            .name(null);
+
+        // invalid
+        test(":\\foo")
+            .invalid();
+        test("C::")
+            .invalid();
+        test("C:\\?")           // invalid character
+            .invalid();
+        test("C:\\*")           // invalid character
+            .invalid();
+        test("C:\\abc\u0001\\foo")
+            .invalid();
+        test("C:\\\u0019\\foo")
+            .invalid();
+        test("\\\\server\u0019\\share")
+            .invalid();
+        test("\\\\server\\share\u0019")
+            .invalid();
+        test("foo\u0000\bar")
+            .invalid();
+        test("C:\\foo ")                // trailing space
+             .invalid();
+        test("C:\\foo \\bar")
+            .invalid();
+        //test("C:\\foo.")              // trailing dot
+            //.invalid();
+        //test("C:\\foo...\\bar")
+            //.invalid();
+
+        // normalization at construction time (remove redundant and replace slashes)
+        test("C:/a/b/c")
+            .string("C:\\a\\b\\c")
+            .root("C:\\")
+            .parent("C:\\a\\b");
+        test("C://a//b//c")
+            .string("C:\\a\\b\\c")
+            .root("C:\\")
+            .parent("C:\\a\\b");
+
+        // hashCode
+        header("hashCode");
+        int h1 = test("C:\\foo").path().hashCode();
+        int h2 = test("c:\\FOO").path().hashCode();
+        if (h1 != h2)
+            throw new RuntimeException("PathOps failed");
+    }
+
+    static void doUnixTests() {
+        header("Unix specific tests");
+
+        // all components
+        test("/a/b/c")
+            .root("/")
+            .parent("/a/b")
+            .name("c");
+
+        // root component only
+        test("/")
+            .root("/")
+            .parent(null)
+            .name(null);
+
+        // no root component
+        test("a/b")
+            .root(null)
+            .parent("a")
+            .name("b");
+
+        // name component only
+        test("foo")
+            .root(null)
+            .parent(null)
+            .name("foo");
+
+        // elements
+        test("a/b/c")
+            .element(0,"a")
+            .element(1,"b")
+            .element(2,"c");
+
+        // isAbsolute
+        test("/")
+            .absolute();
+        test("/tmp")
+            .absolute();
+        test("tmp")
+            .notAbsolute();
+
+        // resolve
+        test("/tmp")
+            .resolve("foo", "/tmp/foo")
+            .resolve("/foo", "/foo");
+        test("tmp")
+            .resolve("foo", "tmp/foo")
+            .resolve("/foo", "/foo");
+
+        // relativize
+        test("/a/b/c")
+            .relativize("/a/b/c", null)
+            .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/x", "../../x");
+
+        // normalize
+        test("/")
+            .normalize("/");
+        test("foo")
+            .normalize("foo");
+        test("/foo")
+            .normalize("/foo");
+        test(".")
+            .normalize(null);
+        test("..")
+            .normalize("..");
+        test("/..")
+            .normalize("/");
+        test("/../..")
+            .normalize("/");
+        test("foo/.")
+            .normalize("foo");
+        test("./foo")
+            .normalize("foo");
+        test("foo/..")
+            .normalize(null);
+        test("../foo")
+            .normalize("../foo");
+        test("../../foo")
+            .normalize("../../foo");
+        test("foo/bar/..")
+            .normalize("foo");
+        test("foo/bar/gus/../..")
+            .normalize("foo");
+        test("/foo/bar/gus/../..")
+            .normalize("/foo");
+
+        // invalid
+        test("foo\u0000\bar")
+            .invalid();
+
+        // normalization
+        test("//foo//bar")
+            .string("/foo/bar")
+            .root("/")
+            .parent("/foo")
+            .name("bar");
+    }
+
+    static void npes() {
+        header("NullPointerException");
+
+        Path path = FileSystems.getDefault().getPath("foo");
+
+        try {
+            path.resolve((String)null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.relativize(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.compareTo(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.startsWith(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.endsWith(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+    }
+
+    public static void main(String[] args) {
+        // all platforms
+        npes();
+
+        // operating system specific
+        String osname = System.getProperty("os.name");
+        if (osname.startsWith("Windows")) {
+            doWindowsTests();
+        }
+        if (osname.equals("SunOS") || osname.equals("Linux")) {
+            doUnixTests();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/SBC.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2007-2008 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.Path.newByteChannel
+ * @library ..
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.file.*;
+import static java.nio.file.StandardOpenOption.*;
+import static com.sun.nio.file.ExtendedOpenOption.*;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.channels.*;
+import java.io.IOException;
+import java.util.*;
+
+public class SBC {
+
+    static boolean supportsLinks;
+
+    public static void main(String[] args) throws Exception {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            supportsLinks = TestUtil.supportsLinks(dir);
+
+            // open options
+            createTests(dir);
+            appendTests(dir);
+            truncateExistingTests(dir);
+            noFollowLinksTests(dir);
+
+            // SeekableByteChannel methods
+            sizeTruncatePositionTests(dir);
+
+            // platform specific
+            if (System.getProperty("os.name").startsWith("Windows"))
+                dosSharingOptionTests(dir);
+
+            // misc. tests
+            badCombinations(dir);
+            unsupportedOptions(dir);
+            nullTests(dir);
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+
+    // test CREATE and CREATE_NEW options
+    static void createTests(Path dir) throws Exception {
+        Path file = dir.resolve("foo");
+
+        // CREATE
+        try {
+            // create file (no existing file)
+            file.newByteChannel(CREATE, WRITE).close();
+            if (file.notExists())
+                throw new RuntimeException("File not created");
+
+            // create file (existing file)
+            file.newByteChannel(CREATE, WRITE).close();
+
+            // create file where existing file is a sym link
+            if (supportsLinks) {
+                Path link = dir.resolve("link").createSymbolicLink(file);
+                try {
+                    // file already exists
+                    link.newByteChannel(CREATE, WRITE).close();
+
+                    // file does not exist
+                    file.delete();
+                    link.newByteChannel(CREATE, WRITE).close();
+                    if (file.notExists())
+                        throw new RuntimeException("File not created");
+
+                } finally {
+                    link.delete();
+                }
+            }
+
+        } finally {
+            file.delete(false);
+        }
+
+        // CREATE_NEW
+        try {
+            // create file
+            file.newByteChannel(CREATE_NEW, WRITE).close();
+            if (file.notExists())
+                throw new RuntimeException("File not created");
+
+            // create should fail
+            try {
+                SeekableByteChannel sbc =
+                    file.newByteChannel(CREATE_NEW, WRITE);
+                sbc.close();
+                throw new RuntimeException("FileAlreadyExistsException not thrown");
+            } catch (FileAlreadyExistsException x) { }
+
+            // create should fail
+            if (supportsLinks) {
+                Path link = dir.resolve("link");
+                Path target = dir.resolve("thisDoesNotExist");
+                link.createSymbolicLink(target);
+                try {
+
+                    try {
+                        SeekableByteChannel sbc =
+                            file.newByteChannel(CREATE_NEW, WRITE);
+                        sbc.close();
+                        throw new RuntimeException("FileAlreadyExistsException not thrown");
+                    } catch (FileAlreadyExistsException x) { }
+
+                } finally {
+                    link.delete();
+                }
+            }
+
+
+        } finally {
+            file.delete(false);
+        }
+
+        // CREATE_NEW + SPARSE
+        try {
+            SeekableByteChannel sbc = file
+                .newByteChannel(CREATE_NEW, WRITE, SPARSE);
+            try {
+                final long hole = 2L * 1024L * 1024L * 1024L;
+                sbc.position(hole);
+                write(sbc, "hello");
+                long size = sbc.size();
+                if (size != (hole + 5))
+                    throw new RuntimeException("Unexpected size");
+            } finally {
+                sbc.close();
+            }
+        } finally {
+            file.delete(false);
+        }
+    }
+
+    // test APPEND option
+    static void appendTests(Path dir) throws Exception {
+        Path file = dir.resolve("foo");
+        try {
+            // "hello there" should be written to file
+            SeekableByteChannel sbc = file
+                .newByteChannel(CREATE_NEW, WRITE, APPEND);
+            try {
+                write(sbc, "hello ");
+                sbc.position(0L);
+                write(sbc, "there");
+            } finally {
+                sbc.close();
+            }
+
+            // check file
+            Scanner s = new Scanner(file);
+            try {
+                String line = s.nextLine();
+                if (!line.equals("hello there"))
+                    throw new RuntimeException("Unexpected file contents");
+            } finally {
+                s.close();
+            }
+
+            // check that read is not allowed
+            sbc = file.newByteChannel(APPEND);
+            try {
+                sbc.read(ByteBuffer.allocate(100));
+            } catch (NonReadableChannelException x) {
+            } finally {
+                sbc.close();
+            }
+        } finally {
+            // clean-up
+            file.delete(false);
+        }
+    }
+
+    // test TRUNCATE_EXISTING option
+    static void truncateExistingTests(Path dir) throws Exception {
+        Path file = dir.resolve("foo");
+        try {
+            SeekableByteChannel sbc =
+                file.newByteChannel(CREATE_NEW, WRITE);
+            try {
+                write(sbc, "Have a nice day!");
+            } finally {
+                sbc.close();
+            }
+
+            // re-open with truncate option
+            // write short message and check
+            sbc = file.newByteChannel(WRITE, TRUNCATE_EXISTING);
+            try {
+                write(sbc, "Hello there!");
+            } finally {
+                sbc.close();
+            }
+            Scanner s = new Scanner(file);
+            try {
+                String line = s.nextLine();
+                if (!line.equals("Hello there!"))
+                    throw new RuntimeException("Unexpected file contents");
+            } finally {
+                s.close();
+            }
+
+            // re-open with create + truncate option
+            // check file is of size 0L
+            sbc = file.newByteChannel(WRITE, CREATE, TRUNCATE_EXISTING);
+            try {
+                long size = ((FileChannel)sbc).size();
+                if (size != 0L)
+                    throw new RuntimeException("File not truncated");
+            } finally {
+                sbc.close();
+            }
+
+        } finally {
+            // clean-up
+            file.delete(false);
+        }
+
+    }
+
+    // test NOFOLLOW_LINKS option
+    static void noFollowLinksTests(Path dir) throws Exception {
+        if (!supportsLinks)
+            return;
+        Path file = dir.resolve("foo").createFile();
+        try {
+            // ln -s foo link
+            Path link = dir.resolve("link").createSymbolicLink(file);
+
+            // open with NOFOLLOW_LINKS option
+            try {
+                link.newByteChannel(READ, LinkOption.NOFOLLOW_LINKS);
+                throw new RuntimeException();
+            } catch (IOException x) {
+            } finally {
+                link.delete();
+            }
+
+        } finally {
+            // clean-up
+            file.delete();
+        }
+    }
+
+    // test size/truncate/position methods
+    static void sizeTruncatePositionTests(Path dir) throws Exception {
+        Path file = dir.resolve("foo");
+        try {
+            SeekableByteChannel sbc = file
+                .newByteChannel(CREATE_NEW, READ, WRITE);
+            try {
+                if (sbc.size() != 0L)
+                    throw new RuntimeException("Unexpected size");
+
+                // check size
+                write(sbc, "hello");
+                if (sbc.size() != 5L)
+                    throw new RuntimeException("Unexpected size");
+
+                // truncate (size and position should change)
+                sbc.truncate(4L);
+                if (sbc.size() != 4L)
+                    throw new RuntimeException("Unexpected size");
+                if (sbc.position() != 4L)
+                    throw new RuntimeException("Unexpected position");
+
+                // truncate (position should not change)
+                sbc.position(2L).truncate(3L);
+                if (sbc.size() != 3L)
+                    throw new RuntimeException("Unexpected size");
+                if (sbc.position() != 2L)
+                    throw new RuntimeException("Unexpected position");
+            } finally {
+                sbc.close();
+            }
+        } finally {
+            file.delete(false);
+        }
+    }
+
+    // Windows specific options for the use by applications that really want
+    // to use legacy DOS sharing options
+    static void dosSharingOptionTests(Path dir) throws Exception {
+        Path file = dir.resolve("foo").createFile();
+        try {
+            SeekableByteChannel ch;
+
+            // no sharing
+            ch = file.newByteChannel(READ,
+                NOSHARE_READ, NOSHARE_WRITE, NOSHARE_DELETE);
+            try {
+                try {
+                    file.newByteChannel(READ);
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+                try {
+                    file.newByteChannel(WRITE);
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+                try {
+                    file.delete();
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+            } finally {
+                ch.close();
+            }
+
+            // read allowed
+            ch = file.newByteChannel(READ, NOSHARE_WRITE, NOSHARE_DELETE);
+            try {
+                file.newByteChannel(READ).close();
+                try {
+                    file.newByteChannel(WRITE);
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+                try {
+                    file.delete();
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+            } finally {
+                ch.close();
+            }
+
+            // write allowed
+            ch = file.newByteChannel(READ, NOSHARE_READ, NOSHARE_DELETE);
+            try {
+                try {
+                    file.newByteChannel(READ);
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+                file.newByteChannel(WRITE).close();
+                try {
+                    file.delete();
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+            } finally {
+                ch.close();
+            }
+
+            // delete allowed
+            ch = file.newByteChannel(READ, NOSHARE_READ, NOSHARE_WRITE);
+            try {
+                try {
+                    file.newByteChannel(READ);
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+                try {
+                    file.newByteChannel(WRITE);
+                    throw new RuntimeException("Sharing violation expected");
+                } catch (IOException ignore) { }
+                file.delete();
+            } finally {
+                ch.close();
+            }
+
+        } finally {
+            file.delete(false);
+        }
+    }
+
+    // invalid combinations of options
+    static void badCombinations(Path dir) throws Exception {
+        Path file = dir.resolve("bad");
+
+        try {
+            file.newByteChannel(READ, APPEND);
+            throw new RuntimeException("IllegalArgumentException expected");
+        } catch (IllegalArgumentException x) { }
+
+        try {
+            file.newByteChannel(WRITE, APPEND, TRUNCATE_EXISTING);
+            throw new RuntimeException("IllegalArgumentException expected");
+        } catch (IllegalArgumentException x) { }
+    }
+
+    // unsupported operations
+    static void unsupportedOptions(Path dir) throws Exception {
+        Path file = dir.resolve("bad");
+
+        OpenOption badOption = new OpenOption() { };
+        try {
+            file.newByteChannel(badOption);
+            throw new RuntimeException("UnsupportedOperationException expected");
+        } catch (UnsupportedOperationException e) { }
+        try {
+            file.newByteChannel(READ, WRITE, badOption);
+            throw new RuntimeException("UnsupportedOperationException expected");
+        } catch (UnsupportedOperationException e) { }
+    }
+
+    // null handling
+    static void nullTests(Path dir) throws Exception {
+        Path file = dir.resolve("foo");
+
+        try {
+            file.newByteChannel((OpenOption[])null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+
+        try {
+            OpenOption[] opts = { READ, null };
+            file.newByteChannel(opts);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+
+        try {
+            file.newByteChannel((Set<OpenOption>)null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+
+        try {
+            Set<OpenOption> opts = new HashSet<OpenOption>();
+            opts.add(READ);
+            opts.add(null);
+            file.newByteChannel(opts);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+
+        try {
+            EnumSet<StandardOpenOption> opts = EnumSet.of(READ);
+            file.newByteChannel(opts, (FileAttribute[])null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+
+        try {
+            EnumSet<StandardOpenOption> opts = EnumSet.of(READ);
+            FileAttribute[] attrs = { null };
+            file.newByteChannel(opts, attrs);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException x) { }
+    }
+
+    static void write(WritableByteChannel wbc, String msg) throws IOException {
+        ByteBuffer buf = ByteBuffer.wrap(msg.getBytes());
+        while (buf.hasRemaining())
+            wbc.write(buf);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/TemporaryFiles.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+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
+        Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+        if (!file.getParent().equals(tmpdir))
+            throw new RuntimeException("Not in temporary directory");
+
+        // check that file can be opened for reading and writing
+        file.newByteChannel(READ).close();
+        file.newByteChannel(WRITE).close();
+        file.newByteChannel(READ,WRITE).close();
+
+        // check file permissions are 0600 or more secure
+        if (file.getFileStore().supportsFileAttributeView("posix")) {
+            Set<PosixFilePermission> perms = Attributes
+                .readPosixFileAttributes(file).permissions();
+            perms.remove(PosixFilePermission.OWNER_READ);
+            perms.remove(PosixFilePermission.OWNER_WRITE);
+            if (!perms.isEmpty())
+                throw new RuntimeException("Temporary file is not secure");
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path file = File.createTempFile("blah", null, false).toPath();
+        try {
+            checkFile(file);
+        } finally {
+            file.delete();
+        }
+
+        // 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();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/UriImportExport.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2007-2008 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.Path
+ */
+
+import java.nio.file.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.io.PrintStream;
+
+public class UriImportExport {
+
+    static final PrintStream log = System.out;
+    static int failures = 0;
+
+    static void test(String fn, String expected) {
+        log.println();
+        Path p = Paths.get(fn);
+        log.println(p);
+        URI u = p.toUri();
+        log.println("  --> " + u);
+        if (expected != null && !(u.toString().equals(expected))) {
+            log.println("FAIL: Expected " + expected);
+            failures++;
+            return;
+        }
+        Path q = Paths.get(u);
+        log.println("  --> " + q);
+        if (!p.toAbsolutePath().equals(q)) {
+            log.println("FAIL: Expected " + p + ", got " + q);
+            failures++;
+            return;
+        }
+    }
+
+    static void test(String fn) {
+        test(fn, null);
+    }
+
+    public static void main(String[] args) throws Exception {
+        test("foo");
+        test("/foo");
+        test("/foo bar");
+
+        String osname = System.getProperty("os.name");
+        if (osname.startsWith("Windows")) {
+            test("C:\\foo");
+            test("C:foo");
+            test("\\\\rialto.dublin.com\\share\\");
+            test("\\\\fe80--203-baff-fe5a-749ds1.ipv6-literal.net\\share\\missing",
+                "file://[fe80::203:baff:fe5a:749d%1]/share/missing");
+        }
+
+        if (failures > 0)
+            throw new RuntimeException(failures + " test(s) failed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/delete_on_close.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,61 @@
+#
+# Copyright 2007-2008 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 DELETE_ON_CLOSE open option
+# @library ..
+# @build DeleteOnClose
+# @run shell delete_on_close.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
+
+TMPFILE="$$.tmp"
+touch $TMPFILE
+$JAVA DeleteOnClose $TMPFILE 2>&1
+if [ $? != 0 ]; then exit 1; fi
+if [ -f $TMPFILE ]; then
+    echo "$TMPFILE was not deleted"
+    exit 1
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/temporary_files.sh	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,65 @@
+#
+# Copyright 2007-2008 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/PathMatcher/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2007-2008 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.PathMatcher
+ */
+
+import java.nio.file.*;
+import java.util.regex.PatternSyntaxException;
+
+public class Basic {
+    static int failures;
+
+    static void match(String name, String pattern, boolean expectedToMatch) {
+        System.out.format("%s -> %s", name, pattern);
+        Path file = Paths.get(name);
+        boolean matched =  file.getFileSystem()
+            .getNameMatcher("glob", pattern).matches(file);
+        if (matched)
+            System.out.print(" (matched)");
+        else
+            System.out.print(" (no match)");
+        if (matched != expectedToMatch) {
+            System.out.println(" ==> UNEXPECTED RESULT!");
+            failures++;
+        } else {
+            System.out.println(" OKAY");
+        }
+    }
+
+    static void assertMatch(String path, String pattern) {
+        match(path, pattern, true);
+    }
+
+    static void assertNotMatch(String path, String pattern) {
+        match(path, pattern, false);
+    }
+
+    static void assertBadPattern(String path, String pattern) {
+        System.out.format("Compile bad pattern %s\t", pattern);
+        try {
+            FileSystems.getDefault().getNameMatcher("glob", pattern);
+            System.out.println("Compiled ==> UNEXPECTED RESULT!");
+            failures++;
+        } catch (PatternSyntaxException e) {
+            System.out.println("Failed to compile ==> OKAY");
+        }
+    }
+
+    public static void main(String[] args) {
+        // basic
+        assertMatch("foo.html", "foo.html");
+        assertNotMatch("foo.html", "foo.htm");
+        assertNotMatch("foo.html", "bar.html");
+
+        // match zero or more characters
+        assertMatch("foo.html", "f*");
+        assertMatch("foo.html", "*.html");
+        assertMatch("foo.html", "foo.html*");
+        assertMatch("foo.html", "*foo.html");
+        assertMatch("foo.html", "*foo.html*");
+        assertNotMatch("foo.html", "*.htm");
+        assertNotMatch("foo.html", "f.*");
+
+        // match one character
+        assertMatch("foo.html", "?oo.html");
+        assertMatch("foo.html", "??o.html");
+        assertMatch("foo.html", "???.html");
+        assertMatch("foo.html", "???.htm?");
+        assertNotMatch("foo.html", "foo.???");
+
+        // group of subpatterns
+        assertMatch("foo.html", "foo{.html,.class}");
+        assertMatch("foo.html", "foo.{class,html}");
+        assertNotMatch("foo.html", "foo{.htm,.class}");
+
+        // bracket expressions
+        assertMatch("foo.html", "[f]oo.html");
+        assertMatch("foo.html", "[e-g]oo.html");
+        assertMatch("foo.html", "[abcde-g]oo.html");
+        assertMatch("foo.html", "[abcdefx-z]oo.html");
+        assertMatch("foo.html", "[!a]oo.html");
+        assertMatch("foo.html", "[!a-e]oo.html");
+        assertMatch("foo-bar", "foo[-a-z]bar");     // match dash
+        assertMatch("foo.html", "foo[!-]html");     // match !dash
+
+        // groups of subpattern with bracket expressions
+        assertMatch("foo.html", "[f]oo.{[h]tml,class}");
+        assertMatch("foo.html", "foo.{[a-z]tml,class}");
+        assertMatch("foo.html", "foo.{[!a-e]tml,.class}");
+
+        // assume special characters are allowed in file names
+        assertMatch("{foo}.html", "\\{foo*");
+        assertMatch("{foo}.html", "*\\}.html");
+        assertMatch("[foo].html", "\\[foo*");
+        assertMatch("[foo].html", "*\\].html");
+
+        // some special characters not allowed on Windows
+        if (!System.getProperty("os.name").startsWith("Windows")) {
+            assertMatch("myfile?", "myfile\\?");
+            assertMatch("one\\two", "one\\\\two");
+            assertMatch("one*two", "one\\*two");
+        }
+
+        // errors
+        assertBadPattern("foo.html", "*[a--z]");            // bad range
+        assertBadPattern("foo.html", "*[a--]");             // bad range
+        assertBadPattern("foo.html", "*[a-z");              // missing ]
+        assertBadPattern("foo.html", "*{class,java");       // missing }
+        assertBadPattern("foo.html", "*.{class,{.java}}");  // nested group
+        assertBadPattern("foo.html", "*.html\\");           // nothing to escape
+
+        // regex syntax
+        {
+            String pattern = ".*\\.html";
+            System.out.format("Test regex pattern: %s", pattern);
+            Path file = Paths.get("foo.html");
+            boolean matched =  file.getFileSystem()
+                .getNameMatcher("regex", pattern).matches(file);
+            if (matched) {
+                System.out.println(" OKAY");
+            } else {
+                System.out.println(" ==> UNEXPECTED RESULT!");
+                failures++;
+            }
+        }
+
+        // unknown syntax
+        try {
+            System.out.format("Test unknown syntax");
+            FileSystems.getDefault().getNameMatcher("grep", "foo");
+            System.out.println(" ==> NOT EXPECTED TO COMPILE");
+            failures++;
+        } catch (UnsupportedOperationException e) {
+            System.out.println(" OKAY");
+        }
+
+        if (failures > 0)
+            throw new RuntimeException(failures +
+                " sub-test(s) failed - see log for details");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/TestUtil.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Random;
+import java.io.IOException;
+
+public class TestUtil {
+    private TestUtil() {
+    }
+
+    public static Path createTemporaryDirectory() throws IOException {
+        Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+        Random r = new Random();
+
+        Path dir;
+        do {
+            dir = tmpdir.resolve("name" + r.nextInt());
+        } while (dir.exists());
+        return dir.createDirectory();
+    }
+
+    static void removeAll(Path dir) {
+        Files.walkFileTree(dir, new FileVisitor<Path>() {
+
+            public FileVisitResult preVisitDirectory(Path dir) {
+                return FileVisitResult.CONTINUE;
+            }
+
+            public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
+                System.err.format("Error occured accessing directory %s\n", dir, exc);
+                return FileVisitResult.CONTINUE;
+            }
+
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                try {
+                    file.delete(false);
+                } catch (IOException x) {
+                    System.err.format("Unable to delete %s: %s\n", file, x);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+                try {
+                    dir.delete(false);
+                } catch (IOException x) {
+                    System.err.format("Unable to delete %s: %s\n", dir, x);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            public FileVisitResult visitFileFailed(Path file, IOException exc) {
+                System.err.format("Unable to visit %s: %s\n", file, exc);
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    /**
+     * Creates a directory tree in the given directory so that the total
+     * size of the path is more than 2k in size. This is used for long
+     * path tests on Windows.
+     */
+    static Path createDirectoryWithLongPath(Path dir)
+        throws IOException
+    {
+        StringBuilder sb = new StringBuilder();
+        for (int i=0; i<240; i++) {
+            sb.append('A');
+        }
+        String name = sb.toString();
+        do {
+            dir = dir.resolve(name).resolve(".");
+            dir.createDirectory();
+        } while (dir.toString().length() < 2048);
+        return dir;
+    }
+
+    /**
+     * Returns true if symbolic links are supported
+     */
+    static boolean supportsLinks(Path dir) {
+        Path link = dir.resolve("testlink");
+        Path target = dir.resolve("testtarget");
+        try {
+            link.createSymbolicLink(target);
+            target.delete(false);
+            return true;
+        } catch (UnsupportedOperationException x) {
+            return false;
+        } catch (IOException x) {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2007-2008 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.WatchService
+ * @library ..
+ * @run main/timeout=120 Basic
+ */
+
+import java.nio.file.*;
+import static java.nio.file.StandardWatchEventKind.*;
+import java.nio.file.attribute.*;
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit test for WatchService that exercises all methods in various scenarios.
+ */
+
+public class Basic {
+
+    static void createFile(Path file) throws IOException {
+        file.newOutputStream().close();
+    }
+
+    static void takeExpectedKey(WatchService watcher, WatchKey expected) {
+        System.out.println("take events...");
+        WatchKey key;
+        try {
+            key = watcher.take();
+        } catch (InterruptedException x) {
+            // not expected
+            throw new RuntimeException(x);
+        }
+        if (key != expected)
+            throw new RuntimeException("removed unexpected key");
+    }
+
+    static void checkExpectedEvent(Iterable<WatchEvent<?>> events,
+                                   WatchEvent.Kind<?> expectedKind,
+                                   Object expectedContext)
+    {
+        WatchEvent<?> event = events.iterator().next();
+        System.out.format("got event: type=%s, count=%d, context=%s\n",
+            event.kind(), event.count(), event.context());
+        if (event.kind() != expectedKind)
+            throw new RuntimeException("unexpected event");
+        if (!expectedContext.equals(event.context()))
+            throw new RuntimeException("unexpected context");
+    }
+
+    /**
+     * Simple test of each of the standard events
+     */
+    static void testEvents(Path dir) throws IOException {
+        System.out.println("-- Standard Events --");
+
+        FileSystem fs = FileSystems.getDefault();
+        Path name = fs.getPath("foo");
+
+        WatchService watcher = fs.newWatchService();
+        try {
+            // --- ENTRY_CREATE ---
+
+            // register for event
+            System.out.format("register %s for ENTRY_CREATE\n", dir);
+            WatchKey myKey = dir.register(watcher,
+                new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+
+            // create file
+            Path file = dir.resolve("foo");
+            System.out.format("create %s\n", file);
+            createFile(file);
+
+            // remove key and check that we got the ENTRY_CREATE event
+            takeExpectedKey(watcher, myKey);
+            checkExpectedEvent(myKey.pollEvents(),
+                StandardWatchEventKind.ENTRY_CREATE, name);
+
+            System.out.println("reset key");
+            if (!myKey.reset())
+                throw new RuntimeException("key has been cancalled");
+
+            System.out.println("OKAY");
+
+            // --- ENTRY_DELETE ---
+
+            System.out.format("register %s for ENTRY_DELETE\n", dir);
+            WatchKey deleteKey = dir.register(watcher,
+                new WatchEvent.Kind<?>[]{ ENTRY_DELETE });
+            if (deleteKey != myKey)
+                throw new RuntimeException("register did not return existing key");
+
+            System.out.format("delete %s\n", file);
+            file.delete(false);
+            takeExpectedKey(watcher, myKey);
+            checkExpectedEvent(myKey.pollEvents(),
+                StandardWatchEventKind.ENTRY_DELETE, name);
+
+            System.out.println("reset key");
+            if (!myKey.reset())
+                throw new RuntimeException("key has been cancalled");
+
+            System.out.println("OKAY");
+
+            // create the file for the next test
+            createFile(file);
+
+            // --- ENTRY_MODIFY ---
+
+            System.out.format("register %s for ENTRY_MODIFY\n", dir);
+            WatchKey newKey = dir.register(watcher,
+                new WatchEvent.Kind<?>[]{ ENTRY_MODIFY });
+            if (newKey != myKey)
+                throw new RuntimeException("register did not return existing key");
+
+            System.out.format("update: %s\n", file);
+            OutputStream out = file.newOutputStream(EnumSet.of(StandardOpenOption.APPEND));
+            try {
+                out.write("I am a small file".getBytes("UTF-8"));
+            } finally {
+                out.close();
+            }
+
+            // remove key and check that we got the ENTRY_MODIFY event
+            takeExpectedKey(watcher, myKey);
+            checkExpectedEvent(myKey.pollEvents(),
+                StandardWatchEventKind.ENTRY_MODIFY, name);
+            System.out.println("OKAY");
+
+            // done
+            file.delete(false);
+
+        } finally {
+            watcher.close();
+        }
+    }
+
+    /**
+     * Check that a cancelled key will never be queued
+     */
+    static void testCancel(Path dir) throws IOException {
+        System.out.println("-- Cancel --");
+
+        WatchService watcher = FileSystems.getDefault().newWatchService();
+        try {
+
+            System.out.format("register %s for events\n", dir);
+            WatchKey myKey = dir.register(watcher,
+                new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+
+            System.out.println("cancel key");
+            myKey.cancel();
+
+            // create a file in the directory
+            Path file = dir.resolve("mars");
+            System.out.format("create: %s\n", file);
+            createFile(file);
+
+            // poll for keys - there will be none
+            System.out.println("poll...");
+            try {
+                WatchKey key = watcher.poll(3000, TimeUnit.MILLISECONDS);
+                if (key != null)
+                    throw new RuntimeException("key should not be queued");
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);
+            }
+
+            // done
+            file.delete(false);
+
+            System.out.println("OKAY");
+
+        } finally {
+            watcher.close();
+        }
+    }
+
+    /**
+     * Check that deleting a registered directory causes the key to be
+     * cancelled and queued.
+     */
+    static void testAutomaticCancel(Path dir) throws IOException {
+        System.out.println("-- Automatic Cancel --");
+
+        Path subdir = dir.resolve("bar").createDirectory();
+
+        WatchService watcher = FileSystems.getDefault().newWatchService();
+        try {
+
+            System.out.format("register %s for events\n", subdir);
+            WatchKey myKey = subdir.register(watcher,
+                new WatchEvent.Kind<?>[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY });
+
+            System.out.format("delete: %s\n", subdir);
+            subdir.delete(false);
+            takeExpectedKey(watcher, myKey);
+
+            System.out.println("reset key");
+            if (myKey.reset())
+                throw new RuntimeException("Key was not cancelled");
+            if (myKey.isValid())
+                throw new RuntimeException("Key is still valid");
+
+            System.out.println("OKAY");
+
+        } finally {
+            watcher.close();
+        }
+    }
+
+    /**
+     * Asynchronous close of watcher causes blocked threads to wakeup
+     */
+    static void testWakeup(Path dir) throws IOException {
+        System.out.println("-- Wakeup Tests --");
+        final WatchService watcher = FileSystems.getDefault().newWatchService();
+        Runnable r = new Runnable() {
+            public void run() {
+                try {
+                    Thread.sleep(5000);
+                    System.out.println("close WatchService...");
+                    watcher.close();
+                } catch (InterruptedException x) {
+                    x.printStackTrace();
+                } catch (IOException x) {
+                    x.printStackTrace();
+                }
+            }
+        };
+
+        // start thread to close watch service after delay
+        new Thread(r).start();
+
+        try {
+            System.out.println("take...");
+            watcher.take();
+            throw new RuntimeException("ClosedWatchServiceException not thrown");
+        } catch (InterruptedException x) {
+            throw new RuntimeException(x);
+        } catch (ClosedWatchServiceException  x) {
+            System.out.println("ClosedWatchServiceException thrown");
+        }
+
+        System.out.println("OKAY");
+    }
+
+    /**
+     * Simple test to check exceptions and other cases
+     */
+    @SuppressWarnings("unchecked")
+    static void testExceptions(Path dir) throws IOException {
+        System.out.println("-- Exceptions and other simple tests --");
+
+        WatchService watcher = FileSystems.getDefault().newWatchService();
+        try {
+
+            // Poll tests
+
+            WatchKey key;
+            System.out.println("poll...");
+            key = watcher.poll();
+            if (key != null)
+                throw new RuntimeException("no keys registered");
+
+            System.out.println("poll with timeout...");
+            try {
+                long start = System.currentTimeMillis();
+                key = watcher.poll(3000, TimeUnit.MILLISECONDS);
+                if (key != null)
+                    throw new RuntimeException("no keys registered");
+                long waited = System.currentTimeMillis() - start;
+                if (waited < 2900)
+                    throw new RuntimeException("poll was too short");
+            } catch (InterruptedException x) {
+                throw new RuntimeException(x);
+            }
+
+            // IllegalArgumentException
+            System.out.println("IllegalArgumentException tests...");
+            try {
+                dir.register(watcher, new WatchEvent.Kind<?>[]{ } );
+                throw new RuntimeException("IllegalArgumentException not thrown");
+            } catch (IllegalArgumentException x) {
+            }
+            try {
+                // OVERFLOW is ignored so this is equivalent to the empty set
+                dir.register(watcher, new WatchEvent.Kind<?>[]{ OVERFLOW });
+                throw new RuntimeException("IllegalArgumentException not thrown");
+            } catch (IllegalArgumentException x) {
+            }
+
+            // UnsupportedOperationException
+            try {
+                dir.register(watcher, new WatchEvent.Kind<?>[]{
+                             new WatchEvent.Kind<Object>() {
+ public String name() { return "custom"; }
+ public Class<Object> type() { return Object.class; }
+                             }});
+            } catch (UnsupportedOperationException x) {
+            }
+            try {
+                dir.register(watcher,
+                             new WatchEvent.Kind<?>[]{ ENTRY_CREATE },
+                             new WatchEvent.Modifier() {
+ public String name() { return "custom"; }
+                             });
+                throw new RuntimeException("UnsupportedOperationException not thrown");
+            } catch (UnsupportedOperationException x) {
+            }
+
+            // NullPointerException
+            System.out.println("NullPointerException tests...");
+            try {
+                dir.register(null, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+                throw new RuntimeException("NullPointerException not thrown");
+            } catch (NullPointerException x) {
+            }
+            try {
+                dir.register(watcher, new WatchEvent.Kind<?>[]{ null });
+                throw new RuntimeException("NullPointerException not thrown");
+            } catch (NullPointerException x) {
+            }
+            try {
+                dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE },
+                    (WatchEvent.Modifier)null);
+                throw new RuntimeException("NullPointerException not thrown");
+            } catch (NullPointerException x) {
+            }
+        } finally {
+            watcher.close();
+        }
+
+        // -- ClosedWatchServiceException --
+
+        System.out.println("ClosedWatchServiceException tests...");
+
+        try {
+            watcher.poll();
+            throw new RuntimeException("ClosedWatchServiceException not thrown");
+        } catch (ClosedWatchServiceException  x) {
+        }
+
+        // assume that poll throws exception immediately
+        long start = System.currentTimeMillis();
+        try {
+            watcher.poll(10000, TimeUnit.MILLISECONDS);
+            throw new RuntimeException("ClosedWatchServiceException not thrown");
+        } catch (InterruptedException x) {
+            throw new RuntimeException(x);
+        } catch (ClosedWatchServiceException  x) {
+            long waited = System.currentTimeMillis() - start;
+            if (waited > 5000)
+                throw new RuntimeException("poll was too long");
+        }
+
+        try {
+            watcher.take();
+            throw new RuntimeException("ClosedWatchServiceException not thrown");
+        } catch (InterruptedException x) {
+            throw new RuntimeException(x);
+        } catch (ClosedWatchServiceException  x) {
+        }
+
+        try {
+            dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+             throw new RuntimeException("ClosedWatchServiceException not thrown");
+        } catch (ClosedWatchServiceException  x) {
+        }
+
+        System.out.println("OKAY");
+    }
+
+    /**
+     * Test that directory can be registered with more than one watch service
+     * and that events don't interfere with each other
+     */
+    static void testTwoWatchers(Path dir) throws IOException {
+        System.out.println("-- Two watchers test --");
+
+        FileSystem fs = FileSystems.getDefault();
+        WatchService watcher1 = fs.newWatchService();
+        WatchService watcher2 = fs.newWatchService();
+        try {
+            Path name1 = fs.getPath("gus1");
+            Path name2 = fs.getPath("gus2");
+
+            // create gus1
+            Path file1 = dir.resolve(name1);
+            System.out.format("create %s\n", file1);
+            createFile(file1);
+
+            // register with both watch services (different events)
+            System.out.println("register for different events");
+            WatchKey key1 = dir.register(watcher1,
+                new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+            WatchKey key2 = dir.register(watcher2,
+                new WatchEvent.Kind<?>[]{ ENTRY_DELETE });
+
+            if (key1 == key2)
+                throw new RuntimeException("keys should be different");
+
+            // create gus2
+            Path file2 = dir.resolve(name2);
+            System.out.format("create %s\n", file2);
+            createFile(file2);
+
+            // check that key1 got ENTRY_CREATE
+            takeExpectedKey(watcher1, key1);
+            checkExpectedEvent(key1.pollEvents(),
+                StandardWatchEventKind.ENTRY_CREATE, name2);
+
+            // check that key2 got zero events
+            WatchKey key = watcher2.poll();
+            if (key != null)
+                throw new RuntimeException("key not expected");
+
+            // delete gus1
+            file1.delete(false);
+
+            // check that key2 got ENTRY_DELETE
+            takeExpectedKey(watcher2, key2);
+            checkExpectedEvent(key2.pollEvents(),
+                StandardWatchEventKind.ENTRY_DELETE, name1);
+
+            // check that key1 got zero events
+            key = watcher1.poll();
+            if (key != null)
+                throw new RuntimeException("key not expected");
+
+            // reset for next test
+            key1.reset();
+            key2.reset();
+
+            // change registration with watcher2 so that they are both
+            // registered for the same event
+            System.out.println("register for same event");
+            key2 = dir.register(watcher2, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+
+            // create file and key2 should be queued
+            System.out.format("create %s\n", file1);
+            createFile(file1);
+            takeExpectedKey(watcher2, key2);
+            checkExpectedEvent(key2.pollEvents(),
+                StandardWatchEventKind.ENTRY_CREATE, name1);
+
+            System.out.println("OKAY");
+
+        } finally {
+            watcher2.close();
+            watcher1.close();
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+
+            testEvents(dir);
+            testCancel(dir);
+            testAutomaticCancel(dir);
+            testWakeup(dir);
+            testExceptions(dir);
+            testTwoWatchers(dir);
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/FileTreeModifier.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2007-2008 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 Sanity test for Sun-specific FILE_TREE watch event modifier
+ * @library ..
+ */
+
+import java.nio.file.*;
+import static java.nio.file.StandardWatchEventKind.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.*;
+import java.util.concurrent.*;
+import static com.sun.nio.file.ExtendedWatchEventModifier.*;
+
+public class FileTreeModifier {
+
+    static void checkExpectedEvent(WatchService watcher,
+                                   WatchEvent.Kind<?> expectedType,
+                                   Object expectedContext)
+    {
+        WatchKey key;
+        try {
+            key = watcher.take();
+        } catch (InterruptedException x) {
+            // should not happen
+            throw new RuntimeException(x);
+        }
+        WatchEvent<?> event = key.pollEvents().iterator().next();
+        System.out.format("Event: type=%s, count=%d, context=%s\n",
+            event.kind(), event.count(), event.context());
+        if (event.kind() != expectedType)
+            throw new RuntimeException("unexpected event");
+        if (!expectedContext.equals(event.context()))
+            throw new RuntimeException("unexpected context");
+    }
+
+    static void doTest(Path top) throws IOException {
+        FileSystem fs = top.getFileSystem();
+        WatchService watcher = fs.newWatchService();
+
+        // create directories
+        Path subdir = top
+           .resolve("a").createDirectory()
+           .resolve("b").createDirectory()
+           .resolve("c").createDirectory();
+
+        // Test ENTRY_CREATE with FILE_TREE modifier.
+
+        WatchKey key = top.register(watcher,
+            new WatchEvent.Kind<?>[]{ ENTRY_CREATE }, FILE_TREE);
+
+        // create file in a/b/c and check we get create event
+        Path file = subdir.resolve("foo").createFile();
+        checkExpectedEvent(watcher, ENTRY_CREATE, top.relativize(file));
+        key.reset();
+
+        // Test ENTRY_DELETE with FILE_TREE modifier.
+
+        WatchKey k = top.register(watcher,
+            new WatchEvent.Kind<?>[]{ ENTRY_DELETE }, FILE_TREE);
+        if (k != key)
+            throw new RuntimeException("Existing key not returned");
+
+        // delete a/b/c/foo and check we get delete event
+        file.delete(false);
+        checkExpectedEvent(watcher, ENTRY_DELETE, top.relativize(file));
+        key.reset();
+
+        // Test changing registration to ENTRY_CREATE without modifier
+
+        k = top.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
+        if (k != key)
+            throw new RuntimeException("Existing key not returned");
+
+        // create a/b/c/foo
+        file.createFile();
+
+        // check that key is not queued
+        try {
+            k = watcher.poll(3, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            throw new RuntimeException();
+        }
+        if (k != null)
+            throw new RuntimeException("WatchKey not expected to be polled");
+
+        // create bar and check we get create event
+        file = top.resolve("bar").createFile();
+        checkExpectedEvent(watcher, ENTRY_CREATE, top.relativize(file));
+        key.reset();
+
+        // Test changing registration to <all> with FILE_TREE modifier
+
+        k = top.register(watcher,
+            new WatchEvent.Kind<?>[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY },
+            FILE_TREE);
+        if (k != key)
+            throw new RuntimeException("Existing key not returned");
+
+        // modify bar and check we get modify event
+        OutputStream out = file.newOutputStream();
+        try {
+            out.write("Double shot expresso please".getBytes("UTF-8"));
+        } finally {
+            out.close();
+        }
+        checkExpectedEvent(watcher, ENTRY_MODIFY, top.relativize(file));
+        key.reset();
+    }
+
+
+    public static void main(String[] args) throws IOException {
+        if (!System.getProperty("os.name").startsWith("Windows")) {
+            System.out.println("This is Windows-only test at this time!");
+            return;
+        }
+
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            doTest(dir);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/WithSecurityManager.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2007-2008 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 Watchable#register's permission checks
+ * @build WithSecurityManager
+ * @run main/othervm WithSecurityManager denyAll.policy - fail
+ * @run main/othervm WithSecurityManager denyAll.policy tree fail
+ * @run main/othervm WithSecurityManager grantDirOnly.policy - pass
+ * @run main/othervm WithSecurityManager grantDirOnly.policy tree fail
+ * @run main/othervm WithSecurityManager grantDirAndOneLevel.policy - pass
+ * @run main/othervm WithSecurityManager grantDirAndOneLevel.policy tree fail
+ * @run main/othervm WithSecurityManager grantDirAndTree.policy - pass
+ * @run main/othervm WithSecurityManager grantDirAndTree.policy tree pass
+ */
+
+import java.nio.file.*;
+import java.io.IOException;
+import com.sun.nio.file.ExtendedWatchEventModifier;
+
+public class WithSecurityManager {
+
+    public static void main(String[] args) throws IOException {
+        String policyFile = args[0];
+        boolean recursive = args[1].equals("tree");
+        boolean expectedToFail = args[2].equals("fail");
+
+        // install security manager with the given policy file
+        String testSrc = System.getProperty("test.src");
+        if (testSrc == null)
+            throw new RuntimeException("This test must be run by jtreg");
+        Path dir = Paths.get(testSrc);
+        System.setProperty("java.security.policy", dir.resolve(policyFile).toString());
+        System.setSecurityManager(new SecurityManager());
+
+        // initialize optional modifier
+        WatchEvent.Modifier[] modifiers;
+        if (recursive) {
+            modifiers = new WatchEvent.Modifier[1];
+            modifiers[0] = ExtendedWatchEventModifier.FILE_TREE;
+        } else {
+            modifiers = new WatchEvent.Modifier[0];
+        }
+
+        // attempt to register directory
+        try {
+            dir.register(dir.getFileSystem().newWatchService(),
+                         new WatchEvent.Kind<?>[]{ StandardWatchEventKind.ENTRY_CREATE },
+                         modifiers);
+            if (expectedToFail)
+                throw new RuntimeException("SecurityException not thrown");
+        } catch (SecurityException e) {
+            if (!expectedToFail)
+                throw e;
+        } catch (UnsupportedOperationException e) {
+            // FILE_TREE modifier only supported on some platforms
+            if (!recursive)
+                throw new RuntimeException(e);
+            System.out.println("FILE_TREE option not supported");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/denyAll.policy	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,3 @@
+// policy file that does not grant any permissions
+grant {
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndOneLevel.policy	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,5 @@
+// policy file that grants read access to source directory and its entries
+grant {
+    permission java.io.FilePermission "${test.src}", "read";
+    permission java.io.FilePermission "${test.src}${file.separator}*", "read";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndTree.policy	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,5 @@
+// policy file that grants read access to source directory and all descendants
+grant {
+    permission java.io.FilePermission "${test.src}", "read";
+    permission java.io.FilePermission "${test.src}${file.separator}-", "read";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirOnly.policy	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,4 @@
+// policy file that grants read access to source directory
+grant {
+    permission java.io.FilePermission "${test.src}", "read";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2007-2008 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.AclFileAttribueView
+ * @library ../..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+import static java.nio.file.attribute.AclEntryType.*;
+import static java.nio.file.attribute.AclEntryPermission.*;
+import static java.nio.file.attribute.AclEntryFlag.*;
+
+public class Basic {
+
+    static void printAcl(List<AclEntry> acl) {
+        for (AclEntry entry: acl) {
+            System.out.format("  %s%n", entry);
+        }
+    }
+
+    // sanity check read and writing ACL
+    static void testReadWrite(Path dir) throws IOException {
+        Path file = dir.resolve("foo");
+        if (file.notExists())
+            file.createFile();
+
+        AclFileAttributeView view = file
+            .getFileAttributeView(AclFileAttributeView.class);
+
+        // print existing ACL
+        List<AclEntry> acl = view.getAcl();
+        System.out.println(" -- current ACL --");
+        printAcl(acl);
+
+        // insert entry to grant owner read access
+        UserPrincipal owner = view.getOwner();
+        AclEntry entry = AclEntry.newBuilder()
+            .setType(ALLOW)
+            .setPrincipal(owner)
+            .setPermissions(READ_DATA, READ_ATTRIBUTES)
+            .build();
+        System.out.println(" -- insert (entry 0) --");
+        System.out.format("  %s%n", entry);
+        acl.add(0, entry);
+        view.setAcl(acl);
+
+        // re-ACL and check entry
+        List<AclEntry> newacl = view.getAcl();
+        System.out.println(" -- current ACL --");
+        printAcl(acl);
+        if (!newacl.get(0).equals(entry)) {
+            throw new RuntimeException("Entry 0 is not expected");
+        }
+
+        // if PosixFileAttributeView then repeat test with OWNER@
+        if (file.getFileStore().supportsFileAttributeView("posix")) {
+            owner = file.getFileSystem().getUserPrincipalLookupService()
+                .lookupPrincipalByName("OWNER@");
+            entry = AclEntry.newBuilder(entry).setPrincipal(owner).build();
+
+            System.out.println(" -- replace (entry 0) --");
+            System.out.format("  %s%n", entry);
+
+            acl.set(0, entry);
+            view.setAcl(acl);
+            newacl = view.getAcl();
+            System.out.println(" -- current ACL --");
+            printAcl(acl);
+            if (!newacl.get(0).equals(entry)) {
+                throw new RuntimeException("Entry 0 is not expected");
+            }
+        }
+    }
+
+    static FileAttribute<List<AclEntry>> asAclAttribute(final List<AclEntry> acl) {
+        return new FileAttribute<List<AclEntry>>() {
+            public String name() { return "acl:acl"; }
+            public List<AclEntry> value() { return acl; }
+        };
+    }
+
+    static void assertEquals(List<AclEntry> actual, List<AclEntry> expected) {
+        if (!actual.equals(expected)) {
+            System.err.format("Actual: %s\n", actual);
+            System.err.format("Expected: %s\n", expected);
+            throw new RuntimeException("ACL not expected");
+        }
+    }
+
+    // sanity check create a file or directory with initial ACL
+    static void testCreateFile(Path dir) throws IOException {
+        UserPrincipal user = Attributes.getOwner(dir);
+
+        // create file with initial ACL
+        System.out.println("-- create file with initial ACL --");
+        Path file = dir.resolve("gus");
+        List<AclEntry> fileAcl = Arrays.asList(
+            AclEntry.newBuilder()
+                .setType(AclEntryType.ALLOW)
+                .setPrincipal(user)
+                .setPermissions(SYNCHRONIZE, READ_DATA, WRITE_DATA,
+                    READ_ATTRIBUTES, READ_ACL, WRITE_ATTRIBUTES, DELETE)
+                .build());
+        file.createFile(asAclAttribute(fileAcl));
+        assertEquals(Attributes.getAcl(file), fileAcl);
+
+        // create directory with initial ACL
+        System.out.println("-- create directory with initial ACL --");
+        Path subdir = dir.resolve("stuff");
+        List<AclEntry> dirAcl = Arrays.asList(
+            AclEntry.newBuilder()
+                .setType(AclEntryType.ALLOW)
+                .setPrincipal(user)
+                .setPermissions(SYNCHRONIZE, ADD_FILE, DELETE)
+                .build(),
+            AclEntry.newBuilder(fileAcl.get(0))
+                .setFlags(FILE_INHERIT)
+                .build());
+        subdir.createDirectory(asAclAttribute(dirAcl));
+        assertEquals(Attributes.getAcl(subdir), dirAcl);
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            if (!dir.getFileStore().supportsFileAttributeView("acl")) {
+                System.out.println("ACLs not supported - test skipped!");
+                return;
+            }
+            testReadWrite(dir);
+
+            // only currently feasible on Windows
+            if (System.getProperty("os.name").startsWith("Windows"))
+                testCreateFile(dir);
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/Attributes/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2007-2008 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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2007-2008 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.BasicFileAttributeView
+ * @library ../..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.io.*;
+
+public class Basic {
+
+    static void check(boolean okay, String msg) {
+        if (!okay)
+            throw new RuntimeException(msg);
+    }
+
+    static void checkAttributesOfDirectory(Path dir)
+        throws IOException
+    {
+        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir);
+        check(attrs.isDirectory(), "is a directory");
+        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");
+        }
+    }
+
+    static void checkAttributesOfFile(Path dir, Path file)
+        throws IOException
+    {
+        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
+        check(attrs.isRegularFile(), "is a regular file");
+        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");
+        }
+
+        // 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());
+        }
+        attrs = view.readAttributes();
+        check(attrs.lastModifiedTime() == dirAttrs.lastModifiedTime(),
+            "last-modified time should be equal");
+        if (dirAttrs.creationTime() != -1L) {
+            check(attrs.creationTime() == dirAttrs.creationTime(),
+                "create time should be the same");
+        }
+
+        // security tests
+        check (!(attrs instanceof PosixFileAttributes),
+            "should not be able to cast to PosixFileAttributes");
+    }
+
+    static void checkAttributesOfLink(Path link)
+        throws IOException
+    {
+        BasicFileAttributes attrs = Attributes
+            .readBasicFileAttributes(link, LinkOption.NOFOLLOW_LINKS);
+        check(attrs.isSymbolicLink(), "is a link");
+        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)
+        throws IOException
+    {
+        // create file
+        Path file = dir.resolve("foo");
+        OutputStream out = file.newOutputStream();
+        try {
+            out.write("this is not an empty file".getBytes("UTF-8"));
+        } finally {
+            out.close();
+        }
+
+        // check attributes of directory and file
+        checkAttributesOfDirectory(dir);
+        checkAttributesOfFile(dir, file);
+
+        // symbolic links may be supported
+        Path link = dir.resolve("link");
+        try {
+            link.createSymbolicLink( file );
+        } catch (UnsupportedOperationException x) {
+            return;
+        } catch (IOException x) {
+            return;
+        }
+        checkAttributesOfLink(link);
+    }
+
+    public static void main(String[] args) throws IOException {
+        // create temporary directory to run tests
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            attributeReadWriteTests(dir);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2007-2008 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.DosFileAttributeView
+ * @library ../..
+ */
+
+import java.nio.file.*;
+import static java.nio.file.LinkOption.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.io.IOException;
+
+public class Basic {
+
+    static void check(boolean okay) {
+        if (!okay)
+            throw new RuntimeException("Test failed");
+    }
+
+    // exercise each setter/getter method, leaving all attributes unset
+    static void testAttributes(DosFileAttributeView view) throws IOException {
+        view.setReadOnly(true);
+        check(view.readAttributes().isReadOnly());
+        view.setReadOnly(false);
+        check(!view.readAttributes().isReadOnly());
+        view.setHidden(true);
+        check(view.readAttributes().isHidden());
+        view.setHidden(false);
+        check(!view.readAttributes().isHidden());
+        view.setArchive(true);
+        check(view.readAttributes().isArchive());
+        view.setArchive(false);
+        check(!view.readAttributes().isArchive());
+        view.setSystem(true);
+        check(view.readAttributes().isSystem());
+        view.setSystem(false);
+        check(!view.readAttributes().isSystem());
+    }
+
+    // set the value of all attributes
+    static void setAll(DosFileAttributeView view, boolean value)
+        throws IOException
+    {
+        view.setReadOnly(value);
+        view.setHidden(value);
+        view.setArchive(value);
+        view.setSystem(value);
+    }
+
+    // read and write FAT attributes
+    static void readWriteTests(Path dir) throws IOException {
+
+        // create "foo" and test that we can read/write each FAT attribute
+        Path file = dir.resolve("foo");
+        file.newOutputStream().close();
+        try {
+            testAttributes(file
+                .getFileAttributeView(DosFileAttributeView.class));
+
+            // Following tests use a symbolic link so skip if not supported
+            if (!TestUtil.supportsLinks(dir))
+                return;
+
+            Path link = dir.resolve("link").createSymbolicLink(file);
+
+            // test following links
+            testAttributes(link
+                .getFileAttributeView(DosFileAttributeView.class));
+
+            // test not following links
+            try {
+                try {
+                    testAttributes(link
+                        .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS));
+                } catch (IOException x) {
+                    // access to link attributes not supported
+                    return;
+                }
+
+                // set all attributes on link
+                // run test on target of link (which leaves them all un-set)
+                // check that attributes of link remain all set
+                setAll(link
+                    .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS), true);
+                testAttributes(link
+                    .getFileAttributeView(DosFileAttributeView.class));
+                DosFileAttributes attrs = Attributes.readDosFileAttributes(link, NOFOLLOW_LINKS);
+                check(attrs.isReadOnly());
+                check(attrs.isHidden());
+                check(attrs.isArchive());
+                check(attrs.isSystem());
+                setAll(link
+                    .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS), false);
+
+                // set all attributes on target
+                // run test on link (which leaves them all un-set)
+                // check that attributes of target remain all set
+                setAll(link
+                    .getFileAttributeView(DosFileAttributeView.class), true);
+                testAttributes(link
+                    .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS));
+                attrs = Attributes.readDosFileAttributes(link, NOFOLLOW_LINKS);
+                check(attrs.isReadOnly());
+                check(attrs.isHidden());
+                check(attrs.isArchive());
+                check(attrs.isSystem());
+                setAll(link
+                    .getFileAttributeView(DosFileAttributeView.class), false);
+            } finally {
+                link.delete(false);
+            }
+        } finally {
+            file.delete(false);
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        // create temporary directory to run tests
+        Path dir = TestUtil.createTemporaryDirectory();
+
+        try {
+            // skip test if DOS file attributes not supported
+            if (!dir.getFileStore().supportsFileAttributeView("dos")) {
+                System.out.println("DOS file attribute not supported.");
+                return;
+            }
+            readWriteTests(dir);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2007-2008 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.FileStoreAttributeView
+ * @library ../..
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Simple unit test for FileStoreAttributeView that checks that the disk space
+ * attribtues are "close" to the equivalent values reported by java.io.File.
+ */
+
+public class Basic {
+
+    static final long K = 1024L;
+    static final long G = 1024L * 1024L * 1024L;
+
+    /**
+     * Print out the disk space information for the given file system
+     */
+    static void printFileStore(FileStore fs) throws IOException {
+        FileStoreSpaceAttributeView view =
+            fs.getFileStoreAttributeView(FileStoreSpaceAttributeView.class);
+        FileStoreSpaceAttributes attrs = view.readAttributes();
+
+        long total = attrs.totalSpace() / K;
+        long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / K;
+        long avail = attrs.usableSpace() / K;
+
+        String s = fs.toString();
+        if (s.length() > 20) {
+            System.out.println(s);
+            s = "";
+        }
+        System.out.format("%-20s %12d %12d %12d\n", s, total, used, avail);
+    }
+
+    /**
+     * Check that two values are within 1GB of each other
+     */
+    static void checkWithin1GB(long value1, long value2) {
+        long diff = Math.abs(value1 - value2);
+        if (diff > G)
+            throw new RuntimeException("values differ by more than 1GB");
+    }
+
+    /**
+     * Check disk space on the file system of the given file
+     */
+    static void checkSpace(Path file) throws IOException {
+        System.out.println(" -- check space -- ");
+        System.out.println(file);
+
+        FileStore fs = file.getFileStore();
+        System.out.format("Filesystem: %s\n", fs);
+
+        // get values reported by java.io.File
+        File f = new File(file.toString());
+        long total = f.getTotalSpace();
+        long free = f.getFreeSpace();
+        long usable = f.getUsableSpace();
+        System.out.println("java.io.File");
+        System.out.format("    Total: %d\n", total);
+        System.out.format("     Free: %d\n", free);
+        System.out.format("   Usable: %d\n", usable);
+
+        // get values reported by the FileStoreSpaceAttributeView
+        FileStoreSpaceAttributes attrs = fs
+            .getFileStoreAttributeView(FileStoreSpaceAttributeView.class)
+            .readAttributes();
+        System.out.println("java.nio.file.FileStoreSpaceAttributeView:");
+        System.out.format("    Total: %d\n", attrs.totalSpace());
+        System.out.format("     Free: %d\n", attrs.unallocatedSpace());
+        System.out.format("   Usable: %d\n", attrs.usableSpace());
+
+        // check values are "close"
+        checkWithin1GB(total, attrs.totalSpace());
+        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");
+            System.out.format("%s vsn:%x compressed:%b%n", store.name(),
+                vsn, compressed);
+        }
+
+    }
+
+    public static void main(String[] args) throws IOException {
+        // print out the disk space information for all file systems
+        FileSystem fs = FileSystems.getDefault();
+        for (FileStore store: fs.getFileStores()) {
+            printFileStore(store);
+        }
+
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            // check space using directory
+            checkSpace(dir);
+
+            // check space using file
+            Path file = dir.resolve("foo");
+            file.newOutputStream().close();
+            try {
+                checkSpace(file);
+            } finally {
+                file.delete(false);
+            }
+
+            // volume attributes (Windows specific)
+            checkVolumeAttributes();
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2007-2008 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.NamedAttributeView
+ * @library ../..
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.file.*;
+import static java.nio.file.LinkOption.*;
+import java.nio.file.attribute.*;
+import java.util.Iterator;
+import java.util.Random;
+import java.io.IOException;
+
+public class Basic {
+
+    private static Random rand = new Random();
+
+    private static final String ATTR_NAME = "user.mime_type";
+    private static final String ATTR_VALUE = "text/plain";
+    private static final String ATTR_VALUE2 = "text/html";
+
+    static boolean hasAttribute(NamedAttributeView view, String attr)
+        throws IOException
+    {
+        for (String name: view.list()) {
+            if (name.equals(ATTR_NAME))
+                return true;
+        }
+        return false;
+    }
+
+    static void test(Path file, LinkOption... options) throws IOException {
+        NamedAttributeView view = file
+            .getFileAttributeView(NamedAttributeView.class, options);
+        ByteBuffer buf = rand.nextBoolean() ?
+            ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100);
+
+        // Test: write
+        buf.put(ATTR_VALUE.getBytes()).flip();
+        int size = buf.remaining();
+        int nwrote = view.write(ATTR_NAME, buf);
+        if (nwrote != size)
+            throw new RuntimeException("Unexpected number of bytes written");
+
+        // Test: size
+        if (view.size(ATTR_NAME) != size)
+            throw new RuntimeException("Unexpected size");
+
+        // Test: read
+        buf.clear();
+        int nread = view.read(ATTR_NAME, buf);
+        if (nread != size)
+            throw new RuntimeException("Unexpected number of bytes read");
+        buf.flip();
+        String value = Charset.defaultCharset().decode(buf).toString();
+        if (!value.equals(ATTR_VALUE))
+            throw new RuntimeException("Unexpected attribute value");
+
+        // Test: read with insufficient space
+        try {
+            view.read(ATTR_NAME, ByteBuffer.allocateDirect(size-1));
+            throw new RuntimeException("Read expected to fail");
+        } catch (IOException x) {
+        }
+
+        // Test: replace value
+        buf.clear();
+        buf.put(ATTR_VALUE2.getBytes()).flip();
+        size = buf.remaining();
+        view.write(ATTR_NAME, buf);
+        if (view.size(ATTR_NAME) != size)
+            throw new RuntimeException("Unexpected size");
+
+        // Test: list
+        if (!hasAttribute(view, ATTR_NAME))
+            throw new RuntimeException("Attribute name not in list");
+
+        // Test: delete
+        view.delete(ATTR_NAME);
+        if (hasAttribute(view, ATTR_NAME))
+            throw new RuntimeException("Attribute name in list");
+    }
+
+    static void miscTests(Path file) throws IOException {
+        NamedAttributeView view = file
+            .getFileAttributeView(NamedAttributeView.class);
+        view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
+
+        // NullPointerException
+        ByteBuffer buf = ByteBuffer.allocate(100);
+        try {
+            view.read(null, buf);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) { }
+        try {
+            view.read(ATTR_NAME, null);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) { }
+        try {
+            view.write(null, buf);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) { }
+        try {
+            view.write(ATTR_NAME, null);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) { }
+        try {
+            view.size(null);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) { }
+        try {
+            view.delete(null);
+            throw new RuntimeException("NPE expected");
+        } catch (NullPointerException x) { }
+
+        // Read-only buffer
+        buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer();
+        view.write(ATTR_NAME, buf);
+        buf.flip();
+        try {
+            view.read(ATTR_NAME, buf);
+            throw new RuntimeException("IAE expected");
+        } catch (IllegalArgumentException x) { }
+
+        // Zero bytes remaining
+        buf = ByteBuffer.allocateDirect(100);
+        buf.position(buf.capacity());
+        try {
+            view.read(ATTR_NAME, buf);
+            throw new RuntimeException("IOE expected");
+        } catch (IOException x) { }
+    }
+
+    public static void main(String[] args) throws IOException {
+        // create temporary directory to run tests
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            if (!dir.getFileStore().supportsFileAttributeView("xattr")) {
+                System.out.println("NamedAttributeView not supported - skip test");
+                return;
+            }
+
+            // test access to named attributes of regular file
+            Path file = dir.resolve("foo.html").createFile();
+            try {
+                test(file);
+            } finally {
+                file.delete();
+            }
+
+            // test access to named attributes of directory
+            file = dir.resolve("foo").createDirectory();
+            try {
+                test(file);
+            } finally {
+                file.delete();
+            }
+
+            // test access to named attributes of sym link
+            if (TestUtil.supportsLinks(dir)) {
+                Path target = dir.resolve("doesnotexist");
+                Path link = dir.resolve("link").createSymbolicLink(target);
+                try {
+                    test(link, NOFOLLOW_LINKS);
+                } catch (IOException x) {
+                    // access to attributes of sym link may not be supported
+                } finally {
+                    link.delete();
+                }
+            }
+
+            // misc. tests
+            try {
+                file = dir.resolve("foo.txt").createFile();
+                miscTests(dir);
+            } finally {
+                file.delete();
+            }
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView/Basic.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2007-2008 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.PosixFileAttributeView
+ * @library ../..
+ */
+
+import java.nio.file.*;
+import static java.nio.file.LinkOption.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Unit test for PosixFileAttributeView, passing silently if this attribute
+ * view is not available.
+ */
+
+public class Basic {
+
+    /**
+     * Use view to update permission to the given mode and check that the
+     * permissions have been updated.
+     */
+    static void testPermissions(PosixFileAttributeView view, String mode)
+        throws IOException
+    {
+        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();
+        if (!current.equals(perms)) {
+            throw new RuntimeException("Actual permissions: " +
+                PosixFilePermissions.toString(current) + ", expected: " +
+                PosixFilePermissions.toString(perms));
+        }
+
+        // repeat test using setAttribute/getAttribute
+        view.setAttribute("permissions", perms);
+        current = (Set<PosixFilePermission>)view.getAttribute("permissions");
+        if (!current.equals(perms)) {
+            throw new RuntimeException("Actual permissions: " +
+                PosixFilePermissions.toString(current) + ", expected: " +
+                PosixFilePermissions.toString(perms));
+        }
+    }
+
+    /**
+     * Check that the actual permissions of a file match or make it more
+     * secure than requested
+     */
+    static void checkSecure(Set<PosixFilePermission> requested,
+                            Set<PosixFilePermission> actual)
+    {
+        for (PosixFilePermission perm: actual) {
+            if (!requested.contains(perm)) {
+                throw new RuntimeException("Actual permissions: " +
+                    PosixFilePermissions.toString(actual) + ", requested: " +
+                    PosixFilePermissions.toString(requested) +
+                    " - file is less secure than requested");
+            }
+        }
+    }
+
+    /**
+     * Create file with given mode and check that the file is created with a
+     * mode that is not less secure
+     */
+    static void createWithPermissions(Path file,
+                                      String mode)
+        throws IOException
+    {
+        Set<PosixFilePermission> requested = PosixFilePermissions.fromString(mode);
+        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();
+        try {
+            checkSecure(requested,  file
+                .getFileAttributeView(PosixFileAttributeView.class)
+                .readAttributes()
+                .permissions());
+        } finally {
+            file.delete(false);
+        }
+
+        System.out.format("create directory with mode: %s\n", mode);
+        file.createDirectory(attr);
+        try {
+            checkSecure(requested,  file
+                .getFileAttributeView(PosixFileAttributeView.class)
+                .readAttributes()
+                .permissions());
+        } finally {
+            file.delete(false);
+        }
+    }
+
+    /**
+     * Test the setPermissions/permissions methods.
+     */
+    static void permissionTests(Path dir)
+        throws IOException
+    {
+        System.out.println("-- Permission Tests  --");
+
+        // create file and test updating and reading its permissions
+        Path file = dir.resolve("foo");
+        System.out.format("create %s\n", file);
+        file.newOutputStream().close();
+        try {
+            // get initial permissions so that we can restore them later
+            PosixFileAttributeView view = file
+                .getFileAttributeView(PosixFileAttributeView.class);
+            Set<PosixFilePermission> save = view.readAttributes()
+                .permissions();
+
+            // 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");
+            } finally {
+                view.setPermissions(save);
+            }
+        } finally {
+            file.delete(false);
+        }
+
+        // create link (to file that doesn't exist) and test reading of
+        // permissions
+        if (TestUtil.supportsLinks(dir)) {
+            Path link = dir.resolve("link");
+            System.out.format("create link %s\n", link);
+            link.createSymbolicLink(file);
+            try {
+                PosixFileAttributes attrs = Attributes
+                    .readPosixFileAttributes(link, NOFOLLOW_LINKS);
+                if (!attrs.isSymbolicLink()) {
+                    throw new RuntimeException("not a link");
+                }
+            } finally {
+                link.delete(false);
+            }
+        }
+
+        System.out.println("OKAY");
+    }
+
+    /**
+     * Test creating a file and directory with initial permissios
+     */
+    static void createTests(Path dir)
+        throws IOException
+    {
+        System.out.println("-- Create Tests  --");
+
+        Path file = dir.resolve("foo");
+
+        createWithPermissions(file, "---------");
+        createWithPermissions(file, "r--------");
+        createWithPermissions(file, "-w-------");
+        createWithPermissions(file, "--x------");
+        createWithPermissions(file, "rwx------");
+        createWithPermissions(file, "---r-----");
+        createWithPermissions(file, "----w----");
+        createWithPermissions(file, "-----x---");
+        createWithPermissions(file, "---rwx---");
+        createWithPermissions(file, "------r--");
+        createWithPermissions(file, "-------w-");
+        createWithPermissions(file, "--------x");
+        createWithPermissions(file, "------rwx");
+        createWithPermissions(file, "r--r-----");
+        createWithPermissions(file, "r--r--r--");
+        createWithPermissions(file, "rw-rw----");
+        createWithPermissions(file, "rwxrwx---");
+        createWithPermissions(file, "rw-rw-r--");
+        createWithPermissions(file, "r-xr-x---");
+        createWithPermissions(file, "r-xr-xr-x");
+        createWithPermissions(file, "rwxrwxrwx");
+
+        System.out.println("OKAY");
+    }
+
+    /**
+     * Test setOwner/setGroup methods - this test simply exercises the
+     * methods to avoid configuration.
+     */
+    static void ownerTests(Path dir)
+        throws IOException
+    {
+        System.out.println("-- Owner Tests  --");
+
+        Path file = dir.resolve("gus");
+        System.out.format("create %s\n", file);
+
+        file.newOutputStream().close();
+        try {
+
+            // read attributes of directory to get owner/group
+            PosixFileAttributeView view = file
+                .getFileAttributeView(PosixFileAttributeView.class);
+            PosixFileAttributes attrs = view.readAttributes();
+
+            // set to existing owner/group
+            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"));
+
+        } finally {
+            file.delete(false);
+        }
+
+        System.out.println("OKAY");
+    }
+
+    /**
+     * Test the lookupPrincipalByName/lookupPrincipalByGroupName methods
+     */
+    static void lookupPrincipalTests(Path dir)
+        throws IOException
+    {
+        System.out.println("-- Lookup UserPrincipal Tests --");
+
+        UserPrincipalLookupService lookupService = dir.getFileSystem()
+            .getUserPrincipalLookupService();
+
+        // read attributes of directory to get owner/group
+        PosixFileAttributes attrs = Attributes.readPosixFileAttributes(dir);
+
+        // lookup owner and check it matches file's owner
+        System.out.format("lookup: %s\n", attrs.owner().getName());
+        try {
+            UserPrincipal owner = lookupService.lookupPrincipalByName(attrs.owner().getName());
+            if (owner instanceof GroupPrincipal)
+                throw new RuntimeException("owner is a group?");
+            if (!owner.equals(attrs.owner()))
+                throw new RuntimeException("owner different from file owner");
+        } catch (UserPrincipalNotFoundException x) {
+            System.out.println("user not found - test skipped");
+        }
+
+        // lookup group and check it matches file's group-owner
+        System.out.format("lookup group: %s\n", attrs.group().getName());
+        try {
+            GroupPrincipal group = lookupService.lookupPrincipalByGroupName(attrs.group().getName());
+            if (!group.equals(attrs.group()))
+                throw new RuntimeException("group different from file group-owner");
+        } catch (UserPrincipalNotFoundException x) {
+            System.out.println("group not found - test skipped");
+        }
+
+        // test that UserPrincipalNotFoundException is thrown
+        String invalidPrincipal = "scumbag99";
+        try {
+            System.out.format("lookup: %s\n", invalidPrincipal);
+            lookupService.lookupPrincipalByName(invalidPrincipal);
+            throw new RuntimeException("'" + invalidPrincipal + "' is a valid user?");
+        } catch (UserPrincipalNotFoundException x) {
+        }
+        try {
+            System.out.format("lookup group: %s\n", invalidPrincipal);
+            lookupService.lookupPrincipalByGroupName("idonotexist");
+            throw new RuntimeException("'" + invalidPrincipal + "' is a valid group?");
+        } catch (UserPrincipalNotFoundException x) {
+        }
+        System.out.println("OKAY");
+    }
+
+    /**
+     * Test various exceptions are thrown as expected
+     */
+    @SuppressWarnings("unchecked")
+    static void exceptionsTests(Path dir)
+        throws IOException
+    {
+        System.out.println("-- Exceptions --");
+
+        PosixFileAttributeView view = dir
+            .getFileAttributeView(PosixFileAttributeView.class);
+
+        // NullPointerException
+        try {
+            view.setOwner(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+        try {
+            view.setGroup(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+
+        UserPrincipalLookupService lookupService = dir.getFileSystem()
+            .getUserPrincipalLookupService();
+        try {
+            lookupService.lookupPrincipalByName(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+        try {
+            lookupService.lookupPrincipalByGroupName(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+        try {
+            view.setPermissions(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+        try {
+            Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
+            perms.add(null);
+            view.setPermissions(perms);
+            throw new RuntimeException("NullPointerException not thrown");
+        }  catch (NullPointerException x) {
+        }
+
+        // ClassCastException
+        try {
+            Set perms = new HashSet();  // raw type
+            perms.add(new Object());
+            view.setPermissions(perms);
+            throw new RuntimeException("ClassCastException not thrown");
+        }  catch (ClassCastException x) {
+        }
+
+        System.out.println("OKAY");
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        try {
+            if (!dir.getFileStore().supportsFileAttributeView("posix")) {
+                System.out.println("PosixFileAttributeView not supported");
+                return;
+            }
+
+            permissionTests(dir);
+            createTests(dir);
+            ownerTests(dir);
+            lookupPrincipalTests(dir);
+            exceptionsTests(dir);
+
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/SetDefaultProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2008 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.spi.FileSystemProvider
+ * @build TestProvider SetDefaultProvider
+ * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider SetDefaultProvider
+ */
+
+import java.nio.file.*;
+import java.nio.file.spi.*;
+
+public class SetDefaultProvider {
+    public static void main(String[] args) throws Exception {
+        Class<?> c = FileSystems.getDefault().provider().getClass();
+
+        Class<?> expected = Class.forName("TestProvider", false,
+            ClassLoader.getSystemClassLoader());
+
+        if (c != expected)
+            throw new RuntimeException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/TestProvider.java	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+import java.nio.file.spi.FileSystemProvider;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.URI;
+import java.util.*;
+import java.io.IOException;
+
+public class TestProvider extends FileSystemProvider {
+
+    private final FileSystem theFileSystem;
+
+    public TestProvider(FileSystemProvider defaultProvider) {
+        theFileSystem = new TestFileSystem(this);
+
+    }
+
+
+    public String getScheme() {
+        return "file";
+    }
+
+
+    public FileSystem newFileSystem(URI uri, Map<String,?> env) {
+        throw new RuntimeException("not implemented");
+    }
+
+
+    public FileSystem getFileSystem(URI uri) {
+        return theFileSystem;
+    }
+
+
+    public Path getPath(URI uri) {
+        throw new RuntimeException("not implemented");
+    }
+
+    static class TestFileSystem extends FileSystem {
+        private final TestProvider provider;
+
+        TestFileSystem(TestProvider provider) {
+            this.provider = provider;
+        }
+
+
+        public FileSystemProvider provider() {
+            return provider;
+        }
+
+
+        public void close() throws IOException {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public boolean isOpen() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public boolean isReadOnly() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public String getSeparator() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public Iterable<Path> getRootDirectories() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public Iterable<FileStore> getFileStores() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public Set<String> supportedFileAttributeViews() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public Path getPath(String path) {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public PathMatcher getNameMatcher(String syntax, String pattern) {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public UserPrincipalLookupService getUserPrincipalLookupService() {
+            throw new RuntimeException("not implemented");
+        }
+
+
+        public WatchService newWatchService() throws IOException {
+            throw new RuntimeException("not implemented");
+        }
+    }
+
+}
--- a/patches/ecj/icedtea-pr261.patch	Mon Jan 12 17:29:21 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-diff -r fa4572c7c75f openjdk-ecj/jdk/make/java/nio/Makefile
---- openjdk-ecj/jdk/make/java/nio/Makefile	Thu Nov 27 08:42:23 2008 +0000
-+++ openjdk-ecj/jdk/make/java/nio/Makefile	Thu Nov 27 10:12:08 2008 +0000
-@@ -85,6 +85,9 @@ ifeq ($(PLATFORM), linux)
- ifeq ($(PLATFORM), linux)
- FILES_java += \
-         sun/nio/ch/AbstractPollSelectorImpl.java \
-+	sun/nio/ch/DevPollArrayWrapper.java \
-+	sun/nio/ch/DevPollSelectorImpl.java \
-+	sun/nio/ch/DevPollSelectorProvider.java \
- 	sun/nio/ch/EPollArrayWrapper.java \
- 	sun/nio/ch/EPollSelectorProvider.java \
- 	sun/nio/ch/EPollSelectorImpl.java \
-@@ -99,6 +102,7 @@ FILES_c += \
- 	NativeThread.c
- 
- FILES_export += \
-+	sun/nio/ch/DevPollArrayWrapper.java \
-         sun/nio/ch/EPollArrayWrapper.java \
- 	sun/nio/ch/InheritedChannel.java \
- 	sun/nio/ch/NativeThread.java
-diff -r 3ee709488c6c openjdk-ecj/jdk/make/java/nio/FILES_java.gmk
---- openjdk-ecj/jdk/make/java/nio/FILES_java.gmk	Thu Nov 27 10:16:56 2008 +0000
-+++ openjdk-ecj/jdk/make/java/nio/FILES_java.gmk	Thu Nov 27 11:08:57 2008 +0000
-@@ -31,6 +31,7 @@ FILES_src = \
- 	java/nio/StringCharBuffer.java \
- 	\
- 	java/nio/channels/ByteChannel.java \
-+	java/nio/channels/CancelledKeyException.java \
- 	java/nio/channels/Channel.java \
- 	java/nio/channels/Channels.java \
- 	java/nio/channels/DatagramChannel.java \
-@@ -38,6 +39,7 @@ FILES_src = \
- 	java/nio/channels/FileLock.java \
- 	java/nio/channels/GatheringByteChannel.java \
- 	java/nio/channels/InterruptibleChannel.java \
-+	java/nio/channels/Pipe.java \
- 	java/nio/channels/ReadableByteChannel.java \
- 	java/nio/channels/ScatteringByteChannel.java \
- 	java/nio/channels/SelectableChannel.java \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-nio2.patch	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,761 @@
+diff -Nru openjdk.orig/jdk/make/docs/CORE_PKGS.gmk openjdk/jdk/make/docs/CORE_PKGS.gmk
+--- openjdk.orig/jdk/make/docs/CORE_PKGS.gmk	2009-01-07 21:17:37.000000000 +0000
++++ openjdk/jdk/make/docs/CORE_PKGS.gmk	2009-01-09 21:21:59.000000000 +0000
+@@ -36,6 +36,7 @@
+   sunw.*                   \
+   com.sun.*                \
+   org.apache.*             \
++  org.classpath.icedtea.*  \
+   org.jcp.*		   \
+   org.w3c.dom.css          \
+   org.w3c.dom.html         \
+diff -Nru openjdk.orig/jdk/make/docs/NON_CORE_PKGS.gmk openjdk/jdk/make/docs/NON_CORE_PKGS.gmk
+--- openjdk.orig/jdk/make/docs/NON_CORE_PKGS.gmk	2009-01-07 21:27:46.000000000 +0000
++++ openjdk/jdk/make/docs/NON_CORE_PKGS.gmk	2009-01-09 21:21:39.000000000 +0000
+@@ -65,6 +65,11 @@
+ HTTPSERVER_PKGS  = com.sun.net.httpserver       \
+                    com.sun.net.httpserver.spi 
+ 
++NIO_PKGS         = com.sun.nio.file 	        \
++		   org.classpath.icedtea.java.nio.file    		\
++		   org.classpath.icedtea.java.nio.file.attribute	 \
++		   org.classpath.icedtea.java.nio.file.spi		 
++
+ DOCLETAPI_PKGS   = com.sun.javadoc
+ 
+ TAGLETAPI_FILE   = com/sun/tools/doclets/Taglet.java
+@@ -89,6 +94,7 @@
+                    $(MGMT_PKGS) \
+                    $(JAAS_PKGS) \
+                    $(JGSS_PKGS) \
++		   $(NIO_PKGS) \
+                    $(OLD_JSSE_PKGS) \
+                    $(HTTPSERVER_PKGS) \
+                    $(SMARTCARDIO_PKGS)
+diff -Nru openjdk.orig/jdk/make/java/java/FILES_java.gmk openjdk/jdk/make/java/java/FILES_java.gmk
+--- openjdk.orig/jdk/make/java/java/FILES_java.gmk	2009-01-07 21:35:50.000000000 +0000
++++ openjdk/jdk/make/java/java/FILES_java.gmk	2009-01-12 15:24:01.000000000 +0000
+@@ -516,6 +516,13 @@
+     sun/misc/JavaLangAccess.java \
+     sun/misc/JavaIOAccess.java \
+     sun/misc/JavaIODeleteOnExitAccess.java \
+-    sun/misc/JavaIOFileDescriptorAccess.java
++    sun/misc/JavaIOFileDescriptorAccess.java \
++    org/classpath/icedtea/java/io/File.java \
++    org/classpath/icedtea/java/io/FilePermission.java \
++    org/classpath/icedtea/java/io/Inputs.java \
++    org/classpath/icedtea/java/io/Outputs.java \
++    org/classpath/icedtea/java/util/Scanner.java \
++    org/classpath/icedtea/misc/SharedSecrets.java \
++    org/classpath/icedtea/misc/JavaIODeleteOnExitAccess.java
+ 
+ FILES_java = $(JAVA_JAVA_java)
+diff -Nru openjdk.orig/jdk/make/java/nio/FILES_java.gmk openjdk/jdk/make/java/nio/FILES_java.gmk
+--- openjdk.orig/jdk/make/java/nio/FILES_java.gmk	2009-01-10 03:21:38.000000000 +0000
++++ openjdk/jdk/make/java/nio/FILES_java.gmk	2009-01-12 21:27:13.000000000 +0000
+@@ -75,7 +75,6 @@
+         sun/nio/ch/DefaultSelectorProvider.java \
+ 	sun/nio/ch/DirectBuffer.java \
+ 	sun/nio/ch/FileChannelImpl.java \
+-	sun/nio/ch/FileDispatcher.java \
+ 	sun/nio/ch/FileKey.java \
+ 	sun/nio/ch/Interruptible.java \
+ 	sun/nio/ch/IOUtil.java \
+@@ -144,7 +143,133 @@
+ 	java/lang/StringCoding.java \
+ 	\
+ 	sun/misc/Cleaner.java \
+-	sun/util/PreHashedMap.java
++	sun/util/PreHashedMap.java \
++	\
++	org/classpath/icedtea/java/nio/channels/AsynchronousByteChannel.java \
++	org/classpath/icedtea/java/nio/channels/AsynchronousChannel.java \
++	org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup.java \
++	org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel.java \
++	org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel.java \
++	org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel.java \
++	org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel.java \
++	org/classpath/icedtea/java/nio/channels/CompletionHandler.java \
++	org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java \
++	org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider.java \
++	org/classpath/icedtea/java/nio/file/AccessDeniedException.java \
++	org/classpath/icedtea/java/nio/file/AccessMode.java \
++	org/classpath/icedtea/java/nio/file/AtomicMoveNotSupportedException.java \
++	org/classpath/icedtea/java/nio/file/ClosedDirectoryStreamException.java \
++	org/classpath/icedtea/java/nio/file/ClosedFileSystemException.java \
++	org/classpath/icedtea/java/nio/file/ClosedWatchServiceException.java \
++	org/classpath/icedtea/java/nio/file/CopyOption.java \
++	org/classpath/icedtea/java/nio/file/DirectoryNotEmptyException.java \
++	org/classpath/icedtea/java/nio/file/DirectoryStream.java \
++	org/classpath/icedtea/java/nio/file/DirectoryStreamFilters.java \
++	org/classpath/icedtea/java/nio/file/FileAction.java \
++	org/classpath/icedtea/java/nio/file/FileAlreadyExistsException.java \
++	org/classpath/icedtea/java/nio/file/FileRef.java \
++	org/classpath/icedtea/java/nio/file/FileStore.java \
++	org/classpath/icedtea/java/nio/file/FileSystem.java \
++	org/classpath/icedtea/java/nio/file/FileSystemAlreadyExistsException.java \
++	org/classpath/icedtea/java/nio/file/FileSystemException.java \
++	org/classpath/icedtea/java/nio/file/FileSystemNotFoundException.java \
++	org/classpath/icedtea/java/nio/file/FileSystems.java \
++	org/classpath/icedtea/java/nio/file/FileTreeWalker.java \
++	org/classpath/icedtea/java/nio/file/FileVisitOption.java \
++	org/classpath/icedtea/java/nio/file/FileVisitResult.java \
++	org/classpath/icedtea/java/nio/file/FileVisitor.java \
++	org/classpath/icedtea/java/nio/file/Files.java \
++	org/classpath/icedtea/java/nio/file/InvalidPathException.java \
++	org/classpath/icedtea/java/nio/file/LinkPermission.java \
++	org/classpath/icedtea/java/nio/file/NoSuchFileException.java \
++	org/classpath/icedtea/java/nio/file/NotDirectoryException.java \
++	org/classpath/icedtea/java/nio/file/NotLinkException.java \
++	org/classpath/icedtea/java/nio/file/OpenOption.java \
++	org/classpath/icedtea/java/nio/file/Path.java \
++	org/classpath/icedtea/java/nio/file/PathMatcher.java \
++	org/classpath/icedtea/java/nio/file/Paths.java \
++	org/classpath/icedtea/java/nio/file/ProviderMismatchException.java \
++	org/classpath/icedtea/java/nio/file/ProviderNotFoundException.java \
++	org/classpath/icedtea/java/nio/file/ReadOnlyFileSystemException.java \
++	org/classpath/icedtea/java/nio/file/SecureDirectoryStream.java \
++	org/classpath/icedtea/java/nio/file/SimpleFileVisitor.java \
++	org/classpath/icedtea/java/nio/file/StandardCopyOption.java \
++	org/classpath/icedtea/java/nio/file/StandardOpenOption.java \
++	org/classpath/icedtea/java/nio/file/StandardWatchEventKind.java \
++	org/classpath/icedtea/java/nio/file/WatchEvent.java \
++	org/classpath/icedtea/java/nio/file/WatchKey.java \
++	org/classpath/icedtea/java/nio/file/WatchService.java \
++	org/classpath/icedtea/java/nio/file/Watchable.java \
++	\
++	org/classpath/icedtea/java/nio/file/attribute/AclEntry.java \
++	org/classpath/icedtea/java/nio/file/attribute/AclEntryFlag.java \
++	org/classpath/icedtea/java/nio/file/attribute/AclEntryPermission.java \
++	org/classpath/icedtea/java/nio/file/attribute/AclEntryType.java \
++	org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/AttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/Attributes.java \
++	org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributes.java \
++	org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/DosFileAttributes.java \
++	org/classpath/icedtea/java/nio/file/attribute/FileAttribute.java \
++	org/classpath/icedtea/java/nio/file/attribute/FileAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/FileOwnerAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/FileStoreSpaceAttributes.java \
++	org/classpath/icedtea/java/nio/file/attribute/GroupPrincipal.java \
++	org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView.java \
++	org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributes.java \
++	org/classpath/icedtea/java/nio/file/attribute/PosixFilePermission.java \
++	org/classpath/icedtea/java/nio/file/attribute/PosixFilePermissions.java \
++	org/classpath/icedtea/java/nio/file/attribute/UserPrincipal.java \
++	org/classpath/icedtea/java/nio/file/attribute/UserPrincipalLookupService.java \
++	org/classpath/icedtea/java/nio/file/attribute/UserPrincipalNotFoundException.java \
++	\
++	org/classpath/icedtea/java/nio/file/spi/AbstractPath.java \
++	org/classpath/icedtea/java/nio/file/spi/FileSystemProvider.java \
++	org/classpath/icedtea/java/nio/file/spi/FileTypeDetector.java \
++	\
++	com/sun/nio/file/ExtendedCopyOption.java \
++	com/sun/nio/file/ExtendedOpenOption.java \
++	com/sun/nio/file/ExtendedWatchEventModifier.java \
++	\
++	sun/nio/ch/AbstractFuture.java \
++	sun/nio/ch/AsynchronousChannelGroupImpl.java \
++	sun/nio/ch/AsynchronousFileChannelImpl.java \
++	sun/nio/ch/AsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/AsynchronousSocketChannelImpl.java \
++	sun/nio/ch/Cancellable.java \
++	sun/nio/ch/CompletedFuture.java \
++	sun/nio/ch/DefaultAsynchronousChannelProvider.java \
++	sun/nio/ch/FileDispatcher.java \
++	sun/nio/ch/FileLockImpl.java \
++	sun/nio/ch/FileLockTable.java \
++	sun/nio/ch/Groupable.java \
++	sun/nio/ch/Invoker.java \
++	sun/nio/ch/PendingFuture.java \
++	sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
++	sun/nio/ch/ThreadPool.java \
++	\
++	sun/nio/fs/AbstractAclFileAttributeView.java \
++	sun/nio/fs/AbstractBasicFileAttributeView.java \
++	sun/nio/fs/AbstractFileStoreSpaceAttributeView.java \
++	sun/nio/fs/AbstractFileTypeDetector.java \
++	sun/nio/fs/AbstractPoller.java \
++	sun/nio/fs/AbstractNamedAttributeView.java \
++	sun/nio/fs/AbstractWatchKey.java \
++	sun/nio/fs/AbstractWatchService.java \
++	sun/nio/fs/Cancellable.java \
++	sun/nio/fs/DefaultFileSystemProvider.java \
++	sun/nio/fs/DefaultFileTypeDetector.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 \
+ 
+ # Generated coder classes
+ #
+@@ -263,7 +388,14 @@
+ 	\
+ 	java/nio/charset/CharacterCodingException.java \
+ 	java/nio/charset/IllegalCharsetNameException.java \
+-	java/nio/charset/UnsupportedCharsetException.java
++	java/nio/charset/UnsupportedCharsetException.java \
++	\
++	org/classpath/icedtea/java/nio/channels/AcceptPendingException.java \
++	org/classpath/icedtea/java/nio/channels/IllegalChannelGroupException.java \
++	org/classpath/icedtea/java/nio/channels/InterruptedByTimeoutException.java \
++	org/classpath/icedtea/java/nio/channels/ReadPendingException.java \
++	org/classpath/icedtea/java/nio/channels/ShutdownChannelGroupException.java \
++	org/classpath/icedtea/java/nio/channels/WritePendingException.java 
+ 
+ FILES_gen_csp = sun/nio/cs/StandardCharsets.java
+ 
+diff -Nru openjdk.orig/jdk/make/java/nio/Makefile openjdk/jdk/make/java/nio/Makefile
+--- openjdk.orig/jdk/make/java/nio/Makefile	2009-01-10 03:22:13.000000000 +0000
++++ openjdk/jdk/make/java/nio/Makefile	2009-01-11 00:42:22.000000000 +0000
+@@ -40,6 +40,11 @@
+ SNIO_SRC = $(SHARE_SRC)/classes/sun/nio
+ SNIO_GEN = $(GENSRCDIR)/sun/nio
+ 
++INIO_SRC = $(SHARE_SRC)/classes/org/classpath/icedtea/java/nio
++INIO_GEN = $(GENSRCDIR)/org/classpath/icedtea/java/nio
++
++SERVICES = $(CLASSBINDIR)/META-INF/services
++
+ #
+ # Files to compile
+ #
+@@ -56,30 +61,128 @@
+         sun/nio/ch/DevPollSelectorProvider.java \
+ 	sun/nio/ch/InheritedChannel.java \
+         sun/nio/ch/PollSelectorProvider.java \
+-        sun/nio/ch/PollSelectorImpl.java
++        sun/nio/ch/PollSelectorImpl.java \
++	sun/nio/ch/Port.java \
++	sun/nio/ch/SimpleAsynchronousFileChannelImpl.java \
++	sun/nio/ch/SolarisAsynchronousChannelProvider.java \
++	sun/nio/ch/SolarisEventPort.java \
++	sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \
++	\
++	sun/nio/fs/GnomeFileTypeDetector.java \
++	sun/nio/fs/PollingWatchService.java \
++	sun/nio/fs/SolarisAclFileAttributeView.java \
++	sun/nio/fs/SolarisFileStore.java \
++	sun/nio/fs/SolarisFileSystem.java \
++	sun/nio/fs/SolarisFileSystemProvider.java \
++	sun/nio/fs/SolarisNamedAttributeView.java \
++	sun/nio/fs/SolarisNativeDispatcher.java \
++	sun/nio/fs/SolarisWatchService.java \
++	sun/nio/fs/UnixChannelFactory.java \
++	sun/nio/fs/UnixCopyFile.java \
++	sun/nio/fs/UnixDirectoryStream.java \
++	sun/nio/fs/UnixException.java \
++	sun/nio/fs/UnixFileAttributeViews.java \
++	sun/nio/fs/UnixFileAttributes.java \
++	sun/nio/fs/UnixFileKey.java \
++	sun/nio/fs/UnixFileModeAttribute.java \
++	sun/nio/fs/UnixFileStore.java \
++	sun/nio/fs/UnixFileStoreAttributes.java \
++	sun/nio/fs/UnixFileSystem.java \
++	sun/nio/fs/UnixFileSystemProvider.java \
++	sun/nio/fs/UnixMountEntry.java \
++	sun/nio/fs/UnixNativeDispatcher.java \
++	sun/nio/fs/UnixPath.java \
++	sun/nio/fs/UnixSecureDirectoryStream.java \
++	sun/nio/fs/UnixUriUtils.java \
++	sun/nio/fs/UnixUserPrincipals.java
+ 
+ FILES_c += \
+         DevPollArrayWrapper.c \
+ 	InheritedChannel.c \
+         PollArrayWrapper.c \
+-	NativeThread.c
++	NativeThread.c \
++	SolarisEventPort.c \
++	UnixAsynchronousServerSocketChannelImpl.c \
++	UnixAsynchronousSocketChannelImpl.c \
++	\
++	GnomeFileTypeDetector.c \
++	SolarisNativeDispatcher.c \
++	SolarisWatchService.c \
++	UnixCopyFile.c \
++	UnixNativeDispatcher.c
+ 
+ FILES_export += \
+ 	sun/nio/ch/DevPollArrayWrapper.java \
+ 	sun/nio/ch/InheritedChannel.java \
+-	sun/nio/ch/NativeThread.java
++	sun/nio/ch/NativeThread.java \
++	sun/nio/ch/SolarisEventPort.java \
++	sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \
++	\
++	sun/nio/fs/GnomeFileTypeDetector.java \
++	sun/nio/fs/SolarisNativeDispatcher.java \
++	sun/nio/fs/SolarisWatchService.java \
++	sun/nio/fs/UnixCopyFile.java \
++	sun/nio/fs/UnixNativeDispatcher.java
++
++FILES_gen += \
++	sun/nio/fs/SolarisConstants.java \
++	sun/nio/fs/UnixConstants.java
+ endif # PLATFORM = solaris
+ 
+ ifeq ($(PLATFORM), windows)
+ FILES_java += \
++	sun/nio/ch/Iocp.java \
++	sun/nio/ch/PendingIoCache.java \
++	sun/nio/ch/WindowsAsynchronousChannelProvider.java \
++	sun/nio/ch/WindowsAsynchronousFileChannelImpl.java \
++	sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java \
+         sun/nio/ch/WindowsSelectorImpl.java \
+-        sun/nio/ch/WindowsSelectorProvider.java
++        sun/nio/ch/WindowsSelectorProvider.java \
++	\
++	sun/nio/fs/RegistryFileTypeDetector.java \
++	sun/nio/fs/WindowsAclFileAttributeView.java \
++	sun/nio/fs/WindowsChannelFactory.java \
++	sun/nio/fs/WindowsConstants.java \
++	sun/nio/fs/WindowsDirectoryStream.java \
++	sun/nio/fs/WindowsException.java \
++	sun/nio/fs/WindowsFileAttributeViews.java \
++	sun/nio/fs/WindowsFileAttributes.java \
++	sun/nio/fs/WindowsFileCopy.java \
++	sun/nio/fs/WindowsFileStore.java \
++	sun/nio/fs/WindowsFileSystem.java \
++	sun/nio/fs/WindowsFileSystemProvider.java \
++	sun/nio/fs/WindowsLinkSupport.java \
++	sun/nio/fs/WindowsNamedAttributeView.java \
++	sun/nio/fs/WindowsNativeDispatcher.java \
++	sun/nio/fs/WindowsPath.java \
++	sun/nio/fs/WindowsPathParser.java \
++	sun/nio/fs/WindowsPathType.java \
++	sun/nio/fs/WindowsSecurity.java \
++	sun/nio/fs/WindowsSecurityDescriptor.java \
++	sun/nio/fs/WindowsUriSupport.java \
++	sun/nio/fs/WindowsUserPrincipals.java \
++	sun/nio/fs/WindowsWatchService.java
+ 
+ FILES_c += \
++	Iocp.c \
++	RegistryFileTypeDetector.c \
++	WindowsAsynchronousFileChannelImpl.c \
++	WindowsAsynchronousServerSocketChannelImpl.c \
++	WindowsAsynchronousSocketChannelImpl.c \
++	WindowsNativeDispatcher.c \
+         WindowsSelectorImpl.c
+ 
+ FILES_export += \
+-	sun/nio/ch/WindowsSelectorImpl.java
++	sun/nio/ch/Iocp.java \
++	sun/nio/ch/WindowsAsynchronousFileChannelImpl.java \
++	sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java \
++	sun/nio/ch/WindowsSelectorImpl.java \
++	sun/nio/fs/WindowsNativeDispatcher.java \
++	sun/nio/fs/RegistryFileTypeDetector.java
+ endif # PLATFORM = windows
+ 
+ ifeq ($(PLATFORM), linux)
+@@ -89,27 +192,84 @@
+ 	sun/nio/ch/DevPollSelectorImpl.java \
+ 	sun/nio/ch/DevPollSelectorProvider.java \
+ 	sun/nio/ch/EPollArrayWrapper.java \
++	sun/nio/ch/EPollPort.java \
+ 	sun/nio/ch/EPollSelectorProvider.java \
+ 	sun/nio/ch/EPollSelectorImpl.java \
+ 	sun/nio/ch/InheritedChannel.java \
++	sun/nio/ch/LinuxAsynchronousChannelProvider.java \
+         sun/nio/ch/PollSelectorProvider.java \
+-        sun/nio/ch/PollSelectorImpl.java
++        sun/nio/ch/PollSelectorImpl.java \
++	sun/nio/ch/Port.java \
++	sun/nio/ch/SimpleAsynchronousFileChannelImpl.java \
++	sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \
++	\
++	sun/nio/fs/GnomeFileTypeDetector.java \
++	sun/nio/fs/LinuxDosFileAttributeView.java \
++	sun/nio/fs/LinuxFileStore.java \
++	sun/nio/fs/LinuxFileSystem.java \
++	sun/nio/fs/LinuxFileSystemProvider.java \
++	sun/nio/fs/LinuxNamedAttributeView.java \
++	sun/nio/fs/LinuxNativeDispatcher.java \
++	sun/nio/fs/LinuxWatchService.java \
++	sun/nio/fs/PollingWatchService.java \
++	sun/nio/fs/UnixChannelFactory.java \
++	sun/nio/fs/UnixCopyFile.java \
++	sun/nio/fs/UnixDirectoryStream.java \
++	sun/nio/fs/UnixException.java \
++	sun/nio/fs/UnixFileAttributeViews.java \
++	sun/nio/fs/UnixFileAttributes.java \
++	sun/nio/fs/UnixFileKey.java \
++	sun/nio/fs/UnixFileModeAttribute.java \
++	sun/nio/fs/UnixFileStore.java \
++	sun/nio/fs/UnixFileStoreAttributes.java \
++	sun/nio/fs/UnixFileSystem.java \
++	sun/nio/fs/UnixFileSystemProvider.java \
++	sun/nio/fs/UnixMountEntry.java \
++	sun/nio/fs/UnixNativeDispatcher.java \
++	sun/nio/fs/UnixPath.java \
++	sun/nio/fs/UnixSecureDirectoryStream.java \
++	sun/nio/fs/UnixUriUtils.java \
++	sun/nio/fs/UnixUserPrincipals.java
+ 
+ FILES_c += \
+ 	EPollArrayWrapper.c \
++	EPollPort.c \
+         PollArrayWrapper.c \
+ 	InheritedChannel.c \
+-	NativeThread.c
++	NativeThread.c \
++	UnixAsynchronousServerSocketChannelImpl.c \
++	UnixAsynchronousSocketChannelImpl.c \
++	\
++	GnomeFileTypeDetector.c \
++	LinuxNativeDispatcher.c \
++	LinuxWatchService.c \
++	UnixCopyFile.c \
++	UnixNativeDispatcher.c
+ 
+ FILES_export += \
+ 	sun/nio/ch/DevPollArrayWrapper.java \
+         sun/nio/ch/EPollArrayWrapper.java \
++	sun/nio/ch/EPollPort.java \
+ 	sun/nio/ch/InheritedChannel.java \
+-	sun/nio/ch/NativeThread.java
++	sun/nio/ch/NativeThread.java \
++	sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \
++	sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \
++	\
++	sun/nio/fs/GnomeFileTypeDetector.java \
++	sun/nio/fs/LinuxNativeDispatcher.java \
++	sun/nio/fs/LinuxWatchService.java \
++	sun/nio/fs/UnixCopyFile.java \
++	sun/nio/fs/UnixNativeDispatcher.java
++
++FILES_gen += \
++	sun/nio/fs/UnixConstants.java
+ endif # PLATFORM = linux
+ 
++#
+ # Find platform-specific C source files
+ #
++vpath %.c $(PLATFORM_SRC)/native/sun/nio/fs
+ vpath %.c $(PLATFORM_SRC)/native/sun/nio/ch
+ vpath %.c $(SHARE_SRC)/native/sun/nio/ch
+ 
+@@ -153,7 +313,7 @@
+ build: sources
+ 
+ clean clobber::
+-	$(RM) -r $(NIO_GEN) $(SNIO_GEN)
++	$(RM) -r $(NIO_GEN) $(SNIO_GEN) $(INIO_GEN)
+ 	$(RM) -r $(CLASSDESTDIR)/java/nio
+ 	$(RM) -r $(CLASSDESTDIR)/sun/nio
+ 
+@@ -180,12 +340,16 @@
+ CS_SRC=$(NIO_SRC)/charset
+ SCH_SRC=$(SNIO_SRC)/ch
+ SCS_SRC=$(SNIO_SRC)/cs
++SFS_SRC=$(SNIO_SRC)/fs
++ICH_SRC=$(INIO_SRC)/channels
+ 
+ BUF_GEN=$(NIO_GEN)
+ CH_GEN=$(NIO_GEN)/channels
+ CS_GEN=$(NIO_GEN)/charset
+ SCH_GEN=$(SNIO_GEN)/ch
+ SCS_GEN=$(SNIO_GEN)/cs
++SFS_GEN=$(SNIO_GEN)/fs
++ICH_GEN=$(INIO_GEN)/channels
+ 
+ sources: $(SPP_JARFILE) $(FILES_genout)
+ 
+@@ -628,6 +792,10 @@
+ 	@$(RM) $@.temp
+ 	$(GEN_EX_CMD) $(SCH_SRC)/exceptions $(SCH_GEN)
+ 
++$(ICH_GEN)/%Exception.java: genExceptions.sh $(ICH_SRC)/exceptions
++	$(prep-target)
++	@$(RM) $@.temp
++	$(GEN_EX_CMD) $(ICH_SRC)/exceptions $(ICH_GEN)
+ 
+ #
+ # Generated charset-provider classes
+@@ -643,4 +811,48 @@
+ 	  HASHER="$(BOOT_JAVA_CMD) -jar $(HASHER_JARFILE)" \
+ 	  SH="$(SH)" $(SH) -e genCharsetProvider.sh $(SCS_SRC)/standard-charsets $(SCS_GEN)
+ 
++# 
++# Generated file system implementation classes (Unix only)
++#
++
++GENUC_SRC = $(PLATFORM_SRC)/native/sun/nio/fs/genUnixConstants.c
++
++GENUC_EXE = $(TEMPDIR)/genUnixConstants
++
++GENUC_COPYRIGHT_YEARS = $(shell $(CAT) $(GENUC_SRC) | \
++	$(NAWK) '/^.*Copyright.*Sun/ { print $$3 }')
++
++$(GENUC_EXE) : $(GENUC_SRC)
++	$(prep-target)
++	$(CC) $(CPPFLAGS) -o $@ $(GENUC_SRC)
++
++$(SFS_GEN)/UnixConstants.java: $(GENUC_EXE)
++	$(prep-target)
++	NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(GENUC_COPYRIGHT_YEARS) > $@
++	$(GENUC_EXE) >> $@
++
++GENSC_SRC = $(PLATFORM_SRC)/native/sun/nio/fs/genSolarisConstants.c
++
++GENSC_EXE = $(TEMPDIR)/genSolarisConstants
++
++GENSC_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSC_SRC) | \
++	$(NAWK) '/^.*Copyright.*Sun/ { print $$3 }')
++
++$(GENSC_EXE) : $(GENSC_SRC)
++	$(prep-target)
++	$(CC) $(CPPFLAGS) -o $@ $(GENSC_SRC)
++
++$(SFS_GEN)/SolarisConstants.java: $(GENSC_EXE)
++	$(prep-target)
++	NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(GENSC_COPYRIGHT_YEARS) > $@
++	$(GENSC_EXE) >> $@
++
++#
++# Files to copy
++#
++
++$(SERVICES)/%: $(PLATFORM_SRC)/classes/sun/nio/fs/META-INF/services/%
++	$(install-file)
++
++
+ .PHONY: sources
+diff -Nru openjdk.orig/jdk/make/java/nio/mapfile-linux openjdk/jdk/make/java/nio/mapfile-linux
+--- openjdk.orig/jdk/make/java/nio/mapfile-linux	2009-01-07 22:08:47.000000000 +0000
++++ openjdk/jdk/make/java/nio/mapfile-linux	2009-01-07 22:15:04.000000000 +0000
+@@ -20,6 +20,14 @@
+ 		Java_sun_nio_ch_EPollArrayWrapper_interrupt;
+ 		Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
+ 		Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
++		Java_sun_nio_ch_EPollPort_init;
++		Java_sun_nio_ch_EPollPort_close0;
++		Java_sun_nio_ch_EPollPort_epollCreate;
++		Java_sun_nio_ch_EPollPort_epollCtl;
++		Java_sun_nio_ch_EPollPort_epollWait;
++		Java_sun_nio_ch_EPollPort_drain1;
++		Java_sun_nio_ch_EPollPort_interrupt;
++		Java_sun_nio_ch_EPollPort_socketpair;
+                 Java_sun_nio_ch_FileChannelImpl_close0;
+                 Java_sun_nio_ch_FileChannelImpl_force0;
+                 Java_sun_nio_ch_FileChannelImpl_initIDs;
+@@ -75,6 +83,74 @@
+ 		Java_sun_nio_ch_ServerSocketChannelImpl_listen;
+                 Java_sun_nio_ch_SocketChannelImpl_checkConnect;
+ 		Java_sun_nio_ch_SocketChannelImpl_shutdown;
++		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
++		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
++		Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
++		Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio;
++		Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio;
++		Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs;
++		Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs;
++		Java_sun_nio_fs_LinuxWatchService_init;
++		Java_sun_nio_fs_LinuxWatchService_inotifyInit;
++		Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch;
++		Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch;
++		Java_sun_nio_fs_LinuxWatchService_configureBlocking;
++		Java_sun_nio_fs_LinuxWatchService_socketpair;
++		Java_sun_nio_fs_LinuxWatchService_poll;
++		Java_sun_nio_fs_LinuxNativeDispatcher_init;
++		Java_sun_nio_fs_LinuxNativeDispatcher_fgetxattr0;
++		Java_sun_nio_fs_LinuxNativeDispatcher_flistxattr;
++		Java_sun_nio_fs_LinuxNativeDispatcher_fsetxattr0;
++		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_getcwd;
++		Java_sun_nio_fs_UnixNativeDispatcher_strerror;
++		Java_sun_nio_fs_UnixNativeDispatcher_dup;
++		Java_sun_nio_fs_UnixNativeDispatcher_access0;
++		Java_sun_nio_fs_UnixNativeDispatcher_stat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fstat;
++		Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
++		Java_sun_nio_fs_UnixNativeDispatcher_chown0;
++		Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fchown;
++		Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
++		Java_sun_nio_fs_UnixNativeDispatcher_futimes;
++		Java_sun_nio_fs_UnixNativeDispatcher_open0;
++		Java_sun_nio_fs_UnixNativeDispatcher_openat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_close;
++		Java_sun_nio_fs_UnixNativeDispatcher_read;
++		Java_sun_nio_fs_UnixNativeDispatcher_write;
++		Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fclose;
++		Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
++		Java_sun_nio_fs_UnixNativeDispatcher_readdir;
++		Java_sun_nio_fs_UnixNativeDispatcher_closedir;
++		Java_sun_nio_fs_UnixNativeDispatcher_link0;
++		Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
++		Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_rename0;
++		Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
++		Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
++		Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
++		Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
++		Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
++		Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
++		Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
++		Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
++		Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
++		Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
++		Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
++		Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
++		Java_sun_nio_fs_UnixNativeDispatcher_getextmntent;
++		Java_sun_nio_fs_UnixCopyFile_transfer;
+ 
+ 	local:
+ 		*;
+diff -Nru openjdk.orig/jdk/make/java/nio/mapfile-solaris openjdk/jdk/make/java/nio/mapfile-solaris
+--- openjdk.orig/jdk/make/java/nio/mapfile-solaris	2009-01-07 22:08:47.000000000 +0000
++++ openjdk/jdk/make/java/nio/mapfile-solaris	2009-01-07 22:18:51.000000000 +0000
+@@ -73,6 +73,75 @@
+ 		Java_sun_nio_ch_ServerSocketChannelImpl_listen;
+                 Java_sun_nio_ch_SocketChannelImpl_checkConnect;
+ 		Java_sun_nio_ch_SocketChannelImpl_shutdown;
++		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
++		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
++		Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
++		Java_sun_nio_ch_SolarisEventPort_init;
++		Java_sun_nio_ch_SolarisEventPort_portCreate;
++		Java_sun_nio_ch_SolarisEventPort_portClose;
++		Java_sun_nio_ch_SolarisEventPort_portAssociate;
++		Java_sun_nio_ch_SolarisEventPort_portGet;
++		Java_sun_nio_ch_SolarisEventPort_portGetn;
++		Java_sun_nio_ch_SolarisEventPort_portSend;
++		Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio;
++		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_getcwd;
++		Java_sun_nio_fs_UnixNativeDispatcher_strerror;
++		Java_sun_nio_fs_UnixNativeDispatcher_dup;
++		Java_sun_nio_fs_UnixNativeDispatcher_access0;
++		Java_sun_nio_fs_UnixNativeDispatcher_stat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fstat;
++		Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
++		Java_sun_nio_fs_UnixNativeDispatcher_chown0;
++		Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fchown;
++		Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
++		Java_sun_nio_fs_UnixNativeDispatcher_futimes;
++		Java_sun_nio_fs_UnixNativeDispatcher_open0;
++		Java_sun_nio_fs_UnixNativeDispatcher_openat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_close;
++		Java_sun_nio_fs_UnixNativeDispatcher_read;
++		Java_sun_nio_fs_UnixNativeDispatcher_write;
++		Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fclose;
++		Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
++		Java_sun_nio_fs_UnixNativeDispatcher_readdir;
++		Java_sun_nio_fs_UnixNativeDispatcher_closedir;
++		Java_sun_nio_fs_UnixNativeDispatcher_link0;
++		Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
++		Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_rename0;
++		Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
++		Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
++		Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
++		Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
++		Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
++		Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
++		Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
++		Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
++		Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
++		Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
++		Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
++		Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
++		Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
++		Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
++		Java_sun_nio_fs_UnixNativeDispatcher_getextmntent;
++		Java_sun_nio_fs_UnixCopyFile_transfer;
++		Java_sun_nio_fs_SolarisNativeDispatcher_init;
++		Java_sun_nio_fs_SolarisNativeDispatcher_facl;
++		Java_sun_nio_fs_SolarisWatchService_init;
++		Java_sun_nio_fs_SolarisWatchService_portCreate;
++		Java_sun_nio_fs_SolarisWatchService_portAssociate;
++		Java_sun_nio_fs_SolarisWatchService_portDissociate;
++		Java_sun_nio_fs_SolarisWatchService_portSend;
++		Java_sun_nio_fs_SolarisWatchService_portGetn;
+ 
+ 	local:
+ 		*;
+diff -Nru openjdk.orig/jdk/make/mkdemo/Makefile openjdk/jdk/make/mkdemo/Makefile
+--- openjdk.orig/jdk/make/mkdemo/Makefile	2009-01-07 22:23:02.000000000 +0000
++++ openjdk/jdk/make/mkdemo/Makefile	2009-01-07 22:23:48.000000000 +0000
+@@ -31,7 +31,7 @@
+ PRODUCT = demos
+ include $(BUILDDIR)/common/Defs.gmk
+ 
+-SUBDIRS = applets jfc jvmti management jni scripting jpda
++SUBDIRS = applets jfc jvmti management jni scripting jpda nio
+ 
+ all build:: nbproject
+ 	$(SUBDIRS-loop)
+diff -Nru openjdk.orig/jdk/make/mksample/nio/Makefile openjdk/jdk/make/mksample/nio/Makefile
+--- openjdk.orig/jdk/make/mksample/nio/Makefile	2009-01-07 22:23:19.000000000 +0000
++++ openjdk/jdk/make/mksample/nio/Makefile	2009-01-07 22:24:06.000000000 +0000
+@@ -31,7 +31,7 @@
+ PRODUCT = java
+ include $(BUILDDIR)/common/Defs.gmk
+ 
+-SUBDIRS = server
++SUBDIRS = aio file server
+ all build clean clobber::
+ 	$(SUBDIRS-loop)
+ 
+diff -Nru openjdk.orig/jdk/src/share/classes/java/io/File.java openjdk/jdk/src/share/classes/java/io/File.java
+--- openjdk.orig/jdk/src/share/classes/java/io/File.java	2009-01-12 13:32:17.000000000 +0000
++++ openjdk/jdk/src/share/classes/java/io/File.java	2009-01-12 13:35:18.000000000 +0000
+@@ -1957,6 +1957,13 @@
+                 }
+             }
+         );
++	org.classpath.icedtea.misc.SharedSecrets.setJavaIODeleteOnExitAccess(
++            new org.classpath.icedtea.misc.JavaIODeleteOnExitAccess() {
++                public void add(String path) {
++		    DeleteOnExitHook.hook().add(path);
++                }
++            }
++        );            									    
+     }
+ 
+ 
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/security/util/SecurityConstants.java openjdk/jdk/src/share/classes/sun/security/util/SecurityConstants.java
+--- openjdk.orig/jdk/src/share/classes/sun/security/util/SecurityConstants.java	2009-01-12 17:45:26.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/security/util/SecurityConstants.java	2009-01-12 17:45:39.000000000 +0000
+@@ -52,6 +52,7 @@
+     public static final String FILE_EXECUTE_ACTION = "execute";
+     public static final String FILE_READ_ACTION = "read";
+     public static final String FILE_WRITE_ACTION = "write";
++    public static final String FILE_READLINK_ACTION = "readlink";
+ 
+     public static final String SOCKET_RESOLVE_ACTION = "resolve";
+     public static final String SOCKET_CONNECT_ACTION = "connect";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-pr261.patch	Mon Jan 12 21:46:12 2009 +0000
@@ -0,0 +1,40 @@
+diff -r fa4572c7c75f openjdk-ecj/jdk/make/java/nio/Makefile
+--- openjdk/jdk/make/java/nio/Makefile	Thu Nov 27 08:42:23 2008 +0000
++++ openjdk/jdk/make/java/nio/Makefile	Thu Nov 27 10:12:08 2008 +0000
+@@ -85,6 +85,9 @@ ifeq ($(PLATFORM), linux)
+ ifeq ($(PLATFORM), linux)
+ FILES_java += \
+         sun/nio/ch/AbstractPollSelectorImpl.java \
++	sun/nio/ch/DevPollArrayWrapper.java \
++	sun/nio/ch/DevPollSelectorImpl.java \
++	sun/nio/ch/DevPollSelectorProvider.java \
+ 	sun/nio/ch/EPollArrayWrapper.java \
+ 	sun/nio/ch/EPollSelectorProvider.java \
+ 	sun/nio/ch/EPollSelectorImpl.java \
+@@ -99,6 +102,7 @@ FILES_c += \
+ 	NativeThread.c
+ 
+ FILES_export += \
++	sun/nio/ch/DevPollArrayWrapper.java \
+         sun/nio/ch/EPollArrayWrapper.java \
+ 	sun/nio/ch/InheritedChannel.java \
+ 	sun/nio/ch/NativeThread.java
+diff -r 3ee709488c6c openjdk-ecj/jdk/make/java/nio/FILES_java.gmk
+--- openjdk/jdk/make/java/nio/FILES_java.gmk	Thu Nov 27 10:16:56 2008 +0000
++++ openjdk/jdk/make/java/nio/FILES_java.gmk	Thu Nov 27 11:08:57 2008 +0000
+@@ -31,6 +31,7 @@ FILES_src = \
+ 	java/nio/StringCharBuffer.java \
+ 	\
+ 	java/nio/channels/ByteChannel.java \
++	java/nio/channels/CancelledKeyException.java \
+ 	java/nio/channels/Channel.java \
+ 	java/nio/channels/Channels.java \
+ 	java/nio/channels/DatagramChannel.java \
+@@ -38,6 +39,7 @@ FILES_src = \
+ 	java/nio/channels/FileLock.java \
+ 	java/nio/channels/GatheringByteChannel.java \
+ 	java/nio/channels/InterruptibleChannel.java \
++	java/nio/channels/Pipe.java \
+ 	java/nio/channels/ReadableByteChannel.java \
+ 	java/nio/channels/ScatteringByteChannel.java \
+ 	java/nio/channels/SelectableChannel.java \