changeset 1620:242c0a9de43f

Merge from IcedTea6. 2009-02-10 Andrew John Hughes <ahughes@redhat.com> Merge from IcedTea6. * patches/ecj/icedtea-pr261.patch: Merged. * patches/icedtea-visualvm.patch: Dropped. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMuteControl.java, * visualvm.desktop, * .hgtags, * ChangeLog, * HACKING, * INSTALL, * IcedTeaPlugin.cc, * Makefile.am, * NEWS, * README, * acinclude.m4, * configure.ac, * generated/sun/nio/ch/SocketOptionRegistry.java: Merged. * 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/net/ProtocolFamily.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/SocketOption.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardProtocolFamily.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardSocketOption.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/DatagramChannel.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/MembershipKey.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/MulticastChannel.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/NetworkChannel.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/SelectorProvider.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/org/classpath/icedtea/java/util/concurrent/ScheduledThreadPoolExecutor.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaIODeleteOnExitAccess.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaUtilConcurrentThreadPoolExecutorAccess.java, * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/SharedSecrets.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/ExtendedSocketOption.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/MembershipKeyImpl.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java, * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/OptionKey.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/demo/nio/ZipFileSystem/META-INF/services/java.nio.file.spi.FileSystemProvider, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/README.txt, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarEntryInfo.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributes.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipEntryInfo.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributes.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributeView.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributes.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStore.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStream.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystemProvider.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipHeaderConstants.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipPathParser.java, * overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipUtils.java, * overlays/nio2/openjdk/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c, * 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/DefaultSelectorProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java, * overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/Port.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/DefaultSelectorProvider.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. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/DefaultLaunchHandler.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AppletWarningPane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertVerifier.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertWarningPane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertsInfoPane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/HttpsCertVerifier.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/MoreInfoPane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityDialogUI.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityWarningDialog.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SingleCertInfoPane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/VariableX509TrustManager.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/viewer/CertificatePane.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/KeyTool.java, * patches/hotspot/14.0b08/icedtea-format.patch, * patches/icedtea-awt-window-size.patch, * patches/icedtea-cc-interp-jvmti.patch, * patches/icedtea-doc-headers.patch, * patches/icedtea-java2d-dasher.patch, * patches/icedtea-nio2.patch, * patches/icedtea-pr261.patch, * patches/icedtea-version.patch, * plugin/icedtea/sun/applet/AppletSecurityContextManager.java, * plugin/icedtea/sun/applet/PluginAppletSecurityContext.java, * plugin/icedtea/sun/applet/PluginAppletViewer.java, * plugin/icedtea/sun/applet/PluginCallRequestFactory.java, * plugin/icedtea/sun/applet/PluginClassLoader.java, * plugin/icedtea/sun/applet/PluginDebug.java, * plugin/icedtea/sun/applet/PluginException.java, * plugin/icedtea/sun/applet/PluginMain.java, * plugin/icedtea/sun/applet/PluginMessageConsumer.java, * plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java, * plugin/icedtea/sun/applet/PluginStreamHandler.java, * plugin/icedtea/sun/applet/RequestQueue.java, * ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp, * ports/hotspot/src/cpu/zero/vm/frame_zero.hpp, * ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp, * ports/hotspot/src/cpu/zero/vm/stack_zero.hpp, * ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp, * ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp, * ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp, * ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp, * ports/hotspot/src/share/vm/includeDB_shark, * ports/hotspot/src/share/vm/shark/llvmHeaders.hpp, * ports/hotspot/src/share/vm/shark/sharkBlock.cpp, * ports/hotspot/src/share/vm/shark/sharkBuilder.cpp, * ports/hotspot/src/share/vm/shark/sharkBuilder.hpp, * ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp, * ports/hotspot/src/share/vm/shark/sharkEntry.cpp, * ports/hotspot/src/share/vm/shark/sharkEntry.hpp, * ports/hotspot/src/share/vm/shark/sharkFunction.cpp, * ports/hotspot/src/share/vm/shark/sharkFunction.hpp, * ports/hotspot/src/share/vm/shark/shark_globals.hpp, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPlaybackLine.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java, * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c, * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioSourcePort.c, * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioTargetPort.c, * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c, * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java, * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineRawTest.java, * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java, * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourcePortTest.java, * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetPortTest.java: Merged.
author Andrew John Hughes <ahughes@redhat.com>
date Tue, 10 Feb 2009 21:56:55 +0000
parents fd8112e82992 (current diff) c402774cf211 (diff)
children 983ed89e8dd3
files .hgtags ChangeLog HACKING IcedTeaPlugin.cc Makefile.am NEWS README acinclude.m4 configure.ac generated/sun/nio/ch/SocketOptionRegistry.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/DefaultLaunchHandler.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AppletWarningPane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertVerifier.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertWarningPane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertsInfoPane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/HttpsCertVerifier.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/MoreInfoPane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityDialogUI.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityWarningDialog.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SingleCertInfoPane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/VariableX509TrustManager.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/viewer/CertificatePane.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/KeyTool.java patches/ecj/icedtea-pr261.patch patches/icedtea-pr261.patch patches/icedtea-version.patch patches/icedtea-visualvm.patch ports/hotspot/src/share/vm/shark/sharkBlock.cpp ports/hotspot/src/share/vm/shark/sharkFunction.cpp pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMuteControl.java visualvm.desktop
diffstat 439 files changed, 82683 insertions(+), 943 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Feb 10 21:09:31 2009 +0000
+++ b/.hgtags	Tue Feb 10 21:56:55 2009 +0000
@@ -12,3 +12,5 @@
 3ef9c9c4e70b8204b73fa9b88243f49f59c2a23f icedtea6-1.3
 be368b1e3c7dca9b4dfe8e8f40be794ecfbef22e icedtea6-1.3.1
 3ced1c5f140358bf1d1ef569017b7914f36d6a5e icedtea-1.8
+6c02b699206db299c6bc96d97d31808bf84f042a icedtea6-1.4pre
+2b1c03c1e9fa88e453da2ca774dc8900227a2e16 icedtea6-1.4
--- a/ChangeLog	Tue Feb 10 21:09:31 2009 +0000
+++ b/ChangeLog	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,446 @@
+2009-02-10  Andrew John Hughes  <ahughes@redhat.com>
+
+	Merge from IcedTea6.
+	* patches/ecj/icedtea-pr261.patch: Merged.
+	* patches/icedtea-visualvm.patch: Dropped.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMuteControl.java,
+	* visualvm.desktop,
+	* .hgtags,
+	* ChangeLog,
+	* HACKING,
+	* INSTALL,
+	* IcedTeaPlugin.cc,
+	* Makefile.am,
+	* NEWS,
+	* README,
+	* acinclude.m4,
+	* configure.ac,
+	* generated/sun/nio/ch/SocketOptionRegistry.java: Merged.
+	* 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/net/ProtocolFamily.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/SocketOption.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardProtocolFamily.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardSocketOption.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/DatagramChannel.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/MembershipKey.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/MulticastChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/NetworkChannel.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/SelectorProvider.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/org/classpath/icedtea/java/util/concurrent/ScheduledThreadPoolExecutor.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaIODeleteOnExitAccess.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaUtilConcurrentThreadPoolExecutorAccess.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/SharedSecrets.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/ExtendedSocketOption.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/MembershipKeyImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/OptionKey.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/demo/nio/ZipFileSystem/META-INF/services/java.nio.file.spi.FileSystemProvider,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/README.txt,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarEntryInfo.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipEntryInfo.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStore.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStream.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipHeaderConstants.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipPathParser.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipUtils.java,
+	* overlays/nio2/openjdk/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c,
+	* 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/DefaultSelectorProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/Port.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/DefaultSelectorProvider.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.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/DefaultLaunchHandler.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AppletWarningPane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertVerifier.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertWarningPane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertsInfoPane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/HttpsCertVerifier.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/MoreInfoPane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityDialogUI.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityWarningDialog.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SingleCertInfoPane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/VariableX509TrustManager.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/viewer/CertificatePane.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/KeyTool.java,
+	* patches/hotspot/14.0b08/icedtea-format.patch,
+	* patches/icedtea-awt-window-size.patch,
+	* patches/icedtea-cc-interp-jvmti.patch,
+	* patches/icedtea-doc-headers.patch,
+	* patches/icedtea-java2d-dasher.patch,
+	* patches/icedtea-nio2.patch,
+	* patches/icedtea-pr261.patch,
+	* patches/icedtea-version.patch,
+	* plugin/icedtea/sun/applet/AppletSecurityContextManager.java,
+	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java,
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java,
+	* plugin/icedtea/sun/applet/PluginCallRequestFactory.java,
+	* plugin/icedtea/sun/applet/PluginClassLoader.java,
+	* plugin/icedtea/sun/applet/PluginDebug.java,
+	* plugin/icedtea/sun/applet/PluginException.java,
+	* plugin/icedtea/sun/applet/PluginMain.java,
+	* plugin/icedtea/sun/applet/PluginMessageConsumer.java,
+	* plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java,
+	* plugin/icedtea/sun/applet/PluginStreamHandler.java,
+	* plugin/icedtea/sun/applet/RequestQueue.java,
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp,
+	* ports/hotspot/src/cpu/zero/vm/frame_zero.hpp,
+	* ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp,
+	* ports/hotspot/src/cpu/zero/vm/stack_zero.hpp,
+	* ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp,
+	* ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp,
+	* ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp,
+	* ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp,
+	* ports/hotspot/src/share/vm/includeDB_shark,
+	* ports/hotspot/src/share/vm/shark/llvmHeaders.hpp,
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkBuilder.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkBuilder.hpp,
+	* ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkEntry.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkEntry.hpp,
+	* ports/hotspot/src/share/vm/shark/sharkFunction.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkFunction.hpp,
+	* ports/hotspot/src/share/vm/shark/shark_globals.hpp,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPlaybackLine.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java,
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c,
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioSourcePort.c,
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioTargetPort.c,
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c,
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java,
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineRawTest.java,
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java,
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourcePortTest.java,
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetPortTest.java: Merged.
+	
 2009-02-10  Andrew John Hughes  <ahughes@redhat.com>
 
 	Bump to b46.
@@ -13,12 +456,81 @@
 	* patches/icedtea-copy-plugs.patch: Recreated
 	due to S6702956.
 
+2009-02-08  Lillian Angel  <langel@redhat.com>
+
+	* Makefile.am: Updated sed to search for OpenJDK instead of IcedTea6. 
+	* patches/icedtea-version.patch: Changed PRODUCT_NAME from IcedTea6 to
+	OpenJDK.
+
+2009-02-05  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	Depend on overlay.stamp rather than patch.stamp.
+	
+2009-02-05  Andrew John Hughes  <ahughes@redhat.com>
+
+	Ensure the NIO2 code is in sync with the latest
+	build drop, b98.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.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/WindowsDirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.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/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/WindowsPath.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/attribute/NamedAttributeView/Basic.java,
+
+2009-02-04  Andrew John Hughes  <ahughes@redhat.com>
+
+	* acinclude.m4:
+	(AC_CHECK_FOR_GCJ_JDK): Drop out of loop
+	when first solution is found.
+	(AC_CHECK_FOR_OPENJDK): Likewise.
+	(AC_CHECK_FOR_ICEDTEA): Likewise.
+	
+2009-02-04  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	Add new patch.
+	* patches/hotspot/14.0b08/icedtea-format.patch,
+	Fix warnings that cause the build to fail with
+	GCC 4.3.3.
+	
+2009-02-03  Andrew John Hughes  <ahughes@redhat.com>
+
+	* patches/icedtea-nio2.patch:
+	(docs/NON_CORE_PKGS.gmk): Rename NIO to NIO2.
+	(docs/Makefile): Add rule for generating NIO2 docs.
+	
+2009-02-03  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	Move doc headers patch above NIO2 patch,
+	as this needs to alter the same file.
+	* patches/icedtea-doc-headers.patch:
+	Add IcedTea bugzilla URL and common licensing
+	to all documentation.
+
 2009-02-03  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am:
 	Bump to b45.
-	
-2009-01-28  Andrew John Hughes  <ahughes@redhat.com>
+
+2009-02-03  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	Add new patch.
+	* patches/icedtea-doc-headers.patch:
+	Fix licensing of documentation.
+
+2009-01-30  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am:
 	Rename PULSEAUDIO_SOURCES and JTREG_SOURCES
@@ -26,7 +538,82 @@
 	endif in download.stamp.
 	* patches/icedtea-rhino.patch:
 	Remove merge conflicts.
-	
+
+2009-01-28  Andrew John Hughes  <ahughes@redhat.com>
+
+	* patches/icedtea-nio2.patch:
+	(mapfile-linux): Add new functions in sun.nio.ch.Net.
+	(Net.java:setIntOption0(FileDescriptor,boolean,int,int,int)): Renamed to...
+	(Net.java:setIntOption1(FileDescriptor,boolean,int,int,int)): to avoid C collision.
+	(Net.c): Add back java_net_SocketOptions.h, bind0 and connect0 and setIntOption0
+	and rename existing setIntOption0 to setIntOption1.
+
+2009-01-29  Omair Majid  <omajid@redhat.com>
+
+	* patches/icedtea-java2d-dasher.patch: New patch. Fix interpretation of
+	dash array elements in BasicStroke.
+	* Makefile.am (ICEDTEA_PATCHES): Apply the above.
+	* HACKING: Document the above.
+
+2009-01-28  Lillian Angel  <langel@redhat.com>
+
+	* NEWS: Updated date.
+
+2009-01-28  Andrew Haley  <aph@redhat.com>
+
+	* NEWS: Updated.
+
+2009-01-28  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Updated for 1.4.
+
+2009-01-27  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java:
+	Use org.classpath.icedtea.java.nio.channels.FileChannel.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/FileSystemProvider.java:
+	Likewise.
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/META-INF/services/java.nio.file.spi.FileSystemProvider,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/README.txt,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarEntryInfo.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipEntryInfo.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributes.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStore.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStream.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipHeaderConstants.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipPathParser.java,
+	* overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipUtils.java:
+	Import NIO2 demo and fix imports.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java:
+	Use org.classpath.icedtea.java.nio.channels.FileChannel.
+
+2009-01-27  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java:
+	(positionSBC(long)): Renamed from position(long).
+	(truncateSBC(long)): Likewise.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java:
+	Same as for FileChannel, prevents conflict with versions in java.nio.channel.FileChannel.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java:
+	Add missing imports.
+	* patches/icedtea-nio2.patch:
+	(FileChannelImpl.positionSBC(long)): Added, simply calls position(long).
+	(FileChannelImpl.truncateSBC(long)): Likewise.
+
+2009-01-27  Andrew Haley  <aph@redhat.com>
+
+	* ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp:
+	Add memory barriers where needed for PPC.
+
 2009-01-26  Andrew John Hughes  <ahughes@redhat.com>
 
 	Bump to b44.
@@ -37,6 +624,389 @@
 	* patches/icedtea-linker-libs-order.patch:
 	Recreated against b44.
 
+2009-01-26  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileLockImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/PollingWatchService.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/LinuxFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxNamedAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.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:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java:
+	Fix imports and use of varargs.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.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/UnixFileSystem.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java:
+	Fix imports and use of varargs.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java:
+	Fix imports.
+	* patches/icedtea-nio2.patch:
+	(FileChannelImpl): Fix imports.
+	(Net.c): Patch to new version with new functions.
+	(nio_util.h): Add RESTARTABLE macro.
+
+2009-01-26  Lillian Angel  <langel@redhat.com>
+
+	* configure.ac: Updated to pre-1.5 version.
+
+2009-01-26  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
+	(JavaThread::has_special_condition_for_native_trans): New method.
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp:
+	(CppInterpreter::native_entry): Correctly handle safepoints
+	during post-call thread state transition.
+
+2009-01-22  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp:
+	(CppInterpreter::native_entry): Correctly handle asynchronous
+	exceptions during post-call thread state transition.
+
+2009-01-22  Omair Majid  <omajid@redhat.com>
+	    Ioana Ivan <iivan@redhat.com>
+			
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java
+	(start): Return silently if already started.
+	(stop): Return silently if already stopped.
+
+2009-01-22  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Use
+	Hashtable to store classloaders, instead of HashMap (values cannot be
+	null in HashTable).
+	* rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Catch CFE in
+	addition to CNFE.
+
+2009-01-22  Andrew Haley  <aph@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/stack_zero.hpp (class
+	ZeroFrame::FrameType): Set ENTRY_FRAME = 0xCAFEBABE.
+
+	* ports/hotspot/src/share/vm/shark/shark_globals.hpp (SHARK_FLAGS):
+	Add SharkPrintAsmOf.
+
+	* ports/hotspot/src/share/vm/shark/sharkFunction.hpp: Add comment.
+
+	* ports/hotspot/src/share/vm/shark/sharkFunction.cpp
+	(SharkFunction::initialize): Set builder()->sharkEntry.
+	Use fnmatch() instead of strcmp().
+	Generate debugging dumps.
+	* ports/hotspot/src/share/vm/shark/sharkEntry.hpp
+	(SharkEntry::code_start, code_limit): Rewrite.
+	(SharkEntry::setBounds): New.
+
+	* ports/hotspot/src/share/vm/shark/sharkBuilder.hpp
+	(SharkBuilder::pointer_constant): New function.
+	* ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp
+	(SharkBytecodeTracer::decode_one_word):
+	use SharkBuilder::pointer_constant.
+	* ports/hotspot/src/share/vm/shark/sharkBuilder.cpp
+	(SharkBuilder::sharkEntry): New.
+	(SharkBuilder::CreateUnimplemented): use SharkBuilder::pointer_constant.
+	(SharkBuilder::CreateShouldNotReachHere): Likewise.
+	(MyJITMemoryManager::endFunctionBody): New method.
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
+	(SharkBlock::check_zero): use SharkBuilder::pointer_constant.
+	(SharkBlock::check_bounds): Likewise.
+	(SharkBlock::add_safepoint): Likewise.
+	(SharkBlock::do_new): Likewise.
+	(SharkBlock::do_monitorexit): Don't check for null monitor.
+
+	* ports/hotspot/src/share/vm/shark/llvmHeaders.hpp: Add
+	llvm/ExecutionEngine/JITMemoryManager.h,
+	llvm/Support/CommandLine.h.
+	* ports/hotspot/src/share/vm/includeDB_shark (sharkBuilder.hpp):
+	add sharkEntry.hpp.
+
+2009-01-22  Lillian Angel  <langel@redhat.com>
+
+	* NEWS: Updated for release candidate.
+
+2009-01-22  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/frame_zero.hpp: Updated copyright year.
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp: Likewise.
+	* ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp: Likewise.
+	* ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp: Likewise.
+	* ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp: Likewise.
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp: Likewise.
+
+2009-01-22  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp
+	(print_zero_threads): New debug function.
+
+2009-01-22  Gary Benson  <gbenson@redhat.com>
+
+	* patches/icedtea-cc-interp-jvmti.patch: Reenable thread signalling.
+
+2009-01-21  Omair Majid  <omajid@redhat.com>
+
+	* patches/icedtea-awt-window-size.patch: Update patch.
+
+2009-01-21  Omair Majid  <omajid@redhat.com>
+
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java: 
+	Remove unused variables volume and muted.
+	(PulseAudioClip): Remove variable volume.
+	(open): Remove muteControl, volume and muted.
+	(native_setVolume): Rename to native_set_volume.
+	(native_update_volume): New function.
+	(isMuted): Remove.
+	(setMuted): Remove.
+	(setVolume): Rename to setCachedVolume.
+	(getVolume): Rename to getCachedVolume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMuteControl.java:
+	Remove file. Mute relied on chaning the volume only through the api. That
+	assumption is invalid as the user can change volume through pulseaudio's
+	controls.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPlaybackLine.java
+	(isMuted): Remove.
+	(setMuted): Remove.
+	(native_setVolume): Rename to native_set_volume.
+	(native_update_volume): New function.
+	(getVolume): Rename to getCachedVolume.
+	(setVolume): Rename to setCachedVolume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java:
+	Remove muted and muteControl. Rename volume to cachedVolume. 
+	(PulseAudioPort): Remove muteControl.
+	(isMuted): Remove function.
+	(setMuted): Remove.
+	(native_setVolume): Rename to native_set_volume.
+	(native_updateVolumeInfo): Rename to native_update_volume.
+	(setVolume): Rename to setCachedVolume.
+	(getVolume): Rename to getCachedVolume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java:
+	Remove muteControl, muted and volume.
+	(open): Remove muteControl.
+	(native_setVolume): Rename to native_set_volume.
+	(native_update_volume): New function.
+	(isMuted): Remove.
+	(setMuted): Remove.
+	(getVolume): Rename to getCachedVolume.
+	(setVolume): Rename to setCachedVolume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java
+	(native_setVolume): Rename to native_set_volume.
+	(native_updateVolumeInfo): Rename to native_update_volume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java
+	(native_setVolume): Rename to native_set_volume.
+	(native_updateVolumeInfo): Rename to native_update_volume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.java
+	(setValue): Dont check for mute.
+	(getValue): Query pulseaudio for any change in volume.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java:
+	New variable cachedVolume.
+	(native_setVolume): Rename to native_set_volume.
+	(native_update_volume): New function.
+	(getCachedVolume): New function.
+	(setCachedVolume): New function.
+	(update_channels_and_volume): New function.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c
+	(sink_input_volume_change_complete): Remove.
+	(sink_input_change_volume): Remove.
+	(Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1set_1sink_1volume):
+	Remove.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioSourcePort.c
+	(Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1updateVolumeInfo):
+	Rename to
+	Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1update_1volume.
+	(Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1setVolume):
+	Rename to
+	Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1set_1volume.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioTargetPort.c
+	(Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1updateVolumeInfo):
+	Rename to
+	Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1update_1volume.
+	(Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1setVolume):
+	Rename to
+	Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1set_1volume.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c
+	(Java_org_classpath_icedtea_pulseaudio_Stream_native_1setVolume): Rename
+	to Java_org_classpath_icedtea_pulseaudio_Stream_native_1set_1volume.
+	(get_sink_input_volume_callback): New function.
+	(Java_org_classpath_icedtea_pulseaudio_Stream_native_1update_1volume): New
+	function.
+
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java
+	(testSupportedControls): Update to not check for MuteControl.
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineRawTest.java
+	(testVolumeAndMute): Rename to testVolume. Remove test for MuteControl.
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java
+	(testVolumeAndMute): Likewise.
+	(testSupportedControls): Update to not check for MuteControl.
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourcePortTest.java	
+	(testControls): Update to not check for MuteControl.
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetPortTest.java
+	(testControls): Likewise.
+
+2009-01-21  Lillian Angel  <langel@redhat.com>
+
+	* plugin/icedtea/sun/applet/AppletSecurityContextManager.java: Added
+	copyright header.
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginCallRequestFactory.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginClassLoader.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginDebug.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginException.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginMain.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginMessageConsumer.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java: Likewise.
+	* plugin/icedtea/sun/applet/PluginStreamHandler.java: Likewise.
+	* plugin/icedtea/sun/applet/RequestQueue.java: Likewise.
+
+2009-01-21  Lillian Angel  <langel@redhat.com>
+
+	* rt/net/sourceforge/jnlp/security/CertVerifier.java: Fixed file name
+	in GPL header.
+	* rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java: Likewise.
+
+2009-01-20  Lillian Angel  <langel@redhat.com>
+
+	* rt/net/sourceforge/jnlp/DefaultLaunchHandler.java: Removed debug
+	lines.
+	* rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Likewise. 
+	* rt/net/sourceforge/jnlp/security/AccessWarningPane.java: Updated
+	imports.
+	* rt/net/sourceforge/jnlp/security/AppletWarningPane.java: Updated
+	imports.
+	* rt/net/sourceforge/jnlp/security/CertWarningPane.java: Updated
+	imports, added certVerifier global variable.
+	(CertWarningPane): Initialized certVerifier.
+	(installComponents): Added checks to determine if certificate is for
+	an https site, and set the name/publisher/from variables
+	appropriately. Also, customized warning pane label for https site.
+	* rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java:
+	(getDetails): Implemented.
+	(addToDetails): Likewise.
+	(R): Likewise.
+	(getPublisher): Likewise.
+	(getRoot): Likewise.
+	(getRootInCacerts): Likewise.
+	(hasSigningIssues): Likewise.
+	(noSigningIssues): Likewise.
+	* rt/net/sourceforge/jnlp/security/MoreInfoPane.java: Fixed imports.
+	* rt/net/sourceforge/jnlp/security/SecurityDialogUI.java: Fixed
+	imports.
+	* rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Fixed
+	imports.
+	* rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Fixed
+	imports.
+	* rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Fixed
+	imports.
+	* rt/net/sourceforge/jnlp/tools/KeyTool.java: Removed debug lines.
+	* rt/net/sourceforge/jnlp/security/CertVerifier.java: Moved file
+	below, here.
+	* rt/net/sourceforge/jnlp/tools/CertVerifier.java: Removed.
+	* rt/net/sourceforge/jnlp/security/VariableX509TrustManager.java:
+	Removed debug lines.
+
+2009-01-20  Lillian Angel  <langel@redhat.com>
+
+	* HACKING: Removed visualvm patch.
+	* INSTALL: Updated to remove visualvm notes.
+	* Makefile.am: Removed building of netbeans and visualvm.
+	* README: Updated to remove visualvm notes.
+	* acinclude.m4: Removed options for netbeans and visualvm.
+	* configure.ac: Likewise.
+	* patches/icedtea-visualvm.patch: Removed.
+	* visualvm.desktop: Removed.
+
+2009-01-20  Matthias Klose  <doko@ubuntu.com>
+	    Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.[ch]pp (i486): Rename
+	to x86.
+	* ports/hotspot/src/cpu/zero/vm/frame_zero.hpp (fp): Remove PRODUCT
+	conditional, make the not-PRODUCT bit the default.
+
+2009-01-19  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java:
+	(getByIndex(int)): New method.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java:
+	Fixed imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java:
+	New files.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java:
+	Fix imports, refer to AsynchronousFileLockImpl instead of FileLockImpl.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java:
+	Fix imports and vararg usage.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java:
+	Fix vararg usage.
+	* 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:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java:
+	Fix imports and vararg usage.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/Port.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:
+	Fix imports.
+	* patches/icedtea-nio2.patch:
+	Add new classes.
+	(Unsafe.copyMemory(long,long,long)): Backported.
+	(Unsafe.copyMemory(Object,long,Object,long,long)): Backported.
+	(Unsafe.ARRAY_BYTE_BASE_OFFSET): Likewise.
+	(DatagramChannelImpl.bind(SocketAddress)): Likewise.
+	(DatagramChannelImpl.getLocalAddress()): Likewise.
+	(DatagramChannelImpl.getOption(SocketOption)): Likewise.
+	(DatagramChannelImpl.innerJoin(InetAddress,NetworkInterface,InetAddress)): Likewise.
+	(DatagramChannelImpl.join(InetAddress,NetworkInterface)): Likewise.
+	(DatagramChannelImpl.join(InetAddress,NetworkInterface,InetAddress)): Likewise.
+	(DatagramChannelImpl.block(MembershipKeyImpl,InetAddress)): Likewise.
+	(DatagramChannelImpl.unblock(MembershipKeyImpl,InetAddress)): Likewise.
+	(DatagramChannelImpl.drop(MembershipKeyImpl)): Likewise.
+	(Net.getInterface4(FileDescriptor)): Likewise.
+	(Net.getInterface6(FileDescriptor)): Likewise.
+	(Net.inet4FromInt(int)): Likewise.
+	(Net.inet6AsByteArray(InetAddress)): Likewise.
+	(Net.join6(FileDescriptor,byte[],int,byte[])): Likewise.
+	(Net.drop6(FileDescriptor,byte[],int,byte[])): Likewise.
+	(Net.joinOrDrop6(boolean,FileDescriptor,byte[],int,byte[])): Likewise.
+	(Net.block6(FileDescriptor,byte[],int,byte[])): Likewise.
+	(Net.unblock6(FileDescriptor,byte[],int,byte[])): Likewise.
+	(Net.blockOrUnblock6(boolean,FileDescriptor,byte[],int,byte[])): Likewise.
+	(Net.join4(FileDescriptor,int,int,int)): Likewise.
+	(Net.drop4(FileDescriptor,int,int,int)): Likewise.
+	(Net.joinOrDrop4(boolean,FileDescriptor,int,int,int)): Likewise.
+	(Net.block4(FileDescriptor,int,int,int)): Likewise.
+	(Net.unblock4(FileDescriptor,int,int,int)): Likewise.
+	(Net.blockOrUnblock4(boolean,FileDescriptor,int,int,int)): Likewise.
+	(Net.connect(FileDescriptor,InetAddress,int)): Likewise.
+	(Net.connect(ProtocolFamily,FileDescriptor,InetAddress,int)): Likewise.
+	(Net.connect0(boolean,FileDescriptor,InetAddress,int)): Likewise.
+	(FileDispatcher.NO_LOCK)): Likewise.
+	(FileDispatcher.LOCKED)): Likewise.
+	(FileDispatcher.RET_EX_LOCK)): Likewise.
+	(FileDispatcher.INTERRUPTED)): Likewise.
+	(FileDispatcher.size(FileDescriptor)): Likewise.
+	(FileDispatcher.truncate(FileDescriptor, long)): Likewise.
+	(FileDispatcher.force(FileDescriptor, boolean)): Likewise.
+	(FileDispatcher.lock(FileDescriptor, boolean, long, long, boolean)): Likewise.
+	(FileDispatcher.release(FileDescriptor, long, long)): Likewise.
+	(FileDispatcher.force0(FileDescriptor,boolean)): Likewise.
+	(FileDispatcher.truncate0(FileDescriptor, long)): Likewise.
+	(FileDispatcher.size0(FileDescriptor)): Likewise.
+	(FileDispatcher.lock0(FileDescriptor, boolean, long, long, boolean)): Likewise.
+	(FileDispatcher.release0(FileDescriptor, long, long)): Likewise.
+
 2009-01-19  Andrew John Hughes  <ahughes@redhat.com>
 
 	Merge with IcedTea6.
@@ -103,6 +1073,40 @@
 	* ports/hotspot/src/share/vm/shark/sharkCompiler.cpp,
 	* ports/hotspot/src/share/vm/shark/sharkFunction.cpp:
 	Merged.
+	
+2009-01-19  Deepak Bhole  <dbhole@redhat.com>
+
+	* IcedTeaPlugin.cc: Add "Java" in the plugin description string. 
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java: Change the way the
+	image was searched locally.
+	* plugin/icedtea/sun/applet/PluginMain.java: Install a custom SSL trust
+	manager.
+	* rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Cache file names
+	from jars.
+	* rt/net/sourceforge/jnlp/security/AccessWarningPane.java: Accept
+	CertVerifier as an additional argument.
+	* rt/net/sourceforge/jnlp/security/AppletWarningPane.java: Same.
+	* rt/net/sourceforge/jnlp/security/CertWarningPane.java: Same.
+	* rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Same.
+	* rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java: New file.
+	Implements information gathering functions used by various prompt dialogs.
+	* rt/net/sourceforge/jnlp/security/MoreInfoPane.java: Accept CertVerifier 
+	as an additional argument.
+	* rt/net/sourceforge/jnlp/security/SecurityDialogUI.java: Same.
+	* rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Use the new
+	common CertVerifier interface to gather information.
+	* rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Accept
+	CertVerifier as an additional argument.
+	* rt/net/sourceforge/jnlp/security/VariableX509TrustManager.java:
+	Customized trustmanager that can temporarily trust certificates on the
+	fly.
+	* rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Accept
+	CertVerifier as an additional argument.
+	* rt/net/sourceforge/jnlp/tools/CertVerifier.java: New common interface
+	that all security related dialogs now query for certificate info (jar and
+	https).
+	* rt/net/sourceforge/jnlp/tools/JarSigner.java: Implement the new
+	CertVerifier verifier interface.
 
 2009-01-18  Andrew John Hughes  <ahughes@redhat.com>
 
@@ -118,6 +1122,35 @@
 	GenerateSBCS.java using java.util.Scanner for ecj builds.
 	* patches/xrender/icedtea-002.patch: Recreated against b43.
 
+2009-01-19  Andrew John Hughes  <ahughes@redhat.com>
+
+	* generated/sun/nio/ch/SocketOptionRegistry.java:
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/DatagramChannel.java:
+	Added (1.7 extensions).
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/exceptions: Fix package.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/spi/SelectorProvider.java:
+	Added (1.7 extensions).
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/SharedSecrets.java:
+	Added to provide access to package-private NetworkInterface.getIndex().
+	* 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/CompletedFuture.java:
+	Fixed imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/ExtendedSocketOption.java: Added.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/Invoker.java: Fixed imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/OptionKey.java: Added.
+	* 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/ThreadPool.java: Fixed imports.
+	* overlays/nio2/openjdk/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java: Added.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java:
+	Fixed imports.
+	* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/DefaultSelectorProvider.java: Added.
+	* patches/icedtea-nio2.patch: Add hook for SharedSecrets to NetworkInterface, extend
+	sun.nio.ch.{Net,DatagramChannelImpl,SelectorProviderImpl} to handle 1.7 extensions.
+
 2009-01-17  Mark Wielaard  <mark@klomp.org>
 
 	* patches/icedtea-version.patch (samejvmsafe): Removed the following
@@ -140,6 +1173,24 @@
 	* ports/hotspot/src/cpu/zero/vm/globals_zero.hpp
 	(StackShadowPages): Increase for 64-bit builds.
 
+2009-01-14  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/FileChannel.java:
+	Extend java.nio.channels.FileChannel to minimise code.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/util/concurrent/ScheduledThreadPoolExecutor.java:
+	Adapted to use the SharedSecrets backdoor.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaUtilConcurrentThreadPoolExecutorAccess.java:
+	Add remaining methods needed for our ScheduledThreadPoolExecutor.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java:
+	Create a ScheduledThreadPoolExecutor directly so ours is used.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java:
+	Refer to AsynchronousFileLockImpl not FileLockImpl.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousFileLockImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/FileLockTable.java:
+	Fix imports.
+	* patches/icedtea-nio2.patch:
+	Update implementation of secrets interface.
+
 2008-12-22  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am: Fix b42 tarball name and checksum
@@ -187,10 +1238,432 @@
 	(getVersionedResourceURL): New function. Constructs a URL with a
 	version-id as the query.
 
+2009-01-13  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaIODeleteOnExitAccess.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/SharedSecrets.java:
+	Add missing SharedSecrets files.
+
+2009-01-13  Andrew John Hughes  <ahughes@redhat.com>
+
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardProtocolFamily.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardSocketOption.java:
+	Added missing files.
+	* 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/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/MulticastChannel.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/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/Path.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/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/attribute/AclFileAttributeView.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/FileStoreSpaceAttributeView.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/PosixFilePermissions.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:
+	Fixed imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/util/concurrent/ScheduledThreadPoolExecutor.java:
+	Added.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaUtilConcurrentThreadPoolExecutorAccess.java:
+	Added to allow access to private members of java.util.concurrent.ThreadPoolExecutor.
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.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/UnixFileSystem.java:
+	Fix imports.
+	* patches/icedtea-nio2.patch:
+	Patch ThreadPoolExecutor to allow access to private variables, add missing files to
+	nio/FILES_java.gmk
+
+2009-01-12  Andrew John Hughes  <ahughes@redhat.com>
+
+	* 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:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/ProtocolFamily.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/SocketOption.java:
+	Add missing files.
+	* 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:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/MembershipKey.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/MulticastChannel.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/NetworkChannel.java:
+	Add missing files.
+	* 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/file/FileSystems.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/spi/AbstractPath.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/AsynchronousServerSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.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/AbstractWatchKey.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java,
+	* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java:
+	Add missing file.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java:
+	Fix imports.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/Port.java:
+	Add missing file.
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.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/UnixFileStore.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/UnixPath.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java,
+	* overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java:
+	Fix imports.
+	* patches/icedtea-nio2.patch:
+	Add missing files to java/nio/FILES_java.gmk
+
 2009-01-13  Gary Benson  <gbenson@redhat.com>
 
 	* contrib/jck/compile-native-code.sh: Build with -m32 or -m64.
 
+2009-01-12  Andrew John Hughes  <ahughes@redhat.com>
+
+	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-13  Matthias Klose  <doko@ubuntu.com>
 
 	* patches/hotspot/14.0b08/icedtea-hotspot-dispatch.patch: Remove,
@@ -454,6 +1927,11 @@
 	* configure.ac:
 	Call AC_CHECK_WITH_HG_REVISION.
 
+2008-12-09  Andrew John Hughes  <ahughes@redhat.com>
+
+	* configure.ac:
+	Capitalise 'XRender' in configure option.
+
 2008-12-09  Mark Wielaard  <mark@klomp.org>
 
 	* Makefile.am:
@@ -478,11 +1956,6 @@
 
 2008-12-09  Andrew John Hughes  <ahughes@redhat.com>
 
-	* configure.ac:
-	Capitalise 'XRender' in configure option.
-
-2008-12-09  Andrew John Hughes  <ahughes@redhat.com>
-
 	* Makefile.am:
 	Don't use find to locate the hotspot directory,
 	explicitly use 'hotspot-' plus the changeset.
--- a/HACKING	Tue Feb 10 21:09:31 2009 +0000
+++ b/HACKING	Tue Feb 10 21:56:55 2009 +0000
@@ -55,7 +55,6 @@
 * icedtea-tools.patch: Remove DebugHelperHelper and add sources in make/java/awt/Makefile to fix build of jvmti.
 * icedtea-use-system-tzdata.patch: Use timezone data from the system (PR70/S6593486).
 * icedtea-version.patch: Replace name and bug URL with IcedTea versions.
-* icedtea-visualvm.patch: Patches sources to build with platform8 and profiler3 instead of platform7 and profiler2.
 * icedtea-webservices.patch: Add applet support.
 * icedtea-zero-build.patch: Add support for the zero assembler build.
 * icedtea-shark-build.patch: Add support for building the Shark JIT.
@@ -80,6 +79,7 @@
 * icedtea-no-precompiled.patch: Don't use precompiled header files in hotspot.
 * icedtea-includedb.patch: Add missing include files.
 * icedtea-awt-window-size.patch: Fix X11 window size calculation (S6721088).
+* icedtea-java2d-dasher.patch: Fix interpretation of dash array elements in BasicStroke (S6793344).
 
 The following patches are only applied to OpenJDK6 in IcedTea6:
 
--- a/INSTALL	Tue Feb 10 21:09:31 2009 +0000
+++ b/INSTALL	Tue Feb 10 21:56:55 2009 +0000
@@ -31,10 +31,6 @@
 zlib-devel
 rhino (can be disabled using --without-rhino)
 
-For building VisualVM, you will need:
-netbeans (harness, platform8, apisupport1, java2, ide9)
-jakarta-commons-logging
-
 For building the PulseAudio based mixer, you will need
 pulseaudio-libs-devel >= 0.9.11
 pulseaudio >= 0.9.11
--- a/IcedTeaPlugin.cc	Tue Feb 10 21:09:31 2009 +0000
+++ b/IcedTeaPlugin.cc	Tue Feb 10 21:56:55 2009 +0000
@@ -275,7 +275,7 @@
 #define PLUGIN_CHECK(message, result)
 #endif
 
-#define PLUGIN_NAME "IcedTea Web Browser Plugin"
+#define PLUGIN_NAME "IcedTea Java Web Browser Plugin"
 #define PLUGIN_DESCRIPTION "The " PLUGIN_NAME PLUGIN_VERSION " executes Java applets."
 #define PLUGIN_MIME_DESC                                               \
   "application/x-java-vm:class,jar:IcedTea;"                           \
--- a/Makefile.am	Tue Feb 10 21:09:31 2009 +0000
+++ b/Makefile.am	Tue Feb 10 21:56:55 2009 +0000
@@ -5,10 +5,6 @@
 CACAO_VERSION = 0.99.3
 CACAO_MD5SUM = 80de3ad344c1a20c086ec5f1390bd1b8
 
-NETBEANS_BASIC_CLUSTER = a7ea855f475fa3a982f094a45c155ab4
-NETBEANS_PROFILER_MD5SUM = ff8e8abc42df6c6749e6b02bcf7bb0a5
-VISUALVM_MD5SUM = 4b55bc623418818793392bb233da2927
-
 if ENABLE_PLUGIN
 ICEDTEAPLUGIN_CLEAN = clean-IcedTeaPlugin
 ICEDTEAPLUGIN_TARGET = IcedTeaPlugin.so
@@ -36,12 +32,6 @@
 PULSE_JAVA_CLASS_DIR =
 endif
 
-if WITH_VISUALVM
-VISUALVM_PATCH = patches/icedtea-visualvm.patch
-else
-VISUALVM_PATCH = 
-endif
-
 # Top-Level Targets
 # =================
 
@@ -63,8 +53,6 @@
 	rm -f IcedTeaPlugin.o IcedTeaPlugin.so
 endif
 	rm -rf cacao
-	rm -rf visualvm
-	rm -rf netbeans
 	rm -f jni-common.o
 if BUILD_NATIVE_ECJ
 	rm -f native-ecj
@@ -83,8 +71,7 @@
 	clean-icedtea icedtea-against-icedtea clean-icedtea-ecj clean-plugs \
 	clean-tools-jar clean-shared-objects \
 	clean-copy clean-hotspot-tools clean-rt $(ICEDTEAPLUGIN_CLEAN) \
-	hotspot hotspot-helper clean-extra clean-jtreg clean-jtreg-reports \
-	clean-visualvm clean-nbplatform
+	hotspot hotspot-helper clean-extra clean-jtreg clean-jtreg-reports 
 
 GENERATED_FILES = generated/com/sun/java/swing/plaf/gtk/resources/gtk_it.java \
 	generated/com/sun/java/swing/plaf/gtk/resources/gtk_de.java \
@@ -1343,6 +1330,13 @@
 EXTRA_DIST = $(GENERATED_FILES) $(top_srcdir)/patches/icedtea-*.patch \
 	tools-copy contrib ports extra overlays \
 	javaws.png javaws.desktop visualvm.desktop \
+=======
+EXTRA_DIST = rt generated \
+	patches/* \
+	gcjwebplugin.cc tools-copy contrib ports \
+	extra overlays \
+	javaws.png javaws.desktop \
+>>>>>>> other
 	jconsole.desktop policytool.desktop \
 	$(JTREG_SRCS) \
 	IcedTeaPlugin.cc \
@@ -1570,30 +1564,6 @@
   CACAO_SRC_ZIP = cacao-$(CACAO_VERSION).tar.gz
 endif
 
-NETBEANS_BASIC_CLUSTER_URL = http://nbi.netbeans.org/files/documents/210/2056/
-
-if USE_ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP
-  NETBEANS_BASIC_CLUSTER_SRC_ZIP = $(ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP)
-else
-  NETBEANS_BASIC_CLUSTER_SRC_ZIP = netbeans-6.1-200805300101-basic_cluster-src.zip 
-endif
-
-NETBEANS_PROFILER_URL = http://icedtea.classpath.org/visualvm/
-
-if USE_ALT_NETBEANS_PROFILER_SRC_ZIP
-  NETBEANS_PROFILER_SRC_ZIP = $(ALT_NETBEANS_PROFILER_SRC_ZIP)
-else
-  NETBEANS_PROFILER_SRC_ZIP = netbeans-profiler-visualvm_preview2.tar.gz
-endif
-
-VISUALVM_URL = http://icedtea.classpath.org/visualvm/
-
-if USE_ALT_VISUALVM_SRC_ZIP
-  VISUALVM_SRC_ZIP = $(ALT_VISUALVM_SRC_ZIP)
-else
-  VISUALVM_SRC_ZIP = visualvm-20081031-src.tar.gz
-endif
-
 stamps/download.stamp: stamps/hgforest.stamp
 if !OPENJDK_SRC_DIR_FOUND
 if USE_ALT_OPENJDK_SRC_ZIP
@@ -1668,46 +1638,6 @@
 endif
 endif
 endif
-if WITH_VISUALVM
-if USE_ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP
-else
-	if ! echo "$(NETBEANS_BASIC_CLUSTER_MD5SUM) $(NETBEANS_BASIC_CLUSTER_SRC_ZIP)" \
-	  | $(MD5SUM) --check ; \
-	then \
-	  if [ $(NETBEANS_BASIC_CLUSTER_SRC_ZIP) ] ; \
-	  then \
-	    mv $(NETBEANS_BASIC_CLUSTER_SRC_ZIP) $(NETBEANS_BASIC_CLUSTER_SRC_ZIP).old ; \
-	  fi ; \
-	$(WGET) $(NETBEANS_BASIC_CLUSTER_URL)$(NETBEANS_BASIC_CLUSTER_SRC_ZIP) \
-	  -O $(NETBEANS_BASIC_CLUSTER_SRC_ZIP) ; \
-	fi
-endif
-if USE_ALT_NETBEANS_PROFILER_SRC_ZIP
-else
-	if ! echo "$(NETBEANS_PROFILER_MD5SUM) $(NETBEANS_PROFILER_SRC_ZIP)" \
-	  | $(MD5SUM) --check ; \
-	then \
-	  if [ $(NETBEANS_PROFILER_SRC_ZIP) ] ; \
-	  then \
-	    mv $(NETBEANS_PROFILER_SRC_ZIP) $(NETBEANS_PROFILER_SRC_ZIP).old ; \
-	  fi ; \
-	  $(WGET) $(NETBEANS_PROFILER_URL)$(NETBEANS_PROFILER_SRC_ZIP) \
-	    -O $(NETBEANS_PROFILER_SRC_ZIP) ; \
-	fi
-endif
-if USE_ALT_VISUALVM_SRC_ZIP
-else
-	if ! echo "$(VISUALVM_MD5SUM) $(VISUALVM_SRC_ZIP)" \
-	  | $(MD5SUM) --check ; \
-	then \
-	  if [ $(VISUALVM_SRC_ZIP) ] ; \
-	  then \
-	    mv $(VISUALVM_SRC_ZIP) $(VISUALVM_SRC_ZIP).old ; \
-	  fi ; \
-	  $(WGET) $(VISUALVM_URL)$(VISUALVM_SRC_ZIP) -O $(VISUALVM_SRC_ZIP) ; \
-	fi
-endif
-endif
 	mkdir -p stamps
 	touch stamps/download.stamp
 
@@ -1746,18 +1676,13 @@
 if WITH_CACAO
 	rm -f $(CACAO_SRC_ZIP)
 endif
-if WITH_VISUALVM
-	rm -f $(VISUALVM_SRC_ZIP) 
-	rm -f $(NETBEANS_PROFILER_SRC_ZIP)
-	rm -rf $(NETBEANS_BASIC_CLUSTER_SRC_ZIP)
-endif
 
 # Link ports sources into tree
 stamps/ports.stamp: stamps/extract.stamp
 	for target in $(abs_top_srcdir)/ports/hotspot/make/*/makefiles/* \
 		      $(abs_top_srcdir)/ports/hotspot/src/*cpu/* \
 		      $(abs_top_srcdir)/ports/hotspot/src/share/vm/*; do \
-	  link=$$(dirname $$target | sed 's/^.*ports/openjdk/'|sed "s#hotspot/build#hotspot/$(HOTSPOT_MAKE_DIR)#"); \
+	  link=$$(dirname $$target | sed 's/^.*ports/openjdk/'|sed "s#hotspot/build#hotspot/make#"); \
 	  ln -sfv $$target $$link; \
 	done
 	ln -sf $(abs_top_builddir)/platform_zero openjdk/hotspot/make/linux
@@ -1868,7 +1793,6 @@
 	patches/icedtea-signed-types.patch \
 	patches/icedtea-lc_ctype.patch \
 	patches/icedtea-messageutils.patch \
-	$(VISUALVM_PATCH) \
 	patches/icedtea-javac-debuginfo.patch \
 	patches/icedtea-xjc.patch \
 	patches/icedtea-renderer-crossing.patch \
@@ -1879,6 +1803,11 @@
 	patches/icedtea-linker-libs-order.patch \
 	patches/icedtea-f2i-overflow.patch \
 	patches/icedtea-testenv.patch \
+	patches/icedtea-samejvm-safe.patch \
+	patches/icedtea-6728542-epoll.patch \
+	patches/icedtea-cc-interp-jvmti.patch \
+	patches/icedtea-pr261.patch \
+	patches/icedtea-doc-headers.patch \
 	patches/icedtea-format-warnings.patch \
 	patches/icedtea-fortify-source.patch \
 	$(ZERO_PATCHES_COND) \
@@ -1927,10 +1856,16 @@
 	patches/icedtea-javafiles.patch
 endif
 
+if ENABLE_NIO2
+ICEDTEA_PATCHES += patches/icedtea-nio2.patch
+endif
+
 ICEDTEA_PATCHES += \
 	$(DISTRIBUTION_PATCHES) \
 	patches/icedtea-demo-swingapplet.patch \
-	patches/icedtea-awt-window-size.patch
+	patches/icedtea-awt-window-size.patch \
+	patches/icedtea-java2d-dasher.patch \
+	patches/hotspot/$(HSBUILD)/icedtea-format.patch
 
 stamps/extract.stamp: stamps/download.stamp
 if OPENJDK_SRC_DIR_FOUND
@@ -1984,27 +1919,6 @@
 	fi
 endif
 endif
-if WITH_VISUALVM
-	if ! test -d visualvm ; \
-	then \
-	  $(TAR) xf $(VISUALVM_SRC_ZIP) ; \
-	fi
-	if ! test -d netbeans ; \
-	then \
-	  mkdir netbeans ; \
-	  $(TAR) xf $(NETBEANS_PROFILER_SRC_ZIP) -C netbeans ; \
-	  $(UNZIP) -q $(NETBEANS_BASIC_CLUSTER_SRC_ZIP) nbbuild/* -d netbeans/ ; \
-	  mv netbeans/profiler/ netbeans/profiler.cvs/ ; \
-	  $(UNZIP) -q $(NETBEANS_BASIC_CLUSTER_SRC_ZIP) \
-	  api.java/* api.progress/* apisupport.harness/* editor.mimelookup/* \
-	  o.jdesktop.layout/* openide.actions/* openide.awt/* \
-	  openide.dialogs/* openide.execution/* openide.explorer/* \
-	  openide.filesystems/* openide.io/* openide.loaders/* \
-	  openide.modules/* openide.nodes/* openide.text/* openide.util/* \
-	  openide.windows/* options.api/* projectapi/* queries/* java.platform/* \
-	  -d netbeans/ ; \
-	fi
-endif
 	touch stamps/extract-cacao.stamp
 
 stamps/generated.stamp: stamps/extract-cacao.stamp
@@ -2166,18 +2080,21 @@
 	if test x"$(VERSION_SUFFIX)" != "x"; then \
 	  ver_suffix="-$(VERSION_SUFFIX)"; \
 	fi ; \
-	sed -i "s#IcedTea#IcedTea $${icedtea_version}#" openjdk/jdk/make/common/shared/Defs.gmk ; \
+	sed -i "s#OpenJDK#OpenJDK (IcedTea $${icedtea_version})#" openjdk/jdk/make/common/shared/Defs.gmk ; \
 	sed -i "s#BUILD_VARIANT_RELEASE)#BUILD_VARIANT_RELEASE)$${proj_suffix}$${ver_suffix}#" \
 	  openjdk/jdk/make/common/shared/Defs.gmk; \
-	cp -r $(abs_top_srcdir)/overlays/openjdk/* openjdk/ \
-	  && touch stamps/overlay.stamp
+	cp -r $(abs_top_srcdir)/overlays/openjdk/* openjdk/
 	chmod -R ug+w openjdk 
+if ENABLE_NIO2
+	cp -r $(abs_top_srcdir)/overlays/nio2/openjdk/* openjdk/
+endif
+	touch stamps/overlay.stamp
 
 # OpenJDK ecj Source Preparation Targets
 # ======================================
 
 # Copy over OpenJDK sources for ecj.
-stamps/clone-ecj.stamp: stamps/patch.stamp
+stamps/clone-ecj.stamp: stamps/overlay.stamp
 	if ! test -d openjdk-ecj ; then \
 	    cp -pPRl openjdk openjdk-ecj ; \
 	fi
@@ -2193,7 +2110,7 @@
 	for target in $(abs_top_srcdir)/ports/hotspot/make/*/makefiles/* \
 		      $(abs_top_srcdir)/ports/hotspot/src/*cpu/* \
 		      $(abs_top_srcdir)/ports/hotspot/src/share/vm/*; do \
-	  link=$$(dirname $$target | sed 's/^.*ports/openjdk-ecj/'|sed "s#hotspot/build#hotspot/$(HOTSPOT_MAKE_DIR)#"); \
+	  link=$$(dirname $$target | sed 's/^.*ports/openjdk-ecj/'|sed "s#hotspot/build#hotspot/make#"); \
 	  ln -sfv $$target $$link; \
 	done
 	ln -sf $(abs_top_builddir)/platform_zero openjdk-ecj/hotspot/make/linux
@@ -2412,7 +2329,7 @@
 	stamps/hotspot-tools.stamp stamps/plugs.stamp \
 	stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \
 	$(ICEDTEAPLUGIN_TARGET) extra-lib/about.jar stamps/cacao.stamp \
-	stamps/visualvm.stamp stamps/pulse-java.stamp
+	stamps/pulse-java.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/ \
@@ -2433,26 +2350,6 @@
 	cp -pPRf pulse-java.jar \
 	  $(BUILD_OUTPUT_DIR)/j2re-image/lib/ext
 endif
-if WITH_VISUALVM
-	mkdir -p $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc ; \
-	mkdir -p $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/visualvm ; \
-	sed "s/APPNAME=\`basename.*\`/APPNAME=visualvm/" \
-	  visualvm/visualvm/launcher/visualvm >> \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/bin/jvisualvm ; \
-	chmod a+x $(BUILD_OUTPUT_DIR)/j2sdk-image/bin/jvisualvm ; \
-	cp visualvm/visualvm/launcher/visualvm.conf \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc ; \
-	echo visualvm >> \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc/visualvm.clusters ; \
-	echo profiler3 >> \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc/visualvm.clusters ; \
-	cp -r visualvm/visualvm/build/cluster/* \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/visualvm ; \
-	cp -r netbeans/nbbuild/netbeans/platform8 \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm ; \
-	cp -r netbeans/nbbuild/netbeans/profiler3 \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm
-endif
 	cp $(NETX_RESOURCE_DIR)/about.jnlp \
 	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)/j2re-image/lib
@@ -2488,26 +2385,6 @@
 	cp -pPRf pulse-java.jar \
 	  $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/ext
 endif
-if WITH_VISUALVM
-	mkdir -p $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc ; \
-	mkdir -p $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/visualvm ; \
-	sed "s/APPNAME=\`basename.*\`/APPNAME=visualvm/" \
-	  visualvm/visualvm/launcher/visualvm >> \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/bin/jvisualvm ; \
-	chmod a+x $(BUILD_OUTPUT_DIR)/j2sdk-image/bin/jvisualvm ; \
-	cp visualvm/visualvm/launcher/visualvm.conf \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc ; \
-	echo visualvm >> \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc/visualvm.clusters ; \
-	echo profiler3 >> \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/etc/visualvm.clusters ; \
-	cp -r visualvm/visualvm/build/cluster/* \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm/visualvm ; \
-	cp -r netbeans/nbbuild/netbeans/platform8 \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm ; \
-	cp -r netbeans/nbbuild/netbeans/profiler3 \
-	  $(BUILD_OUTPUT_DIR)/j2sdk-image/lib/visualvm
-endif
 	cp $(NETX_RESOURCE_DIR)/default.jnlp \
 	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib
@@ -2623,7 +2500,7 @@
 	javax/script
 endif
 
-stamps/copy-source-files.stamp: stamps/patch.stamp
+stamps/copy-source-files.stamp: stamps/overlay.stamp
 	for copy_dir in $(ICEDTEA_COPY_DIRS) ; \
 	do \
 	  mkdir -p rt/$$copy_dir ; \
@@ -2651,8 +2528,7 @@
         $(SHARE):$(SOLARIS):$(LANGTOOLS):$(JAXP):$(CORBA):$(JAXWS)
 
 # tools.jar class files.
-stamps/hotspot-tools-copy-source-files.stamp: stamps/patch.stamp \
-	stamps/overlay.stamp
+stamps/hotspot-tools-copy-source-files.stamp: stamps/overlay.stamp
 	for copy_dir in \
 	  `cat $(abs_top_srcdir)/tools-copy/tools-jdk-copy-files.txt` ; \
 	do \
@@ -3059,64 +2935,6 @@
 dist-openjdk-fsg: stamps/patch-fsg.stamp
 	$(ZIP) -r openjdk-fsg-$(OPENJDK_VERSION) openjdk/
 
-# VisualVM
-
-stamps/visualvm.stamp: $(BOOTSTRAP_DIRECTORY_STAMP) stamps/download.stamp \
-	stamps/extract.stamp stamps/nbplatform.stamp
-if WITH_VISUALVM
-	cd visualvm/visualvm ; \
-	ln -s $(abs_top_srcdir)/netbeans/nbbuild/netbeans . ; \
-	rm netbeans/profiler3 && mv netbeans/extra netbeans/profiler3 ; \
-	JAVA_HOME=$(ICEDTEA_HOME) $(ANT) build
-endif
-	mkdir -p stamps
-	touch $@
-
-clean-visualvm:
-	rm -rf visualvm
-	rm -f stamps/visualvm.stamp
-
-# Netbeans platform and profiler
-
-stamps/nbplatform.stamp: $(BOOTSTRAP_DIRECTORY_STAMP) stamps/extract.stamp \
-	stamps/download.stamp
-if WITH_VISUALVM
-	cd netbeans ; \
-	ln -s $(abs_top_srcdir)/netbeans/profiler.cvs/libs/jfluid/ lib.profiler ; \
-	ln -s $(abs_top_srcdir)/netbeans/profiler.cvs/libs/common/ lib.profiler.common ; \
-	ln -s $(abs_top_srcdir)/netbeans/profiler.cvs/libs/jfluid-ui/ lib.profiler.ui ; \
-	ln -s $(abs_top_srcdir)/netbeans/profiler.cvs/modules/nbmodule/ profiler.nbmodule ; \
-	mkdir -p ./nbbuild/netbeans/ ; \
-	ln -s $(SYSTEM_NETBEANS_DIR)/platform8/ ./nbbuild/netbeans/platform8 ; \
-	ln -s $(SYSTEM_NETBEANS_DIR)/apisupport1/ ./nbbuild/netbeans/apisupport1 ; \
-	ln -s $(SYSTEM_NETBEANS_DIR)/harness/ ./nbbuild/netbeans/harness ; \
-	ln -s $(SYSTEM_NETBEANS_DIR)/java2/ ./nbbuild/netbeans/java2 ; \
-	ln -s $(SYSTEM_NETBEANS_DIR)/ide9/ ./nbbuild/netbeans/ide9 ; \
-	cd profiler.cvs/libs/jfluid/native/build ; \
-	if ! ($(ARCH_PREFIX) uname -a | grep x86_64) ; then \
-	  buildscript=./buildnative-linux-15.sh ; \
-	else \
-	  buildscript=./buildnative-linux64-15.sh ; \
-	fi ; \
-	JAVA_HOME_15=$(ICEDTEA_HOME) JAVA_HOME_16=$(ICEDTEA_HOME) \
-	  $$buildscript ; \
-	cd ../../../../.. ; \
-	ln -s $(abs_top_srcdir)/netbeans/nbbuild/netbeans/extra nbbuild/netbeans/profiler3 ; \
-	ln -s $(abs_top_srcdir)/netbeans/profiler.cvs/modules/main/ profiler ; \
-	for dir in jfluid jfluid-ui common ; do \
-	  JAVA_HOME=$(ICEDTEA_HOME) $(ANT) -Dpermit.jdk6.builds=true \
-	    -f profiler.cvs/libs/$$dir/build.xml ; \
-	done ; \
-	JAVA_HOME=$(ICEDTEA_HOME) $(ANT) -Dpermit.jdk6.builds=true \
-	  -f profiler.cvs/modules/main/build.xml ;
-endif
-	mkdir -p stamps
-	touch $@
-
-clean-nbplatform:
-	rm -rf netbeans
-	rm -f stamps/nbplatform.stamp
-
 # Target Aliases
 # ===============
 
@@ -3130,10 +2948,6 @@
 
 cacao: stamps/cacao.stamp
 
-visualvm: stamps/visualvm.stamp
-
-nbplatform: stamps/nbplatform.stamp
-
 clone-ecj: stamps/clone-ecj.stamp
 
 copy-source-files: stamps/copy-source-files.stamp
--- a/NEWS	Tue Feb 10 21:09:31 2009 +0000
+++ b/NEWS	Tue Feb 10 21:56:55 2009 +0000
@@ -1,5 +1,52 @@
 New in release 1.9 (XXXX-XX-XX)
 
+- Security fixes for:
+  CVE-2008-5360 - Temporary files have guessable file names.
+  CVE-2008-5350 - Allows to list files within the user home directory.
+  CVE-2008-5348 - Denial-Of-Service in kerberos authentication.
+  CVE-2008-5359 - Buffer overflow in image processing.
+  CVE-2008-5351 - UTF-8 decoder accepts non-shortest form sequences.
+  CVE-2008-5356 - Font processing vulnerability.
+  CVE-2008-5353 - Calendar object deserialization allows privilege escalation.
+  CVE-2008-5354 - Privilege escalation in command line applications.
+  CVE-2008-5357 - Truetype Font processing vulnerability.
+  CVE-2008-5352 - Jar200 Decompression buffer overflow.
+  CVE-2008-5358 - Buffer Overflow in GIF image processing.
+- Updated to OpenJDK b14 build.
+- Upgraded to new OpenJDK7 Hotspot 14. The old OpenJDK6 Hotspot 11 can
+  still be configured --with-hotspot-build=original but future versions
+  will drop support for the old version and only support HS14. Zero
+  and Shark have been forward ported to HS14 (from HS12).
+- XRender pipeline support: Java2D are noticably faster and running over a 
+  remote X connection feels like it is all local. Build by default
+  (disable with --disable-xrender). Runtime enabled by running java
+  -Dsun.java2d.xrender=True (default is to use the old X renderer for now).
+- IcedTeaPlugin now supports HTTPS sites and adds a user prompt for
+  untrusted https certificates.
+- Use the ALSA 'default' device. Makes Java play nicer with PulseAudio.
+- VisualVM integration has been removed.
+- Gervill soft synthesizer integration updated to latest CVS version.
+- Integrated jtreg upgraded to 4_0-src-b02-15_oct_2008.
+- make check runs much faster now. jtreg -samevm support has been
+  integrated into the langtools and jdk subsystems. Please package the
+  test/jtreg-summary.log file with your distribution package so end users
+  can compare the test results.
+- Shark (--enable-shark) now builds on 64 bit platforms, but is a
+  pre-alpha technology preview and not recommended for use.
+- Better support for bootstrapping with different jar programs
+  (supporting -J options).
+- If --with-pkgversion isn't given the short mercurial rev node version
+  will be used.  Package distributors are encouraged to build packages with
+  --with-pkgversion to uniquely identify their distribution version number
+  when java -version is run to help distribution specific bug reporting.
+- Various freetype font, pisces renderer and awt X window size fixes
+  to fix visual anomalies.
+- Build fixes for gcc 4.3 and 4.4-pre-release.
+- Added support for building against a specific openjdk src dir
+  or hg revision (--with-openjdk-src-dir or --with-hg-revision).
+- Many other Plugin, Zero, Shark and PulseAudio bug fixes.
+- Build clean up.
+
 New in release 1.8 (2008-11-20)
 
   IcedTea is based on the hard work of a lot of people that contributed to
--- a/README	Tue Feb 10 21:09:31 2009 +0000
+++ b/README	Tue Feb 10 21:56:55 2009 +0000
@@ -163,20 +163,6 @@
 The environment variable CACAO_CONFIGURE_ARGS can be used to pass
 additional arguments to the cacao configure.
 
-VisualVM
-========
-
-Passing --enable-visualvm to configure will build the VisualVM profiling
-and troubleshooting tool. NetBeans profiler3 (visualvm_preview2) is 
-built from source before building VisualVM. NetBeans 6.1 must be installed 
-on the system. A binary launcher jvisualvm is placed in the
-openjdk/control/build/arch/j2sdk-image/bin directory after the jdk is built.
-Other useful VisualVM configure options include --with-visualvm-src-zip,
-and --with-netbeans-profiler-src-zip which can be used to prevent 
-re-downloading of the source zips. --with-netbeans-home can be used to specify
-where the Netbeans tools are installed (default /usr/share/netbeans).
-
-
 
 PulseAudio Mixer
 ================
--- a/acinclude.m4	Tue Feb 10 21:09:31 2009 +0000
+++ b/acinclude.m4	Tue Feb 10 21:56:55 2009 +0000
@@ -446,57 +446,6 @@
   AC_SUBST(ALT_OPENJDK_SRC_ZIP)
 ])
 
-AC_DEFUN([WITH_VISUALVM_SRC_ZIP],
-[
-  AC_MSG_CHECKING(for a VisualVM source zip)
-  AC_ARG_WITH([visualvm-src-zip],
-              [AS_HELP_STRING(--with-visualvm-src-zip, specify the location of the visualvm source zip)],
-  [
-    ALT_VISUALVM_SRC_ZIP=${withval}
-    AM_CONDITIONAL(USE_ALT_VISUALVM_SRC_ZIP, test x = x)
-  ],
-  [ 
-    ALT_VISUALVM_SRC_ZIP="not specified"
-    AM_CONDITIONAL(USE_ALT_VISUALVM_SRC_ZIP, test x != x)
-  ])
-  AC_MSG_RESULT(${ALT_VISUALVM_SRC_ZIP})
-  AC_SUBST(ALT_VISUALVM_SRC_ZIP)
-])
-
-AC_DEFUN([WITH_NETBEANS_PROFILER_SRC_ZIP],
-[
-  AC_MSG_CHECKING(for a NetBeans profiler source zip)
-  AC_ARG_WITH([netbeans-profiler-src-zip],
-              [AS_HELP_STRING(--with-netbeans-profiler-src-zip, specify the location of the netbeans profiler source zip)],
-  [
-    ALT_NETBEANS_PROFILER_SRC_ZIP=${withval}
-    AM_CONDITIONAL(USE_ALT_NETBEANS_PROFILER_SRC_ZIP, test x = x)
-  ],
-  [ 
-    ALT_NETBEANS_PROFILER_SRC_ZIP="not specified"
-    AM_CONDITIONAL(USE_ALT_NETBEANS_PROFILER_SRC_ZIP, test x != x)
-  ])
-  AC_MSG_RESULT(${ALT_NETBEANS_PROFILER_SRC_ZIP})
-  AC_SUBST(ALT_NETBEANS_PROFILER_SRC_ZIP)
-])
-
-AC_DEFUN([WITH_NETBEANS_BASIC_CLUSTER_SRC_ZIP],
-[
-  AC_MSG_CHECKING(for a NetBeans basic cluster source zip)
-  AC_ARG_WITH([netbeans-basic-cluster-src-zip],
-              [AS_HELP_STRING(--with-netbeans-basic-cluster-src-zip, specify the location of the netbeans basic cluster source zip)],
-  [
-    ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP=${withval}
-    AM_CONDITIONAL(USE_ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP, test x = x)
-  ],
-  [ 
-    ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP="not specified"
-    AM_CONDITIONAL(USE_ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP, test x != x)
-  ])
-  AC_MSG_RESULT(${ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP})
-  AC_SUBST(ALT_NETBEANS_BASIC_CLUSTER_SRC_ZIP)
-])
-
 AC_DEFUN([WITH_ALT_JAR_BINARY],
 [
   AC_MSG_CHECKING(for an alternate jar command)
@@ -609,31 +558,6 @@
   AC_SUBST(XERCES2_JAR)
 ])
 
-AC_DEFUN([FIND_NETBEANS],
-[
-  AC_ARG_WITH([netbeans],
-              [AS_HELP_STRING(--with-netbeans,specify location of netbeans)],
-  [
-    if test -f "${withval}"; then
-      AC_MSG_CHECKING(netbeans)
-      NETBEANS="${withval}"
-      AC_MSG_RESULT(${withval})
-    else
-      AC_PATH_PROG(NETBEANS, "${withval}")
-    fi
-  ],
-  [
-    NETBEANS=
-  ])
-  if test -z "${NETBEANS}"; then
-    AC_PATH_PROG(NETBEANS, "netbeans")
-  fi
-  if test -z "${NETBEANS}"; then
-    AC_MSG_ERROR("NetBeans was not found.")
-  fi
-  AC_SUBST(NETBEANS)
-])
-
 AC_DEFUN([FIND_RHINO_JAR],
 [
   AC_MSG_CHECKING(whether to include Javascript support via Rhino)
@@ -1109,7 +1033,10 @@
               ])
   if test -z "${SYSTEM_GCJ_DIR}"; then
     for dir in /usr/lib/jvm/java-gcj /usr/lib/jvm/gcj-jdk /usr/lib/jvm/cacao ; do
-       test -d $dir && SYSTEM_GCJ_DIR=$dir
+       if test -d $dir; then
+         SYSTEM_GCJ_DIR=$dir
+	 break
+       fi
     done
   fi
   AC_MSG_RESULT(${SYSTEM_GCJ_DIR})
@@ -1142,7 +1069,10 @@
               ])
   if test -z "${SYSTEM_OPENJDK_DIR}"; then
     for dir in /usr/lib/jvm/java-openjdk /usr/lib/jvm/openjdk ; do
-       test -d $dir && SYSTEM_OPENJDK_DIR=$dir
+       if test -d $dir; then
+         SYSTEM_OPENJDK_DIR=$dir
+	 break
+       fi
     done
   fi
   AC_MSG_RESULT(${SYSTEM_OPENJDK_DIR})
@@ -1175,7 +1105,10 @@
               ])
   if test -z "${SYSTEM_ICEDTEA_DIR}"; then
     for dir in /usr/lib/jvm/java-icedtea /usr/lib/jvm/icedtea6 /usr/lib/jvm/java-6-openjdk ; do
-       test -d $dir && SYSTEM_ICEDTEA_DIR=$dir
+       if test -d $dir; then
+         SYSTEM_ICEDTEA_DIR=$dir
+	 break
+       fi
     done
   fi
   AC_MSG_RESULT(${SYSTEM_ICEDTEA_DIR})
--- a/configure.ac	Tue Feb 10 21:09:31 2009 +0000
+++ b/configure.ac	Tue Feb 10 21:56:55 2009 +0000
@@ -73,24 +73,6 @@
 AM_CONDITIONAL(WITH_OPENJDK, test "${with_openjdk}" = true)
 AC_MSG_RESULT(${with_openjdk})
 
-AC_MSG_CHECKING([for a NetBeans installation])
-AC_ARG_WITH([netbeans-home],
-	    [AS_HELP_STRING([--with-netbeans-home],
-                            [NetBeans home directory (default is /usr/share/netbeans)])],
-            [
-              if test "x${withval}" = x
-              then
-                SYSTEM_NETBEANS_DIR=/usr/share/netbeans
-              else
-                SYSTEM_NETBEANS_DIR=${withval}
-              fi
-            ],
-            [
-              SYSTEM_NETBEANS_DIR=/usr/share/netbeans
-            ])
-AC_MSG_RESULT([${SYSTEM_NETBEANS_DIR}])
-AC_SUBST(SYSTEM_NETBEANS_DIR)
-
 AC_MSG_CHECKING(for Ant home directory)
 AC_ARG_WITH([ant-home],
             [AS_HELP_STRING([--with-ant-home],
@@ -141,18 +123,13 @@
 AM_CONDITIONAL([ENABLE_XRENDER], [test x$ENABLE_XRENDER = xyes])
 AC_MSG_RESULT(${ENABLE_XRENDER})
 
-AC_MSG_CHECKING([whether to build VisualVM])
-AC_ARG_ENABLE([visualvm],
-              [AS_HELP_STRING([--enable-visualvm],
-			                  [Enable compilation of visualvm.])],
-              [enable_visualvm="${enableval}"], [enable_visualvm="no"])
-AM_CONDITIONAL(WITH_VISUALVM, test "x${enable_visualvm}" = "xyes")
-AC_MSG_RESULT(${enable_visualvm})
-
-if test "x${enable_visualvm}" = "xyes"
-then
-  FIND_NETBEANS
-fi
+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([how many parallel build jobs to execute])
 AC_ARG_WITH([parallel-jobs],
@@ -244,9 +221,6 @@
 WITH_OPENJDK_SRC_ZIP
 WITH_HOTSPOT_SRC_ZIP
 WITH_OPENJDK_SRC_DIR
-WITH_VISUALVM_SRC_ZIP
-WITH_NETBEANS_PROFILER_SRC_ZIP
-WITH_NETBEANS_BASIC_CLUSTER_SRC_ZIP
 WITH_ALT_JAR_BINARY
 AC_CHECK_ENABLE_CACAO
 AC_CHECK_WITH_CACAO_HOME
--- a/generated/sun/nio/ch/SocketOptionRegistry.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/generated/sun/nio/ch/SocketOptionRegistry.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,5 +1,9 @@
 /*
+<<<<<<< local
  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+=======
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+>>>>>>> other
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -26,18 +30,21 @@
  */
 // AUTOMATICALLY GENERATED FILE - DO NOT EDIT                                  
 package sun.nio.ch;                                                            
+
 import java.net.SocketOption;                                                  
 import java.net.StandardSocketOption;                                          
 import java.net.ProtocolFamily;                                                
 import java.net.StandardProtocolFamily;                                        
+
 import java.util.Map;                                                          
 import java.util.HashMap;                                                      
+
 class SocketOptionRegistry {                                                   
     private SocketOptionRegistry() { }                                         
     private static class RegistryKey {                                         
-        private final SocketOption name;                                       
+        private final SocketOption<?> name;                                    
         private final ProtocolFamily family;                                   
-        RegistryKey(SocketOption name, ProtocolFamily family) {                
+        RegistryKey(SocketOption<?> name, ProtocolFamily family) {                
             this.name = name;                                                  
             this.family = family;                                              
         }                                                                      
@@ -76,7 +83,7 @@
             return map;                                                        
         }                                                                      
     }                                                                          
-    public static OptionKey findOption(SocketOption name, ProtocolFamily family) { 
+    public static OptionKey findOption(SocketOption<?> name, ProtocolFamily family) { 
         RegistryKey key = new RegistryKey(name, family);                       
         return LazyInitialization.options.get(key);                            
     }                                                                          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/make/mkdemo/nio/Makefile	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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 org.classpath.icedtea.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	Tue Feb 10 21:56:55 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 org.classpath.icedtea.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	Tue Feb 10 21:56:55 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 org.classpath.icedtea.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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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/net/ProtocolFamily.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,40 @@
+/*
+ * 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.net;
+
+/**
+ * Represents a family of communication protocols.
+ *
+ * @since 1.7
+ */
+
+public interface ProtocolFamily {
+    /**
+     * Returns the name of the protocol family.
+     */
+    String name();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/SocketOption.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,56 @@
+/*
+ * 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.net;
+
+/**
+ * A socket option associated with a socket.
+ *
+ * <p> In the {@link java.nio.channels channels} package, the {@link
+ * java.nio.channels.NetworkChannel} interface defines the {@link
+ * java.nio.channels.NetworkChannel#setOption(SocketOption,Object) setOption}
+ * and {@link java.nio.channels.NetworkChannel#getOption(SocketOption) getOption}
+ * methods to set and query the channel's socket options.
+ *
+ * @param   <T>     The type of the socket option value.
+ *
+ * @since 1.7
+ *
+ * @see StandardSocketOption
+ */
+
+public interface SocketOption<T> {
+
+    /**
+     * Returns the name of the socket option.
+     */
+    String name();
+
+    /**
+     * Returns the type of the socket option value.
+     */
+    Class<T> type();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardProtocolFamily.java	Tue Feb 10 21:56:55 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.net;
+
+/**
+ * Defines the standard families of communication protocols.
+ *
+ * @since 1.7
+ */
+
+public enum StandardProtocolFamily implements ProtocolFamily {
+
+    /**
+     * Internet Protocol Version 4 (IPv4)
+     */
+    INET,
+
+    /**
+     * Internet Protocol Version 6 (IPv6)
+     */
+    INET6
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/net/StandardSocketOption.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,370 @@
+/*
+ * 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.net;
+
+import java.net.NetworkInterface;
+
+/**
+ * Defines the <em>standard</em> socket options.
+ *
+ * <p> The {@link SocketOption#name name} of each socket option defined by this
+ * class is its field name.
+ *
+ * <p> In this release, the socket options defined here are used by {@link
+ * java.nio.channels.NetworkChannel network} channels in the {@link
+ * java.nio.channels channels} package.
+ *
+ * @since 1.7
+ */
+
+public final class StandardSocketOption {
+    private StandardSocketOption() { }
+
+    // -- SOL_SOCKET --
+
+    /**
+     * Allow transmission of broadcast datagrams.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. The option is specific to
+     * datagram-oriented sockets sending to {@link java.net.Inet4Address IPv4}
+     * broadcast addresses. When the socket option is enabled then the socket
+     * can be used to send <em>broadcast datagrams</em>.
+     *
+     * <p> The initial value of this socket option is {@code FALSE}. The socket
+     * option may be enabled or disabled at any time. Some operating systems may
+     * require that the Java virtual machine be started with implementation
+     * specific privileges to enable this option or send broadcast datagrams.
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc919.txt">RFC&nbsp;929:
+     * Broadcasting Internet Datagrams</a>
+     * @see DatagramSocket#setBroadcast
+     */
+    public static final SocketOption<Boolean> SO_BROADCAST =
+        new StdSocketOption<Boolean>("SO_BROADCAST", Boolean.class);
+
+    /**
+     * Keep connection alive.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. When the {@code SO_KEEPALIVE}
+     * option is enabled the operating system may use a <em>keep-alive</em>
+     * mechanism to periodically probe the other end of a connection when the
+     * connection is otherwise idle. The exact semantics of the keep alive
+     * mechanism is system dependent and therefore unspecified.
+     *
+     * <p> The initial value of this socket option is {@code FALSE}. The socket
+     * option may be enabled or disabled at any time.
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC&nbsp;1122
+     * Requirements for Internet Hosts -- Communication Layers</a>
+     * @see Socket#setKeepAlive
+     */
+    public static final SocketOption<Boolean> SO_KEEPALIVE =
+        new StdSocketOption<Boolean>("SO_KEEPALIVE", Boolean.class);
+
+    /**
+     * The size of the socket send buffer.
+     *
+     * <p> The value of this socket option is an {@code Integer} that is the
+     * size of the socket send buffer in bytes. The socket send buffer is an
+     * output buffer used by the networking implementation. It may need to be
+     * increased for high-volume connections. The value of the socket option is
+     * a <em>hint</em> to the implementation to size the buffer and the actual
+     * size may differ. The socket option can be queried to retrieve the actual
+     * size.
+     *
+     * <p> For datagram-oriented sockets, the size of the send buffer may limit
+     * the size of the datagrams that may be sent by the socket. Whether
+     * datagrams larger than the buffer size are sent or discarded is system
+     * dependent.
+     *
+     * <p> The initial/default size of the socket send buffer and the range of
+     * allowable values is system dependent although a negative size is not
+     * allowed. An attempt to set the socket send buffer to larger than its
+     * maximum size causes it to be set to its maximum size.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Whether an implementation allows the
+     * socket send buffer to be changed after the socket is bound is system
+     * dependent.
+     *
+     * @see Socket#setSendBufferSize
+     */
+    public static final SocketOption<Integer> SO_SNDBUF =
+        new StdSocketOption<Integer>("SO_SNDBUF", Integer.class);
+
+
+    /**
+     * The size of the socket receive buffer.
+     *
+     * <p> The value of this socket option is an {@code Integer} that is the
+     * size of the socket receive buffer in bytes. The socket receive buffer is
+     * an input buffer used by the networking implementation. It may need to be
+     * increased for high-volume connections or decreased to limit the possible
+     * backlog of incoming data. The value of the socket option is a
+     * <em>hint</em> to the implementation to size the buffer and the actual
+     * size may differ.
+     *
+     * <p> For datagram-oriented sockets, the size of the receive buffer may
+     * limit the size of the datagrams that can be received. Whether datagrams
+     * larger than the buffer size can be received is system dependent.
+     * Increasing the socket receive buffer may be important for cases where
+     * datagrams arrive in bursts faster than they can be processed.
+     *
+     * <p> In the case of stream-oriented sockets and the TCP/IP protocol, the
+     * size of the socket receive buffer may be used when advertising the size
+     * of the TCP receive window to the remote peer.
+     *
+     * <p> The initial/default size of the socket receive buffer and the range
+     * of allowable values is system dependent although a negative size is not
+     * allowed. An attempt to set the socket receive buffer to larger than its
+     * maximum size causes it to be set to its maximum size.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Whether an implementation allows the
+     * socket receive buffer to be changed after the socket is bound is system
+     * dependent.
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc1323.txt">RFC&nbsp;1323: TCP
+     * Extensions for High Performance</a>
+     * @see Socket#setReceiveBufferSize
+     * @see ServerSocket#setReceiveBufferSize
+     */
+    public static final SocketOption<Integer> SO_RCVBUF =
+        new StdSocketOption<Integer>("SO_RCVBUF", Integer.class);
+
+    /**
+     * Re-use address.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. The exact semantics of this
+     * socket option are socket type and system dependent.
+     *
+     * <p> In the case of stream-oriented sockets, this socket option will
+     * usually determine whether the socket can be bound to a socket address
+     * when a previous connection involving that socket address is in the
+     * <em>TIME_WAIT</em> state. On implementations where the semantics differ,
+     * and the socket option is not required to be enabled in order to bind the
+     * socket when a previous connection is in this state, then the
+     * implementation may choose to ignore this option.
+     *
+     * <p> For datagram-oriented sockets the socket option is used to allow
+     * multiple programs bind to the same address. This option should be enabled
+     * when the socket is to be used for Internet Protocol (IP) multicasting.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Changing the value of this socket option
+     * after the socket is bound has no effect. The default value of this
+     * socket option is system dependent.
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc793.txt">RFC&nbsp;793: Transmission
+     * Control Protocol</a>
+     * @see ServerSocket#setReuseAddress
+     */
+    public static final SocketOption<Boolean> SO_REUSEADDR =
+        new StdSocketOption<Boolean>("SO_REUSEADDR", Boolean.class);
+
+    /**
+     * Linger on close if data is present.
+     *
+     * <p> The value of this socket option is an {@code Integer} that controls
+     * the action taken when unsent data is queued on the socket and a method
+     * to close the socket is invoked. If the value of the socket option is zero
+     * or greater, then it represents a timeout value, in seconds, known as the
+     * <em>linger interval</em>. The linger interval is the timeout for the
+     * {@code close} method to block while the operating system attempts to
+     * transmit the unsent data or it decides that it is unable to transmit the
+     * data. If the value of the socket option is less than zero then the option
+     * is disabled. In that case the {@code close} method does not wait until
+     * unsent data is transmitted; if possible the operating system will transmit
+     * any unsent data before the connection is closed.
+     *
+     * <p> This socket option is intended for use with sockets that are configured
+     * in {@link java.nio.channels.SelectableChannel#isBlocking() blocking} mode
+     * only. The behavior of the {@code close} method when this option is
+     * enabled on a non-blocking socket is not defined.
+     *
+     * <p> The initial value of this socket option is a negative value, meaning
+     * that the option is disabled. The option may be enabled, or the linger
+     * interval changed, at any time. The maximum value of the linger interval
+     * is system dependent. Setting the linger interval to a value that is
+     * greater than its maximum value causes the linger interval to be set to
+     * its maximum value.
+     *
+     * @see Socket#setSoLinger
+     */
+    public static final SocketOption<Integer> SO_LINGER =
+        new StdSocketOption<Integer>("SO_LINGER", Integer.class);
+
+
+    // -- IPPROTO_IP --
+
+    /**
+     * The Type of Service (ToS) octet in the Internet Protocol (IP) header.
+     *
+     * <p> The value of this socket option is an {@code Integer} representing
+     * the value of the ToS octet in IP packets sent by sockets to an {@link
+     * StandardProtocolFamily#INET IPv4} socket. The interpretation of the ToS
+     * octet is network specific and is not defined by this class. Further
+     * information on the ToS octet can be found in <a
+     * href="http://www.ietf.org/rfc/rfc1349.txt">RFC&nbsp;1349</a> and <a
+     * href="http://www.ietf.org/rfc/rfc2474.txt">RFC&nbsp;2474</a>. The value
+     * of the socket option is a <em>hint</em>. An implementation may ignore the
+     * value, or ignore specific values.
+     *
+     * <p> The initial/default value of the TOS field in the ToS octet is
+     * implementation specific but will typically be {@code 0}. For
+     * datagram-oriented sockets the option may be configured at any time after
+     * the socket has been bound. The new value of the octet is used when sending
+     * subsequent datagrams. It is system dependent whether this option can be
+     * queried or changed prior to binding the socket.
+     *
+     * <p> The behavior of this socket option on a stream-oriented socket, or an
+     * {@link StandardProtocolFamily#INET6 IPv6} socket, is not defined in this
+     * release.
+     *
+     * @see DatagramSocket#setTrafficClass
+     */
+    public static final SocketOption<Integer> IP_TOS =
+        new StdSocketOption<Integer>("IP_TOS", Integer.class);
+
+    /**
+     * The network interface for Internet Protocol (IP) multicast datagrams.
+     *
+     * <p> The value of this socket option is a {@link NetworkInterface} that
+     * represents the outgoing interface for multicast datagrams sent by the
+     * datagram-oriented socket. For {@link StandardProtocolFamily#INET6 IPv6}
+     * sockets then it is system dependent whether setting this option also
+     * sets the outgoing interface for multlicast datagrams sent to IPv4
+     * addresses.
+     *
+     * <p> The initial/default value of this socket option may be {@code null}
+     * to indicate that outgoing interface will be selected by the operating
+     * system, typically based on the network routing tables. An implementation
+     * allows this socket option to be set after the socket is bound. Whether
+     * the socket option can be queried or changed prior to binding the socket
+     * is system dependent.
+     *
+     * @see java.nio.channels.MulticastChannel
+     * @see MulticastSocket#setInterface
+     */
+    public static final SocketOption<NetworkInterface> IP_MULTICAST_IF =
+        new StdSocketOption<NetworkInterface>("IP_MULTICAST_IF", NetworkInterface.class);
+
+    /**
+     * The <em>time-to-live</em> for Internet Protocol (IP) multicast datagrams.
+     *
+     * <p> The value of this socket option is an {@code Integer} in the range
+     * <tt>0&nbsp;<=&nbsp;value&nbsp;<=&nbsp;255</tt>. It is used to control
+     * the scope of multicast datagrams sent by the datagram-oriented socket.
+     * In the case of an {@link StandardProtocolFamily#INET IPv4} socket
+     * the option is the time-to-live (TTL) on multicast datagrams sent by the
+     * socket. Datagrams with a TTL of zero are not transmitted on the network
+     * but may be delivered locally. In the case of an {@link
+     * StandardProtocolFamily#INET6 IPv6} socket the option is the
+     * <em>hop limit</em> which is number of <em>hops</em> that the datagram can
+     * pass through before expiring on the network. For IPv6 sockets it is
+     * system dependent whether the option also sets the <em>time-to-live</em>
+     * on multicast datagrams sent to IPv4 addresses.
+     *
+     * <p> The initial/default value of the time-to-live setting is typically
+     * {@code 1}. An implementation allows this socket option to be set after
+     * the socket is bound. Whether the socket option can be queried or changed
+     * prior to binding the socket is system dependent.
+     *
+     * @see java.nio.channels.MulticastChannel
+     * @see MulticastSocket#setTimeToLive
+     */
+    public static final SocketOption<Integer> IP_MULTICAST_TTL =
+        new StdSocketOption<Integer>("IP_MULTICAST_TTL", Integer.class);
+
+    /**
+     * Loopback for Internet Protocol (IP) multicast datagrams.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that controls
+     * the <em>loopback</em> of multicast datagrams. The value of the socket
+     * option represents if the option is enabled or disabled.
+     *
+     * <p> The exact semantics of this socket options are system dependent.
+     * In particular, it is system dependent whether the loopback applies to
+     * multicast datagrams sent from the socket or received by the socket.
+     * For {@link StandardProtocolFamily#INET6 IPv6} sockets then it is
+     * system dependent whether the option also applies to multicast datagrams
+     * sent to IPv4 addresses.
+     *
+     * <p> The initial/default value of this socket option is {@code TRUE}. An
+     * implementation allows this socket option to be set after the socket is
+     * bound. Whether the socket option can be queried or changed prior to
+     * binding the socket is system dependent.
+     *
+     * @see java.nio.channels.MulticastChannel
+     *  @see MulticastSocket#setLoopbackMode
+     */
+    public static final SocketOption<Boolean> IP_MULTICAST_LOOP =
+        new StdSocketOption<Boolean>("IP_MULTICAST_LOOP", Boolean.class);
+
+
+    // -- IPPROTO_TCP --
+
+    /**
+     * Disable the Nagle algorithm.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. The socket option is specific to
+     * stream-oriented sockets using the TCP/IP protocol. TCP/IP uses an algorithm
+     * known as <em>The Nagle Algorithm</em> to coalesce short segments and
+     * improve network efficiency.
+     *
+     * <p> The default value of this socket option is {@code FALSE}. The
+     * socket option should only be enabled in cases where it is known that the
+     * coalescing impacts performance. The socket option may be enabled at any
+     * time. In other words, the Nagle Algorithm can be disabled. Once the option
+     * is enabled, it is system dependent whether it can be subsequently
+     * disabled. If it cannot, then invoking the {@code setOption} method to
+     * disable the option has no effect.
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC&nbsp;1122:
+     * Requirements for Internet Hosts -- Communication Layers</a>
+     * @see Socket#setTcpNoDelay
+     */
+    public static final SocketOption<Boolean> TCP_NODELAY =
+        new StdSocketOption<Boolean>("TCP_NODELAY", Boolean.class);
+
+
+    private static class StdSocketOption<T> implements SocketOption<T> {
+        private final String name;
+        private final Class<T> type;
+        StdSocketOption(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/channels/AsynchronousByteChannel.java	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,317 @@
+/*
+ * 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.util.concurrent.*;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,707 @@
+/*
+ * 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.util.concurrent.TimeUnit;
+import java.util.concurrent.Future;
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+import org.classpath.icedtea.java.net.SocketOption;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,777 @@
+/*
+ * 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.io.IOException;
+import java.util.concurrent.Future;
+import java.util.concurrent.ExecutorService;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,305 @@
+/*
+ * 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.net.SocketAddress;
+import java.util.concurrent.Future;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.net.SocketOption;
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,672 @@
+/*
+ * 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.util.concurrent.TimeUnit;
+import java.util.concurrent.Future;
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+import org.classpath.icedtea.java.net.SocketOption;
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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/DatagramChannel.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,223 @@
+/*
+ * 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.IOException;
+import java.net.DatagramSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+import org.classpath.icedtea.java.net.SocketOption;
+
+import org.classpath.icedtea.java.nio.channels.spi.SelectorProvider;
+
+/**
+ * A selectable channel for datagram-oriented sockets.
+ *
+ * <p> {@note revised} A datagram channel is created by invoking one of the {@link #open open} methods
+ * of this class. It is not possible to create a channel for an arbitrary,
+ * pre-existing datagram socket. A newly-created datagram channel is open but not
+ * connected. A datagram channel 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 are otherwise performed as part of
+ * every send and receive operation.  A datagram channel must be connected in
+ * order to use the {@link #read(java.nio.ByteBuffer) read} and {@link
+ * #write(java.nio.ByteBuffer) write} methods, since those methods do not
+ * accept or return socket addresses.
+ *
+ * <p> Once connected, a datagram channel remains connected until it is
+ * disconnected or closed.  Whether or not a datagram channel is connected may
+ * be determined by invoking its {@link #isConnected isConnected} method.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. A datagram channel to an Internet Protocol 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> Datagram channels are safe for use by multiple concurrent threads.  They
+ * support concurrent reading and writing, though at most one thread may be
+ * reading and at most one thread may be writing at any given time.  </p>
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ * @updated 1.7
+ */
+
+public abstract class DatagramChannel
+    extends java.nio.channels.DatagramChannel
+    implements MulticastChannel
+{
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected DatagramChannel(SelectorProvider provider) {
+        super(provider);
+    }
+
+    /**
+     * Opens a datagram channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * java.nio.channels.spi.SelectorProvider#openDatagramChannel()
+     * openDatagramChannel} method of the system-wide default {@link
+     * java.nio.channels.spi.SelectorProvider} object.  The channel will not be
+     * connected.  </p>
+     *
+     * @return  A new datagram channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static DatagramChannel open() throws IOException {
+        return SelectorProvider.provider().openDatagramChannel();
+    }
+
+    /**
+     * Opens a datagram channel.
+     *
+     * <p> The {@code family} parameter is used to specify the {@link
+     * ProtocolFamily}. If the datagram channel is to be used for IP multicasing
+     * then this should correspond to the address type of the multicast groups
+     * that this channel will join.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * java.nio.channels.spi.SelectorProvider#openDatagramChannel(ProtocolFamily)
+     * openDatagramChannel} method of the system-wide default {@link
+     * java.nio.channels.spi.SelectorProvider} object.  The channel will not be
+     * connected.
+     *
+     * @param   family
+     *          The protocol family
+     *
+     * @return  A new 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 StandardProtocolFamily.INET6}
+     *          but IPv6 is not enabled on the platform.
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @since   1.7
+     */
+    public static DatagramChannel open(ProtocolFamily family) throws IOException {
+        return SelectorProvider.provider().openDatagramChannel(family);
+    }
+
+
+    // -- 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
+     *
+     * @since 1.7
+     */
+    public abstract DatagramChannel bind(SocketAddress local)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     *
+     * @since 1.7
+     */
+    public abstract <T> DatagramChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * {@note new}
+     * Returns the remote address to which this channel's socket is connected.
+     *
+     * @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
+     *
+     * @since 1.7
+     */
+    public abstract SocketAddress getRemoteAddress() 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/FileChannel.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,404 @@
+/*
+ * 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.GatheringByteChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * 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 java.nio.channels.FileChannel
+    implements SeekableByteChannel
+{
+    /**
+     * 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);
+    }
+
+    /**
+     * 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 positionSBC(long newPosition) 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 truncateSBC(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/FileLock.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,321 @@
+/*
+ * 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;
+
+import java.nio.channels.Channel;
+
+/**
+ * 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/MembershipKey.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,183 @@
+/*
+ * 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.net.InetAddress;
+import java.net.NetworkInterface;
+import java.io.IOException;
+
+/**
+ * A token representing the membership of an Internet Protocol (IP) multicast
+ * group.
+ *
+ * <p> A membership key may represent a membership to receive all datagrams sent
+ * to the group, or it may be <em>source-specific</em>, meaning that it
+ * represents a membership that receives only datagrams from a specific source
+ * address. Whether or not a membership key is source-specific may be determined
+ * by invoking its {@link #sourceAddress() sourceAddress} method.
+ *
+ * <p> A membership key is valid upon creation and remains valid until the
+ * membership is dropped by invoking the {@link #drop() drop} method, or
+ * the channel is closed. The validity of the membership key may be tested
+ * by invoking its {@link #isValid() isValid} method.
+ *
+ * <p> Where a membership key is not source-specific and the underlying operation
+ * system supports source filtering, then the {@link #block block} and {@link
+ * #unblock unblock} methods can be used to block or unblock multicast datagrams
+ * from particular source addresses.
+ *
+ * @see MulticastChannel
+ *
+ * @since 1.7
+ */
+public abstract class MembershipKey {
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected MembershipKey() {
+    }
+
+    /**
+     * Tells whether or not this membership is valid.
+     *
+     * <p> A multicast group membership is valid upon creation and remains
+     * valid until the membership is dropped by invoking the {@link #drop() drop}
+     * method, or the channel is closed.
+     *
+     * @return  {@code true} if this membership key is valid, {@code false}
+     *          otherwise
+     */
+    public abstract boolean isValid();
+
+    /**
+     * Drop membership.
+     *
+     * <p> If the membership key represents a membership to receive all datagrams
+     * then the membership is dropped and the channel will no longer receive any
+     * datagrams sent to the group. If the membership key is source-specific
+     * then the channel will no longer receive datagrams sent to the group from
+     * that source address.
+     *
+     * <p> After membership is dropped it may still be possible to receive
+     * datagrams sent to the group. This can arise when datagrams are waiting to
+     * be received in the socket's receive buffer. After membership is dropped
+     * then the channel may {@link MulticastChannel#join join} the group again
+     * in which case a new membership key is returned.
+     *
+     * <p> Upon return, this membership object will be {@link #isValid() invalid}.
+     * If the multicast group membership is already invalid then invoking this
+     * method has no effect. Once a multicast group membership is invalid,
+     * it remains invalid forever.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract void drop() throws IOException;
+
+    /**
+     * Block multicast datagrams from the given source address.
+     *
+     * <p> If this membership key is not source-specific, and the underlying
+     * operating system supports source filtering, then this method blocks
+     * multicast datagrams from the given source address. If the given source
+     * address is already blocked then this method has no effect.
+     * After a source address is blocked it may still be possible to receive
+     * datagams from that source. This can arise when datagrams are waiting to
+     * be received in the socket's receive buffer.
+     *
+     * @param   source
+     *          The source address to block
+     *
+     * @return  This membership key
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code source} parameter is not a unicast address or
+     *          is not the same address type as the multicast group
+     * @throws  IllegalStateException
+     *          If this membership key is source-specific or is no longer valid
+     * @throws  UnsupportedOperationException
+     *          If the underlying operating system does not support source
+     *          filtering
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract MembershipKey block(InetAddress source) throws IOException;
+
+    /**
+     * Unblock multicast datagrams from the given source address that was
+     * previously blocked using the {@link #block(InetAddress) block} method.
+     *
+     * @param   source
+     *          The source address to unblock
+     *
+     * @return  This membership key
+     *
+     * @throws  IllegalStateException
+     *          If the given source address is not currently blocked or the
+     *          membership key is no longer valid
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract MembershipKey unblock(InetAddress source) throws IOException;
+
+    /**
+     * Returns the channel for which this membership key was created. This
+     * method will continue to return the channel even after the membership
+     * becomes {@link #isValid invalid}.
+     *
+     * @return  the channel
+     */
+    public abstract MulticastChannel channel();
+
+    /**
+     * Returns the multicast group for which this membership key was created.
+     * This method will continue to return the group even after the membership
+     * becomes {@link #isValid invalid}.
+     *
+     * @return  the multicast group
+     */
+    public abstract InetAddress group();
+
+    /**
+     * Returns the network interface for which this membership key was created.
+     * This method will continue to return the network interface even after the
+     * membership becomes {@link #isValid invalid}.
+     *
+     * @return  the network interface
+     */
+    public abstract NetworkInterface networkInterface();
+
+    /**
+     * Returns the source address if this membership key is source-specific,
+     * or {@code null} if this membership is not source-specific.
+     *
+     * @return  The source address if this membership key is source-specific,
+     *          otherwise {@code null}
+     */
+    public abstract InetAddress sourceAddress();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/channels/MulticastChannel.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,216 @@
+/*
+ * 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.net.InetAddress;
+import java.net.NetworkInterface;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;             // javadoc
+import org.classpath.icedtea.java.net.StandardProtocolFamily;     // javadoc
+import org.classpath.icedtea.java.net.StandardSocketOption;       // javadoc
+
+/**
+ * A network channel that supports Internet Protocol (IP) multicasting.
+ *
+ * <p> IP multicasting is the transmission of IP datagrams to members of
+ * a <em>group</em> that is zero or more hosts identified by a single destination
+ * address.
+ *
+ * <p> In the case of a channel to an {@link StandardProtocolFamily#INET IPv4} socket,
+ * the underlying operating system supports <a href="http://www.ietf.org/rfc/rfc2236.txt">
+ * <i>RFC&nbsp;2236: Internet Group Management Protocol, Version 2 (IGMPv2)</i></a>.
+ * It may optionally support source filtering as specified by <a
+ * href="http://www.ietf.org/rfc/rfc3376.txt"> <i>RFC&nbsp;3376: Internet Group
+ * Management Protocol, Version 3 (IGMPv3)</i></a>.
+ * For channels to an {@link StandardProtocolFamily#INET6 IPv6} socket, the equivalent
+ * standards are <a href="http://www.ietf.org/rfc/rfc2710.txt"> <i>RFC&nbsp;2710:
+ * Multicast Listener Discovery (MLD) for IPv6</i></a> and <a
+ * href="http://www.ietf.org/rfc/rfc3810.txt"> <i>RFC&nbsp;3810: Multicast Listener
+ * Discovery Version 2 (MLDv2) for IPv6</i></a>.
+ *
+ * <p> The {@link #join(InetAddress,NetworkInterface)} method is used to
+ * join a group and receive all multicast datagrams sent to the group. A channel
+ * may join several multicast groups and may join the same group on several
+ * {@link NetworkInterface interfaces}. Membership is dropped by invoking the {@link
+ * MembershipKey#drop drop} method on the returned {@link MembershipKey}. If the
+ * underlying platform supports source filtering then the {@link MembershipKey#block
+ * block} and {@link MembershipKey#unblock unblock} methods can be used to block or
+ * unblock multicast datagrams from particular source addresses.
+ *
+ * <p> The {@link #join(InetAddress,NetworkInterface,InetAddress)} method
+ * is used to begin receiving datagrams sent to a group whose source address matches
+ * a given source address. This method throws {@link UnsupportedOperationException}
+ * if the underlying platform does not support source filtering.  Membership is
+ * <em>cumulative</em> and this method may be invoked again with the same group
+ * and interface to allow receiving datagrams from other source addresses. The
+ * method returns a {@link MembershipKey} that represents membership to receive
+ * datagrams from the given source address. Invoking the key's {@link
+ * MembershipKey#drop drop} method drops membership so that datagrams from the
+ * source address can no longer be received.
+ *
+ * <h4>Platform dependencies</h4>
+ *
+ * The multicast implementation is intended to map directly to the native
+ * multicasting facility. Consequently, the following items should be considered
+ * when developing an application that receives IP multicast datagrams:
+ *
+ * <ol>
+ *
+ * <li><p> The creation of the channel should specify the {@link ProtocolFamily}
+ * that corresponds to the address type of the multicast groups that the channel
+ * will join. There is no guarantee that a channel to a socket in one protocol
+ * family can join and receive multicast datagrams when the address of the
+ * multicast group corresponds to another protocol family. For example, it is
+ * implementation specific if a channel to an {@link StandardProtocolFamily#INET6 IPv6}
+ * socket can join an {@link StandardProtocolFamily#INET IPv4} multicast group and receive
+ * multicast datagrams sent to the group. </p></li>
+ *
+ * <li><p> The channel's socket should be bound to the {@link
+ * InetAddress#isAnyLocalAddress wildcard} address. If the socket is bound to
+ * a specific address, rather than the wildcard address then it is implementation
+ * specific if multicast datagrams are received by the socket. </p></li>
+ *
+ * <li><p> The {@link StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} option should be
+ * enabled prior to {@link NetworkChannel#bind binding} the socket. This is
+ * required to allow multiple members of the group to bind to the same
+ * address. </p></li>
+ *
+ * </ol>
+ *
+ * <p> <b>Usage Example:</b>
+ * <pre>
+ *     // join multicast group on this interface, and also use this
+ *     // interface for outgoing multicast datagrams
+ *     NetworkInterface ni = NetworkInterface.getByName("hme0");
+ *
+ *     DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
+ *         .setOption(StandardSocketOption.SO_REUSEADDR, true)
+ *         .bind(new InetSocketAddress(5000))
+ *         .setOption(StandardSocketOption.IP_MULTICAST_IF, ni);
+ *
+ *     InetAddress group = InetAddress.getByName("225.4.5.6");
+ *
+ *     MembershipKey key = dc.join(group, ni);
+ * </pre>
+ *
+ * @since 1.7
+ */
+
+public interface MulticastChannel
+    extends NetworkChannel
+{
+    /**
+     * Joins a multicast group to begin receiving all datagrams sent to the group,
+     * returning a membership key.
+     *
+     * <p> If this channel is currently a member of the group on the given
+     * interface to receive all datagrams then the membership key, representing
+     * that membership, is returned. Otherwise this channel joins the group and
+     * the resulting new membership key is returned. The resulting membership key
+     * is not {@link MembershipKey#sourceAddress source-specific}.
+     *
+     * <p> A multicast channel may join several multicast groups, including
+     * the same group on more than one interface. An implementation may impose a
+     * limit on the number of groups that may be joined at the same time.
+     *
+     * @param   group
+     *          The multicast address to join
+     * @param   interf
+     *          The network interface on which to join the group
+     *
+     * @return  The membership key
+     *
+     * @throws  IllegalArgumentException
+     *          If the group parameter is not a {@link InetAddress#isMulticastAddress
+     *          multicast} address, or the group parameter is an address type
+     *          that is not supported by this channel
+     * @throws  IllegalStateException
+     *          If the channel already has source-specific membership of the
+     *          group on the interface
+     * @throws  UnsupportedOperationException
+     *          If the channel's socket is not an Internet Protocol socket
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is set, and its
+     *          {@link SecurityManager#checkMulticast(InetAddress) checkMulticast}
+     *          method denies access to the multiast group
+     */
+    MembershipKey join(InetAddress group, NetworkInterface interf)
+        throws IOException;
+
+    /**
+     * Joins a multicast group to begin receiving datagrams sent to the group
+     * from a given source address.
+     *
+     * <p> If this channel is currently a member of the group on the given
+     * interface to receive datagrams from the given source address then the
+     * membership key, representing that membership, is returned. Otherwise this
+     * channel joins the group and the resulting new membership key is returned.
+     * The resulting membership key is {@link MembershipKey#sourceAddress
+     * source-specific}.
+     *
+     * <p> Membership is <em>cumulative</em> and this method may be invoked
+     * again with the same group and interface to allow receiving datagrams sent
+     * by other source addresses to the group.
+     *
+     * @param   group
+     *          The multicast address to join
+     * @param   interf
+     *          The network interface on which to join the group
+     * @param   source
+     *          The source address
+     *
+     * @return  The membership key
+     *
+     * @throws  IllegalArgumentException
+     *          If the group parameter is not a {@link
+     *          InetAddress#isMulticastAddress multicast} address, the
+     *          source parameter is not a unicast address, the group
+     *          parameter is an address type that is not supported by this channel,
+     *          or the source parameter is not the same address type as the group
+     * @throws  IllegalStateException
+     *          If the channel is currently a member of the group on the given
+     *          interface to receive all datagrams
+     * @throws  UnsupportedOperationException
+     *          If the channel's socket is not an Internet Protocol socket or
+     *          source filtering is not supported
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is set, and its
+     *          {@link SecurityManager#checkMulticast(InetAddress) checkMulticast}
+     *          method denies access to the multiast group
+     */
+    MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source)
+        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/NetworkChannel.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,165 @@
+/*
+ * 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.net.SocketAddress;
+
+import java.nio.channels.Channel;
+
+import java.util.Set;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.net.SocketOption;
+
+/**
+ * A channel to a network socket.
+ *
+ * <p> A channel that implements this interface is a channel to a network
+ * socket. The {@link #bind(SocketAddress) bind} method is used to bind the
+ * socket to a local {@link SocketAddress address}, the {@link #getLocalAddress()
+ * getLocalAddress} method returns the address that the socket is bound to, and
+ * the {@link #setOption(SocketOption,Object) setOption} and {@link
+ * #getOption(SocketOption) getOption} methods are used to set and query socket
+ * options.  An implementation of this interface should specify the socket options
+ * that it supports.
+ *
+ * <p> The {@link #bind bind} and {@link #setOption setOption} methods that do
+ * not otherwise have a value to return are specified to return the network
+ * 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
+ */
+
+public interface NetworkChannel
+    extends Channel
+{
+    /**
+     * Binds the channel's socket to a local address.
+     *
+     * <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 channel is closed. If the {@code local} parameter has the
+     * value {@code null} then the socket will be bound to an address that is
+     * assigned automatically.
+     *
+     * @param   local
+     *          The address to bind the socket, or {@code null} to bind the socket
+     *          to an automatically assigned socket address
+     *
+     * @return  This channel
+     *
+     * @throws  AlreadyBoundException
+     *          If the socket is already bound
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given address is not supported
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is installed and it denies an unspecified
+     *          permission. An implementation of this interface should specify
+     *          any required permissions.
+     *
+     * @see #getLocalAddress
+     */
+    NetworkChannel bind(SocketAddress local) throws IOException;
+
+    /**
+     * Returns the socket address that this channel's socket is bound to, or
+     * {@code null} if the socket is not bound.
+     *
+     * <p> Where the channel is {@link #bind bound} to an Internet Protocol
+     * socket address then the return value from this method is of type {@link
+     * java.net.InetSocketAddress}.
+     *
+     * @return  The socket address that the socket is bound to, or {@code null}
+     *          if the channel's socket is not bound
+     *
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    SocketAddress getLocalAddress() throws IOException;
+
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param   name
+     *          The socket option
+     * @param   value
+     *          The value of the socket option. A value of {@code null} may be
+     *          a valid value for some socket options.
+     *
+     * @return  This channel
+     *
+     * @throws  UnsupportedOperationException
+     *          If the socket option is not supported by this channel
+     * @throws  IllegalArgumentException
+     *          If the value is not a valid value for this socket option
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see java.net.StandardSocketOption
+     */
+    <T> NetworkChannel setOption(SocketOption<T> name, T value) throws IOException;
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param   name
+     *          The socket option
+     *
+     * @return  The value of the socket option. A value of {@code null} may be
+     *          a valid value for some socket options.
+     *
+     * @throws  UnsupportedOperationException
+     *          If the socket option is not supported by this channel
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see java.net.StandardSocketOption
+     */
+    <T> T getOption(SocketOption<T> name) throws IOException;
+
+    /**
+     * Returns a set of the socket options supported by this channel.
+     *
+     * <p> This method will continue to return the set of options even after the
+     * channel has been closed.
+     *
+     * @return  A set of the socket options supported by this channel
+     */
+    Set<SocketOption<?>> supportedOptions();
+}
--- /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	Tue Feb 10 21:56:55 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 positionSBC(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 truncateSBC(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	Tue Feb 10 21:56:55 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=org.classpath.icedtea.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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,284 @@
+/*
+ * 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.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;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup;
+import org.classpath.icedtea.java.nio.channels.AsynchronousDatagramChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousServerSocketChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel;
+
+/**
+ * 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/SelectorProvider.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,199 @@
+/*
+ * 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.spi;
+
+import java.io.IOException;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+import java.util.ServiceConfigurationError;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+
+import org.classpath.icedtea.java.nio.channels.DatagramChannel;
+
+/**
+ * Service-provider class for selectors and selectable channels.
+ *
+ * <p> A selector 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> The system-wide default provider is used by the static <tt>open</tt>
+ * methods of the {@link java.nio.channels.DatagramChannel#open
+ * DatagramChannel}, {@link java.nio.channels.Pipe#open Pipe}, {@link
+ * java.nio.channels.Selector#open Selector}, {@link
+ * java.nio.channels.ServerSocketChannel#open ServerSocketChannel}, and {@link
+ * java.nio.channels.SocketChannel#open SocketChannel} classes.  It is also
+ * used by the {@link java.lang.System#inheritedChannel System.inheritedChannel()}
+ * method. A program may make use of a provider other than the default provider
+ * by instantiating that provider and then directly invoking the <tt>open</tt>
+ * methods defined in this class.
+ *
+ * <p> All of the methods in this class are safe for use by multiple concurrent
+ * threads.  </p>
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ */
+
+public abstract class SelectorProvider
+    extends java.nio.channels.spi.SelectorProvider {
+
+    private static final Object lock = new Object();
+    private static SelectorProvider provider = null;
+
+    /**
+     * Opens a datagram channel.  </p>
+     *
+     * @return  The new channel
+     */
+    public abstract DatagramChannel openDatagramChannel()
+        throws IOException;
+
+    /**
+     * {@note new}
+     * Opens a datagram channel.
+     *
+     * @param   family
+     *          The protocol family
+     *
+     * @return  A new datagram channel
+     *
+     * @throws  UnsupportedOperationException
+     *          If the specified protocol family is not supported
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @since 1.7
+     */
+    public abstract DatagramChannel openDatagramChannel(ProtocolFamily family)
+        throws IOException;
+
+    /**
+     * Returns the system-wide default selector 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.SelectorProvider</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.SelectorProvider</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 selector provider
+     */
+    public static SelectorProvider provider() {
+        synchronized (lock) {
+            if (provider != null)
+                return provider;
+            return AccessController
+                .doPrivileged(new PrivilegedAction<SelectorProvider>() {
+                        public SelectorProvider run() {
+                            if (loadProviderFromProperty())
+                                return provider;
+                            if (loadProviderAsService())
+                                return provider;
+                            provider = sun.nio.ch.DefaultSelectorProvider.create();
+                            return provider;
+                        }
+                    });
+        }
+    }
+
+    private static boolean loadProviderFromProperty() {
+        String cn = System.getProperty("org.classpath.icedtea.java.nio.channels.spi.SelectorProvider");
+        if (cn == null)
+            return false;
+        try {
+            Class<?> c = Class.forName(cn, true,
+                                       ClassLoader.getSystemClassLoader());
+            provider = (SelectorProvider)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<SelectorProvider> sl =
+            ServiceLoader.load(SelectorProvider.class,
+                               ClassLoader.getSystemClassLoader());
+        Iterator<SelectorProvider> 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;
+            }
+        }
+    }
+}
--- /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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,415 @@
+/*
+ * 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.net.URI;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.lang.reflect.Constructor;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,247 @@
+/*
+ * 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.util.*;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,177 @@
+/*
+ * 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.file.attribute.BasicFileAttributes;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,405 @@
+/*
+ * 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.util.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.classpath.icedtea.java.nio.file.spi.FileTypeDetector;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,1575 @@
+/*
+ * 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.channels.SeekableByteChannel;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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.net.URI;
+import java.util.Iterator;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,327 @@
+/*
+ * 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.util.Set;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,123 @@
+/*
+ * 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 org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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.attribute;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,714 @@
+/*
+ * 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.FileStore;
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,94 @@
+/*
+ * 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.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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,231 @@
+/*
+ * 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> 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. The attribute value is returned as a byte array (byte[]). The {@link
+ * #setAttribute setAttribute} method may be used to write the value of a
+ * user-defined/named attribute from a buffer (as if by invoking the {@link
+ * #write write} method), or byte array (byte[]).
+ *
+ * @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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,196 @@
+/*
+ * 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;
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,190 @@
+/*
+ * 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 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;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,542 @@
+/*
+ * 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.channels.*;
+import java.nio.ByteBuffer;
+import java.io.*;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+
+import org.classpath.icedtea.java.nio.file.AtomicMoveNotSupportedException;
+import org.classpath.icedtea.java.nio.file.CopyOption;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.NoSuchFileException;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.PathMatcher;
+import org.classpath.icedtea.java.nio.file.StandardOpenOption;
+import org.classpath.icedtea.java.nio.file.StandardCopyOption;
+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 org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,441 @@
+/*
+ * 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.net.URI;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.FileSystems;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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.spi;
+
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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/org/classpath/icedtea/java/util/concurrent/ScheduledThreadPoolExecutor.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,1371 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package org.classpath.icedtea.java.util.concurrent;
+
+import java.util.*;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.RunnableScheduledFuture;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
+
+import org.classpath.icedtea.misc.JavaUtilConcurrentThreadPoolExecutorAccess;
+import org.classpath.icedtea.misc.SharedSecrets;
+
+/**
+ * A {@link ThreadPoolExecutor} that can additionally schedule
+ * commands to run after a given delay, or to execute
+ * periodically. This class is preferable to {@link java.util.Timer}
+ * when multiple worker threads are needed, or when the additional
+ * flexibility or capabilities of {@link ThreadPoolExecutor} (which
+ * this class extends) are required.
+ *
+ * <p>Delayed tasks execute no sooner than they are enabled, but
+ * without any real-time guarantees about when, after they are
+ * enabled, they will commence. Tasks scheduled for exactly the same
+ * execution time are enabled in first-in-first-out (FIFO) order of
+ * submission.
+ *
+ * <p>When a submitted task is cancelled before it is run, execution
+ * is suppressed. By default, such a cancelled task is not
+ * automatically removed from the work queue until its delay
+ * elapses. While this enables further inspection and monitoring, it
+ * may also cause unbounded retention of cancelled tasks. To avoid
+ * this, set {@link #setRemoveOnCancelPolicy} to {@code true}, which
+ * causes tasks to be immediately removed from the work queue at
+ * time of cancellation.
+ *
+ * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
+ * of the inherited tuning methods are not useful for it. In
+ * particular, because it acts as a fixed-sized pool using
+ * {@code corePoolSize} threads and an unbounded queue, adjustments
+ * to {@code maximumPoolSize} have no useful effect. Additionally, it
+ * is almost never a good idea to set {@code corePoolSize} to zero or
+ * use {@code allowCoreThreadTimeOut} because this may leave the pool
+ * without threads to handle tasks once they become eligible to run.
+ *
+ * <p><b>Extension notes:</b> This class overrides the
+ * {@link ThreadPoolExecutor#execute execute} and
+ * {@link AbstractExecutorService#submit(Runnable) submit}
+ * methods to generate internal {@link ScheduledFuture} objects to
+ * control per-task delays and scheduling.  To preserve
+ * functionality, any further overrides of these methods in
+ * subclasses must invoke superclass versions, which effectively
+ * disables additional task customization.  However, this class
+ * provides alternative protected extension method
+ * {@code decorateTask} (one version each for {@code Runnable} and
+ * {@code Callable}) that can be used to customize the concrete task
+ * types used to execute commands entered via {@code execute},
+ * {@code submit}, {@code schedule}, {@code scheduleAtFixedRate},
+ * and {@code scheduleWithFixedDelay}.  By default, a
+ * {@code ScheduledThreadPoolExecutor} uses a task type extending
+ * {@link FutureTask}. However, this may be modified or replaced using
+ * subclasses of the form:
+ *
+ *  <pre> {@code
+ * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
+ *
+ *   static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
+ *
+ *   protected <V> RunnableScheduledFuture<V> decorateTask(
+ *                Runnable r, RunnableScheduledFuture<V> task) {
+ *       return new CustomTask<V>(r, task);
+ *   }
+ *
+ *   protected <V> RunnableScheduledFuture<V> decorateTask(
+ *                Callable<V> c, RunnableScheduledFuture<V> task) {
+ *       return new CustomTask<V>(c, task);
+ *   }
+ *   // ... add constructors, etc.
+ * }}</pre>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ScheduledThreadPoolExecutor
+        extends ThreadPoolExecutor
+        implements ScheduledExecutorService {
+
+    /*
+     * This class specializes ThreadPoolExecutor implementation by
+     *
+     * 1. Using a custom task type, ScheduledFutureTask for
+     *    tasks, even those that don't require scheduling (i.e.,
+     *    those submitted using ExecutorService execute, not
+     *    ScheduledExecutorService methods) which are treated as
+     *    delayed tasks with a delay of zero.
+     *
+     * 2. Using a custom queue (DelayedWorkQueue), a variant of
+     *    unbounded DelayQueue. The lack of capacity constraint and
+     *    the fact that corePoolSize and maximumPoolSize are
+     *    effectively identical simplifies some execution mechanics
+     *    (see delayedExecute) compared to ThreadPoolExecutor.
+     *
+     * 3. Supporting optional run-after-shutdown parameters, which
+     *    leads to overrides of shutdown methods to remove and cancel
+     *    tasks that should NOT be run after shutdown, as well as
+     *    different recheck logic when task (re)submission overlaps
+     *    with a shutdown.
+     *
+     * 4. Task decoration methods to allow interception and
+     *    instrumentation, which are needed because subclasses cannot
+     *    otherwise override submit methods to get this effect. These
+     *    don't have any impact on pool control logic though.
+     */
+
+    /**
+     * False if should cancel/suppress periodic tasks on shutdown.
+     */
+    private volatile boolean continueExistingPeriodicTasksAfterShutdown;
+
+    /**
+     * False if should cancel non-periodic tasks on shutdown.
+     */
+    private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
+
+    /**
+     * True if ScheduledFutureTask.cancel should remove from queue
+     */
+    private volatile boolean removeOnCancel = false;
+
+    /**
+     * Sequence number to break scheduling ties, and in turn to
+     * guarantee FIFO order among tied entries.
+     */
+    private static final AtomicLong sequencer = new AtomicLong(0);
+
+    /**
+     * Returns current nanosecond time.
+     */
+    final long now() {
+        return System.nanoTime();
+    }
+
+    private class ScheduledFutureTask<V>
+            extends FutureTask<V> implements RunnableScheduledFuture<V> {
+
+        /** Sequence number to break ties FIFO */
+        private final long sequenceNumber;
+
+        /** The time the task is enabled to execute in nanoTime units */
+        private long time;
+
+        /**
+         * Period in nanoseconds for repeating tasks.  A positive
+         * value indicates fixed-rate execution.  A negative value
+         * indicates fixed-delay execution.  A value of 0 indicates a
+         * non-repeating task.
+         */
+        private final long period;
+
+        /** The actual task to be re-enqueued by reExecutePeriodic */
+        RunnableScheduledFuture<V> outerTask = this;
+
+        /**
+         * Index into delay queue, to support faster cancellation.
+         */
+        int heapIndex;
+
+        /**
+         * Creates a one-shot action with given nanoTime-based trigger time.
+         */
+        ScheduledFutureTask(Runnable r, V result, long ns) {
+            super(r, result);
+            this.time = ns;
+            this.period = 0;
+            this.sequenceNumber = sequencer.getAndIncrement();
+        }
+
+        /**
+         * Creates a periodic action with given nano time and period.
+         */
+        ScheduledFutureTask(Runnable r, V result, long ns, long period) {
+            super(r, result);
+            this.time = ns;
+            this.period = period;
+            this.sequenceNumber = sequencer.getAndIncrement();
+        }
+
+        /**
+         * Creates a one-shot action with given nanoTime-based trigger.
+         */
+        ScheduledFutureTask(Callable<V> callable, long ns) {
+            super(callable);
+            this.time = ns;
+            this.period = 0;
+            this.sequenceNumber = sequencer.getAndIncrement();
+        }
+
+        public long getDelay(TimeUnit unit) {
+            return unit.convert(time - now(), TimeUnit.NANOSECONDS);
+        }
+
+        public int compareTo(Delayed other) {
+            if (other == this) // compare zero ONLY if same object
+                return 0;
+            if (other instanceof ScheduledFutureTask) {
+                ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
+                long diff = time - x.time;
+                if (diff < 0)
+                    return -1;
+                else if (diff > 0)
+                    return 1;
+                else if (sequenceNumber < x.sequenceNumber)
+                    return -1;
+                else
+                    return 1;
+            }
+            long d = (getDelay(TimeUnit.NANOSECONDS) -
+                      other.getDelay(TimeUnit.NANOSECONDS));
+            return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
+        }
+
+        /**
+         * Returns true if this is a periodic (not a one-shot) action.
+         *
+         * @return true if periodic
+         */
+        public boolean isPeriodic() {
+            return period != 0;
+        }
+
+        /**
+         * Sets the next time to run for a periodic task.
+         */
+        private void setNextRunTime() {
+            long p = period;
+            if (p > 0)
+                time += p;
+            else
+                time = triggerTime(-p);
+        }
+
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            boolean cancelled = super.cancel(mayInterruptIfRunning);
+            if (cancelled && removeOnCancel && heapIndex >= 0)
+                remove(this);
+            return cancelled;
+        }
+
+        /**
+         * Overrides FutureTask version so as to reset/requeue if periodic.
+         */
+        public void run() {
+            boolean periodic = isPeriodic();
+            if (!canRunInCurrentRunState(periodic))
+                cancel(false);
+            else if (!periodic)
+                ScheduledFutureTask.super.run();
+            else if (ScheduledFutureTask.super.runAndReset()) {
+                setNextRunTime();
+                reExecutePeriodic(outerTask);
+            }
+        }
+    }
+
+    /**
+     * Returns true if can run a task given current run state
+     * and run-after-shutdown parameters.
+     *
+     * @param periodic true if this task periodic, false if delayed
+     */
+    boolean canRunInCurrentRunState(boolean periodic) {
+        return isRunningOrShutdownSTPE(periodic ?
+				       continueExistingPeriodicTasksAfterShutdown :
+				       executeExistingDelayedTasksAfterShutdown);
+    }
+
+    /**
+     * Main execution method for delayed or periodic tasks.  If pool
+     * is shut down, rejects the task. Otherwise adds task to queue
+     * and starts a thread, if necessary, to run it.  (We cannot
+     * prestart the thread to run the task because the task (probably)
+     * shouldn't be run yet,) If the pool is shut down while the task
+     * is being added, cancel and remove it if required by state and
+     * run-after-shutdown parameters.
+     *
+     * @param task the task
+     */
+    private void delayedExecute(RunnableScheduledFuture<?> task) {
+        if (isShutdown())
+            rejectSTPE(task);
+        else {
+            super.getQueue().add(task);
+            if (isShutdown() &&
+                !canRunInCurrentRunState(task.isPeriodic()) &&
+                remove(task))
+                task.cancel(false);
+            else
+                prestartCoreThread();
+        }
+    }
+
+    /**
+     * Requeues a periodic task unless current run state precludes it.
+     * Same idea as delayedExecute except drops task rather than rejecting.
+     *
+     * @param task the task
+     */
+    void reExecutePeriodic(RunnableScheduledFuture<?> task) {
+        if (canRunInCurrentRunState(true)) {
+            super.getQueue().add(task);
+            if (!canRunInCurrentRunState(true) && remove(task))
+                task.cancel(false);
+            else
+                prestartCoreThread();
+        }
+    }
+
+    /**
+     * Cancels and clears the queue of all tasks that should not be run
+     * due to shutdown policy.  Invoked within super.shutdown.
+     */
+ void onShutdown() {
+        BlockingQueue<Runnable> q = super.getQueue();
+        boolean keepDelayed =
+            getExecuteExistingDelayedTasksAfterShutdownPolicy();
+        boolean keepPeriodic =
+            getContinueExistingPeriodicTasksAfterShutdownPolicy();
+        if (!keepDelayed && !keepPeriodic)
+            q.clear();
+        else {
+            // Traverse snapshot to avoid iterator exceptions
+            for (Object e : q.toArray()) {
+                if (e instanceof RunnableScheduledFuture) {
+                    RunnableScheduledFuture<?> t =
+                        (RunnableScheduledFuture<?>)e;
+                    if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
+                        t.isCancelled()) { // also remove if already cancelled
+                        if (q.remove(t))
+                            t.cancel(false);
+                    }
+                }
+            }
+        }
+        tryTerminateSTPE();
+    }
+
+    /**
+     * Modifies or replaces the task used to execute a runnable.
+     * This method can be used to override the concrete
+     * class used for managing internal tasks.
+     * The default implementation simply returns the given task.
+     *
+     * @param runnable the submitted Runnable
+     * @param task the task created to execute the runnable
+     * @return a task that can execute the runnable
+     * @since 1.6
+     */
+    protected <V> RunnableScheduledFuture<V> decorateTask(
+        Runnable runnable, RunnableScheduledFuture<V> task) {
+        return task;
+    }
+
+    /**
+     * Modifies or replaces the task used to execute a callable.
+     * This method can be used to override the concrete
+     * class used for managing internal tasks.
+     * The default implementation simply returns the given task.
+     *
+     * @param callable the submitted Callable
+     * @param task the task created to execute the callable
+     * @return a task that can execute the callable
+     * @since 1.6
+     */
+    protected <V> RunnableScheduledFuture<V> decorateTask(
+        Callable<V> callable, RunnableScheduledFuture<V> task) {
+        return task;
+    }
+
+    /**
+     * Creates a new {@code ScheduledThreadPoolExecutor} with the
+     * given core pool size.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     */
+    public ScheduledThreadPoolExecutor(int corePoolSize) {
+        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+              new DelayedWorkQueue());
+    }
+
+    /**
+     * Creates a new {@code ScheduledThreadPoolExecutor} with the
+     * given initial parameters.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
+     * @param threadFactory the factory to use when the executor
+     *        creates a new thread
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     * @throws NullPointerException if {@code threadFactory} is null
+     */
+    public ScheduledThreadPoolExecutor(int corePoolSize,
+                             ThreadFactory threadFactory) {
+        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+              new DelayedWorkQueue(), threadFactory);
+    }
+
+    /**
+     * Creates a new ScheduledThreadPoolExecutor with the given
+     * initial parameters.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
+     * @param handler the handler to use when execution is blocked
+     *        because the thread bounds and queue capacities are reached
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     * @throws NullPointerException if {@code handler} is null
+     */
+    public ScheduledThreadPoolExecutor(int corePoolSize,
+                              RejectedExecutionHandler handler) {
+        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+              new DelayedWorkQueue(), handler);
+    }
+
+    /**
+     * Creates a new ScheduledThreadPoolExecutor with the given
+     * initial parameters.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
+     * @param threadFactory the factory to use when the executor
+     *        creates a new thread
+     * @param handler the handler to use when execution is blocked
+     *        because the thread bounds and queue capacities are reached
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     * @throws NullPointerException if {@code threadFactory} or
+     *         {@code handler} is null
+     */
+    public ScheduledThreadPoolExecutor(int corePoolSize,
+                              ThreadFactory threadFactory,
+                              RejectedExecutionHandler handler) {
+        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+              new DelayedWorkQueue(), threadFactory, handler);
+    }
+
+    /**
+     * Returns the trigger time of a delayed action.
+     */
+    private long triggerTime(long delay, TimeUnit unit) {
+        return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
+    }
+
+    /**
+     * Returns the trigger time of a delayed action.
+     */
+    long triggerTime(long delay) {
+        return now() +
+            ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
+    }
+
+    /**
+     * Constrains the values of all delays in the queue to be within
+     * Long.MAX_VALUE of each other, to avoid overflow in compareTo.
+     * This may occur if a task is eligible to be dequeued, but has
+     * not yet been, while some other task is added with a delay of
+     * Long.MAX_VALUE.
+     */
+    private long overflowFree(long delay) {
+        Delayed head = (Delayed) super.getQueue().peek();
+        if (head != null) {
+            long headDelay = head.getDelay(TimeUnit.NANOSECONDS);
+            if (headDelay < 0 && (delay - headDelay < 0))
+                delay = Long.MAX_VALUE + headDelay;
+        }
+        return delay;
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public ScheduledFuture<?> schedule(Runnable command,
+                                       long delay,
+                                       TimeUnit unit) {
+        if (command == null || unit == null)
+            throw new NullPointerException();
+        RunnableScheduledFuture<?> t = decorateTask(command,
+            new ScheduledFutureTask<Void>(command, null,
+                                          triggerTime(delay, unit)));
+        delayedExecute(t);
+        return t;
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+                                           long delay,
+                                           TimeUnit unit) {
+        if (callable == null || unit == null)
+            throw new NullPointerException();
+        RunnableScheduledFuture<V> t = decorateTask(callable,
+            new ScheduledFutureTask<V>(callable,
+                                       triggerTime(delay, unit)));
+        delayedExecute(t);
+        return t;
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     * @throws IllegalArgumentException   {@inheritDoc}
+     */
+    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+                                                  long initialDelay,
+                                                  long period,
+                                                  TimeUnit unit) {
+        if (command == null || unit == null)
+            throw new NullPointerException();
+        if (period <= 0)
+            throw new IllegalArgumentException();
+        ScheduledFutureTask<Void> sft =
+            new ScheduledFutureTask<Void>(command,
+                                          null,
+                                          triggerTime(initialDelay, unit),
+                                          unit.toNanos(period));
+        RunnableScheduledFuture<Void> t = decorateTask(command, sft);
+        sft.outerTask = t;
+        delayedExecute(t);
+        return t;
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     * @throws IllegalArgumentException   {@inheritDoc}
+     */
+    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+                                                     long initialDelay,
+                                                     long delay,
+                                                     TimeUnit unit) {
+        if (command == null || unit == null)
+            throw new NullPointerException();
+        if (delay <= 0)
+            throw new IllegalArgumentException();
+        ScheduledFutureTask<Void> sft =
+            new ScheduledFutureTask<Void>(command,
+                                          null,
+                                          triggerTime(initialDelay, unit),
+                                          unit.toNanos(-delay));
+        RunnableScheduledFuture<Void> t = decorateTask(command, sft);
+        sft.outerTask = t;
+        delayedExecute(t);
+        return t;
+    }
+
+    /**
+     * Executes {@code command} with zero required delay.
+     * This has effect equivalent to
+     * {@link #schedule(Runnable,long,TimeUnit) schedule(command, 0, anyUnit)}.
+     * Note that inspections of the queue and of the list returned by
+     * {@code shutdownNow} will access the zero-delayed
+     * {@link ScheduledFuture}, not the {@code command} itself.
+     *
+     * <p>A consequence of the use of {@code ScheduledFuture} objects is
+     * that {@link ThreadPoolExecutor#afterExecute afterExecute} is always
+     * called with a null second {@code Throwable} argument, even if the
+     * {@code command} terminated abruptly.  Instead, the {@code Throwable}
+     * thrown by such a task can be obtained via {@link Future#get}.
+     *
+     * @throws RejectedExecutionException at discretion of
+     *         {@code RejectedExecutionHandler}, if the task
+     *         cannot be accepted for execution because the
+     *         executor has been shut down
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void execute(Runnable command) {
+        schedule(command, 0, TimeUnit.NANOSECONDS);
+    }
+
+    // Override AbstractExecutorService methods
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public Future<?> submit(Runnable task) {
+        return schedule(task, 0, TimeUnit.NANOSECONDS);
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public <T> Future<T> submit(Runnable task, T result) {
+        return schedule(Executors.callable(task, result),
+                        0, TimeUnit.NANOSECONDS);
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public <T> Future<T> submit(Callable<T> task) {
+        return schedule(task, 0, TimeUnit.NANOSECONDS);
+    }
+
+    /**
+     * Sets the policy on whether to continue executing existing
+     * periodic tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow} or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code false}.
+     *
+     * @param value if {@code true}, continue after shutdown, else don't.
+     * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
+     */
+    public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
+        continueExistingPeriodicTasksAfterShutdown = value;
+        if (!value && isShutdown())
+            onShutdown();
+    }
+
+    /**
+     * Gets the policy on whether to continue executing existing
+     * periodic tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow} or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code false}.
+     *
+     * @return {@code true} if will continue after shutdown
+     * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
+     */
+    public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
+        return continueExistingPeriodicTasksAfterShutdown;
+    }
+
+    /**
+     * Sets the policy on whether to execute existing delayed
+     * tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow}, or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code true}.
+     *
+     * @param value if {@code true}, execute after shutdown, else don't.
+     * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
+     */
+    public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
+        executeExistingDelayedTasksAfterShutdown = value;
+        if (!value && isShutdown())
+            onShutdown();
+    }
+
+    /**
+     * Gets the policy on whether to execute existing delayed
+     * tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow}, or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code true}.
+     *
+     * @return {@code true} if will execute after shutdown
+     * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
+     */
+    public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
+        return executeExistingDelayedTasksAfterShutdown;
+    }
+
+    /**
+     * Sets the policy on whether cancelled tasks should be immediately
+     * removed from the work queue at time of cancellation.  This value is
+     * by default {@code false}.
+     *
+     * @param value if {@code true}, remove on cancellation, else don't
+     * @see #getRemoveOnCancelPolicy
+     * @since 1.7
+     */
+    public void setRemoveOnCancelPolicy(boolean value) {
+        removeOnCancel = value;
+    }
+
+    /**
+     * Gets the policy on whether cancelled tasks should be immediately
+     * removed from the work queue at time of cancellation.  This value is
+     * by default {@code false}.
+     *
+     * @return {@code true} if cancelled tasks are immediately removed
+     *         from the queue
+     * @see #setRemoveOnCancelPolicy
+     * @since 1.7
+     */
+    public boolean getRemoveOnCancelPolicy() {
+        return removeOnCancel;
+    }
+
+    /**
+     * Initiates an orderly shutdown in which previously submitted
+     * tasks are executed, but no new tasks will be accepted.
+     * Invocation has no additional effect if already shut down.
+     *
+     * <p>This method does not wait for previously submitted tasks to
+     * complete execution.  Use {@link #awaitTermination awaitTermination}
+     * to do that.
+     *
+     * <p>If the {@code ExecuteExistingDelayedTasksAfterShutdownPolicy}
+     * has been set {@code false}, existing delayed tasks whose delays
+     * have not yet elapsed are cancelled.  And unless the {@code
+     * ContinueExistingPeriodicTasksAfterShutdownPolicy} has been set
+     * {@code true}, future executions of existing periodic tasks will
+     * be cancelled.
+     *
+     * @throws SecurityException {@inheritDoc}
+     */
+    public void shutdown() {
+        super.shutdown();
+    }
+
+    /**
+     * Attempts to stop all actively executing tasks, halts the
+     * processing of waiting tasks, and returns a list of the tasks
+     * that were awaiting execution.
+     *
+     * <p>This method does not wait for actively executing tasks to
+     * terminate.  Use {@link #awaitTermination awaitTermination} to
+     * do that.
+     *
+     * <p>There are no guarantees beyond best-effort attempts to stop
+     * processing actively executing tasks.  This implementation
+     * cancels tasks via {@link Thread#interrupt}, so any task that
+     * fails to respond to interrupts may never terminate.
+     *
+     * @return list of tasks that never commenced execution.
+     *         Each element of this list is a {@link ScheduledFuture},
+     *         including those tasks submitted using {@code execute},
+     *         which are for scheduling purposes used as the basis of a
+     *         zero-delay {@code ScheduledFuture}.
+     * @throws SecurityException {@inheritDoc}
+     */
+    public List<Runnable> shutdownNow() {
+        return super.shutdownNow();
+    }
+
+    /**
+     * Returns the task queue used by this executor.  Each element of
+     * this queue is a {@link ScheduledFuture}, including those
+     * tasks submitted using {@code execute} which are for scheduling
+     * purposes used as the basis of a zero-delay
+     * {@code ScheduledFuture}.  Iteration over this queue is
+     * <em>not</em> guaranteed to traverse tasks in the order in
+     * which they will execute.
+     *
+     * @return the task queue
+     */
+    public BlockingQueue<Runnable> getQueue() {
+        return super.getQueue();
+    }
+
+    /**
+     * Specialized delay queue. To mesh with TPE declarations, this
+     * class must be declared as a BlockingQueue<Runnable> even though
+     * it can only hold RunnableScheduledFutures.
+     */
+    static class DelayedWorkQueue extends AbstractQueue<Runnable>
+        implements BlockingQueue<Runnable> {
+
+        /*
+         * A DelayedWorkQueue is based on a heap-based data structure
+         * like those in DelayQueue and PriorityQueue, except that
+         * every ScheduledFutureTask also records its index into the
+         * heap array. This eliminates the need to find a task upon
+         * cancellation, greatly speeding up removal (down from O(n)
+         * to O(log n)), and reducing garbage retention that would
+         * otherwise occur by waiting for the element to rise to top
+         * before clearing. But because the queue may also hold
+         * RunnableScheduledFutures that are not ScheduledFutureTasks,
+         * we are not guaranteed to have such indices available, in
+         * which case we fall back to linear search. (We expect that
+         * most tasks will not be decorated, and that the faster cases
+         * will be much more common.)
+         *
+         * All heap operations must record index changes -- mainly
+         * within siftUp and siftDown. Upon removal, a task's
+         * heapIndex is set to -1. Note that ScheduledFutureTasks can
+         * appear at most once in the queue (this need not be true for
+         * other kinds of tasks or work queues), so are uniquely
+         * identified by heapIndex.
+         */
+
+        private static final int INITIAL_CAPACITY = 16;
+        private RunnableScheduledFuture[] queue =
+            new RunnableScheduledFuture[INITIAL_CAPACITY];
+        private final ReentrantLock lock = new ReentrantLock();
+        private int size = 0;
+
+        /**
+         * Thread designated to wait for the task at the head of the
+         * queue.  This variant of the Leader-Follower pattern
+         * (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to
+         * minimize unnecessary timed waiting.  When a thread becomes
+         * the leader, it waits only for the next delay to elapse, but
+         * other threads await indefinitely.  The leader thread must
+         * signal some other thread before returning from take() or
+         * poll(...), unless some other thread becomes leader in the
+         * interim.  Whenever the head of the queue is replaced with a
+         * task with an earlier expiration time, the leader field is
+         * invalidated by being reset to null, and some waiting
+         * thread, but not necessarily the current leader, is
+         * signalled.  So waiting threads must be prepared to acquire
+         * and lose leadership while waiting.
+         */
+        private Thread leader = null;
+
+        /**
+         * Condition signalled when a newer task becomes available at the
+         * head of the queue or a new thread may need to become leader.
+         */
+        private final Condition available = lock.newCondition();
+
+        /**
+         * Set f's heapIndex if it is a ScheduledFutureTask.
+         */
+        private void setIndex(RunnableScheduledFuture f, int idx) {
+            if (f instanceof ScheduledFutureTask)
+                ((ScheduledFutureTask)f).heapIndex = idx;
+        }
+
+        /**
+         * Sift element added at bottom up to its heap-ordered spot.
+         * Call only when holding lock.
+         */
+        private void siftUp(int k, RunnableScheduledFuture key) {
+            while (k > 0) {
+                int parent = (k - 1) >>> 1;
+                RunnableScheduledFuture e = queue[parent];
+                if (key.compareTo(e) >= 0)
+                    break;
+                queue[k] = e;
+                setIndex(e, k);
+                k = parent;
+            }
+            queue[k] = key;
+            setIndex(key, k);
+        }
+
+        /**
+         * Sift element added at top down to its heap-ordered spot.
+         * Call only when holding lock.
+         */
+        private void siftDown(int k, RunnableScheduledFuture key) {
+            int half = size >>> 1;
+            while (k < half) {
+                int child = (k << 1) + 1;
+                RunnableScheduledFuture c = queue[child];
+                int right = child + 1;
+                if (right < size && c.compareTo(queue[right]) > 0)
+                    c = queue[child = right];
+                if (key.compareTo(c) <= 0)
+                    break;
+                queue[k] = c;
+                setIndex(c, k);
+                k = child;
+            }
+            queue[k] = key;
+            setIndex(key, k);
+        }
+
+        /**
+         * Resize the heap array.  Call only when holding lock.
+         */
+        private void grow() {
+            int oldCapacity = queue.length;
+            int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
+            if (newCapacity < 0) // overflow
+                newCapacity = Integer.MAX_VALUE;
+            queue = Arrays.copyOf(queue, newCapacity);
+        }
+
+        /**
+         * Find index of given object, or -1 if absent
+         */
+        private int indexOf(Object x) {
+            if (x != null) {
+                if (x instanceof ScheduledFutureTask) {
+                    int i = ((ScheduledFutureTask) x).heapIndex;
+                    // Sanity check; x could conceivably be a
+                    // ScheduledFutureTask from some other pool.
+                    if (i >= 0 && i < size && queue[i] == x)
+                        return i;
+                } else {
+                    for (int i = 0; i < size; i++)
+                        if (x.equals(queue[i]))
+                            return i;
+                }
+            }
+            return -1;
+        }
+
+        public boolean contains(Object x) {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return indexOf(x) != -1;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public boolean remove(Object x) {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                int i = indexOf(x);
+                if (i < 0)
+                    return false;
+
+                setIndex(queue[i], -1);
+                int s = --size;
+                RunnableScheduledFuture replacement = queue[s];
+                queue[s] = null;
+                if (s != i) {
+                    siftDown(i, replacement);
+                    if (queue[i] == replacement)
+                        siftUp(i, replacement);
+                }
+                return true;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public int size() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return size;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public boolean isEmpty() {
+            return size() == 0;
+        }
+
+        public int remainingCapacity() {
+            return Integer.MAX_VALUE;
+        }
+
+        public RunnableScheduledFuture peek() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return queue[0];
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public boolean offer(Runnable x) {
+            if (x == null)
+                throw new NullPointerException();
+            RunnableScheduledFuture e = (RunnableScheduledFuture)x;
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                int i = size;
+                if (i >= queue.length)
+                    grow();
+                size = i + 1;
+                if (i == 0) {
+                    queue[0] = e;
+                    setIndex(e, 0);
+                } else {
+                    siftUp(i, e);
+                }
+                if (queue[0] == e) {
+                    leader = null;
+                    available.signal();
+                }
+            } finally {
+                lock.unlock();
+            }
+            return true;
+        }
+
+        public void put(Runnable e) {
+            offer(e);
+        }
+
+        public boolean add(Runnable e) {
+            return offer(e);
+        }
+
+        public boolean offer(Runnable e, long timeout, TimeUnit unit) {
+            return offer(e);
+        }
+
+        /**
+         * Performs common bookkeeping for poll and take: Replaces
+         * first element with last and sifts it down.  Call only when
+         * holding lock.
+         * @param f the task to remove and return
+         */
+        private RunnableScheduledFuture finishPoll(RunnableScheduledFuture f) {
+            int s = --size;
+            RunnableScheduledFuture x = queue[s];
+            queue[s] = null;
+            if (s != 0)
+                siftDown(0, x);
+            setIndex(f, -1);
+            return f;
+        }
+
+        public RunnableScheduledFuture poll() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                RunnableScheduledFuture first = queue[0];
+                if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+                    return null;
+                else
+                    return finishPoll(first);
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public RunnableScheduledFuture take() throws InterruptedException {
+            final ReentrantLock lock = this.lock;
+            lock.lockInterruptibly();
+            try {
+                for (;;) {
+                    RunnableScheduledFuture first = queue[0];
+                    if (first == null)
+                        available.await();
+                    else {
+                        long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                        if (delay <= 0)
+                            return finishPoll(first);
+                        else if (leader != null)
+                            available.await();
+                        else {
+                            Thread thisThread = Thread.currentThread();
+                            leader = thisThread;
+                            try {
+                                available.awaitNanos(delay);
+                            } finally {
+                                if (leader == thisThread)
+                                    leader = null;
+                            }
+                        }
+                    }
+                }
+            } finally {
+                if (leader == null && queue[0] != null)
+                    available.signal();
+                lock.unlock();
+            }
+        }
+
+        public RunnableScheduledFuture poll(long timeout, TimeUnit unit)
+            throws InterruptedException {
+            long nanos = unit.toNanos(timeout);
+            final ReentrantLock lock = this.lock;
+            lock.lockInterruptibly();
+            try {
+                for (;;) {
+                    RunnableScheduledFuture first = queue[0];
+                    if (first == null) {
+                        if (nanos <= 0)
+                            return null;
+                        else
+                            nanos = available.awaitNanos(nanos);
+                    } else {
+                        long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                        if (delay <= 0)
+                            return finishPoll(first);
+                        if (nanos <= 0)
+                            return null;
+                        if (nanos < delay || leader != null)
+                            nanos = available.awaitNanos(nanos);
+                        else {
+                            Thread thisThread = Thread.currentThread();
+                            leader = thisThread;
+                            try {
+                                long timeLeft = available.awaitNanos(delay);
+                                nanos -= delay - timeLeft;
+                            } finally {
+                                if (leader == thisThread)
+                                    leader = null;
+                            }
+                        }
+                    }
+                }
+            } finally {
+                if (leader == null && queue[0] != null)
+                    available.signal();
+                lock.unlock();
+            }
+        }
+
+        public void clear() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                for (int i = 0; i < size; i++) {
+                    RunnableScheduledFuture t = queue[i];
+                    if (t != null) {
+                        queue[i] = null;
+                        setIndex(t, -1);
+                    }
+                }
+                size = 0;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        /**
+         * Return and remove first element only if it is expired.
+         * Used only by drainTo.  Call only when holding lock.
+         */
+        private RunnableScheduledFuture pollExpired() {
+            RunnableScheduledFuture first = queue[0];
+            if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+                return null;
+            return finishPoll(first);
+        }
+
+        public int drainTo(Collection<? super Runnable> c) {
+            if (c == null)
+                throw new NullPointerException();
+            if (c == this)
+                throw new IllegalArgumentException();
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                RunnableScheduledFuture first;
+                int n = 0;
+                while ((first = pollExpired()) != null) {
+                    c.add(first);
+                    ++n;
+                }
+                return n;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public int drainTo(Collection<? super Runnable> c, int maxElements) {
+            if (c == null)
+                throw new NullPointerException();
+            if (c == this)
+                throw new IllegalArgumentException();
+            if (maxElements <= 0)
+                return 0;
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                RunnableScheduledFuture first;
+                int n = 0;
+                while (n < maxElements && (first = pollExpired()) != null) {
+                    c.add(first);
+                    ++n;
+                }
+                return n;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public Object[] toArray() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return Arrays.copyOf(queue, size, Object[].class);
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public <T> T[] toArray(T[] a) {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                if (a.length < size)
+                    return (T[]) Arrays.copyOf(queue, size, a.getClass());
+                System.arraycopy(queue, 0, a, 0, size);
+                if (a.length > size)
+                    a[size] = null;
+                return a;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public Iterator<Runnable> iterator() {
+            return new Itr(Arrays.copyOf(queue, size));
+        }
+
+        /**
+         * Snapshot iterator that works off copy of underlying q array.
+         */
+        private class Itr implements Iterator<Runnable> {
+            final RunnableScheduledFuture[] array;
+            int cursor = 0;     // index of next element to return
+            int lastRet = -1;   // index of last element, or -1 if no such
+
+            Itr(RunnableScheduledFuture[] array) {
+                this.array = array;
+            }
+
+            public boolean hasNext() {
+                return cursor < array.length;
+            }
+
+            public Runnable next() {
+                if (cursor >= array.length)
+                    throw new NoSuchElementException();
+                lastRet = cursor;
+                return array[cursor++];
+            }
+
+            public void remove() {
+                if (lastRet < 0)
+                    throw new IllegalStateException();
+                DelayedWorkQueue.this.remove(array[lastRet]);
+                lastRet = -1;
+            }
+        }
+    }
+
+  // Duplicated package-private methods from ThreadPoolExecutor
+
+    private static final int COUNT_BITS = Integer.SIZE - 3;
+    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
+    private static final int RUNNING    = -1 << COUNT_BITS;
+    private static final int SHUTDOWN   =  0 << COUNT_BITS;
+    private static final int TIDYING    =  2 << COUNT_BITS;
+    private static final int TERMINATED =  3 << COUNT_BITS;
+
+    // Packing and unpacking ctl
+    private static int runStateOf(int c)     { return c & ~CAPACITY; }
+    private static int workerCountOf(int c)  { return c & CAPACITY; }
+    private static int ctlOf(int rs, int wc) { return rs | wc; }
+
+    private static final boolean ONLY_ONE = true;
+
+    /**
+     * Transitions to TERMINATED state if either (SHUTDOWN and pool
+     * and queue empty) or (STOP and pool empty).  If otherwise
+     * eligible to terminate but workerCount is nonzero, interrupts an
+     * idle worker to ensure that shutdown signals propagate. This
+     * method must be called following any action that might make
+     * termination possible -- reducing worker count or removing tasks
+     * from the queue during shutdown. The method is non-private to
+     * allow access from ScheduledThreadPoolExecutor.
+     */
+    private final void tryTerminateSTPE() {
+        final JavaUtilConcurrentThreadPoolExecutorAccess juctpea = 
+	  SharedSecrets.getJavaUtilConcurrentThreadPoolExecutorAccess();
+        final AtomicInteger ctl = juctpea.getCtl(this);
+        for (;;) {
+	    int c = ctl.get();
+            if (isRunning(c) ||
+                runStateAtLeast(c, TIDYING) ||
+                (runStateOf(c) == SHUTDOWN && ! juctpea.isWorkQueueEmpty(this)))
+                return;
+            if (workerCountOf(c) != 0) { // Eligible to terminate
+	        juctpea.interruptIdleWorkers(this, ONLY_ONE);
+                return;
+            }
+
+            juctpea.lockMainLock(this);
+            try {
+                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
+                    try {
+                        terminated();
+                    } finally {
+                        ctl.set(ctlOf(TERMINATED, 0));
+                        juctpea.signalAll(this);
+                    }
+                    return;
+                }
+            } finally {
+	        juctpea.unlockMainLock(this);
+            }
+            // else retry on failed CAS
+        }
+    }
+
+    /**
+     * State check needed by ScheduledThreadPoolExecutor to
+     * enable running tasks during shutdown.
+     *
+     * @param shutdownOK true if should return true if SHUTDOWN
+     */
+    private final boolean isRunningOrShutdownSTPE(boolean shutdownOK) {
+        int rs = runStateOf(SharedSecrets.getJavaUtilConcurrentThreadPoolExecutorAccess().getCtl(this).get());
+        return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
+    }
+
+    /**
+     * Invokes the rejected execution handler for the given command.
+     * Package-protected for use by ScheduledThreadPoolExecutor.
+     */
+    private final void rejectSTPE(Runnable command) {
+        SharedSecrets.getJavaUtilConcurrentThreadPoolExecutorAccess().rejectedExecution(command, this);
+    }
+
+    private static boolean isRunning(int c) {
+        return c < SHUTDOWN;
+    }
+
+    private static boolean runStateAtLeast(int c, int s) {
+        return c >= s;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaIODeleteOnExitAccess.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,43 @@
+/* JavaIODeleteOnExitAccess.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.classpath.icedtea.misc;
+
+public interface JavaIODeleteOnExitAccess
+{
+  void add(String path);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,46 @@
+/* JavaNetGetIndex.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.classpath.icedtea.misc;
+
+import java.net.NetworkInterface;
+
+public interface JavaNetGetIndexAccess
+{
+  int getIndex(NetworkInterface nf);
+  NetworkInterface getByIndex(int i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaUtilConcurrentThreadPoolExecutorAccess.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,58 @@
+/* JavaUtilConcurrentThreadPoolExecutorAccess.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.classpath.icedtea.misc;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public interface JavaUtilConcurrentThreadPoolExecutorAccess
+{
+  AtomicInteger getCtl(ThreadPoolExecutor e);
+  void lockMainLock(ThreadPoolExecutor e);
+  void unlockMainLock(ThreadPoolExecutor e);
+  void signalAll(ThreadPoolExecutor e);
+  void rejectedExecution(Runnable command, ThreadPoolExecutor e);
+  boolean isWorkQueueEmpty(ThreadPoolExecutor e);
+  void interruptIdleWorkers(ThreadPoolExecutor e, boolean onlyOne);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/SharedSecrets.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,102 @@
+/* SharedSecrets.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+/** Based on sun.misc.SharedSecrets */
+package org.classpath.icedtea.misc;
+
+import sun.misc.Unsafe;
+
+/** A repository of "shared secrets", which are a mechanism for
+    calling implementation-private methods in another package without
+    using reflection. A package-private class implements a public
+    interface and provides the ability to call package-private methods
+    within that package; the object implementing that interface is
+    provided through a third package to which access is restricted.
+    This framework avoids the primary disadvantage of using reflection
+    for this purpose, namely the loss of compile-time checking. */
+
+public class SharedSecrets 
+{
+  private static final Unsafe unsafe = Unsafe.getUnsafe();
+  private static JavaIODeleteOnExitAccess javaIODeleteOnExitAccess;
+  private static JavaUtilConcurrentThreadPoolExecutorAccess javaUtilConcurrentThreadPoolExecutorAccess;
+  private static JavaNetGetIndexAccess javaNetGetIndexAccess;
+
+  public static void setJavaIODeleteOnExitAccess(JavaIODeleteOnExitAccess jida) 
+  {
+    javaIODeleteOnExitAccess = jida;
+  }
+  
+  public static JavaIODeleteOnExitAccess getJavaIODeleteOnExitAccess() 
+  {
+    if (javaIODeleteOnExitAccess == null) 
+      {
+	unsafe.ensureClassInitialized(java.io.File.class);
+      }
+    return javaIODeleteOnExitAccess;
+  }
+
+  public static void setJavaUtilConcurrentThreadPoolExecutorAccess(JavaUtilConcurrentThreadPoolExecutorAccess juctpea) 
+  {
+    javaUtilConcurrentThreadPoolExecutorAccess = juctpea;
+  }
+  
+  public static JavaUtilConcurrentThreadPoolExecutorAccess getJavaUtilConcurrentThreadPoolExecutorAccess() 
+  {
+    if (javaUtilConcurrentThreadPoolExecutorAccess == null) 
+      {
+	unsafe.ensureClassInitialized(java.util.concurrent.ThreadPoolExecutor.class);
+      }
+    return javaUtilConcurrentThreadPoolExecutorAccess;
+  }
+
+  public static void setJavaNetGetIndexAccess(JavaNetGetIndexAccess jngia) 
+  {
+    javaNetGetIndexAccess = jngia;
+  }
+  
+  public static JavaNetGetIndexAccess getJavaNetGetIndexAccess() 
+  {
+    if (javaNetGetIndexAccess == null) 
+      {
+	unsafe.ensureClassInitialized(java.net.NetworkInterface.class);
+      }
+    return javaNetGetIndexAccess;
+  }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,64 @@
+/*
+ * 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.util.concurrent.Future;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannel;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,359 @@
+/*
+ * 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.io.IOException;
+import java.io.FileDescriptor;
+import java.util.Queue;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+
+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;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup;
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+import org.classpath.icedtea.java.util.concurrent.ScheduledThreadPoolExecutor;
+
+/**
+ * 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 =
+	  new ScheduledThreadPoolExecutor(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	Tue Feb 10 21:56:55 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.ch;
+
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.locks.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.FileLock;
+
+/**
+ * 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) {
+                        ((AsynchronousFileLockImpl)fl).invalidate();
+                    }
+                });
+            } catch (IOException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    /**
+     * Adds region to lock table
+     */
+    protected final AsynchronousFileLockImpl addToFileLockTable(long position, long size, boolean shared) {
+        final AsynchronousFileLockImpl 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 AsynchronousFileLockImpl(this, position, size, shared);
+            // may throw OverlappedFileLockException
+            fileLockTable.add(fli);
+        } finally {
+            end();
+        }
+        return fli;
+    }
+
+    protected final void removeFromFileLockTable(AsynchronousFileLockImpl fli) {
+        fileLockTable.remove(fli);
+    }
+
+    /**
+     * Invoked by FileLockImpl to release lock acquired by this channel.
+     */
+    abstract void release(AsynchronousFileLockImpl 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,68 @@
+/*
+ * 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.Channel;
+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;
+
+    AsynchronousFileLockImpl(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	Tue Feb 10 21:56:55 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.
+ */
+
+package sun.nio.ch;
+
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.classpath.icedtea.java.net.SocketOption;
+import org.classpath.icedtea.java.net.StandardSocketOption;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousServerSocketChannel;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,546 @@
+/*
+ * 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.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.*;
+
+import org.classpath.icedtea.java.net.SocketOption;
+import org.classpath.icedtea.java.net.StandardSocketOption;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel;
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+import org.classpath.icedtea.java.nio.channels.ReadPendingException;
+import org.classpath.icedtea.java.nio.channels.WritePendingException;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,114 @@
+/*
+ * 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.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutionException;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannel;
+
+/**
+ * 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/ExtendedSocketOption.java	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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 org.classpath.icedtea.java.net.SocketOption;
+
+/**
+ * Defines socket options that are supported by the implementation
+ * but not defined in StandardSocketOption.
+ */
+
+class ExtendedSocketOption {
+    private ExtendedSocketOption() { }
+
+    static final SocketOption<Boolean> SO_OOBINLINE =
+        new SocketOption<Boolean>() {
+            public String name() { return "SO_OOBINLINE"; }
+            public Class<Boolean> type() { return Boolean.class; }
+            public String toString() { return name(); }
+        };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/FileLockTable.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,287 @@
+/*
+ * 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.OverlappingFileLockException;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.ref.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.FileLock;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,274 @@
+/*
+ * 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.util.concurrent.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannel;
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+import org.classpath.icedtea.java.nio.channels.ShutdownChannelGroupException;
+
+/**
+ * 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/MembershipKeyImpl.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,224 @@
+/*
+ * 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.net.InetAddress;
+import java.net.NetworkInterface;
+import java.io.IOException;
+import java.util.HashSet;
+
+import org.classpath.icedtea.java.nio.channels.MembershipKey;
+import org.classpath.icedtea.java.nio.channels.MulticastChannel;
+
+/**
+ * MembershipKey implementation.
+ */
+
+class MembershipKeyImpl
+    extends MembershipKey
+{
+    private final MulticastChannel ch;
+    private final InetAddress group;
+    private final NetworkInterface interf;
+    private final InetAddress source;
+
+    // true when key is valid
+    private volatile boolean valid = true;
+
+    // lock used when creating or accessing blockedSet
+    private Object stateLock = new Object();
+
+    // set of source addresses that are blocked
+    private HashSet<InetAddress> blockedSet;
+
+    private MembershipKeyImpl(MulticastChannel ch,
+                              InetAddress group,
+                              NetworkInterface interf,
+                              InetAddress source)
+    {
+        this.ch = ch;
+        this.group = group;
+        this.interf = interf;
+        this.source = source;
+    }
+
+    /**
+     * MembershipKey will additional context for IPv4 membership
+     */
+    static class Type4 extends MembershipKeyImpl {
+        private final int groupAddress;
+        private final int interfAddress;
+        private final int sourceAddress;
+
+        Type4(MulticastChannel ch,
+              InetAddress group,
+              NetworkInterface interf,
+              InetAddress source,
+              int groupAddress,
+              int interfAddress,
+              int sourceAddress)
+        {
+            super(ch, group, interf, source);
+            this.groupAddress = groupAddress;
+            this.interfAddress = interfAddress;
+            this.sourceAddress = sourceAddress;
+        }
+
+        int groupAddress() {
+            return groupAddress;
+        }
+
+        int interfaceAddress() {
+            return interfAddress;
+        }
+
+        int source() {
+            return sourceAddress;
+        }
+    }
+
+    /**
+     * MembershipKey will additional context for IPv6 membership
+     */
+    static class Type6 extends MembershipKeyImpl {
+        private final byte[] groupAddress;
+        private final int index;
+        private final byte[] sourceAddress;
+
+        Type6(MulticastChannel ch,
+              InetAddress group,
+              NetworkInterface interf,
+              InetAddress source,
+              byte[] groupAddress,
+              int index,
+              byte[] sourceAddress)
+        {
+            super(ch, group, interf, source);
+            this.groupAddress = groupAddress;
+            this.index = index;
+            this.sourceAddress = sourceAddress;
+        }
+
+        byte[] groupAddress() {
+            return groupAddress;
+        }
+
+        int index() {
+            return index;
+        }
+
+        byte[] source() {
+            return sourceAddress;
+        }
+    }
+
+    public boolean isValid() {
+        return valid;
+    }
+
+    // package-private
+    void invalidate() {
+        valid = false;
+    }
+
+    public void drop() throws IOException {
+        // delegate to channel
+        ((DatagramChannelImpl)ch).drop(this);
+    }
+
+
+    public MulticastChannel channel() {
+        return ch;
+    }
+
+
+    public InetAddress group() {
+        return group;
+    }
+
+
+    public NetworkInterface networkInterface() {
+        return interf;
+    }
+
+
+    public InetAddress sourceAddress() {
+        return source;
+    }
+
+
+    public MembershipKey block(InetAddress toBlock)
+        throws IOException
+    {
+        if (source != null)
+            throw new IllegalStateException("key is source-specific");
+
+        synchronized (stateLock) {
+            if ((blockedSet != null) && blockedSet.contains(toBlock)) {
+                // already blocked, nothing to do
+                return this;
+            }
+
+            ((DatagramChannelImpl)ch).block(this, toBlock);
+
+            // created blocked set if required and add source address
+            if (blockedSet == null)
+                blockedSet = new HashSet<InetAddress>();
+            blockedSet.add(toBlock);
+        }
+        return this;
+    }
+
+
+    public MembershipKey unblock(InetAddress toUnblock)
+        throws IOException
+    {
+        synchronized (stateLock) {
+            if ((blockedSet == null) || !blockedSet.contains(toUnblock))
+                throw new IllegalStateException("not blocked");
+
+            ((DatagramChannelImpl)ch).unblock(this, toUnblock);
+
+            blockedSet.remove(toUnblock);
+        }
+        return this;
+    }
+
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(64);
+        sb.append('<');
+        sb.append(group.getHostAddress());
+        sb.append(',');
+        sb.append(interf.getName());
+        if (source != null) {
+            sb.append(',');
+            sb.append(source.getHostAddress());
+        }
+        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/MembershipRegistry.java	Tue Feb 10 21:56:55 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.
+ */
+
+package sun.nio.ch;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.channels.MembershipKey;
+
+/**
+ * Simple registry of membership keys for a MulticastChannel.
+ *
+ * Instances of this object are not safe by multiple concurrent threads.
+ */
+
+class MembershipRegistry {
+
+    // map multicast group to keys
+    private Map<InetAddress,List<MembershipKeyImpl>> groups = null;
+
+    MembershipRegistry() {
+    }
+
+    /**
+     * Checks registry for membership of the group on the given
+     * network interface.
+     */
+    MembershipKey checkMembership(InetAddress group, NetworkInterface interf,
+                                  InetAddress source)
+    {
+        if (groups != null) {
+            List<MembershipKeyImpl> keys = groups.get(group);
+            if (keys != null) {
+                for (MembershipKeyImpl key: keys) {
+                    if (key.networkInterface().equals(interf)) {
+                        // already a member to receive all packets so return
+                        // existing key or detect conflict
+                        if (source == null) {
+                            if (key.sourceAddress() == null)
+                                return key;
+                            throw new IllegalStateException("Already a member to receive all packets");
+                        }
+
+                        // already have source-specific membership so return key
+                        // or detect conflict
+                        if (key.sourceAddress() == null)
+                            throw new IllegalStateException("Already have source-specific membership");
+                        if (source.equals(key.sourceAddress()))
+                            return key;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Add membership to the registry, returning a new membership key.
+     */
+    void add(MembershipKeyImpl key) {
+        InetAddress group = key.group();
+        List<MembershipKeyImpl> keys;
+        if (groups == null) {
+            groups = new HashMap<InetAddress,List<MembershipKeyImpl>>();
+            keys = null;
+        } else {
+            keys = groups.get(group);
+        }
+        if (keys == null) {
+            keys = new LinkedList<MembershipKeyImpl>();
+            groups.put(group, keys);
+        }
+        keys.add(key);
+    }
+
+    /**
+     * Remove a key from the registry
+     */
+    void remove(MembershipKeyImpl key) {
+        InetAddress group = key.group();
+        List<MembershipKeyImpl> keys = groups.get(group);
+        if (keys != null) {
+            Iterator<MembershipKeyImpl> i = keys.iterator();
+            while (i.hasNext()) {
+                if (i.next() == key) {
+                    i.remove();
+                    break;
+                }
+            }
+            if (keys.isEmpty()) {
+                groups.remove(group);
+            }
+        }
+    }
+
+    /**
+     * Invalidate all keys in the registry
+     */
+    void invalidateAll() {
+        if (groups != null) {
+            for (InetAddress group: groups.keySet()) {
+                for (MembershipKeyImpl key: groups.get(group)) {
+                    key.invalidate();
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/OptionKey.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+/**
+ * Represents the level/name of a socket option
+ */
+
+class OptionKey {
+    private int level;
+    private int name;
+
+    OptionKey(int level, int name) {
+        this.level = level;
+        this.name = name;
+    }
+
+    int level() {
+        return level;
+    }
+
+    int name() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/PendingFuture.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,259 @@
+/*
+ * 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.util.concurrent.*;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannel;
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,425 @@
+/*
+ * 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.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetConnectedException;
+
+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;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+import org.classpath.icedtea.java.net.SocketOption;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousDatagramChannel;
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+import org.classpath.icedtea.java.nio.channels.DatagramChannel;
+import org.classpath.icedtea.java.nio.channels.InterruptedByTimeoutException;
+import org.classpath.icedtea.java.nio.channels.MembershipKey;
+import org.classpath.icedtea.java.nio.channels.MulticastChannel;
+import org.classpath.icedtea.java.nio.channels.ShutdownChannelGroupException;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,437 @@
+/*
+ * 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.util.concurrent.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+import org.classpath.icedtea.java.nio.channels.FileLock;
+import org.classpath.icedtea.java.nio.channels.ShutdownChannelGroupException;
+
+/**
+ * "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 FileDispatcher();
+
+    // 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 AsynchronousFileLockImpl 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
+        AsynchronousFileLockImpl 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(AsynchronousFileLockImpl 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	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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.util.concurrent.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.attribute.AclEntry;
+import org.classpath.icedtea.java.nio.file.attribute.AclFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,210 @@
+/*
+ * 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.io.IOException;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,121 @@
+/*
+ * 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.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributeView;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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.
+ */
+
+package sun.nio.fs;
+
+import java.io.IOException;
+import sun.nio.fs.MimeType;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.spi.FileTypeDetector;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,125 @@
+/*
+ * 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.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.attribute.NamedAttributeView;
+
+/**
+ * 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;
+         try {
+             size = size(attribute);
+         } catch (IOException e) {
+             // not found or some other I/O error
+             if (list().contains(attribute))
+                 throw e;
+             return null;
+         }
+         byte[] buf = new byte[size];
+         int n = read(attribute, ByteBuffer.wrap(buf));
+         return (n == size) ? buf : Arrays.copyOf(buf, n);
+    }
+
+
+    public final void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+         ByteBuffer bb;
+         if (value instanceof byte[]) {
+             bb = ByteBuffer.wrap((byte[])value);
+         } else {
+             bb = (ByteBuffer)value;
+         }
+         write(attribute, bb);
+    }
+
+
+    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;
+            } else {
+                names.add(name);
+            }
+        }
+        if (readAll)
+            names = list();
+
+        // read each value and return in map
+        Map<String,Object> result = new HashMap<String,Object>();
+        for (String name: names) {
+            Object value = getAttribute(name);
+            if (value != null)
+                result.put(name, value);
+        }
+
+        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	Tue Feb 10 21:56:55 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.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.ClosedWatchServiceException;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.StandardWatchEventKind;
+import org.classpath.icedtea.java.nio.file.WatchEvent;
+import org.classpath.icedtea.java.nio.file.WatchKey;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,179 @@
+/*
+ * 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 org.classpath.icedtea.java.nio.file.StandardWatchEventKind;
+import org.classpath.icedtea.java.nio.file.WatchEvent;
+import org.classpath.icedtea.java.nio.file.WatchKey;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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.concurrent.*;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.ClosedWatchServiceException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.WatchEvent;
+import org.classpath.icedtea.java.nio.file.WatchKey;
+import org.classpath.icedtea.java.nio.file.WatchService;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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 given task in its own thread. If this (meaning the current)
+     * thread is interrupted then an attempt is make to cancel the background
+     * thread by writing into the memory location that it polls cooperatively.
+     */
+    static void runInterruptibly(Cancellable task) throws ExecutionException {
+        Thread t = new Thread(task);
+        t.start();
+        boolean cancelledByInterrupt = false;
+        while (t.isAlive()) {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+                cancelledByInterrupt = true;
+                task.cancel();
+            }
+        }
+        if (cancelledByInterrupt)
+            Thread.currentThread().interrupt();
+        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	Tue Feb 10 21:56:55 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.
+ */
+
+package sun.nio.fs;
+
+import java.util.*;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.attribute.AclFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileOwnerAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,454 @@
+/*
+ * 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.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.ClosedWatchServiceException;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.NotDirectoryException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.StandardWatchEventKind;
+import org.classpath.icedtea.java.nio.file.WatchEvent;
+import org.classpath.icedtea.java.nio.file.WatchKey;
+
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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/demo/nio/ZipFileSystem/META-INF/services/java.nio.file.spi.FileSystemProvider	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,1 @@
+com.sun.nio.zipfs.ZipFileSystemProvider
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/README.txt	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,29 @@
+ZipFileSystem is a file system provider that treats the contents of a zip or
+JAR file as a read-only file system.
+
+To deploy the provider you must copy ZipFileSystem.jar into your extensions
+directory or else add <JDK_HOME>/demo/nio/ZipFileSystem/ZipFileSystem.jar
+to your class path.
+
+The factory methods defined by the java.nio.file.FileSystems class can be
+used to create a FileSystem, eg:
+
+   // use file type detection
+   Map<String,?> env = Collections.emptyMap();
+   Path jarfile = Path.get("foo.jar");
+   FileSystem fs = FileSystems.newFileSystem(jarfile, env);
+
+-or
+
+   // locate file system by URI
+   Map<String,?> env = Collections.emptyMap();
+   URI uri = URI.create("zip:///mydir/foo.jar");
+   FileSystem fs = FileSystems.newFileSystem(uri, env);
+
+Once a FileSystem is created then classes in the java.nio.file package
+can be used to access files in the zip/JAR file, eg:
+
+   Path mf = fs.getPath("/META-INF/MANIFEST.MF");
+   InputStream in = mf.newInputStream();
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarEntryInfo.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.util.Map;
+import java.util.Set;
+
+public class JarEntryInfo extends ZipEntryInfo {
+    JarEntryInfo(ZipEntryInfo entry){
+        super(entry);
+    }
+
+    Set<Map.Entry<Object, Object>> entryAttributs;
+    Set<Map.Entry<Object, Object>> manifestMainAttrs;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributeView.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+public class JarFileAttributeView extends ZipFileAttributeView {
+
+    /** Creates a new instance of ZipFileAttributeView */
+    public JarFileAttributeView(FileRef file) {
+        super(file);
+    }
+
+
+    public String name() {
+        return "jar";
+    }
+
+    public Object getAttribute(String attribute) throws IOException {
+        JarFileAttributes jfa = readAttributes();
+        if (attribute.equals("manifestAttributes")) {
+            return jfa.getManifestAttributes();
+        }
+        if (attribute.equals("entryAttributes")) {
+            return jfa.getEntryAttributes();
+        }
+        return super.readAttributes(attribute);
+    }
+
+
+    public JarFileAttributes readAttributes()
+            throws IOException {
+        return new JarFileAttributes(super.getBinding());
+    }
+
+
+    public Map<String, ?> readAttributes(String first, String... rest) throws IOException {
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.putAll(super.readAttributes(first, rest));
+
+        // FIXME - add manifest and entry attributes if requested
+
+        return Collections.unmodifiableMap(result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/JarFileAttributes.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.util.concurrent.*;
+import java.io.*;
+import java.util.Map;
+import java.util.Set;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+public class JarFileAttributes extends ZipFileAttributes {
+
+    /** Creates a new instance of ZipFileAttributes */
+    public JarFileAttributes(FileRef file)
+            throws IOException {
+        super(file);
+
+    }
+
+    public Set<Map.Entry<Object, Object>> getManifestAttributes() {
+        return ((JarEntryInfo) ze).manifestMainAttrs;
+    }
+
+    public Set<Map.Entry<Object, Object>> getEntryAttributes() {
+        return ((JarEntryInfo) ze).entryAttributs;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipEntryInfo.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+public class ZipEntryInfo {
+
+    byte[] filename;
+    int compSize;
+    int size;
+    byte[] comment;
+    long crc;
+    byte[] extraField;
+    int method;
+    int extAttrs;
+    long createTime = -1;
+    boolean isDirectory;
+    boolean isOtherFile;
+    boolean isRegularFile;
+    boolean isArchiveFile;
+    long lastAccessTime = -1;
+    long lastModifiedTime;
+    long streamOffset;
+    int versionMadeBy;
+    ZipEntryInfo(ZipEntryInfo entry){
+        this.filename = entry.filename;
+        this.compSize = entry.compSize;
+        this.size = entry.size;
+        this.comment = entry.comment;
+        this.crc = entry.crc;
+        this.extraField = entry.extraField;
+        this.method = entry.method;
+        this.extAttrs = entry.extAttrs;
+        this.createTime = entry.createTime;
+        this.isDirectory = entry.isDirectory;
+        this.isOtherFile = entry.isOtherFile;
+        this.isRegularFile = entry.isRegularFile;
+        this.isArchiveFile = entry.isArchiveFile;
+        this.lastAccessTime = entry.lastAccessTime;
+        this.lastModifiedTime = entry.lastModifiedTime;
+        this.streamOffset = entry.streamOffset;
+        this.versionMadeBy = entry.versionMadeBy;
+
+    }
+    ZipEntryInfo(){
+        super();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributeView.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+public class ZipFileAttributeView extends ZipFileBasicAttributeView {
+
+    /** Creates a new instance of ZipFileAttributeView */
+    public ZipFileAttributeView(FileRef file) {
+        super(file);
+    }
+
+
+    public String name() {
+        return "zip";
+    }
+
+    public Object getAttribute(String attribute) throws IOException {
+        ZipFileAttributes zfa = readAttributes();
+        if (attribute.equals("comment")) {
+            return zfa.comment();
+        }
+        if (attribute.equals("compressedSize")) {
+            return zfa.compressedSize();
+        }
+        if (attribute.equals("crc")) {
+            return zfa.crc();
+        }
+        if (attribute.equals("extraField")) {
+            return zfa.extra();
+        }
+        if (attribute.equals("method")) {
+            return zfa.method();
+        }
+        if (attribute.equals("fileName")) {
+            return zfa.name();
+        }
+        if (attribute.equals("isArchiveFile")) {
+            return zfa.isArchiveFile();
+        }
+        if (attribute.equals("versionMadeBy")) {
+            return zfa.versionMadeBy();
+        }
+        if (attribute.equals("externalAttrs")) {
+            return zfa.getExternalAttrs();
+        }
+        return super.getAttribute(attribute);
+    }
+
+
+    public Map<String, ?> readAttributes(String first, String... rest) throws IOException {
+        int rem = rest.length;
+        String[] attrs = new String[1 + rem];
+        attrs[0] = first;
+        if (rem > 0)
+            System.arraycopy(rest, 0, attrs, 1, rem);
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.putAll(super.readAttributes(first, rest));
+        ZipFileAttributes zfa = readAttributes();
+        boolean added = false;
+        for (String attr : attrs) {
+            added = addAttribute(result, attr, "comment",zfa.comment());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "compressedSize",zfa.compressedSize());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "crc",zfa.crc());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "extraField",zfa.extra());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "method",zfa.method());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "fileName",zfa.name());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "isArchiveFile",zfa.isArchiveFile());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "versionMadeBy",zfa.versionMadeBy());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "externalAttrs",zfa.getExternalAttrs());
+            if (attr.equals("*")){
+                break;
+            }
+        }
+        return Collections.unmodifiableMap(result);
+    }
+
+    private boolean addAttribute(Map<String, Object> result, String attr, String checkAttr,Object value) {
+        if ((result.containsKey(checkAttr))) {
+            return true;
+        }
+        if (attr.equals("*") || attr.equals(checkAttr)) {
+            result.put(checkAttr, value);
+            if (attr.equals("*")) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    public ZipFileAttributes readAttributes()
+            throws IOException {
+        return new ZipFileAttributes(super.getBinding());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileAttributes.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.util.concurrent.*;
+import java.io.*;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+public class ZipFileAttributes extends ZipFileBasicAttributes {
+
+    /** Creates a new instance of ZipFileAttributes */
+    private String[] version = {"FAT file system (DOS, OS/2, NT)", "Amiga", "VMS (VAX or Alpha AXP)", "Unix", "VM/CMS", "Atari", "HPFS file system (OS/2, NT 3.x)",
+        "Macintosh", "Z-System", "CP/M", "TOPS-20", "NTFS file system (NT)", "SMS/QDOS", "Acorn RISC OS", "VFAT file system (Win95, NT)",
+        "MVS", "BeOS (BeBox or PowerMac)", "Tandem"
+    };
+
+    public ZipFileAttributes(FileRef file)
+            throws IOException {
+        super(file);
+    }
+
+
+    public byte[] comment() {
+        return ze.comment;
+    }
+
+    public int compressedSize() {
+        return ze.compSize;
+    }
+
+    public long crc() {
+        return ze.crc;
+    }
+
+    public byte[] extra() {
+        return ze.extraField;
+    }
+
+    public int method() {
+        return ze.method;
+    }
+
+    public byte[] name() {
+        return ze.filename;
+    }
+
+    public boolean isArchiveFile() {
+        return ze.isArchiveFile;
+    }
+
+    public String versionMadeBy() {
+        int ver = (ze.versionMadeBy >> 8);
+        if (ver >= 0 && ver < 17) {
+            return version[ver];
+        } else {
+            return "unused";
+        }
+    }
+
+    public int getExternalAttrs() {
+        return ze.extAttrs;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributeView.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.ReadOnlyFileSystemException;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+
+public class ZipFileBasicAttributeView implements
+        BasicFileAttributeView {
+    // encapsulates the object that we are bound too
+
+    private final FileRef file;
+
+    /** Creates a new instance of ZipFileAttributeView */
+    public ZipFileBasicAttributeView(FileRef file) {
+        this.file = file;
+    }
+
+
+    public String name() {
+        return "basic";
+    }
+
+
+    public Object getAttribute(String attribute) throws IOException {
+
+        BasicFileAttributes bfa = readAttributes();
+        if (attribute.equals("lastModifiedTime")) {
+            return bfa.lastModifiedTime();
+        }
+        if (attribute.equals("lastAccessTime")) {
+            return bfa.lastAccessTime();
+        }
+        if (attribute.equals("creationTime")) {
+            return bfa.creationTime();
+        }
+        if (attribute.equals("size")) {
+            return bfa.size();
+        }
+        if (attribute.equals("isRegularFile")) {
+            return bfa.isRegularFile();
+        }
+        if (attribute.equals("isDirectory")) {
+            return bfa.isDirectory();
+        }
+        if (attribute.equals("isSymbolicLink")) {
+            return bfa.isSymbolicLink();
+        }
+        if (attribute.equals("isOther")) {
+            return bfa.isOther();
+        }
+        if (attribute.equals("linkCount")) {
+            return bfa.linkCount();
+        }
+        if (attribute.equals("fileKey")) {
+            return bfa.fileKey();
+        }
+        return null;
+    }
+
+
+    public void setAttribute(String attribute, Object value) {
+        throw new ReadOnlyFileSystemException();
+    }
+
+
+    public Map<String, ?> readAttributes(String first, String... rest) throws IOException {
+        int rem = rest.length;
+        String[] attrs = new String[1 + rem];
+        attrs[0] = first;
+        if (rem > 0)
+            System.arraycopy(rest, 0, attrs, 1, rem);
+        Map<String, Object> result = new HashMap<String, Object>();
+        BasicFileAttributes ba = readAttributes();
+        boolean added = false;
+        for (String attr : attrs) {
+            added = addAttribute(result, attr, "lastModifiedTime", ba.lastModifiedTime());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "lastAccessTime", ba.lastAccessTime());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "creationTime", ba.creationTime());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "size", ba.size());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "isRegularFile", ba.isRegularFile());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "isDirectory", ba.isDirectory());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "isSymbolicLink", ba.isSymbolicLink());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "isOther", ba.isOther());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "linkCount", ba.linkCount());
+            if (added) {
+                continue;
+            }
+            added = addAttribute(result, attr, "fileKey", ba.fileKey());
+            if (added) {
+                continue;
+            }
+            if (attr.equals("*")) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    FileRef getBinding() {
+        FileRef b = file;
+        return b;
+    }
+
+    public BasicFileAttributes readAttributes()
+            throws IOException {
+        return new ZipFileBasicAttributes(getBinding());
+    }
+
+    public void setTimes(Long lastModifiedTime, Long lastAccessTime, Long createTime, TimeUnit unit) throws IOException {
+        throw new ReadOnlyFileSystemException();
+    }
+
+    private boolean addAttribute(Map<String, Object> result, String attr, String checkAttr, Object value) {
+        if ((result.containsKey(checkAttr))) {
+            return true;
+        }
+        if (attr.equals("*") || attr.equals(checkAttr)) {
+            result.put(checkAttr, value);
+            if (attr.equals("*")) {
+                return false; // not added completely.
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileBasicAttributes.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.util.concurrent.*;
+import java.io.IOException;
+import java.util.Calendar;
+
+import org.classpath.icedtea.java.nio.file.ClosedFileSystemException;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.ReadOnlyFileSystemException;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+
+public class ZipFileBasicAttributes implements
+        BasicFileAttributes {
+
+    FileRef file;
+    ZipEntryInfo ze;
+
+    /** Creates a new instance of ZipFileAttributes */
+    public ZipFileBasicAttributes(FileRef file)
+            throws IOException {
+        this.file = file;
+        ensureOpen();
+        ze = ZipUtils.getEntry(file);
+    }
+
+    void ensureOpen() {
+        if (file instanceof ZipFilePath && !((ZipFilePath) file).getFileSystem().isOpen()) {
+            throw new ClosedFileSystemException();
+        }
+    }
+
+
+    public long creationTime() {
+        return ze.createTime;
+    }
+
+    public boolean isDirectory() {
+        return ze.isDirectory;
+    }
+
+    public boolean isLink() {
+        return false;
+    }
+
+    public boolean isOther() {
+        return ze.isOtherFile;
+    }
+
+    public boolean isRegularFile() {
+        return ze.isRegularFile;
+    }
+
+    public long lastAccessTime() {
+        return ze.lastAccessTime;
+    }
+
+    public long lastModifiedTime() {
+        long time = ze.lastModifiedTime;
+        Calendar cal = dosTimeToJavaTime(time);
+        return cal.getTimeInMillis();
+    }
+
+    private Calendar dosTimeToJavaTime(long time) {
+        Calendar cal = Calendar.getInstance();
+        cal.set((int) (((time >> 25) & 0x7f) + 1980),
+                (int) (((time >> 21) & 0x0f) - 1),
+                (int) ((time >> 16) & 0x1f),
+                (int) ((time >> 11) & 0x1f),
+                (int) ((time >> 5) & 0x3f),
+                (int) ((time << 1) & 0x3e));
+        return cal;
+    }
+
+    public int linkCount() {
+        return 0;
+    }
+
+    public TimeUnit resolution() {
+        return TimeUnit.MILLISECONDS;
+    }
+
+    public long size() {
+        return ze.size;
+    }
+
+    public boolean isSymbolicLink() {
+        return false;
+    }
+
+    public Object fileKey() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,1027 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.*;
+import java.net.URI;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+
+import org.classpath.icedtea.java.nio.file.AccessDeniedException;
+import org.classpath.icedtea.java.nio.file.AccessMode;
+import org.classpath.icedtea.java.nio.file.ClosedFileSystemException;
+import org.classpath.icedtea.java.nio.file.CopyOption;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.DirectoryStream.Filter;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.NoSuchFileException;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.Paths;
+import org.classpath.icedtea.java.nio.file.PathMatcher;
+import org.classpath.icedtea.java.nio.file.ProviderMismatchException;
+import org.classpath.icedtea.java.nio.file.ReadOnlyFileSystemException;
+import org.classpath.icedtea.java.nio.file.StandardOpenOption;
+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 org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+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.spi.AbstractPath;
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Jar/Zip path implementation of Path
+ * We use "/" as the Zip File entry seperator.
+ * @author      Rajendra Gutupalli,Jaya Hangal
+ */
+public class ZipFilePath extends AbstractPath {
+
+    private ZipFileSystem fileSystem;
+    //zip file separator
+    public static final String separator = "/";
+    // path inside zip and it can contain nested zip/jar paths
+    private final byte[] path;
+    // array of offsets of components in path - created lazily
+    private volatile ArrayList<Integer> offsets;
+    // array of offsets of entry elements in the path
+    private volatile ArrayList<Integer> entryOffsets;
+    // resolved path for locating zip inside zip file
+    // resloved path does not contain ./ and .. components
+    private final byte[] pathForZip;
+    private final ReadLock readLock = new ReentrantReadWriteLock().readLock();
+    private ZipFilePath pathToZip;
+    private final byte[] pathForprint;
+
+    // package-private
+    ZipFilePath(ZipFileSystem fileSystem, byte[] pathInZip) {
+        this.fileSystem = fileSystem;
+        this.path = pathInZip;
+        this.pathForprint = pathInZip;
+        boolean isAbs = (path[0] == '/');
+        String toResolve = new String(path);
+        if (!isAbs) {
+            String defdir = fileSystem.getDefaultDir();
+            boolean endsWith = defdir.endsWith("/");
+            if (endsWith) {
+                toResolve = defdir + toResolve;
+            } else {
+                toResolve = defdir + "/" + toResolve;
+            }
+
+        }
+        pathForZip = ZipPathParser.resolve(toResolve).getBytes();
+    }
+    // if given path is resolved
+    ZipFilePath(ZipFileSystem fileSystem, byte[] pathInZip, byte[] pathForZip) {
+        this.fileSystem = fileSystem;
+        this.path = pathForZip;
+        this.pathForZip = pathForZip;
+        this.pathForprint = pathInZip; //given path
+    }
+
+    public boolean isNestedZip() {
+        Pattern pattern = Pattern.compile("\\.(?i)(zip|jar)");
+        Matcher matcher = null;
+        for (int i = 0; i < getNameCount(); i++) {
+            String entry = getName(i).toString();
+            matcher = pattern.matcher(entry);
+            if (matcher.find()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isArchiveFile() {
+        Path name = getName();
+        if (name == null) {
+            return false;
+        }
+        String fileName = name.toString().toLowerCase();
+        return (fileName.endsWith(".zip") || fileName.endsWith(".jar"));
+    }
+
+    /**
+     * A path represents directory if it ends with '/'.
+     * The normalize method does not remove the trailing '/'
+     */
+    public boolean isDirectory() {
+        try {
+            begin();
+            try {
+                ZipFilePath resolved = getResolvedPathForZip();
+                return Attributes.readBasicFileAttributes(resolved, LinkOption.NOFOLLOW_LINKS)
+                    .isDirectory();
+            } catch (IOException e) {
+                return false;
+            }
+        } finally {
+            end();
+        }
+    }
+
+    static int nextSeparator(byte[] path, int index) {
+
+        int length = path.length;
+
+        while (index < length && path[index] != '/') {
+            index++;
+        }
+        return index;
+    }
+
+    final void begin() {
+        readLock.lock();
+        if (!fileSystem.isOpen()) {
+            throw new ClosedFileSystemException();
+        }
+    }
+
+    final void end() {
+        readLock.unlock();
+    }
+
+    static int nextNonSeparator(byte[] path, int index) {
+
+        int length = path.length;
+        while (index < length && path[index] == '/') {
+            index++;
+        }
+        return index;
+    }
+
+    // create offset list if not already created
+    private void initOffsets() {
+        if (offsets == null) {
+            ArrayList<Integer> list = new ArrayList<Integer>();
+            int pathLen = path.length;
+            int index = nextNonSeparator(path, 0) - 1;
+
+            int root = index;
+
+            while ((index = nextSeparator(path, index + 1)) < pathLen && (index + 1 != pathLen)) {
+                list.add(index + 1); // puls 1 for file separator
+            }
+
+            if (root + 1 < index) { // begin index
+                list.add(0, root + 1);
+            }
+
+            offsets = list;
+        }
+
+    }
+
+    private void initEntryOffsets() {
+        if (entryOffsets == null) {
+
+            ArrayList<Integer> list1 = new ArrayList<Integer>();
+            int count = getNameCount();
+            Pattern pattern = Pattern.compile("\\.(?i)(zip|jar)");
+            Matcher matcher = null;
+            int i = 0;
+            int off = 0;
+            while (i < (count - 1)) {
+                String name = getName(i).toString();
+                matcher = pattern.matcher(name);
+                if (matcher.find()) {
+                    off = offsets.get(i + 1);
+                    list1.add(off);
+                }
+                i++;
+
+            }
+            if (count > 0) {
+                int firstNonSeparatorIndex = nextNonSeparator(path, 0);
+                list1.add(0, firstNonSeparatorIndex);
+            }
+            entryOffsets = list1;
+
+        }
+    }
+
+
+    public ZipFilePath getRoot() {
+        if (this.isAbsolute()) {
+            return new ZipFilePath(this.fileSystem, new byte[]{path[0]});
+        } else {
+            return null;
+        }
+    }
+
+
+    public Path getName() {
+        initOffsets();
+        if (offsets.size() == 0) {
+            return null;
+        }
+        String result = subString(offsets.get(offsets.size() - 1), path.length);
+        result = (result.endsWith("/")) ? result.substring(0, result.length() - 1) : result;
+        return new ZipFilePath(this.fileSystem, result.getBytes());
+
+    }
+
+    public ZipFilePath getEntryName() {
+        initEntryOffsets();
+        if (entryOffsets.size() == 0) {
+            return null;
+        }
+        String result = subString(entryOffsets.get(entryOffsets.size() - 1), path.length);
+        result = (result.endsWith("/")) ? result.substring(0, result.length() - 1) : result;
+        return new ZipFilePath(this.fileSystem, result.getBytes());
+
+    }
+
+
+    public ZipFilePath getParent() {
+        int count = getNameCount();
+        if (count == 0 || count == 1) {
+            return null;
+        }
+        int position = offsets.get(count - 1);
+        String parent = subString(0, position - 1);
+        return new ZipFilePath(this.fileSystem, parent.getBytes());
+
+    }
+
+    public ZipFilePath getParentEntry() {
+        int entryCount = getEntryNameCount();
+        if (entryCount == 0 || entryCount == 1) {
+            return null;
+        }
+        int position = entryOffsets.get(entryCount - 1);
+        String parent = subString(0, position - 1);
+        byte[] parentBytes = parent.getBytes();
+        ZipFilePath path1 = new ZipFilePath(this.fileSystem, parentBytes);
+        return path1;
+    }
+
+
+    public int getNameCount() {
+
+        initOffsets();
+        return offsets.size();
+    }
+
+    public int getEntryNameCount() {
+
+        initEntryOffsets();
+        return entryOffsets.size();
+    }
+
+
+    public ZipFilePath getName(int index) {
+
+
+        initOffsets();
+        if (index < 0 || index >= offsets.size()) {
+            throw new IllegalArgumentException();
+        }
+        if (index == offsets.size() - 1) {
+            String s = subString(offsets.get(index), path.length);
+            s = (s.endsWith("/")) ? s.substring(0, s.length() - 1) : s;
+            return new ZipFilePath(this.fileSystem, s.getBytes());
+        }
+        byte[] pathInBytes = subString(offsets.get(index), offsets.get(index + 1) - 1).getBytes();
+        return new ZipFilePath(this.fileSystem, pathInBytes);
+    }
+
+    public ZipFilePath getEntryName(int index) {
+
+        initEntryOffsets();
+        if (index < 0 || index >= entryOffsets.size()) {
+            throw new IllegalArgumentException();
+        }
+        if (index == entryOffsets.size() - 1) {
+            String s = subString(entryOffsets.get(index), path.length);
+            s = (s.endsWith("/")) ? s.substring(0, s.length() - 1) : s;
+            return new ZipFilePath(this.fileSystem, s.getBytes());
+        }
+        byte[] pathInBytes = subString(entryOffsets.get(index), entryOffsets.get(index + 1) - 1).getBytes();
+        return new ZipFilePath(this.fileSystem, pathInBytes);
+    }
+
+    String subString(int beginIndex, int endIndex) {
+        int length = endIndex - beginIndex;
+        byte[] arr = new byte[length];
+        System.arraycopy(path, beginIndex, arr, 0, length);
+        return new String(arr);
+    }
+
+
+    public ZipFilePath subpath(int beginIndex, int endIndex) {
+
+        initOffsets();
+        if (beginIndex < 0) {
+            throw new IllegalArgumentException();
+        }
+        if (beginIndex >= (1 + offsets.size())) {
+            throw new IllegalArgumentException();
+        }
+        if (endIndex > (1 + offsets.size())) {
+            throw new IllegalArgumentException();
+        }
+        if (beginIndex >= endIndex) {
+            throw new IllegalArgumentException();
+        }
+
+        int elements = endIndex - beginIndex;
+        String result = null;
+        StringBuffer result1 = new StringBuffer("");
+        int index = beginIndex;
+        for (; elements-- != 0;) {
+            if (endIndex == offsets.size() && elements == 0) {
+                result1.append(subString(offsets.get(index), path.length));
+                break;
+            }
+            result1.append(subString(offsets.get(index), offsets.get(++index)));
+        }
+        result = result1.toString();
+        result = (result.endsWith("/")) ? result.substring(0, result.length() - 1) : result;
+        return new ZipFilePath(fileSystem, result.getBytes());
+    }
+
+    public ZipFilePath subEntryPath(int beginIndex, int endIndex) {
+
+        initEntryOffsets();
+        if (beginIndex < 0) {
+            throw new IllegalArgumentException();
+        }
+        if (beginIndex >= (1 + entryOffsets.size())) {
+            throw new IllegalArgumentException();
+        }
+        if (endIndex > (1 + entryOffsets.size())) {
+            throw new IllegalArgumentException();
+        }
+        if (beginIndex >= endIndex) {
+            throw new IllegalArgumentException();
+        }
+
+        int elements = endIndex - beginIndex;
+        String result = null;
+        StringBuffer result1 = new StringBuffer("");
+        int index = beginIndex;
+
+        for (; elements-- != 0;) {
+            if (endIndex == entryOffsets.size() && elements == 0) {
+                result1.append(subString(entryOffsets.get(index), path.length));
+                break;
+            }
+            result1.append(subString(entryOffsets.get(index), entryOffsets.get(++index)));
+        }
+        result = result1.toString();
+        result = (result.endsWith("/")) ? result.substring(0, result.length() - 1) : result;
+        return new ZipFilePath(fileSystem, result.getBytes());
+    }
+
+
+    public ZipFilePath toRealPath(boolean resolveLinks) throws IOException {
+        ZipFilePath realPath = new ZipFilePath(this.fileSystem, pathForZip);
+        realPath.checkAccess();
+        return realPath;
+    }
+
+
+    public boolean isHidden() {
+        return false;
+    }
+
+
+    public ZipFilePath toAbsolutePath() {
+        if (isAbsolute()) {
+            return this;
+        } else {
+            //add / bofore the existing path
+            byte[] defaultdir = fileSystem.getDefaultDir().getBytes();
+            int defaultlen = defaultdir.length;
+            boolean endsWith = (defaultdir[defaultlen - 1] == '/');
+            byte[] t = null;
+            if (endsWith) {
+                t = new byte[defaultlen + path.length];
+            } else {
+                t = new byte[defaultlen + 1 + path.length];
+            }
+
+            System.arraycopy(defaultdir, 0, t, 0, defaultlen);
+            if (!endsWith) {
+                t[defaultlen++] = '/';
+            }
+            System.arraycopy(path, 0, t, defaultlen, path.length);
+            return new ZipFilePath(this.fileSystem, t);
+        }
+
+    }
+
+
+    public URI toUri() {
+
+        String fullPath = fileSystem.getZipFileSystemFile();
+        if (File.separatorChar == '\\') {
+            fullPath = "/" + fullPath.replace("\\", "/"); // if Windows replace all separators by '/'
+        }
+        boolean endsWithSlash = (path[path.length - 1] == '/');  //
+        byte[] t = this.path;
+        if (!endsWithSlash) {
+            if (this.isArchiveFile() || this.isDirectory()) {
+                t = new byte[path.length + 1];
+                System.arraycopy(path, 0, t, 0, path.length);
+                t[t.length - 1] = '/';
+            }
+        }
+        String pathStr = new String(t);
+        if (!isAbsolute()) {
+            String defaultdir = fileSystem.getDefaultDir();
+            if (defaultdir.endsWith("/")) {
+                pathStr = defaultdir + pathStr;
+            } else {
+                pathStr = defaultdir + "/" + pathStr;
+            }
+        }
+        try {
+            return new URI("zip", "", fullPath, pathStr);
+        } catch (Exception ex) {
+            throw new AssertionError(ex);
+        }
+    }
+    // package private
+    URI toUri0() {
+        try {
+            String fullPath = fileSystem.getZipFileSystemFile();
+            if (File.separatorChar == '\\') {
+                fullPath = "/" + fullPath.replace("\\", "/"); // if Windows replace all separators by '/'
+            }
+            boolean endsWithSlash = (path.length > 1 && path[path.length - 1] == '/');  //0 for root
+            byte[] t = this.path;
+            if (!endsWithSlash && this.isArchiveFile()) {
+                t = new byte[path.length + 1];
+                System.arraycopy(path, 0, t, 0, path.length);
+                t[t.length - 1] = '/';
+            }
+            String pathStr = new String(t);
+            if (!isAbsolute()) {
+                String defaultdir = fileSystem.getDefaultDir();
+                if (defaultdir.endsWith("/")) {
+                    pathStr = defaultdir + pathStr;
+                } else {
+                    pathStr = defaultdir + "/" + pathStr;
+                }
+            }
+            return new URI("zip", "", fullPath, pathStr);
+        } catch (Exception ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+
+    public Path relativize(Path other) {
+        if (other == null) {
+            throw new NullPointerException();
+        }
+        if (!(other instanceof ZipFilePath)) {
+            throw new ProviderMismatchException();
+        }
+        ZipFilePath other1 = (ZipFilePath) other;
+        if (other1.equals(this)) {
+            return null;
+        }
+        if (this.isAbsolute() != other1.isAbsolute()) {
+            return other1;
+        }
+
+        int i = 0;
+        int ti = this.getNameCount();
+        int oi = other1.getNameCount();
+
+        for (; i < ti && i < oi; i++) {
+            if (!this.getName(i).equals(other1.getName(i))) {
+                break;
+            }
+        }
+        int nc = ti - i;
+        byte[] arr = new byte[nc * 3];
+        for (int j = 0; j < arr.length; j += 3) {
+            arr[j] = arr[j + 1] = '.';
+            arr[j + 2] = '/';
+        }
+        //contruct final path
+        ZipFilePath subPath = null;
+        int subpathlen = 0;
+        if (i < oi) {
+            subPath = other1.subpath(i, oi);
+            subpathlen = subPath.path.length;
+        }
+        byte[] result = new byte[arr.length + subpathlen];
+        if (nc > 0) {
+            System.arraycopy(arr, 0, result, 0, arr.length - 1);
+        }
+        if (subpathlen > 0) {
+            if (arr.length > 0) {
+                result[arr.length - 1] = '/';
+            }
+            System.arraycopy(subPath.path, 0, result, arr.length, subpathlen);
+        }
+        return new ZipFilePath(this.fileSystem, result);
+    }
+
+    //@Override
+    public ZipFileSystem getFileSystem() {
+        return fileSystem;
+    }
+
+
+    public boolean isAbsolute() {
+        return (this.path[0] == '/');
+    }
+
+    public ZipFilePath resolve(Path other) {
+        // zip/jar path are always absolute
+        if (other == null) {
+            throw new NullPointerException();
+        }
+        if (!(other instanceof ZipFilePath)) {
+            throw new ProviderMismatchException();
+        }
+        ZipFilePath other1 = (ZipFilePath) other;
+        if (other1.isAbsolute()) {
+            return other1;
+        }
+        byte[] resolved = null;
+        if (this.path[path.length - 1] == '/') {
+            resolved = new byte[path.length + other1.path.length];
+            System.arraycopy(path, 0, resolved, 0, path.length);
+            System.arraycopy(other1.path, 0, resolved, path.length, other1.path.length);
+        } else {
+            resolved = new byte[path.length + 1 + other1.path.length];
+            System.arraycopy(path, 0, resolved, 0, path.length);
+            resolved[path.length] = '/';
+            System.arraycopy(other1.path, 0, resolved, path.length + 1, other1.path.length);
+        }
+        return new ZipFilePath(this.fileSystem, resolved);
+    }
+
+
+    public ZipFilePath resolve(String other) {
+        return resolve(getFileSystem().getPath(other));
+    }
+
+
+    public boolean startsWith(Path other) {
+
+        ZipFilePath other1 = null;
+        if (other == null) {
+            throw new NullPointerException();
+        }
+        if (other instanceof ZipFilePath) {
+            other1 = (ZipFilePath) other;
+        }
+
+        int otherCount = other1.getNameCount();
+        if (getNameCount() < otherCount) {
+            return false;
+        }
+
+        for (int i = 0; i < otherCount; i++) {
+            if (other1.getName(i).equals(getName(i))) {
+                continue;
+            } else {
+                return false;
+            }
+        }
+        return true;
+
+    }
+
+
+    public boolean endsWith(Path other) {
+        ZipFilePath other1 = null;
+        if (other == null) {
+            throw new NullPointerException();
+        }
+        if (other instanceof ZipFilePath) {
+            other1 = (ZipFilePath) other;
+        }
+        int i = other1.getNameCount();
+        int j = getNameCount();
+
+        if (j < i) {
+            return false;
+        }
+
+        for (--i, --j; i >= 0; i--, j--) {
+            if (other1.getName(i).equals(getName(j))) {
+                continue;
+            } else {
+                return false;
+            }
+        }
+        return true;
+
+    }
+
+    public FileSystemProvider provider() {
+        return fileSystem.provider();
+    }
+
+
+    public String toString() {
+        return new String(pathForprint);
+    }
+
+
+    public int hashCode() {
+        int hashCode = 0;
+        int i = 0;
+
+        while (i < path.length) {
+            byte v = path[i];
+            hashCode = hashCode * 31 + (v);
+            i++;
+        }
+        return hashCode;
+
+    }
+
+
+    public boolean equals(Object ob) {
+        if ((ob != null) && (ob instanceof ZipFilePath)) {
+            return compareTo((Path) ob) == 0;
+        }
+        return false;
+    }
+
+
+    public int compareTo(Path other) {
+
+        ZipFilePath otherPath = (ZipFilePath) other;
+        //int c = zipPath.compareTo(otherPath.zipPath);
+
+        int len1 = path.length;
+        int len2 = otherPath.path.length;
+
+        int n = Math.min(len1, len2);
+        byte v1[] = path;
+        byte v2[] = otherPath.path;
+
+        int k = 0;
+        while (k < n) {
+            int c1 = v1[k];
+            int c2 = v2[k];
+            if (c1 != c2) {
+
+                return c1 - c2;
+            }
+            k++;
+        }
+        return len1 - len2;
+    }
+
+
+    public Path createSymbolicLink(
+            Path target, FileAttribute<?>... attrs) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+
+    public Path createLink(
+            Path existing) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+
+    public Path readSymbolicLink() throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+
+    public Path createDirectory(
+            FileAttribute<?>... attrs) throws IOException {
+        throw new ReadOnlyFileSystemException();
+    }
+
+    ZipFilePath getResolvedPathForZip() {
+        if (pathToZip == null) {
+            pathToZip = new ZipFilePath(fileSystem, path, pathForZip);
+        }
+        return pathToZip;
+    }
+
+
+    public InputStream newInputStream() throws IOException {
+        try {
+            begin();
+            ZipFilePath realPath = getResolvedPathForZip();
+            if (realPath.getNameCount() == 0) {
+                throw new IOException("entry missing in the path");
+            } else {
+                String zf = getZipFile();
+                ZipFile zfile = new ZipFile(zf);
+                String entryStr = realPath.getEntryName(realPath.getEntryNameCount() - 1).toString();
+                ZipEntry entry = zfile.getEntry(entryStr);
+                if (entry == null) {
+                    zfile.close();
+                    throw new IOException("entry not found" + entryStr);
+                }
+                InputStream is = zfile.getInputStream(entry);
+                fileSystem.addCloseableObjects(is);
+                return is;
+            }
+        } finally {
+            end();
+        }
+
+    }
+
+
+    public OutputStream newOutputStream(
+            Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
+        throw new ReadOnlyFileSystemException();
+    }
+
+
+    public DirectoryStream<Path> newDirectoryStream(
+            Filter<? super Path> filter) throws IOException {
+        try {
+            begin();
+            return new ZipFileStream(getResolvedPathForZip(), filter);
+        } finally {
+            end();
+        }
+    }
+
+
+    public void delete(boolean failIfNotExists) throws IOException {
+        throw new ReadOnlyFileSystemException();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V getFileAttributeView(Class<V> type, LinkOption... options) {
+        if (type == null)
+            throw new NullPointerException();
+        if (type == BasicFileAttributeView.class)
+            return (V) new ZipFileBasicAttributeView(this);
+        if (type == ZipFileAttributeView.class)
+            return (V) new ZipFileAttributeView(this);
+        if (type == JarFileAttributeView.class)
+            return (V) new JarFileAttributeView(this);
+        return null;
+    }
+
+
+    public FileAttributeView getFileAttributeView(String name, LinkOption... options) {
+        if (name.equals("basic"))
+            return new ZipFileBasicAttributeView(this);
+        if (name.equals("zip"))
+            return new ZipFileAttributeView(this);
+        if (name.equals("jar"))
+            return new JarFileAttributeView(this);
+        return null;
+    }
+
+
+    public FileStore getFileStore() throws IOException {
+        try {
+            begin();
+            if (isAbsolute()) {
+                return ZipFileStore.create(getRoot());
+            } else {
+                return ZipFileStore.create(getResolvedPathForZip().getRoot());
+            }
+        } finally {
+            end();
+        }
+    }
+
+
+    public boolean isSameFile(FileRef other) throws IOException {
+
+        if ((other != null) && (other instanceof ZipFilePath)) {
+
+            // check both file systems are same.
+
+            ZipFilePath other1 = (ZipFilePath) other;
+            String fileSystem1 = this.getFileSystem().getZipFileSystemFile();
+            String fileSystem2 = other1.getFileSystem().getZipFileSystemFile();
+            boolean isSameFileSystem = fileSystem1.equals(fileSystem2);
+            if (!isSameFileSystem) {
+                return false;
+            }
+
+            // if file systems are same then do they exist
+            // finally compare the paths
+            // compare the real paths
+            ZipFilePath thisZip = this.toRealPath(false);
+            ZipFilePath otherZip = other1.toRealPath(false);
+            return (thisZip.startsWith(otherZip) && thisZip.endsWith(otherZip));
+        }
+        return false;
+
+    }
+
+    public WatchKey register(
+            WatchService watcher,
+            WatchEvent.Kind<?>[] events,
+            WatchEvent.Modifier... modifiers) throws IOException {
+        if (watcher == null || events == null || modifiers == null)
+            throw new NullPointerException();
+        throw new ProviderMismatchException();
+    }
+
+
+    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 ReadOnlyFileSystemException();
+            }
+        };
+    }
+
+
+    public SeekableByteChannel newByteChannel(
+            Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
+
+        // check for options of null type and option is an intance of StandardOpenOption
+
+        for (OpenOption option : options) {
+            if (option == null) {
+                throw new NullPointerException();
+            }
+            if (!(option instanceof StandardOpenOption)) {
+                throw new IllegalArgumentException();
+            }
+        }
+        boolean openedForWriteOrAppend = options.contains(StandardOpenOption.WRITE) ||
+                options.contains(StandardOpenOption.APPEND);
+        if (openedForWriteOrAppend) {
+            throw new ReadOnlyFileSystemException();
+        }
+        boolean openedForRead = options.contains(StandardOpenOption.READ);
+        openedForRead = openedForRead || true; // if not opened for read then set openedForRed to true;
+
+        if (!openedForRead) {
+            throw new IllegalArgumentException("not opened for Read"); //this is never thrown
+        }
+        try {
+            begin();
+            ZipFilePath realPath = getResolvedPathForZip();
+            if (realPath.getNameCount() == 0) { //Need to Remove null check
+                throw new IOException("entry Not Found");
+            } else {
+                String zf = getZipFile();
+                ZipFile zfile = new ZipFile(zf);
+                String entryStr = realPath.getEntryName(realPath.getEntryNameCount() - 1).toString();
+                ZipEntry entry = zfile.getEntry(entryStr);
+                if (entry == null) {
+                    throw new IOException("entry not found" + entryStr);
+                }
+
+                InputStream in = zfile.getInputStream(entry);
+                Path pathtoZip = Paths.get(ZipUtils.readFileInZip(in));
+                zfile.close();
+                SeekableByteChannel sbc = FileChannel.open(pathtoZip, options);
+                fileSystem.addCloseableObjects(sbc);
+                return sbc;
+            }
+        } finally {
+            end();
+        }
+
+    }
+
+    private String getZipFile() throws IOException {
+
+        String pathtoZip = null;
+        ZipFilePath realPath = getResolvedPathForZip();
+        int entryCount = realPath.getEntryNameCount();
+        if (realPath.isNestedZip()) {
+            if (realPath.isArchiveFile() && entryCount == 1) {
+                pathtoZip = this.fileSystem.getZipFileSystemFile();
+            } else {
+                pathtoZip = ZipUtils.extractNestedZip(realPath.getParentEntry()).toString();
+            }
+        } else {
+            pathtoZip = this.fileSystem.getZipFileSystemFile();
+        }
+
+        return pathtoZip;
+    }
+
+
+    public void checkAccess(AccessMode... modes) throws IOException {
+        boolean w = false;
+        boolean x = false;
+
+        for (AccessMode mode: modes) {
+            switch (mode) {
+                case READ: break;
+                case WRITE : w = true; break;
+                case EXECUTE : x = true; break;
+                default:
+                    throw new UnsupportedOperationException();
+            }
+        }
+
+        try {
+            begin();
+            ZipFilePath resolvedZipPath = getResolvedPathForZip();
+            int nameCount = resolvedZipPath.getNameCount();
+            if (nameCount == 0)
+                throw new NoSuchFileException(toString());
+
+            if (w) {
+                throw new AccessDeniedException("write access denied for the file: " + this.toString());
+            }
+            if (x) {
+                ZipEntryInfo ze = ZipUtils.getEntry(resolvedZipPath);
+                long attrs = ze.extAttrs;
+                if (!((((attrs << 4) >> 24) & 0x04) == 0x04))
+                    throw new AccessDeniedException("execute access denied for the file: " + this.toString());
+            }
+        } finally {
+            end();
+        }
+    }
+
+
+    public Path normalize() {
+        throw new RuntimeException("not implemented yet");
+    }
+
+
+    protected void implCopyTo(Path target, CopyOption... options) throws IOException {
+        throw new ReadOnlyFileSystemException();
+    }
+
+
+    protected void implMoveTo(Path target, CopyOption... options) throws IOException {
+        throw new ReadOnlyFileSystemException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStore.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.io.IOException;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.FileSystems;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.ProviderMismatchException;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.Attributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+
+public class ZipFileStore extends FileStore {
+
+    private final ZipFilePath root;
+    private final String zipFileName;
+    private final String type = "zipfs";
+
+    ZipFileStore(ZipFilePath path) {
+        this.root = path;
+        zipFileName = path.getFileSystem().getZipFileSystemFile();
+    }
+
+    static FileStore create(ZipFilePath root) throws IOException {
+        return new ZipFileStore(root);
+    }
+
+
+    public String name() {
+        return zipFileName;
+    }
+
+
+    public String type() {
+        return type;
+    }
+
+
+    public boolean isReadOnly() {
+        return root.getFileSystem().isReadOnly();
+    }
+
+
+    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        if (type == BasicFileAttributeView.class)
+            return true;
+        if (type == ZipFileAttributeView.class)
+            return true;
+        if (type == JarFileAttributeView.class)
+            return true;
+        return false;
+    }
+
+
+    public boolean supportsFileAttributeView(String name) {
+        // FIXME
+        if (name.equals("basic") || name.equals("zip") || name.equals("jar")) {
+            return true;
+        }
+        return false;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> viewType) {
+        if (viewType == FileStoreSpaceAttributeView.class) {
+            return (V) new ZipFileStoreAttributeView(this);
+        }
+        return null;
+    }
+
+
+    public FileStoreAttributeView getFileStoreAttributeView(String name) {
+        if (name.equals("space")) {
+            return new ZipFileStoreAttributeView(this);
+        }
+        return null;
+    }
+
+    private static class ZipFileStoreAttributeView implements FileStoreSpaceAttributeView {
+
+        private final ZipFileStore fileStore;
+
+        public ZipFileStoreAttributeView(ZipFileStore fileStore) {
+            this.fileStore = fileStore;
+        }
+
+
+        public String name() {
+            return "space";
+        }
+
+
+        public Object getAttribute(String attribute) throws IOException {
+            FileStoreSpaceAttributes attrs = readAttributes();
+            if (attribute.equals("totalSpace")) {
+                return attrs.totalSpace();
+            }
+            if (attribute.equals("unallocatedSpace")) {
+                return attrs.unallocatedSpace();
+            }
+            if (attribute.equals("usableSpace")) {
+                return attrs.usableSpace();
+            }
+
+            return null;
+        }
+
+
+        public void setAttribute(String attribute, Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        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 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 result;
+        }
+
+        public FileStoreSpaceAttributes readAttributes() throws IOException {
+            // get the size of the zip file
+            String file = fileStore.name();
+            Path path = FileSystems.getDefault().getPath(file);
+            final long size = Attributes.readBasicFileAttributes(path).size();
+            return new FileStoreSpaceAttributes() {
+
+                public long totalSpace() {
+                    return size; // size of the zip/jar file
+
+                }
+
+                public long usableSpace() {
+                    return 0; // no usable space in zip/jar file
+
+                }
+
+                public long unallocatedSpace() {
+                    return 0; // no unallocated space in zip/jar file.
+
+                }
+            };
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileStream.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Map;
+import java.io.IOException;
+import java.util.HashSet;
+
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.NotDirectoryException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.ReadOnlyFileSystemException;
+
+public class ZipFileStream implements DirectoryStream<Path> {
+
+    private final ZipFilePath zipPath;
+    private final DirectoryStream.Filter<? super Path> filter;
+    private volatile boolean isOpen;
+    private final Object closeLock;
+    private Iterator<Path> iterator;
+
+    private class ZipFilePathIterator implements
+            Iterator<Path> {
+
+        private boolean atEof;
+        private Path nextEntry;
+        private Path prevEntry;
+        private Iterator<Path> entryIterator;
+
+        ZipFilePathIterator() throws IOException {
+            atEof = false;
+            Map<ZipFilePath, ZipEntryInfo> entries = null;
+            int nameCount = zipPath.getNameCount();
+            entries = ZipUtils.getEntries(zipPath);
+            Set<ZipFilePath> s = entries.keySet();
+            Set<Path> s1 = new HashSet<Path>();
+            for (ZipFilePath f : s) {
+
+                boolean b = f.startsWith(zipPath);
+                if ((nameCount + 1) > f.getNameCount() || !b) {
+                    continue;
+                }
+                ZipFilePath entry = zipPath.resolve(f.getName(nameCount));
+                if (filter == null || filter.accept(entry)) {
+                    s1.add(entry);
+                }
+            }
+            if (s1.isEmpty()) {
+            // if there is no file keep quiet
+            }
+            entryIterator = s1.iterator();
+        }
+
+        @SuppressWarnings("unchecked")
+        private boolean accept(Path entry) {
+            return filter.accept(entry);
+        }
+
+        private Path readNextEntry() {
+            Path entry = entryIterator.next();
+            if ((filter == null) || accept(entry)) {
+                return entry;
+            }
+            return null;
+        }
+
+        public synchronized boolean hasNext() {
+            boolean isThereNext = entryIterator.hasNext();
+            if (!isThereNext) {
+                atEof = true;
+            }
+            return isThereNext;
+        }
+
+        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() {
+            UnsupportedOperationException e = new UnsupportedOperationException();
+            e.initCause(new ReadOnlyFileSystemException());
+            throw e;
+        }
+    }
+
+
+    public Iterator<Path> iterator() {
+        synchronized (this) {
+            if (iterator != null) {
+                throw new IllegalStateException();
+            }
+            try {
+                iterator = new ZipFilePathIterator();
+            } catch (IOException e) {
+                IllegalStateException ie = new IllegalStateException();
+                ie.initCause(e);
+                throw ie;
+            }
+            return iterator;
+        }
+    }
+
+    public void close() throws IOException {
+    // no impl
+    }
+
+    /** Creates a new instance of ZipFileStream */
+    public ZipFileStream(ZipFilePath zipPath,
+            DirectoryStream.Filter<? super Path> filter)
+            throws IOException {
+
+        if (zipPath.getNameCount() != 0) { // if path is '/' no need for check existence
+            zipPath.checkAccess();
+        }
+
+        if (!zipPath.isArchiveFile() && !zipPath.isDirectory()) {
+            throw new NotDirectoryException("Not a Directory " + zipPath.toString());
+        }
+        this.zipPath = zipPath;
+        this.filter = filter;
+        this.isOpen = true;
+        this.closeLock = new Object();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.URI;
+import java.util.*;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Pattern;
+
+import org.classpath.icedtea.java.nio.file.ClosedFileSystemException;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.InvalidPathException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.PathMatcher;
+import org.classpath.icedtea.java.nio.file.WatchService;
+
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipalLookupService;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+public class ZipFileSystem extends FileSystem {
+
+    private final ZipFileSystemProvider provider;
+    //path upto first zip file
+    // for example in Win c:/foo/bar.zip/a/b/c - zipFile represents c:/foo/bar.zip
+    // this contains real path following the links (change it, if no need to follow links)
+    private final String zipFile;
+    private final String defaultdir;
+    private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
+    private boolean open = true;
+    private Set<Closeable> closeableObjects = new HashSet<Closeable>();
+
+    ZipFileSystem(ZipFileSystemProvider provider,
+            FileRef fref) {
+
+        this(provider, fref.toString(), "/");
+
+    }
+
+    ZipFileSystem(ZipFileSystemProvider provider, String path, String defaultDir) {
+        this.provider = provider;
+        this.zipFile = path;
+        this.defaultdir = defaultDir;
+    }
+
+
+    public FileSystemProvider provider() {
+        return provider;
+    }
+
+
+    public String getSeparator() {
+        return "/";
+    }
+
+
+    public boolean isOpen() {
+        return open;
+    }
+
+
+    public boolean isReadOnly() {
+        return true;
+    }
+
+
+    public void close() throws IOException {
+        closeLock.writeLock().lock();
+        URI root = null;
+        try {
+            if (!open) {
+                return;
+            }
+            root = getPath("/").toUri();
+            open = false;
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+        implClose(root);
+    }
+
+    final void begin() {
+        closeLock.readLock().lock();
+        if (!isOpen()) {
+            throw new ClosedFileSystemException();
+        }
+    }
+
+    final void end() {
+        closeLock.readLock().unlock();
+    }
+    // Free all cached Zip/Jar files
+    private void implClose(URI root) throws IOException {
+        ZipUtils.remove(root); // remove cached filesystem
+        provider.removeFileSystem(root);
+        Iterator<Closeable> itr = closeableObjects.iterator();
+        while (itr.hasNext()) {
+            try {
+                itr.next().close();
+                itr.remove();
+            } catch (IOException e) {
+                throw e;
+            }
+        }
+    }
+
+    boolean addCloseableObjects(Closeable obj) {
+        return closeableObjects.add(obj);
+    }
+
+
+    public Iterable<Path> getRootDirectories() {
+        try {
+            begin();
+            ArrayList<Path> pathArr = new ArrayList<Path>();
+            ZipFilePath root = new ZipFilePath(this, new byte[]{'/'});
+            pathArr.add(root);
+            return pathArr;
+        } finally {
+            end();
+        }
+
+    }
+
+    String getDefaultDir() {
+        return defaultdir;
+    }
+
+    String getZipFileSystemFile() {
+        return zipFile;
+    }
+
+
+    public ZipFilePath getPath(String path) {
+
+        if (path == null) {
+            throw new NullPointerException();
+        }
+        if (path.equals("")) {
+            throw new InvalidPathException(path, "path should not be empty");
+        }
+        try {
+            begin();
+            byte[] parsedPath = ZipPathParser.normalize(path).getBytes();
+            return new ZipFilePath(this, parsedPath);
+        } finally {
+            end();
+        }
+    }
+
+
+    public UserPrincipalLookupService getUserPrincipalLookupService() {
+        return null;
+    }
+
+
+    public WatchService newWatchService() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public Iterable<FileStore> getFileStores() {
+        try {
+            begin();
+            Iterator<Path> iterator = this.getRootDirectories().iterator();
+            final ZipFileStoreIterator zipIterator = new ZipFileStoreIterator(iterator);
+            return new Iterable<FileStore>() {
+
+                public Iterator<FileStore> iterator() {
+                    return zipIterator;
+                }
+            };
+        } finally {
+            end();
+        }
+    }
+
+    private static class ZipFileStoreIterator implements Iterator<FileStore> {
+
+        private final Iterator<Path> roots;
+        private FileStore next;
+
+        ZipFileStoreIterator(Iterator<Path> root) {
+            roots = root;
+        }
+
+        private FileStore readNext() {
+            for (;;) {
+                if (!roots.hasNext()) {
+                    return null;
+                }
+                try {
+                    ZipFilePath root = (ZipFilePath) roots.next();
+                    FileStore fs = ZipFileStore.create(root);
+                    if (fs != null) {
+                        return fs;
+                    }
+                } catch (IOException e) {
+
+                }
+            }
+        }
+
+
+        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("");
+        }
+    }
+
+    private static final Set<String> supportedFileAttributeViews =
+        Collections.unmodifiableSet(new HashSet(Arrays.asList("basic", "zip", "jar")));
+
+
+    public Set<String> supportedFileAttributeViews() {
+        return supportedFileAttributeViews;
+    }
+
+
+    public String toString() {
+        return getZipFileSystemFile();
+    }
+
+
+    public PathMatcher getNameMatcher(String syntax, String expr) {
+        if (syntax.equalsIgnoreCase("glob")) {
+             // Temporary
+             String regex = sun.nio.fs.Globs.toRegexPattern(expr);
+             final Pattern pattern = Pattern.compile(regex,
+                 (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE));
+             final DirectoryStream.Filter<Path> filter =
+                new DirectoryStream.Filter<Path>() {
+
+                    public boolean accept(Path entry)  {
+                        return pattern.matcher(entry.getName().toString()).matches();
+                    }
+                };
+
+            return new PathMatcher() {
+
+                public boolean matches(Path path) {
+                    // match on file name only
+                    Path name = path.getName();
+                    if (name == null)
+                        return false;
+                    return filter.accept(name);
+                }};
+        }
+        if (syntax.equalsIgnoreCase("regex")) {
+            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();
+                }};
+        }
+        throw new UnsupportedOperationException("Syntax '" + syntax +
+            "' not recognized");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystemProvider.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.net.URI;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.FileSystems;
+import org.classpath.icedtea.java.nio.file.FileSystemNotFoundException;
+import org.classpath.icedtea.java.nio.file.InvalidPathException;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+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.spi.FileSystemProvider;
+
+public class ZipFileSystemProvider
+        extends FileSystemProvider {
+
+    private String scheme = "zip";
+    private Map<URI, ZipFileSystem> fileSystems = new HashMap<URI, ZipFileSystem>();
+
+    public ZipFileSystemProvider() {
+    }
+
+
+    public String getScheme() {
+        return scheme;
+    }
+
+
+    public FileSystem newFileSystem(URI uri, Map<String, ?> env)
+            throws IOException {
+        String scheme1 = uri.getScheme();
+        if ((scheme1 == null) || !scheme1.equalsIgnoreCase(scheme)) {
+            throw new IllegalArgumentException("URI scheme is not '" + scheme + "'");
+        }
+
+        URI uriPath = null;
+        try {
+            uriPath = new URI("file", uri.getHost(), uri.getPath(), null);
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+        Path nativePath = null;
+        try {
+            nativePath = Paths.get(uriPath); //making use of underlying URI path parsing
+        } catch (InvalidPathException e) {
+            throw e;
+        }
+        if (!checkZipFilePath(nativePath)) {
+            throw new InvalidPathException(nativePath.toString(), "file name does not contain zip/jar File");
+        }
+        nativePath.checkAccess(); // check the existance of the path before proceed
+
+        ZipFileSystem fileSystem = null;
+        // construct uri to find in cached file systems
+        try {
+            uriPath = new URI("zip", uri.getHost(), uri.getPath(), null);
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+        String pathStr = nativePath.toAbsolutePath().toString(); // think whether to pass .toRealPath(true) to follow links
+
+        String defaultdir = null;
+        Object obj = null;
+        if (env != null) {
+            obj = env.get("default.dir");
+            if ((obj != null) && !(obj instanceof String)) {
+                throw new IllegalArgumentException();
+            }
+            defaultdir = (String) obj;
+        }
+        if (defaultdir == null) {
+            defaultdir = "/";
+        }
+        if (defaultdir.charAt(0) != '/') {
+            throw new IllegalArgumentException("default dir should be absolute");
+        }
+        if (!defaultdir.equals("/")) {
+            defaultdir = ZipPathParser.normalize(defaultdir);
+        }
+        fileSystem = new ZipFileSystem(this, pathStr, defaultdir);
+        fileSystems.put(uriPath, fileSystem);
+        return fileSystem;
+    }
+
+
+    public FileSystem newFileSystem(FileRef file,
+            Map<String, ?> env)
+            throws IOException {
+        ZipFileSystem fileSystem = null;
+        if (!((Path) file).toUri().getScheme().equalsIgnoreCase("file")) {
+            throw new UnsupportedOperationException();
+        }
+        if (!checkZipFilePath(file)) {
+            throw new UnsupportedOperationException();
+        }
+        try {
+            ((Path) file).checkAccess();
+        } catch (IOException e) {
+            throw e;
+        }
+        String pathStr = ((Path) file).toAbsolutePath().toString(); //follow links
+        String defaultdir = null;
+        Object obj = null;
+        if (env != null) {
+            obj = env.get("default.dir");
+            if ((obj != null) && !(obj instanceof String)) {
+                throw new IllegalArgumentException();
+            }
+            defaultdir = (String) obj;
+        }
+        if (defaultdir == null) {
+            defaultdir = "/";
+        }
+        if (defaultdir.charAt(0) != '/') {
+            throw new IllegalArgumentException("default dir should be absolute");
+        }
+        if (!defaultdir.equals("/")) {
+            defaultdir = ZipPathParser.normalize(defaultdir);
+        }
+        fileSystem = new ZipFileSystem(this, pathStr, defaultdir);
+        return fileSystem;
+    }
+
+    boolean checkZipFilePath(FileRef file) {
+        // check file ends with zip file
+        Path path = ((Path) file);
+        if (path.getName() == null) {
+            return false;
+        }
+        String fileName = path.getName().toString().toLowerCase();
+        boolean b = (fileName.endsWith(".zip") || fileName.endsWith(".jar"));
+        return (b);
+    }
+
+
+    public ZipFilePath getPath(URI uri) {
+
+        String scheme1 = uri.getScheme();
+
+        if ((scheme1 == null) || !scheme1.equalsIgnoreCase(scheme)) {
+            throw new IllegalArgumentException("URI scheme is not '" + scheme + "'");
+        }
+        String fragment = uri.getFragment();
+        if (fragment == null) {
+            throw new IllegalArgumentException("uri " + uri + " does not contain path fragment ex. zip:///c:/test.zip#/DirA");
+        }
+        URI uripath = null;
+        try {
+            uripath = new URI(uri.getScheme(), uri.getHost(), uri.getPath(), null);
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e);
+        }
+        ZipFileSystem fileSystem = fileSystems.get(uripath);
+        if (fileSystem == null) {
+            throw new FileSystemNotFoundException();
+        }
+        // if fragment is empty, the following method throws InvalidPathException.
+        ZipFilePath path = fileSystem.getPath(fragment);
+        return path;
+    }
+
+
+    public FileChannel newFileChannel(Path path,
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        FileSystem defFileSystem = FileSystems.getDefault();
+        Path nativePath = defFileSystem.getPath(path.toString());
+        return defFileSystem.provider().newFileChannel(nativePath, options);
+    }
+
+
+    public FileSystem getFileSystem(URI uri) {
+        String scheme1 = uri.getScheme();
+        if (scheme1 == null || !scheme.equalsIgnoreCase(getScheme())) {
+            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
+        }
+        //construct uri ignoring fragement in the given URI
+        URI uriPath = null;
+        try {
+            uriPath = new URI("zip", uri.getHost(), uri.getPath(), null);
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+        ZipFileSystem fileSystem = fileSystems.get(uriPath);
+        if (fileSystem == null) {
+            throw new FileSystemNotFoundException();
+        }
+        return fileSystem;
+    }
+
+    void removeFileSystem(URI uri) {
+        //construct uri ignoring fragement in the given URI
+        URI uriPath = null;
+        try {
+            uriPath = new URI("zip", uri.getHost(), uri.getPath(), null);
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+        fileSystems.remove(uriPath);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipHeaderConstants.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+public class ZipHeaderConstants {
+
+    public static final int LOCAL_FILE_HDR_SIG = 0x04034b50;
+    public static final int CENTRAL_FILE_HDR_SIG = 0x02014b50;
+    public static final int END_CENTRAL_HDR_SIG = 0x06054b50;
+
+    // All offsets are in bytes
+
+    // Local File Header offsets
+    public static final long COMP_METHOD_OFF = 8;
+    public static final long COMP_SIZE_OFF = 18;
+    public static final long UCOMP_SIZE_OFF = COMP_SIZE_OFF + 4;
+    public static final long FILE_NAME_LEN_OFF = UCOMP_SIZE_OFF + 4;
+    public static final long EXTRA_FLD_LEN_OFF = FILE_NAME_LEN_OFF + 2;
+    public static final long FILE_NAME_OFF =  EXTRA_FLD_LEN_OFF + 2;
+
+    // File Header of Central Directory Structure
+    public static final long C_VER_MADE_BY  = 4;
+    public static final long C_COMP_METHOD_OFF = COMP_METHOD_OFF + 2;
+    public static final long C_LAST_MOD_TIME_OFF = C_COMP_METHOD_OFF + 2;
+    public static final long C_LAST_MOD_DATE_OFF = C_LAST_MOD_TIME_OFF + 2;
+    public static final long C_CRC_OFF =  C_LAST_MOD_DATE_OFF + 2;
+    public static final long C_COMP_SIZE_OFF =  C_CRC_OFF + 4;
+    public static final long C_UCOMP_SIZE_OFF = C_COMP_SIZE_OFF + 4;
+    public static final long C_FILE_NAME_LEN_OFF = C_UCOMP_SIZE_OFF + 4;
+    public static final long C_EXTRA_FLD_LEN_OFF = C_FILE_NAME_LEN_OFF + 2;
+    public static final long C_COMMENT_LEN_OFF = C_EXTRA_FLD_LEN_OFF + 2;
+    public static final long C_DISK_NO_OFF = C_COMMENT_LEN_OFF + 2;
+    public static final long C_INT_ATTR_OFF = C_DISK_NO_OFF + 2;
+    public static final long C_EXT_ATTR_OFF = C_INT_ATTR_OFF + 2;
+    public static final long C_REL_OFF_LOCAL_HDR_OFF = C_EXT_ATTR_OFF + 4;
+    public static final long C_FILE_NAME_OFF =  C_REL_OFF_LOCAL_HDR_OFF + 4;
+
+    // End of Central directory Record
+    public static final int C_COMMENT_LEN_BLEN = 2;
+    public static final int C_EXT_ATTR_BLEN = 4;
+
+    public static final long C_TOTAL_ENTRIES_OFF =10;
+    public static final int C_DIR_START_OFF = 16;
+
+    public static final int C_END_RECORD_MIN_OFF = 19;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipPathParser.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,308 @@
+/*
+ * 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.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.util.LinkedList;
+import java.util.Stack;
+import java.util.regex.*;
+
+import org.classpath.icedtea.java.nio.file.InvalidPathException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.Paths;
+
+public class ZipPathParser {
+
+    public static final String invalidChars = "\":<>*?";
+
+    static class Result {
+
+        String zipFile;
+        byte[] pathInZip;
+
+        Result(String path, String pathInZip) {
+            this.zipFile = path;
+            this.pathInZip = pathInZip.getBytes();
+        }
+    }
+
+    static Result parse(String path) {
+
+        if (path == null) {
+            throw new NullPointerException();
+        }
+        if (path.equals("")) {
+            throw new InvalidPathException(path, "path should not be empty");
+        }
+        int prefixLen = getPrefixLen(path);
+
+        // We got the prefix length, and get all the components.
+        int off = findZipComponent(prefixLen, path);
+        if (off == -1) {
+            try {
+                Paths.get(path); //if any invalid char includes in the
+            // path this statement throws IPE with specific position.
+            } catch (InvalidPathException e) {
+                throw new InvalidPathException("", e.getMessage()); //This reduces long stack trace
+            }
+            throw new InvalidPathException(path, "Archive Jar/Zip Not Found in the path");
+        }
+        String pathZip = path.substring(0, off);
+        Path pathUpToZip = Paths.get(pathZip);
+        String nomalizedPathInZip = null;
+        if (off != path.length()) {
+            String pathInZip = path.substring(off, path.length());
+            nomalizedPathInZip = normalize(pathInZip);
+        } else {
+            nomalizedPathInZip = "/"; //Default path
+        }
+        return new Result(pathUpToZip.toString(), nomalizedPathInZip);
+    }
+    static char fileSepa = java.io.File.separatorChar;
+
+    static int getPrefixLen(String path) {
+
+        int pathLen = path.length();
+        if (pathLen == 0) {
+            return -1;
+        }
+        char ch0 = path.charAt(0);
+        if (pathLen > 0 && isSeparator(ch0)) {
+            if (pathLen > 1) {
+                char ch1 = path.charAt(1);
+                if (isSeparator(ch1) && fileSepa == '\\') {
+                    int off = 2;
+                    off = nextNonSeparator(path, off); //server comp begin index
+                    if (off == pathLen) {
+                        throw new InvalidPathException(path, "does not contain Server component");
+                    }
+                    off = nextSeparator(path, off); //server comp end index
+                    off = nextNonSeparator(path, off); //share comp begin index
+                    if (off == pathLen) {
+                        throw new InvalidPathException(path, "does not contain share");
+                    }
+                    off = nextSeparator(path, off); //share comp end index
+                    off = nextNonSeparator(path, off); // if any separators follows immediately
+                    return off; // comment the above line also works perfect.
+                }
+            }
+            int off = 1;
+            off = nextNonSeparator(path, off); // unix - all the preceding separators
+            return off; //you can comment the above line  incase you dont want
+        //prefix lenght upto first component of the path
+        } else if (pathLen > 1) {
+            if (fileSepa == '\\' && path.charAt(1) == ':') { // fileSepa check is needed
+                ch0 = Character.toUpperCase(ch0);            // as it is applicable only in Windows
+                if (ch0 >= 'A' && ch0 <= 'Z') {
+                    if (pathLen > 2 && isSeparator(path.charAt(2))) {
+                        int off = 2;
+                        off = nextNonSeparator(path, off); //if any separators follows after C:////
+                        return off;  //incase you comment the above line return 3
+                    } else {
+                        return 2;
+                    }
+                }
+                throw new InvalidPathException(path, "Invalid Prefix in Windows"); //Illegal Prefix in Windows
+            }
+            return 0; // path length >1 and No Prefix
+        }
+        return 0; //Path lenght=1 and it does not have any prefix
+    }
+
+    static int nextNonSeparator(String path, int off) {
+        int pathLen = path.length();
+        while ((off < pathLen) && isSeparator(path.charAt(off))) {
+            off++;
+        }
+        return off;
+    }
+
+    static int nextSeparator(String path, int off) {
+        int pathLen = path.length();
+        while ((off < pathLen) && !(isSeparator(path.charAt(off)))) {
+            off++;
+        }
+        return off;
+    }
+
+    static boolean isSeparator(char ch) {
+        if (fileSepa == '\\') {
+            return ((ch == '\\') || (ch == '/')); //in Windows file separator is \\ or /
+        } else {
+            return (ch == '/'); //in unix file separator is /
+        }
+    }
+
+    static LinkedList<String> getComponents(String path) {
+        LinkedList<String> compList = new LinkedList<String>();
+        if (path == null || path.equals("")) {
+            return compList;
+        }
+        int firstChar = path.charAt(0);
+        int prefix = (firstChar == '/') ? 1 : 0;
+        int compStartIndex = prefix; // prefix starts with componenent begin index
+        int compEndIndex = prefix;
+        int pathLen = path.length();
+
+        while (compEndIndex < pathLen) {
+            compStartIndex = nextNonSeparator(path, compEndIndex);
+            compEndIndex = nextSeparator(path, compStartIndex);
+            if (compStartIndex != compEndIndex) {
+                compList.add(path.substring(compStartIndex, compEndIndex));
+            }
+        }
+        return compList;
+
+    }
+
+    private static int findZipComponent(int prefixLen, String path) {
+        int compStartIndex = prefixLen; // prefix starts with componenent begin index
+        int compEndIndex = prefixLen;
+        int pathLen = path.length();
+
+        Pattern pattern = Pattern.compile("\\.(?i)(zip|jar)");
+        //".*\\.(?i)(\\Qzip\\E|\\Qjar\\E)[\\/]*"
+        Matcher matcher = null;
+        while (compEndIndex < pathLen) {
+            compStartIndex = nextNonSeparator(path, compEndIndex);
+            compEndIndex = nextSeparator(path, compStartIndex);
+            String pathComp = path.substring(compStartIndex, compEndIndex);
+            matcher = pattern.matcher(pathComp);
+            boolean b = matcher.find();
+            if (b) {
+                return compEndIndex;
+            }
+        }
+        return -1;
+    }
+
+    static String normalize(String pathInZip) {
+        int len = pathInZip.length();
+        char pathArr[] = new char[len];
+        pathInZip.getChars(0, len, pathArr, 0);
+
+        //Repleace all Separators \\ with Zip Separator /
+        //throws InavalidPathException in Windows and Unux if char is not valid
+        // in respective file systems.
+
+        for (int i = 0; i < len; i++) {
+            if (pathArr[i] == '\\') {
+                pathArr[i] = '/';
+            }
+            if (fileSepa == '\\') { //If Path is In Windows
+                if ((pathArr[i] < '\u0020') || (invalidChars.indexOf(pathArr[i]) != -1)) {
+                    throw new InvalidPathException(pathInZip, "Invalid char at " + i);
+                }
+                if ((i > 0) && (((pathArr[i] == '/') && (pathArr[i - 1] == ' ')) ||
+                        ((i == len - 1) && pathArr[i] == ' '))) {
+                    throw new InvalidPathException(pathInZip, "Trailing space at" + (i - 1));
+                }
+            } else if (fileSepa == '/') { //If path In In Unix
+                if (pathArr[i] == '\u0000') {
+                    throw new InvalidPathException(pathInZip, "Null char at" + i);
+                }
+            }
+        }
+
+        // Remove if any extra slashes
+        int size = len;
+        for (int i = 1; i < size; i++) {
+            if (pathArr[i] == '/' && pathArr[i - 1] == '/') {
+                System.arraycopy(pathArr, i, pathArr, i - 1, size - i);
+                size--;
+                i--;
+            }
+
+        }
+        return new String(pathArr).substring(0, size);
+
+
+    }
+
+    // Remove DotSlash(./) and resolve DotDot (..) components
+    static String resolve(String path) {
+
+        int len = path.length();
+        char pathArr[] = new char[len];
+        path.getChars(0, len, pathArr, 0);
+        //Remove ./ component ,Remove this if not necessary
+        char ch = pathArr[0];
+        int prefixPos = (ch == '/') ? 1 : 0;
+        int size = len;
+
+        for (int i = prefixPos + 1; i < size; i++) {
+            if ((pathArr[i] == '/' && pathArr[i - 1] == '.') &&
+                    (i == prefixPos + 1 || pathArr[i - 2] == '/')) {
+                System.arraycopy(pathArr, i + 1, pathArr, i - 1, size - (i + 1));
+                size -= 2;
+                i--;
+            }
+
+        }
+        //Remove final . if path has one. which is not needed for zip path
+        if ((size >= 2) && pathArr[size - 1] == '.' && pathArr[size - 2] == '/') {
+            System.arraycopy(pathArr, 0, pathArr, 0, size - 1);
+            size -= 1;
+        }
+
+        //Resolve ../ components
+        String pathStr = new String(pathArr, 0, size);
+        boolean prefix = pathStr.startsWith("/");
+        boolean endsWith = pathStr.endsWith("/");
+        LinkedList<String> compArr = getComponents(pathStr);
+        Stack<String> stack = new Stack<String>();
+        for (int i = 0; i < compArr.size(); i++) {
+            stack.push(compArr.get(i));
+            if (compArr.get(i).equals("..")) {
+                stack.pop();
+                if (i > 0 && stack.size() > 0) {
+                    stack.pop();
+                }
+            }
+        }
+        //Construct final path
+        StringBuffer resolved = (prefix) ? new StringBuffer("/") : new StringBuffer("");
+        for (String comp : stack) {
+            resolved.append(comp).append("/");
+
+        }
+
+        String resolvedPath = "";
+        if (!resolved.toString().equals("")) {
+            if (!endsWith && resolved.length() != 1) {
+                resolvedPath = resolved.substring(0, resolved.length() - 1);
+            } else {
+                resolvedPath = resolved.toString();
+            }
+        }
+        return (resolvedPath);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipUtils.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,481 @@
+/*
+ * 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.
+ */
+package com.sun.nio.zipfs;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import static com.sun.nio.zipfs.ZipHeaderConstants.*;
+import java.io.*;
+import java.net.URI;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.zip.*;
+
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.FileSystems;
+import org.classpath.icedtea.java.nio.file.NoSuchFileException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.Paths;
+import org.classpath.icedtea.java.nio.file.StandardOpenOption;
+
+/**
+ * This class implements static methods for reading the zip file contents
+ * It reads all the entries and caches them into a weak has map.
+ * Note that Zip reader may not work well for self extracting zips and
+ * other variants.
+ * This is a demo quality implementation, but can be enhanced easily.
+ */
+public class ZipUtils {
+
+    /**
+     * This map stores all the zip files that are extracted during the
+     * course of time when zip operations are performed on the zip file.
+     * The key for the map is the zip file reference.
+     * The zip file entries themselves are stored as map entries whose
+     * keys are zip file references to the entries.
+     */
+    public static Map<URI, Map<ZipFilePath, ZipEntryInfo>> cachedEntries =
+            new HashMap<URI, Map<ZipFilePath, ZipEntryInfo>>();
+    private static final boolean debug = true;
+    private static final FileSystem defFileSystem = FileSystems.getDefault();
+
+    static SeekableByteChannel open(FileRef fr) throws IOException {
+        Set<StandardOpenOption> options = new HashSet<StandardOpenOption>();
+        options.add(StandardOpenOption.READ);
+        return FileChannel.open((Path) fr, options);
+    }
+
+    private static ByteBuffer getHeaderField(
+            SeekableByteChannel ch, long offset, int nBytes)
+            throws IOException {
+        ByteBuffer buf = ByteBuffer.allocate(nBytes);
+        buf = buf.order(ByteOrder.LITTLE_ENDIAN);
+        ch.positionSBC(offset);
+        int read = ch.read(buf);
+        if (read <= 0) {
+            return null;
+        }
+        buf.flip();
+        return (buf);
+    }
+
+    private static int readInt(SeekableByteChannel ch, long offset)
+            throws IOException {
+        ByteBuffer buf = getHeaderField(ch, offset, 4);
+        return buf.getInt();
+    }
+
+    private static int readShort(SeekableByteChannel ch, long offset)
+            throws IOException {
+        ByteBuffer buf = getHeaderField(ch, offset, 2);
+        return buf.getShort();
+    }
+
+    private static byte[] readBytes(SeekableByteChannel ch, long offset, int len)
+            throws IOException {
+        ByteBuffer buf = getHeaderField(ch, offset, len);
+        return buf.array();
+    }
+
+    static long locateEndOfCentralDirRecord(
+            SeekableByteChannel ch, FileRef file)
+            throws IOException {
+
+        long fileLen = ch.size();
+        // read the file backwards 4 bytes at a time
+        long backOffset = fileLen - C_END_RECORD_MIN_OFF;
+        byte[] signature = new byte[]{0x06, 0x05, 0x4b, 0x50};
+        int matchedIndex = 0;
+        for (; (backOffset >= 0); backOffset--) {
+            ByteBuffer buf = getHeaderField(ch, backOffset, 1);
+            if (buf == null) {
+                break;
+            }
+            byte b;
+            if ((b = buf.get()) == signature[matchedIndex]) {
+                matchedIndex++;
+            } else {
+                matchedIndex = 0;
+            }
+            if (matchedIndex == 4) {
+                return backOffset; // this needs to be verified.
+            }
+        }
+        throw new IOException("Could not locate the central header");
+    }
+
+    /**
+     * logicalRef is the Logical file reference to the zip file.
+     * LogicalRef is of type: ZipFileRef
+     * <tt>file</tt> is the reference to the physical location of the file
+     * and is of type FileRef.
+     */
+    public static Map<ZipFilePath, ZipEntryInfo> fillEntries(
+            ZipFilePath zipPath, FileRef file)
+            throws IOException {
+
+        SeekableByteChannel ch = open(file);
+        ZipFileSystem m = zipPath.getFileSystem();
+        FileSystem fs = null;
+        Map<ZipFilePath, ZipEntryInfo> entries =
+                new HashMap<ZipFilePath, ZipEntryInfo>();
+
+        long endOfCentralDirOff = locateEndOfCentralDirRecord(ch, file);
+        int totalEntries = readShort(ch,
+                endOfCentralDirOff + C_TOTAL_ENTRIES_OFF);
+        long centralDirOff = readInt(ch,
+                endOfCentralDirOff + C_DIR_START_OFF);
+        Path fileName1 = zipPath.getName();
+        boolean isJar = false;
+        if (fileName1 != null) {
+            isJar = isJar(fileName1.toString());
+        } else {
+            isJar = isJar(zipPath.getFileSystem().getZipFileSystemFile());
+        }
+
+        for (int count = 0; count < totalEntries; count++) {
+            int sig;
+            if ((sig = readInt(ch, centralDirOff)) != CENTRAL_FILE_HDR_SIG) {
+                throw new IOException("Not the beginning of the central directory!");
+            }
+            ZipEntryInfo ze = new ZipEntryInfo();
+            JarEntryInfo jentry = null;
+            ze.versionMadeBy = readShort(ch, centralDirOff + C_VER_MADE_BY);
+            ze.method = readShort(ch, centralDirOff + C_COMP_METHOD_OFF);
+            ze.lastModifiedTime = readInt(ch, centralDirOff + C_LAST_MOD_TIME_OFF);
+            ze.crc = readInt(ch, centralDirOff + C_CRC_OFF);
+            ze.compSize = readInt(ch, centralDirOff + C_COMP_SIZE_OFF);
+            ze.size = readInt(ch, centralDirOff + C_UCOMP_SIZE_OFF);
+
+            int filenameLen = readShort(ch, centralDirOff + C_FILE_NAME_LEN_OFF);
+            int extraFieldLen = readShort(ch, centralDirOff + C_EXTRA_FLD_LEN_OFF);
+            int commentLen = readShort(ch, centralDirOff + C_COMMENT_LEN_OFF);
+
+            ze.extAttrs = readInt(ch, centralDirOff + C_EXT_ATTR_OFF);
+
+            // check which address the offset is relative to
+            ze.streamOffset = readInt(ch, centralDirOff + C_REL_OFF_LOCAL_HDR_OFF);
+            // the above line will give offset for the file name.
+
+            ze.filename = readBytes(ch, centralDirOff + C_FILE_NAME_OFF, filenameLen);
+            if (extraFieldLen > 0) {
+                ze.extraField = readBytes(ch, centralDirOff + C_FILE_NAME_OFF +
+                        filenameLen, extraFieldLen);
+            }
+            if (commentLen > 0) {
+                ze.comment = readBytes(ch, centralDirOff + C_FILE_NAME_OFF +
+                        filenameLen + extraFieldLen, commentLen);
+            }
+            centralDirOff = centralDirOff + C_FILE_NAME_OFF +
+                    filenameLen + extraFieldLen + commentLen;
+
+            ZipFilePath entryPath = null;
+            entryPath = zipPath.resolve(new String(ze.filename));
+
+            ze.isArchiveFile = entryPath.isArchiveFile();
+            ze.isDirectory = (entryPath.toString().endsWith("/") ? true : false);
+            ze.isRegularFile = !ze.isDirectory;
+            if (isJar) {
+                jentry = new JarEntryInfo(ze);
+                JarFile jarfile = new JarFile(file.toString());
+                Manifest manifest = jarfile.getManifest();
+                Attributes attrs = null;
+                if (manifest != null) {
+                    attrs = manifest.getMainAttributes();
+                }
+                if (attrs != null) {
+                    jentry.manifestMainAttrs = attrs.entrySet();
+                }
+                JarEntry jarentry = jarfile.getJarEntry(new String(ze.filename));
+                if (jarentry != null) {
+                    Attributes attributes = jarentry.getAttributes();
+                    if (attributes != null) {
+                        jentry.entryAttributs = attributes.entrySet();
+                    }
+                }
+            }
+            // cache the entry
+            if (!isJar) {
+                entries.put(entryPath, ze);
+            } else {
+                entries.put(entryPath, jentry);
+            }
+        }
+        ch.close();
+
+        //root entry
+
+        ZipEntryInfo rootentry = new ZipEntryInfo();
+        rootentry.isDirectory = true;
+        rootentry.isRegularFile = false;
+        JarEntryInfo jarRootEntry = null;
+        if (isJar) {
+            jarRootEntry = new JarEntryInfo(rootentry);
+        }
+        ZipFilePath root1 = zipPath.getRoot();
+        ZipFilePath root = (root1 == null) ? zipPath.toAbsolutePath().getRoot() : root1;
+        if (isJar) {
+            entries.put(root, jarRootEntry);
+        } else {
+            entries.put(root, rootentry);
+        }
+        return entries;
+    }
+
+    public static boolean isJar(String path) {
+        String lowerCase = path.toLowerCase();
+        return (lowerCase.endsWith(".jar"));
+
+    }
+
+    public static void extractZip(ZipFilePath f)
+            throws IOException {
+        Map<ZipFilePath, ZipEntryInfo> entries;
+        FileRef refToPhysicalZipFile = f;
+        if (f.isNestedZip()) {
+            refToPhysicalZipFile = extractNestedZip(f);
+        } else {
+            refToPhysicalZipFile = defFileSystem.getPath(f.getFileSystem().getZipFileSystemFile());//zp.zipPath;
+        }
+        entries = fillEntries(f, refToPhysicalZipFile);
+        cachedEntries.put(f.toUri0(), entries);
+    }
+
+    /**
+     *  getKey() returns path upto archive file if exists
+     *  otherwise path to Zip file in native filesytem
+     */
+    public static ZipFilePath getKey(ZipFilePath zp) {
+        int count = zp.getEntryNameCount();
+        if ((count == 0 || count == 1) && !zp.isArchiveFile()) { // / or /a/b/c
+            ZipFilePath root1 = zp.getRoot();
+            ZipFilePath root = (root1 == null) ? zp.toAbsolutePath().getRoot() : root1;
+            return root; //zp.zipPath;
+        }
+        if (count > 1 && !zp.isArchiveFile()) {  // /a.zip/e/f --> /a.zip
+            return zp.getParentEntry();
+        }
+        return zp; //no change /a.zip, /x/b.zip, /a.zip/b.zip, /a.zip/b.jar
+
+    }
+
+    /*
+     * Returns a map containing the all the entries of the given zip file
+     */
+    public static Map<ZipFilePath, ZipEntryInfo> getEntries(
+            ZipFilePath file)
+            throws IOException {
+
+        //getKey() returns path upto archive file if exists
+        //otherwise path to Zip file in native filesytem
+
+        ZipFilePath key = getKey(file);
+        Map<ZipFilePath, ZipEntryInfo> entries = cachedEntries.get(key.toUri0());
+        if (entries == null) {
+            extractZip(key);
+        }
+        entries = cachedEntries.get(key.toUri0());
+        if (entries == null) {
+
+            throw new IOException(
+                    "Zip entries for the file could not be found:" + key);
+        }
+        return entries;
+    }
+
+    /**
+     * Returns an entry refered by the given file reference
+     */
+    public static ZipEntryInfo getEntry(FileRef file1)
+            throws IOException {
+        Map<ZipFilePath, ZipEntryInfo> entries = null;
+        ZipEntryInfo ze = null;
+        ZipFilePath file = (ZipFilePath) file1;
+        int entryCount = file.getEntryNameCount();
+        if (file.isArchiveFile() && entryCount == 1) {
+            ZipFilePath root1 = file.getRoot();
+            ZipFilePath root = (root1 == null) ? (file.toAbsolutePath().getRoot()) : root1;
+            entries = ZipUtils.getEntries(root);
+            ze = getElement(entries, file);
+            ze.isDirectory = true; // Since it is Archive
+            ze.isRegularFile = false;
+        } else if (file.isArchiveFile() && entryCount > 1) {
+            ZipFilePath path = file.getParentEntry();
+            entries = ZipUtils.getEntries(path);
+            ze = getElement(entries, file);
+            ze.isDirectory = true; // Since it is Archive
+            ze.isArchiveFile = false;
+        } else {
+            entries = ZipUtils.getEntries(file);
+            ze = getElement(entries, file);
+        }
+        if (ze == null) {
+            throw new NoSuchFileException(
+                    "Zip file entry not found:" + file);
+        }
+        return ze;
+    }
+
+    static ZipEntryInfo getElement(Map<ZipFilePath, ZipEntryInfo> entries, ZipFilePath zfp)
+            throws IOException {
+
+        ZipEntryInfo zei = null;
+        zei = entries.get(zfp);
+        if (zei != null) {
+            if (zfp.getNameCount() == 0) { //zfp.equals(zfp.getRoot())
+                Path p = Paths.get(zfp.getFileSystem().getZipFileSystemFile());
+                try {
+                    long time =
+		      org.classpath.icedtea.java.nio.file.attribute.Attributes.readBasicFileAttributes(p).lastModifiedTime();
+                    zei.lastModifiedTime = javaTimeToDosTime(time);
+                } catch (IOException e) {
+                    throw e;
+                }
+            }
+            return zei;
+        }
+        for (ZipFilePath f : entries.keySet()) {
+            if (f.startsWith(zfp)) {
+                if (zfp.getNameCount() == f.getNameCount()) {
+                    zei = entries.get(f);
+                    return zei;
+                }
+            }
+        }
+        for (ZipFilePath f : entries.keySet()) {
+            if (f.startsWith(zfp)) {
+                if (zfp.getNameCount() < f.getNameCount()) {
+                    zei = new ZipEntryInfo(); //it is a path component in an entry,
+                    zei.isDirectory = true;   // jar/zip file won't contain any information
+                    zei.isRegularFile = false;  // about this dir component
+                    // Set directory as readable and executable
+                    zei.extAttrs = Integer.parseInt("-1111110101111111111111111111111", 2);
+                    boolean isJar = false;
+                    if (f.getEntryNameCount() > 1) {
+                        isJar = f.getParentEntry().getName().toString().toLowerCase().endsWith(".jar");
+                    } else {
+                        isJar = f.getFileSystem().getZipFileSystemFile().toLowerCase().endsWith(".jar");
+                    }
+                    if (isJar) {
+                        zei = new JarEntryInfo(zei);
+                    }
+                    return zei;
+                }
+            }
+        }
+        throw new NoSuchFileException("" + zfp); // no matching
+
+    }
+
+    private static long javaTimeToDosTime(long time) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis(time);
+        int year = cal.get(Calendar.YEAR);
+        if (year < 1980) {
+            return ((1 << 21) | (1 << 16));
+        }
+        return ((year - 1980) << 25 | (cal.get(Calendar.MONTH) + 1) << 21 |
+                cal.get(Calendar.DAY_OF_MONTH) << 16 | cal.get(Calendar.HOUR_OF_DAY) << 11 | cal.get(Calendar.MINUTE) << 5 |
+                cal.get(Calendar.SECOND) >> 1);
+    }
+
+    static void remove(URI uri) {
+        cachedEntries.remove(uri);
+    }
+
+    /**
+     * Extract the nested zips in a given file reference
+     * by extracting the intermediate zip file contents to a temporary
+     * location of the Platform file system
+     */
+    static FileRef extractNestedZip(ZipFilePath f) throws IOException {
+
+
+        if (f.getEntryNameCount() == 0) {
+            return null;
+        }
+        String zipFile = f.getFileSystem().getZipFileSystemFile();
+        int end = f.getEntryNameCount();
+        ZipFile zfile = null;
+        for (int i = 0; i < end; i++) {
+            try {
+                String nestedZip = f.getEntryName(i).toString();
+                zfile = new ZipFile(zipFile);
+                ZipEntry entry = zfile.getEntry(nestedZip);
+                if (entry == null) {
+                    throw new IOException("Invalid Zip Entry:" + nestedZip);
+                }
+                zipFile = readFileInZip(zfile.getInputStream(entry));
+            } finally {
+                zfile.close();
+            }
+        }
+        FileSystem m = FileSystems.getDefault();
+        FileRef retrievedZip = m.getPath(zipFile);
+        return retrievedZip;
+    }
+
+    static String readFileInZip(InputStream entry) throws IOException {
+
+        File tmpFile = null;
+        try {
+            BufferedInputStream zipStream = new BufferedInputStream(
+                    entry);
+
+            // unzip the file contents to a temp directory
+            String prefix = "zipfs";
+            String suffix = String.valueOf((new Date()).getTime());
+            tmpFile = File.createTempFile(prefix, suffix);
+            FileOutputStream tmpOut = new FileOutputStream(tmpFile);
+            byte buf[] = new byte[1024];
+            int read;
+            int offset = 0;
+            while ((read = zipStream.read(buf)) > 0) {
+                tmpOut.write(buf, 0, read);
+                offset = offset + read;
+            }
+            zipStream.close();
+            tmpOut.close();
+            tmpFile.deleteOnExit();
+        } catch (IOException e) {
+            throw e;
+        }
+        return tmpFile.getAbsolutePath();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c	Tue Feb 10 21:56:55 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>
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#endif
+
+/**
+ * Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level
+ * socket options to the platform specific level and option.
+ */
+
+static void out(char* s) {
+    printf("%s\n", s);
+}
+
+static void emit(const char *name, char * family, int level, int optname) {
+    printf("            map.put(new RegistryKey(%s, %s),", name, family);
+    printf(" new OptionKey(%d, %d));\n", level, optname);
+}
+
+static void emit_unspec(const char *name, int level, int optname) {
+    emit(name, "Net.UNSPEC", level, optname);
+}
+
+static  void emit_inet(const char *name, int level, int optname) {
+    emit(name, "StandardProtocolFamily.INET", level, optname);
+}
+
+static void emit_inet6(const char *name, int level, int optname) {
+    emit(name, "StandardProtocolFamily.INET6", level, optname);
+}
+
+int main(int argc, const char* argv[]) {
+    out("// AUTOMATICALLY GENERATED FILE - DO NOT EDIT                                  ");
+    out("package sun.nio.ch;                                                            ");
+    out("import java.util.Map;                                                          ");
+    out("import java.util.HashMap;                                                      ");
+    out("import org.classpath.icedtea.java.net.ProtocolFamily;                          ");
+    out("import org.classpath.icedtea.java.net.StandardProtocolFamily;                  ");
+    out("import org.classpath.icedtea.java.net.SocketOption;                            ");
+    out("import org.classpath.icedtea.java.net.StandardSocketOption;                    ");
+    out("class SocketOptionRegistry {                                                   ");
+    out("    private SocketOptionRegistry() { }                                         ");
+    out("    private static class RegistryKey {                                         ");
+    out("        private final SocketOption<?> name;                                    ");
+    out("        private final ProtocolFamily family;                                   ");
+    out("        RegistryKey(SocketOption<?> name, ProtocolFamily family) {                ");
+    out("            this.name = name;                                                  ");
+    out("            this.family = family;                                              ");
+    out("        }                                                                      ");
+    out("        public int hashCode() {                                                ");
+    out("            return name.hashCode() + family.hashCode();                        ");
+    out("        }                                                                      ");
+    out("        public boolean equals(Object ob) {                                     ");
+    out("            if (ob == null) return false;                                      ");
+    out("            if (!(ob instanceof RegistryKey)) return false;                    ");
+    out("            RegistryKey other = (RegistryKey)ob;                               ");
+    out("            if (this.name != other.name) return false;                         ");
+    out("            if (this.family != other.family) return false;                     ");
+    out("            return true;                                                       ");
+    out("        }                                                                      ");
+    out("    }                                                                          ");
+    out("    private static class LazyInitialization {                                  ");
+    out("        static final Map<RegistryKey,OptionKey> options = options();           ");
+    out("        private static Map<RegistryKey,OptionKey> options() {                  ");
+    out("            Map<RegistryKey,OptionKey> map =                                   ");
+    out("                new HashMap<RegistryKey,OptionKey>();                          ");
+
+    emit_unspec("StandardSocketOption.SO_BROADCAST", SOL_SOCKET, SO_BROADCAST);
+    emit_unspec("StandardSocketOption.SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE);
+    emit_unspec("StandardSocketOption.SO_LINGER",    SOL_SOCKET, SO_LINGER);
+    emit_unspec("StandardSocketOption.SO_SNDBUF",    SOL_SOCKET, SO_SNDBUF);
+    emit_unspec("StandardSocketOption.SO_RCVBUF",    SOL_SOCKET, SO_RCVBUF);
+    emit_unspec("StandardSocketOption.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR);
+    emit_unspec("StandardSocketOption.TCP_NODELAY",  IPPROTO_TCP, TCP_NODELAY);
+
+    emit_inet("StandardSocketOption.IP_TOS",            IPPROTO_IP,     IP_TOS);
+    emit_inet("StandardSocketOption.IP_MULTICAST_IF",   IPPROTO_IP,     IP_MULTICAST_IF);
+    emit_inet("StandardSocketOption.IP_MULTICAST_TTL",  IPPROTO_IP,     IP_MULTICAST_TTL);
+    emit_inet("StandardSocketOption.IP_MULTICAST_LOOP", IPPROTO_IP,     IP_MULTICAST_LOOP);
+
+#ifdef AF_INET6
+    emit_inet6("StandardSocketOption.IP_MULTICAST_IF",   IPPROTO_IPV6,  IPV6_MULTICAST_IF);
+    emit_inet6("StandardSocketOption.IP_MULTICAST_TTL",  IPPROTO_IPV6,  IPV6_MULTICAST_HOPS);
+    emit_inet6("StandardSocketOption.IP_MULTICAST_LOOP", IPPROTO_IPV6,  IPV6_MULTICAST_LOOP);
+#endif
+
+    emit_unspec("ExtendedSocketOption.SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE);
+
+    out("            return map;                                                        ");
+    out("        }                                                                      ");
+    out("    }                                                                          ");
+    out("    public static OptionKey findOption(SocketOption<?> name, ProtocolFamily family) { ");
+    out("        RegistryKey key = new RegistryKey(name, family);                       ");
+    out("        return LazyInitialization.options.get(key);                            ");
+    out("    }                                                                          ");
+    out("}                                                                              ");
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/sample/nio/aio/EchoServer.java	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,57 @@
+/*
+ * 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.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * 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/DefaultSelectorProvider.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2001-2005 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.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+
+import org.classpath.icedtea.java.nio.channels.spi.SelectorProvider;
+
+/**
+ * Creates this platform's default SelectorProvider
+ */
+
+public class DefaultSelectorProvider {
+
+    /**
+     * Prevent instantiation.
+     */
+    private DefaultSelectorProvider() { }
+
+    /**
+     * Returns the default SelectorProvider.
+     */
+    public static SelectorProvider create() {
+        String osname = AccessController.doPrivileged(
+            new GetPropertyAction("os.name"));
+        if ("SunOS".equals(osname)) {
+            return new sun.nio.ch.DevPollSelectorProvider();
+        }
+
+        // use EPollSelectorProvider for Linux kernels >= 2.6
+        if ("Linux".equals(osname)) {
+            String osversion = AccessController.doPrivileged(
+                new GetPropertyAction("os.version"));
+            String[] vers = osversion.split("\\.", 0);
+            if (vers.length >= 2) {
+                try {
+                    int major = Integer.parseInt(vers[0]);
+                    int minor = Integer.parseInt(vers[1]);
+                    if (major > 2 || (major == 2 && minor >= 6)) {
+                        return new sun.nio.ch.EPollSelectorProvider();
+                    }
+                } catch (NumberFormatException x) {
+                    // format not recognized
+                }
+            }
+        }
+
+        return new sun.nio.ch.PollSelectorProvider();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java	Tue Feb 10 21:56:55 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.ch;
+
+import java.io.IOException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+import sun.misc.Unsafe;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * AsynchronousChannelGroup implementation based on the Linux epoll facility.
+ */
+
+final class EPollPort
+    extends Port
+{
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    /**
+     * typedef union epoll_data {
+     *     void *ptr;
+     *     int fd;
+     *     __uint32_t u32;
+     *     __uint64_t u64;
+     *  } epoll_data_t;
+     *
+     * struct epoll_event {
+     *     __uint32_t events;
+     *     epoll_data_t data;
+     * }
+     */
+    // FIMXE - make this architecture independent
+    private static final short SIZEOF_EPOLLEVENT  = 12;
+    private static final short EVENT_OFFSET       = 0;
+    private static final short FD_OFFSET          = 4;
+
+    // opcodes
+    private static final int EPOLL_CTL_ADD  = 1;
+    private static final int EPOLL_CTL_DEL  = 2;
+    private static final int EPOLL_CTL_MOD  = 3;
+
+    // maximum number of events to poll at a time
+    private static final int MAX_EPOLL_EVENTS = 512;
+
+    // flags
+    private static final int  EPOLLONESHOT   = (1 << 30);
+
+    // errors
+    private static final int ENOENT     = 2;
+
+    // epoll file descriptor
+    private final int epfd;
+
+    // true if epoll closed
+    private boolean closed;
+
+    // socket pair used for wakeup
+    private final int sp[];
+
+    // number of wakeups pending
+    private final AtomicInteger wakeupCount = new AtomicInteger();
+
+    // address of the poll array passed to epoll_wait
+    private final long address;
+
+    // encapsulates an event for a channel
+    static class Event {
+        final PollableChannel channel;
+        final int events;
+
+        Event(PollableChannel channel, int events) {
+            this.channel = channel;
+            this.events = events;
+        }
+
+        PollableChannel channel()   { return channel; }
+        int events()                { return events; }
+    }
+
+    // queue of events for cases that a polling thread dequeues more than one
+    // event
+    private final ArrayBlockingQueue<Event> queue;
+    private final Event NEED_TO_POLL = new Event(null, 0);
+    private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0);
+
+    EPollPort(AsynchronousChannelProvider provider, ThreadPool pool)
+        throws IOException
+    {
+        super(provider, pool);
+
+        // open epoll
+        this.epfd = epollCreate();
+
+        // create socket pair for wakeup mechanism
+        int[] sv = new int[2];
+        try {
+            socketpair(sv);
+            // register one end with epoll
+            epollCtl(epfd, EPOLL_CTL_ADD, sv[0], POLLIN);
+        } catch (IOException x) {
+            close0(epfd);
+            throw x;
+        }
+        this.sp = sv;
+
+        // allocate the poll array
+        int allocationSize = MAX_EPOLL_EVENTS * SIZEOF_EPOLLEVENT;
+        this.address = unsafe.allocateMemory(allocationSize);
+
+        // create the queue and offer the special event to ensure that the first
+        // threads polls
+        this.queue = new ArrayBlockingQueue<Event>(MAX_EPOLL_EVENTS);
+        this.queue.offer(NEED_TO_POLL);
+    }
+
+    EPollPort start() {
+        startThreads(new EventHandlerTask());
+        return this;
+    }
+
+    /**
+     * Release all resources
+     */
+    private void implClose() {
+        synchronized (this) {
+            if (closed)
+                return;
+            closed = true;
+        }
+        unsafe.freeMemory(address);
+        close0(sp[0]);
+        close0(sp[1]);
+        close0(epfd);
+    }
+
+    private void wakeup() {
+        if (wakeupCount.incrementAndGet() == 1) {
+            // write byte to socketpair to force wakeup
+            try {
+                interrupt(sp[1]);
+            } 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 interrupt to each thread
+            while (nThreads-- > 0) {
+                wakeup();
+            }
+        }
+    }
+
+    // invoke by clients to register a file descriptor
+
+    void startPoll(int fd, int events) {
+        // update events (or add to epoll on first usage)
+        int err = epollCtl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
+        if (err == ENOENT)
+            err = epollCtl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
+        if (err != 0)
+            throw new AssertionError();     // should not happen
+    }
+
+    /*
+     * Task to process events from epoll and and dispatch to the channel's
+     * onEvent handler.
+     *
+     * Events are retreived from epoll in batch and offered to a BlockingQueue
+     * where they are consumed by handler threads. A special "NEED_TO_POLL"
+     * event is used to signal one consumer to re-poll when all events have
+     * been consumed.
+     */
+    private class EventHandlerTask implements Runnable {
+        private Event poll() throws IOException {
+            try {
+                for (;;) {
+                    int n = epollWait(epfd, address, MAX_EPOLL_EVENTS);
+                    /*
+                     * 'n' events have been read. Here we map them to their
+                     * corresponding channel in batch and queue n-1 so that
+                     * they can be handled by other handler threads. The last
+                     * event is handled by this thread (and so is not queued).
+                     */
+                    fdToChannelLock.readLock().lock();
+                    try {
+                        while (n-- > 0) {
+                            long eventAddress = address + (SIZEOF_EPOLLEVENT*n);
+                            int fd = unsafe.getInt(eventAddress + FD_OFFSET);
+
+                            // wakeup
+                            if (fd == sp[0]) {
+                                if (wakeupCount.decrementAndGet() == 0) {
+                                    // no more wakeups so drain pipe
+                                    drain1(sp[0]);
+                                }
+
+                                // queue special event if there are more events
+                                // to handle.
+                                if (n > 0) {
+                                    queue.offer(EXECUTE_TASK_OR_SHUTDOWN);
+                                    continue;
+                                }
+                                return EXECUTE_TASK_OR_SHUTDOWN;
+                            }
+
+                            PollableChannel channel = fdToChannel.get(fd);
+                            if (channel != null) {
+                                int events = unsafe.getInt(eventAddress + EVENT_OFFSET);
+                                Event ev = new Event(channel, events);
+
+                                // n-1 events are queued; This thread handles
+                                // the last one except for the wakeup
+                                if (n > 0) {
+                                    queue.offer(ev);
+                                } else {
+                                    return ev;
+                                }
+                            }
+                        }
+                    } finally {
+                        fdToChannelLock.readLock().unlock();
+                    }
+                }
+            } finally {
+                // to ensure that some thread will poll when all events have
+                // been consumed
+                queue.offer(NEED_TO_POLL);
+            }
+        }
+
+        public void run() {
+            Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+                Invoker.getGroupAndInvokeCount();
+            boolean replaceMe = false;
+            Event ev;
+            try {
+                for (;;) {
+                    // reset invoke count
+                    if (myGroupAndInvokeCount != null)
+                        myGroupAndInvokeCount.resetInvokeCount();
+
+                    try {
+                        replaceMe = false;
+                        ev = queue.take();
+
+                        // no events and this thread has been "selected" to
+                        // poll for more.
+                        if (ev == NEED_TO_POLL) {
+                            try {
+                                ev = poll();
+                            } catch (IOException x) {
+                                x.printStackTrace();
+                                return;
+                            }
+                        }
+                    } catch (InterruptedException x) {
+                        continue;
+                    }
+
+                    // handle wakeup to execute task or shutdown
+                    if (ev == EXECUTE_TASK_OR_SHUTDOWN) {
+                        Runnable task = pollTask();
+                        if (task == null) {
+                            // shutdown request
+                            return;
+                        }
+                        // run task (may throw error/exception)
+                        replaceMe = true;
+                        task.run();
+                        continue;
+                    }
+
+                    // process event
+                    try {
+                        ev.channel().onEvent(ev.events());
+                    } catch (Error x) {
+                        replaceMe = true; throw x;
+                    } catch (RuntimeException x) {
+                        replaceMe = true; throw x;
+                    }
+                }
+            } finally {
+                // last handler to exit when shutdown releases resources
+                int remaining = threadExit(this, replaceMe);
+                if (remaining == 0 && isShutdown()) {
+                    implClose();
+                }
+            }
+        }
+    }
+
+    // -- Native methods --
+
+    private static native void init();
+
+    private static native int epollCreate() throws IOException;
+
+    private static native int epollCtl(int epfd, int opcode, int fd, int events);
+
+    private static native int epollWait(int epfd, long pollAddress, int numfds)
+        throws IOException;
+
+    private static native void socketpair(int[] sv) throws IOException;
+
+    private static native void interrupt(int fd) throws IOException;
+
+    private static native void drain1(int fd) throws IOException;
+
+    private static native void close0(int epfd);
+
+    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/LinuxAsynchronousChannelProvider.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,100 @@
+/*
+ * 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.util.concurrent.ExecutorService;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup;
+import org.classpath.icedtea.java.nio.channels.AsynchronousDatagramChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousServerSocketChannel;
+import org.classpath.icedtea.java.nio.channels.IllegalChannelGroupException;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+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/Port.java	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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.io.Closeable;
+import java.io.FileDescriptor;
+import java.nio.channels.Channel;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.classpath.icedtea.java.nio.channels.ShutdownChannelGroupException;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * Base implementation of AsynchronousChannelGroupImpl for Unix systems.
+ */
+
+abstract class Port extends AsynchronousChannelGroupImpl {
+    static final short POLLIN       = 0x0001;
+    static final short POLLOUT      = 0x0004;
+    static final short POLLERR      = 0x0008;
+    static final short POLLHUP      = 0x0010;
+
+    /**
+     * Implemented by clients registered with this port.
+     */
+    interface PollableChannel extends Closeable {
+        void onEvent(int events);
+    }
+
+    // maps fd to "pollable" channel
+    protected final ReadWriteLock fdToChannelLock = new ReentrantReadWriteLock();
+    protected final Map<Integer,PollableChannel> fdToChannel =
+        new HashMap<Integer,PollableChannel>();
+
+
+    Port(AsynchronousChannelProvider provider, ThreadPool pool) {
+        super(provider, pool);
+    }
+
+    /**
+     * Register channel identified by its file descriptor
+     */
+    final void register(int fd, PollableChannel ch) {
+        fdToChannelLock.writeLock().lock();
+        try {
+            if (isShutdown())
+                throw new ShutdownChannelGroupException();
+            fdToChannel.put(Integer.valueOf(fd), ch);
+        } finally {
+            fdToChannelLock.writeLock().unlock();
+        }
+    }
+
+    /**
+     * Unregister channel identified by its file descriptor
+     */
+    final void unregister(int fd) {
+        boolean checkForShutdown = false;
+
+        fdToChannelLock.writeLock().lock();
+        try {
+            fdToChannel.remove(Integer.valueOf(fd));
+
+            // last key to be removed so check if group is shutdown
+            if (fdToChannel.isEmpty())
+                checkForShutdown = true;
+
+        } finally {
+            fdToChannelLock.writeLock().unlock();
+        }
+
+        // continue shutdown
+        if (checkForShutdown && isShutdown()) {
+            try {
+                shutdownNow();
+            } catch (IOException ignore) { }
+        }
+    }
+    /**
+     * Register file descriptor with polling mechanism for given events.
+     */
+    abstract void startPoll(int fd, int events);
+
+
+    final boolean isEmpty() {
+        fdToChannelLock.writeLock().lock();
+        try {
+            return fdToChannel.isEmpty();
+        } finally {
+            fdToChannelLock.writeLock().unlock();
+        }
+    }
+
+
+    final Object attachForeignChannel(final Channel channel, FileDescriptor fd) {
+        int fdVal = IOUtil.fdVal(fd);
+        register(fdVal, new PollableChannel() {
+            public void onEvent(int events) { }
+            public void close() throws IOException {
+                channel.close();
+            }
+        });
+        return Integer.valueOf(fdVal);
+    }
+
+
+    final void detachForeignChannel(Object key) {
+        unregister((Integer)key);
+    }
+
+
+    final void closeAllChannels() {
+        /**
+         * Close channels in batches of up to 128 channels. This allows close
+         * to remove the channel from the map without interference.
+         */
+        final int MAX_BATCH_SIZE = 128;
+        PollableChannel channels[] = new PollableChannel[MAX_BATCH_SIZE];
+        int count;
+        do {
+            // grab a batch of up to 128 channels
+            fdToChannelLock.writeLock().lock();
+            count = 0;
+            try {
+                for (Integer fd: fdToChannel.keySet()) {
+                    channels[count++] = fdToChannel.get(fd);
+                    if (count >= MAX_BATCH_SIZE)
+                        break;
+                }
+            } finally {
+                fdToChannelLock.writeLock().unlock();
+            }
+
+            // close them
+            for (int i=0; i<count; i++) {
+                try {
+                    channels[i].close();
+                } catch (IOException ignore) { }
+            }
+        } while (count > 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,103 @@
+/*
+ * 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.util.concurrent.ExecutorService;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.net.ProtocolFamily;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousChannelGroup;
+import org.classpath.icedtea.java.nio.channels.AsynchronousDatagramChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel;
+import org.classpath.icedtea.java.nio.channels.AsynchronousServerSocketChannel;
+import org.classpath.icedtea.java.nio.channels.IllegalChannelGroupException;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,243 @@
+/*
+ * 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.util.concurrent.RejectedExecutionException;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,320 @@
+/*
+ * 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.util.concurrent.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.net.InetSocketAddress;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.classpath.icedtea.java.nio.channels.AcceptPendingException;
+import org.classpath.icedtea.java.nio.channels.AsynchronousSocketChannel;
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,685 @@
+/*
+ * 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.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+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;
+
+import org.classpath.icedtea.java.nio.channels.CompletionHandler;
+import org.classpath.icedtea.java.nio.channels.InterruptedByTimeoutException;
+import org.classpath.icedtea.java.nio.channels.ShutdownChannelGroupException;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,74 @@
+/*
+ * 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 sun.security.action.GetPropertyAction;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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 org.classpath.icedtea.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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,99 @@
+/*
+ * 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.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,300 @@
+/*
+ * 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.util.concurrent.TimeUnit;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.DosFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.DosFileAttributeView;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,186 @@
+/*
+ * 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.io.IOException;
+import java.util.*;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+import static sun.nio.fs.LinuxNativeDispatcher.*;
+
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.WatchService;
+
+import org.classpath.icedtea.java.nio.file.attribute.DosFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.NamedAttributeView;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,344 @@
+/*
+ * 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.io.IOException;
+import java.util.*;
+import sun.misc.Unsafe;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+
+import org.classpath.icedtea.java.nio.file.FileSystemException;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,469 @@
+/*
+ * 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.util.*;
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+import org.classpath.icedtea.java.nio.file.NotDirectoryException;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.StandardWatchEventKind;
+import org.classpath.icedtea.java.nio.file.WatchEvent;
+import org.classpath.icedtea.java.nio.file.WatchKey;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,289 @@
+/*
+ * 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.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 org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.StandardOpenOption;
+
+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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,615 @@
+/*
+ * 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.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ExecutionException;
+import com.sun.nio.file.ExtendedCopyOption;
+
+import org.classpath.icedtea.java.nio.file.AtomicMoveNotSupportedException;
+import org.classpath.icedtea.java.nio.file.CopyOption;
+import org.classpath.icedtea.java.nio.file.DirectoryNotEmptyException;
+import org.classpath.icedtea.java.nio.file.FileAlreadyExistsException;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.LinkPermission;
+import org.classpath.icedtea.java.nio.file.StandardCopyOption;
+
+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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,270 @@
+/*
+ * 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.Iterator;
+import java.util.ConcurrentModificationException;
+import java.util.NoSuchElementException;
+import java.util.concurrent.locks.*;
+import java.io.IOException;
+import static sun.nio.fs.UnixNativeDispatcher.*;
+
+import org.classpath.icedtea.java.nio.file.ClosedDirectoryStreamException;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.Path;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.AccessDeniedException;
+import org.classpath.icedtea.java.nio.file.FileAlreadyExistsException;
+import org.classpath.icedtea.java.nio.file.FileSystemException;
+import org.classpath.icedtea.java.nio.file.NoSuchFileException;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,401 @@
+/*
+ * 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.util.concurrent.TimeUnit;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.ProviderMismatchException;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileOwnerAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.GroupPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+
+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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,312 @@
+/*
+ * 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.concurrent.TimeUnit;
+import java.util.Set;
+import java.util.HashSet;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission;
+import org.classpath.icedtea.java.nio.file.attribute.GroupPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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 org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission;
+
+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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,289 @@
+/*
+ * 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.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.*;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.Paths;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileOwnerAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.FileStoreSpaceAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView;
+
+/**
+ * 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,375 @@
+/*
+ * 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.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import sun.security.action.GetBooleanAction;
+
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.PathMatcher;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.FileOwnerAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.GroupPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipalLookupService;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+/**
+ * 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,151 @@
+/*
+ * 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.util.concurrent.ExecutorService;
+import java.io.IOException;
+import java.util.*;
+
+import org.classpath.icedtea.java.nio.channels.AsynchronousFileChannel;
+import org.classpath.icedtea.java.nio.channels.FileChannel;
+
+import org.classpath.icedtea.java.nio.channels.spi.AsynchronousChannelProvider.ThreadPoolType;
+
+import org.classpath.icedtea.java.nio.file.FileSystem;
+import org.classpath.icedtea.java.nio.file.FileSystemAlreadyExistsException;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.ProviderMismatchException;
+
+import org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+
+import org.classpath.icedtea.java.nio.file.spi.FileSystemProvider;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,1201 @@
+/*
+ * 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.io.*;
+import java.net.URI;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.util.*;
+import sun.security.util.SecurityConstants;
+
+import org.classpath.icedtea.java.io.FilePermission;
+
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+
+import org.classpath.icedtea.java.nio.file.AccessMode;
+import org.classpath.icedtea.java.nio.file.CopyOption;
+import org.classpath.icedtea.java.nio.file.DirectoryNotEmptyException;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.FileRef;
+import org.classpath.icedtea.java.nio.file.FileStore;
+import org.classpath.icedtea.java.nio.file.FileSystemException;
+import org.classpath.icedtea.java.nio.file.InvalidPathException;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.LinkPermission;
+import org.classpath.icedtea.java.nio.file.NotDirectoryException;
+import org.classpath.icedtea.java.nio.file.NotLinkException;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.ProviderMismatchException;
+import org.classpath.icedtea.java.nio.file.StandardOpenOption;
+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 org.classpath.icedtea.java.nio.file.attribute.FileAttribute;
+import org.classpath.icedtea.java.nio.file.attribute.FileAttributeView;
+
+import org.classpath.icedtea.java.nio.file.spi.AbstractPath;
+
+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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,664 @@
+/*
+ * 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.util.concurrent.TimeUnit;
+import java.io.IOException;
+
+import org.classpath.icedtea.java.nio.channels.SeekableByteChannel;
+
+import org.classpath.icedtea.java.nio.file.AtomicMoveNotSupportedException;
+import org.classpath.icedtea.java.nio.file.ClosedDirectoryStreamException;
+import org.classpath.icedtea.java.nio.file.DirectoryNotEmptyException;
+import org.classpath.icedtea.java.nio.file.DirectoryStream;
+import org.classpath.icedtea.java.nio.file.LinkOption;
+import org.classpath.icedtea.java.nio.file.NotDirectoryException;
+import org.classpath.icedtea.java.nio.file.OpenOption;
+import org.classpath.icedtea.java.nio.file.Path;
+import org.classpath.icedtea.java.nio.file.ProviderMismatchException;
+import org.classpath.icedtea.java.nio.file.SecureDirectoryStream;
+
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.BasicFileAttributeView;
+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.FileOwnerAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.GroupPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributes;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFileAttributeView;
+import org.classpath.icedtea.java.nio.file.attribute.PosixFilePermission;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,179 @@
+/*
+ * 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.io.IOException;
+
+import org.classpath.icedtea.java.nio.file.attribute.GroupPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipal;
+import org.classpath.icedtea.java.nio.file.attribute.UserPrincipalNotFoundException;
+
+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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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/DefaultSelectorProvider.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2001-2002 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.SelectorProvider;
+
+
+/**
+ * Creates this platform's default SelectorProvider
+ */
+
+public class DefaultSelectorProvider {
+
+    /**
+     * Prevent instantiation.
+     */
+    private DefaultSelectorProvider() { }
+
+    /**
+     * Returns the default SelectorProvider.
+     */
+    public static SelectorProvider create() {
+        return new sun.nio.ch.WindowsSelectorProvider();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/ch/Iocp.java	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,226 @@
+/*
+ * 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 = WindowsLinkSupport.getFinalPath(file, followLinks);
+        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 = WindowsLinkSupport.getFinalPath(file, followLinks);
+
+        // 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 = WindowsLinkSupport.getFinalPath(file, followLinks);
+
+        // 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 = WindowsLinkSupport.getFinalPath(file, followLinks);
+        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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,348 @@
+/*
+ * 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 OPEN_REPARSE_POINT = new OpenOption() { };
+
+    /**
+     * Represents the flags from a user-supplied set of open options.
+     */
+    private static class Flags {
+        boolean read;
+        boolean write;
+        boolean append;
+        boolean truncateExisting;
+        boolean create;
+        boolean createNew;
+        boolean deleteOnClose;
+        boolean sparse;
+        boolean overlapped;
+        boolean sync;
+        boolean dsync;
+
+        // non-standard
+        boolean shareRead = true;
+        boolean shareWrite = true;
+        boolean shareDelete = true;
+        boolean noFollowLinks;
+        boolean openReparsePoint;
+
+        static Flags toFlags(Set<? extends OpenOption> options) {
+            Flags flags = new Flags();
+            for (OpenOption option: options) {
+                if (!(option instanceof StandardOpenOption)) {
+                    if (option == ExtendedOpenOption.NOSHARE_READ) {
+                        flags.shareRead = false;
+                        continue;
+                    }
+                    if (option == ExtendedOpenOption.NOSHARE_WRITE) {
+                        flags.shareWrite = false;
+                        continue;
+                    }
+                    if (option == ExtendedOpenOption.NOSHARE_DELETE) {
+                        flags.shareDelete = false;
+                        continue;
+                    }
+                    if (option == LinkOption.NOFOLLOW_LINKS) {
+                        flags.noFollowLinks = true;
+                        continue;
+                    }
+                    if (option == OPEN_REPARSE_POINT) {
+                        flags.openReparsePoint = 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 : flags.sparse = true; break;
+                    case SYNC : flags.sync = true; break;
+                    case DSYNC : flags.dsync = true; break;
+                    default: throw new AssertionError("Should not get here");
+                }
+            }
+            return flags;
+        }
+    }
+
+    /**
+     * 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
+    {
+        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(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
+        return FileChannelImpl.open(fdObj, flags.read, flags.write, 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
+    {
+        Flags flags = Flags.toFlags(options);
+
+        // Overlapped I/O required
+        flags.overlapped = true;
+
+        // default is reading
+        if (!flags.read && !flags.write) {
+            flags.read = true;
+        }
+
+        // validation
+        if (flags.append)
+            throw new UnsupportedOperationException("APPEND not allowed");
+
+        // open file for overlapped I/O
+        FileDescriptor fdObj;
+        try {
+            fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(pathForWindows);
+            return null;
+        }
+
+        // create the AsynchronousFileChannel
+        try {
+            return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, 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,
+                                       Flags flags,
+                                       long pSecurityDescriptor)
+        throws WindowsException
+    {
+        // set to true if file must be truncated after open
+        boolean truncateAfterOpen = false;
+
+        // map options
+        int dwDesiredAccess = 0;
+        if (flags.read)
+            dwDesiredAccess |= GENERIC_READ;
+        if (flags.write)
+            dwDesiredAccess |= (flags.append) ? FILE_APPEND_DATA : GENERIC_WRITE;
+
+        int dwShareMode = 0;
+        if (flags.shareRead)
+            dwShareMode |= FILE_SHARE_READ;
+        if (flags.shareWrite)
+            dwShareMode |= FILE_SHARE_WRITE;
+        if (flags.shareDelete)
+            dwShareMode |= FILE_SHARE_DELETE;
+
+        int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+        int dwCreationDisposition = OPEN_EXISTING;
+        if (flags.write) {
+            if (flags.createNew) {
+                dwCreationDisposition = CREATE_NEW;
+                // force create to fail if file is orphaned reparse point
+                dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
+            } else {
+                if (flags.create)
+                    dwCreationDisposition = OPEN_ALWAYS;
+                if (flags.truncateExisting) {
+                    // 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 (flags.dsync || flags.sync)
+            dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
+        if (flags.overlapped)
+            dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
+        if (flags.deleteOnClose)
+            dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+
+        // NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point
+        boolean okayToFollowLinks = true;
+        if (dwCreationDisposition != CREATE_NEW &&
+            (flags.noFollowLinks ||
+             flags.openReparsePoint ||
+             flags.deleteOnClose))
+        {
+            if (flags.noFollowLinks)
+                okayToFollowLinks = false;
+            dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
+        }
+
+        // permission check
+        if (pathToCheck != null) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                if (flags.read)
+                    sm.checkRead(pathToCheck);
+                if (flags.write)
+                    sm.checkWrite(pathToCheck);
+                if (flags.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 && flags.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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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;
+
+        try {
+            // 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 += "\\*";
+            }
+
+            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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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.*;
+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 = WindowsLinkSupport.getFinalPath(file, followLinks);
+            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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,527 @@
+/*
+ * 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 = asWin32Path(source);
+        final String targetPath = asWin32Path(target);
+
+        // 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();
+        }
+
+        final String sourcePath = asWin32Path(source);
+        final String targetPath = asWin32Path(target);
+
+        // 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);
+        }
+    }
+
+
+    private static String asWin32Path(WindowsPath path) throws IOException {
+        try {
+            return path.getPathForWin32Calls();
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(path);
+            return null;
+        }
+    }
+
+    /**
+     * Copy DACL/owner/group from source to target
+     */
+    private static void copySecurityAttributes(WindowsPath source,
+                                               WindowsPath target,
+                                               boolean followLinks)
+        throws IOException
+    {
+        String path = WindowsLinkSupport.getFinalPath(source, followLinks);
+
+        // 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	Tue Feb 10 21:56:55 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, true);
+            } else {
+                // file must exist
+                WindowsFileAttributes.get(file, true);
+                target = file.getPathForWin32Calls();
+            }
+            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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(file);
+            return null;
+        } 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,466 @@
+/*
+ * 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, boolean followLinks)
+        throws IOException
+    {
+        WindowsFileSystem fs = input.getFileSystem();
+
+        try {
+            // if not following links then don't need final path
+            if (!followLinks || !fs.supportsLinks())
+                return input.getPathForWin32Calls();
+
+            // if file is a sym link then don't need final path
+            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	Tue Feb 10 21:56:55 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) throws WindowsException {
+        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.OPEN_REPARSE_POINT);
+            fc = WindowsChannelFactory
+                .newFileChannel(join(file, name), null, opts, 0L);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(join(file.getPathForPermissionCheck(), 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.OPEN_REPARSE_POINT);
+            fc = WindowsChannelFactory
+                .newFileChannel(join(file, name), null, opts, 0L);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(join(file.getPathForPermissionCheck(), 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.OPEN_REPARSE_POINT);
+            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.getPathForPermissionCheck(), 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 path = WindowsLinkSupport.getFinalPath(file, followLinks);
+        String toDelete = join(path, 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,1312 @@
+/*
+ * 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 java.lang.ref.WeakReference;
+
+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();
+
+    // The maximum path that does not require long path prefix. On Windows
+    // the maximum path is 260 minus 1 (NUL) but for directories it is 260
+    // minus 12 minus 1 (to allow for the creation of a 8.3 file in the
+    // directory).
+    private static final int MAX_PATH = 247;
+
+    // Maximum extended-length path
+    private static final int MAX_LONG_PATH = 32000;
+
+    // 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;
+
+    // the path to use in Win32 calls. This differs from path for relative
+    // paths and has a long path prefix for all paths longer than MAX_PATH.
+    private volatile WeakReference<String> pathForWin32Calls;
+
+    // offsets into name components (computed lazily)
+    private volatile Integer[] offsets;
+
+    // computed hash code (computed lazily, no need to be volatile)
+    private 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;
+    }
+
+    /**
+     * 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 path;
+    }
+
+    // use this path for Win32 calls
+    // This method will prefix long paths with \\?\ or \\?\UNC as required.
+    String getPathForWin32Calls() throws WindowsException {
+        // short absolute paths can be used directly
+        if (isAbsolute() && path.length() <= MAX_PATH)
+            return path;
+
+        // return cached values if available
+        WeakReference<String> ref = pathForWin32Calls;
+        String resolved = (ref != null) ? ref.get() : null;
+        if (resolved != null) {
+            // Win32 path already available
+            return resolved;
+        }
+
+        // resolve against default directory
+        resolved = getAbsolutePath();
+
+        // 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)
+        if (resolved.length() > MAX_PATH) {
+            if (resolved.length() > MAX_LONG_PATH) {
+                throw new WindowsException("Cannot access file with path exceeding "
+                    + MAX_LONG_PATH + " characters");
+            }
+            resolved = addPrefixIfNeeded(GetFullPathName(resolved));
+        }
+
+        // cache the resolved path (except drive relative paths as the working
+        // directory on removal media devices can change during the lifetime
+        // of the VM)
+        if (type != WindowsPathType.DRIVE_RELATIVE) {
+            synchronized (path) {
+                pathForWin32Calls = new WeakReference<String>(resolved);
+            }
+        }
+        return resolved;
+    }
+
+    // return this path resolved against the file system's default directory
+    private String getAbsolutePath() throws WindowsException {
+        if (isAbsolute())
+            return path;
+
+        // Relative path ("foo" for example)
+        if (type == WindowsPathType.RELATIVE) {
+            String defaultDirectory = getFileSystem().defaultDirectory();
+            if (defaultDirectory.endsWith("\\")) {
+                return defaultDirectory + path;
+            } else {
+                StringBuilder sb =
+                    new StringBuilder(defaultDirectory.length() + path.length() + 1);
+                return sb.append(defaultDirectory).append('\\').append(path).toString();
+            }
+        }
+
+        // Directory relative path ("\foo" for example)
+        if (type == WindowsPathType.DIRECTORY_RELATIVE) {
+            String defaultRoot = getFileSystem().defaultRoot();
+            return defaultRoot + path.substring(1);
+        }
+
+        // Drive relative path ("C:foo" for example).
+        if (isSameDrive(root, getFileSystem().defaultRoot())) {
+            // 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 result;
+        } else {
+            // relative to some other drive
+            String wd;
+            try {
+                int dt = GetDriveType(root + "\\");
+                if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR)
+                    throw new WindowsException("");
+                wd = GetFullPathName(root + ".");
+            } catch (WindowsException x) {
+                throw new WindowsException("Unable to get working directory of drive '" +
+                    Character.toUpperCase(root.charAt(0)) + "'");
+            }
+            String result = wd;
+            if (wd.endsWith("\\")) {
+                result += path.substring(root.length());
+            } else {
+                if (path.length() > root.length())
+                    result += "\\" + path.substring(root.length());
+            }
+            return result;
+        }
+    }
+
+    // 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 target = WindowsLinkSupport.getFinalPath(this, true);
+        NativeBuffer aclBuffer = WindowsAclFileAttributeView
+            .getFileSecurity(target, 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");
+        }
+
+        try {
+            return createFromNormalizedPath(getFileSystem(), getAbsolutePath());
+        } catch (WindowsException x) {
+            throw new IOError(new IOException(x.getMessage()));
+        }
+    }
+
+
+    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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun 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) {
+                boolean interrupted = Thread.interrupted();
+                if (!interrupted)
+                    throw new RuntimeException("Interrupt status was not set");
+                System.out.println("Copy failed (this is expected)");
+            }
+
+            // 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,273 @@
+/*
+ * 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.Arrays;
+import java.util.Map;
+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 interface Task {
+        void run() throws Exception;
+    }
+
+    static void tryCatch(Class<? extends Throwable> ex, Task task) {
+        boolean caught = false;
+        try {
+            task.run();
+        } catch (Throwable x) {
+            if (ex.isAssignableFrom(x.getClass())) {
+                caught = true;
+            } else {
+                throw new RuntimeException(x);
+            }
+        }
+        if (!caught)
+            throw new RuntimeException(ex.getName() + " expected");
+    }
+
+    static void expectNullPointerException(Task task) {
+        tryCatch(NullPointerException.class, task);
+    }
+
+    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 {
+        final 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
+        tryCatch(IOException.class, new Task() {
+            public void run() throws IOException {
+                view.read(ATTR_NAME, ByteBuffer.allocateDirect(1));
+            }});
+
+        // 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");
+
+        // Test: dynamic access
+        byte[] valueAsBytes = ATTR_VALUE.getBytes();
+        view.setAttribute(ATTR_NAME, valueAsBytes);
+        byte[] actualAsBytes = (byte[])view.getAttribute(ATTR_NAME);
+        if (!Arrays.equals(valueAsBytes, actualAsBytes))
+            throw new RuntimeException("Unexpected attribute value");
+        Map<String,?> map = view.readAttributes(ATTR_NAME);
+        if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
+            throw new RuntimeException("Unexpected attribute value");
+        map = view.readAttributes(ATTR_NAME, "*");
+        if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
+            throw new RuntimeException("Unexpected attribute value");
+        map = view.readAttributes("DoesNotExist");
+        if (!map.isEmpty())
+            throw new RuntimeException("Map expected to be empty");
+    }
+
+    static void miscTests(Path file) throws IOException {
+        final NamedAttributeView view = file
+            .getFileAttributeView(NamedAttributeView.class);
+        view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
+
+        // NullPointerException
+        final ByteBuffer buf = ByteBuffer.allocate(100);
+
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.read(null, buf);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.read(ATTR_NAME, null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.write(null, buf);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+               view.write(ATTR_NAME, null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.size(null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.delete(null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.getAttribute(null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.setAttribute(ATTR_NAME, null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.setAttribute(null, new byte[0]);
+            }});
+         expectNullPointerException(new Task() {
+            public void run() throws IOException {
+               view.readAttributes(null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.readAttributes("*", (String[])null);
+            }});
+        expectNullPointerException(new Task() {
+            public void run() throws IOException {
+                view.readAttributes("*", ATTR_NAME, null);
+            }});
+
+        // Read-only buffer
+        tryCatch(IllegalArgumentException.class, new Task() {
+            public void run() throws IOException {
+                ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer();
+                view.write(ATTR_NAME, buf);
+                buf.flip();
+                view.read(ATTR_NAME, buf);
+            }});
+
+        // Zero bytes remaining
+        tryCatch(IOException.class, new Task() {
+            public void run() throws IOException {
+                ByteBuffer buf = buf = ByteBuffer.allocateDirect(100);
+                buf.position(buf.capacity());
+                view.read(ATTR_NAME, buf);
+            }});
+    }
+
+    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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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	Tue Feb 10 21:56:55 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/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/DefaultLaunchHandler.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/DefaultLaunchHandler.java	Tue Feb 10 21:56:55 2009 +0000
@@ -107,8 +107,6 @@
             result.append(causes[i].getMessage());
             result.append(")");
         }
-
-        System.out.println(result);
     }
 
 }
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Tue Feb 10 21:56:55 2009 +0000
@@ -29,7 +29,6 @@
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
-import java.security.Policy;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Enumeration;
@@ -38,6 +37,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.TreeSet;
 import java.util.Vector;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -131,7 +131,11 @@
 
 	private boolean signing = false;
 	
+	/** ArrayList containing jar indexes for various jars available to this classloader */
 	private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>();
+	
+	/** File entries in the jar files available to this classloader */
+	private TreeSet jarEntries = new TreeSet();
 
     /**
      * Create a new JNLPClassLoader from the specified file.
@@ -478,7 +482,6 @@
                 // transfer the Jars
                 waitForJars(jars);
 
-
                 for (int i=0; i < jars.size(); i++) {
                     JARDesc jar = (JARDesc) jars.get(i);
 
@@ -488,8 +491,23 @@
                     File localFile = tracker.getCacheFile(jar.getLocation());
                     try {
                         URL location = jar.getLocation(); // non-cacheable, use source location
-                        if (localFile != null)
+                        if (localFile != null) {
                             location = localFile.toURL(); // cached file
+                            
+                            // This is really not the best way.. but we need some way for 
+                            // PluginAppletViewer::getCachedImageRef() to check if the image 
+                            // is available locally, and it cannot use getResources() because 
+                            // that prefetches the resource, which confuses MediaTracker.waitForAll() 
+                            // which does a wait(), waiting for notification (presumably 
+                            // thrown after a resource is fetched). This bug manifests itself
+                            // particularly when using The FileManager applet from Webmin.
+                            
+                            JarFile jarFile = new JarFile(localFile);
+                            Enumeration e = jarFile.entries();
+                            while (e.hasMoreElements())
+                                jarEntries.add(((JarEntry) e.nextElement()).getName());
+
+                        }
 
                         addURL(location);
 
@@ -727,7 +745,6 @@
 
                             try {
                                 u = tracker.getCacheURL(remoteURL);
-                                System.out.println("URL = " + u);
                             } catch (Exception e) {
                                 throw new ClassNotFoundException(name);
                             }
@@ -758,6 +775,7 @@
                     return loaders[i].findClass(name);
             }
             catch(ClassNotFoundException ex) { }
+            catch(ClassFormatError cfe) {}
         }
 
         throw new ClassNotFoundException(name);
@@ -829,6 +847,16 @@
 
         return resources.elements();
     }
+    
+    /**
+     * Returns if the specified resource is available locally from a cached jar
+     * 
+     * @param s The name of the resource
+     * @return Whether or not the resource is available locally
+     */
+    public boolean resourceAvailableLocally(String s) {
+        return jarEntries.contains(s);
+    }
 
     /**
      * Adds whatever resources have already been downloaded in the
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -37,11 +37,24 @@
 
 package net.sourceforge.jnlp.security;
 
-import java.awt.*;
-import javax.swing.*;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
-import java.net.URL;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
 
 import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
@@ -59,12 +72,12 @@
 	JCheckBox alwaysAllow;
 	Object[] extras;
 	
-	public AccessWarningPane(JComponent x) {
-		super(x);
+	public AccessWarningPane(JComponent x, CertVerifier certVerifier) {
+		super(x, certVerifier);
 	}
 
-	public AccessWarningPane(JComponent x, Object[] extras) {
-		super(x);
+	public AccessWarningPane(JComponent x, Object[] extras, CertVerifier certVerifier) {
+		super(x, certVerifier);
 		this.extras = extras;
 	}
 
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AppletWarningPane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AppletWarningPane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -50,10 +50,11 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 
+
 public class AppletWarningPane extends SecurityDialogUI {
 
-	public AppletWarningPane(JComponent x) {
-		super(x);
+	public AppletWarningPane(JComponent x, CertVerifier certVerifier) {
+		super(x, certVerifier);
 	}
 
 	protected void installComponents() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertVerifier.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,92 @@
+/* CertVerifier.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+
+/**
+ * An interface that provides various details about a certificate 
+ */
+
+public interface CertVerifier {
+
+    /**
+     * Return if the publisher is already trusted
+     */
+    public boolean getAlreadyTrustPublisher();
+
+    /**
+     * Return if the root is in CA certs
+     */
+    public boolean getRootInCacerts();
+
+    /**
+     * Return if there are signing issues with the certificate(s) being veried
+     */
+    public boolean hasSigningIssues();
+
+    /**
+     * Return if there are no signing issues with this cert (!hasSigningIssues())
+     */
+    public boolean noSigningIssues();
+
+    /**
+     * Get the details regarding issue(s) with this certificate
+     */
+    public ArrayList<String> getDetails();
+
+    /**
+     * Return a valid certificate path to this certificate(s) being verified
+     * @return The CertPath
+     */
+    public ArrayList<CertPath> getCerts();
+
+    /** 
+     * Returns the application's publisher's certificate.
+     */
+    public abstract Certificate getPublisher();
+
+    /**
+     * Returns the application's root's certificate. This
+     * may return the same certificate as getPublisher() in
+     * the event that the application is self signed.
+     */
+    public abstract Certificate getRoot();
+}
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertWarningPane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertWarningPane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -37,15 +37,27 @@
 
 package net.sourceforge.jnlp.security;
 
-import java.awt.*;
-import javax.swing.*;
-
-
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
 import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.PluginBridge;
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
@@ -62,9 +74,11 @@
 public class CertWarningPane extends SecurityDialogUI {
 
 	JCheckBox alwaysTrust;
+	CertVerifier certVerifier;
 
-	public CertWarningPane(JComponent x) {
-		super(x);
+	public CertWarningPane(JComponent x, CertVerifier certVerifier) {
+		super(x, certVerifier);
+		this.certVerifier = certVerifier;
 	}
 
 	/**
@@ -75,7 +89,9 @@
 			((SecurityWarningDialog)optionPane).getType();
 		JNLPFile file =
 			((SecurityWarningDialog)optionPane).getFile();
-
+		Certificate c = ((SecurityWarningDialog)optionPane)
+                                .getJarSigner().getPublisher();
+		
 		String name = "";
 		String publisher = "";
 		String from = "";
@@ -83,7 +99,11 @@
 		//We don't worry about exceptions when trying to fill in
 		//these strings -- we just want to fill in as many as possible.
 		try {
-			if (file instanceof PluginBridge)
+			if ((certVerifier instanceof HttpsCertVerifier) && 
+			     (c instanceof X509Certificate))
+			   name = getCN(((X509Certificate)c)
+                                        .getSubjectX500Principal().getName());
+			else if (file instanceof PluginBridge)
 				name = file.getTitle();
 			else
 				name = file.getInformation().getTitle();
@@ -91,8 +111,6 @@
 		}
 
 		try {
-			Certificate c = ((SecurityWarningDialog)optionPane)
-				.getJarSigner().getPublisher();
 			if (c instanceof X509Certificate) {
 				publisher = getCN(((X509Certificate)c)
 					.getSubjectX500Principal().getName());
@@ -111,20 +129,27 @@
 		//Top label
 		String topLabelText = "";
 		String propertyName = "";
-		switch (type) {
-		case VERIFIED:
-			topLabelText = R("SSigVerified");
+		if (certVerifier instanceof HttpsCertVerifier)
+		{
+		  topLabelText = "The website's certificate cannot be verified. " +
+				 "Do you want to continue?";
+		  propertyName = "OptionPane.warningIcon";
+		}
+		else
+		  switch (type) {
+		  case VERIFIED:
+		 	topLabelText = R("SSigVerified");
 			propertyName = "OptionPane.informationIcon";
 			break;
-		case UNVERIFIED:
+		  case UNVERIFIED:
 			topLabelText = R("SSigUnverified");
 			propertyName = "OptionPane.warningIcon";
 			break;
-		case SIGNING_ERROR:
+	  	  case SIGNING_ERROR:
 			topLabelText = R("SSignatureError");
 			propertyName = "OptionPane.warningIcon";
 			break;
-		}
+		  }
 		ImageIcon icon = new ImageIcon((new sun.misc.Launcher())
 				.getClassLoader().getResource("net/sourceforge/jnlp/resources/warning.png"));
 		JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT);
@@ -151,7 +176,10 @@
 		JPanel infoPanel = new JPanel(new GridLayout(4,1));
 		infoPanel.add(nameLabel);
 		infoPanel.add(publisherLabel);
-		infoPanel.add(fromLabel);
+
+		if (!(certVerifier instanceof HttpsCertVerifier))
+		  infoPanel.add(fromLabel);
+
 		infoPanel.add(alwaysTrust);
 		infoPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
 
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertsInfoPane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/CertsInfoPane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -76,8 +76,8 @@
     private String[] columnNames = { "Field", "Value" };
 	protected ArrayList<String[][]> certsData;
 
-	public CertsInfoPane(JComponent x) {
-		super(x);
+	public CertsInfoPane(JComponent x, CertVerifier certVerifier) {
+		super(x, certVerifier);
 	}
 
 	/**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/HttpsCertVerifier.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,175 @@
+/* HttpsCertVerifier.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.tools.KeyTool;
+ 
+public class HttpsCertVerifier implements CertVerifier {
+
+    private VariableX509TrustManager tm;
+    private X509Certificate[] chain;
+    private String authType;
+    private ArrayList<String> details = new ArrayList<String>();
+    
+    public HttpsCertVerifier(VariableX509TrustManager tm, X509Certificate[] chain, String authType) {
+        this.tm = tm;
+        this.chain = chain;
+        this.authType = authType;
+    }
+
+    public boolean getAlreadyTrustPublisher() {
+        try {
+            tm.checkServerTrusted(chain, authType, true);
+            return true;
+        } catch (CertificateException ce) {
+            return false;
+        }
+    }
+
+    public ArrayList<CertPath> getCerts() {
+        
+        ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
+        for (int i=0; i < chain.length; i++)
+            list.add(chain[i]);
+
+        ArrayList<CertPath> certPaths = new ArrayList<CertPath>();
+        
+        try {
+            certPaths.add(CertificateFactory.getInstance("X.509").generateCertPath(list));
+        } catch (CertificateException ce) {
+            ce.printStackTrace();
+            
+            // carry on
+        }
+
+        return certPaths; 
+    }
+
+    public ArrayList<String> getDetails() {
+	boolean hasExpiredCert=false; 
+	boolean hasExpiringCert=false;
+	boolean notYetValidCert=false;
+	boolean isUntrusted=false; 
+
+	if (! getAlreadyTrustPublisher())
+              isUntrusted = true;
+
+	for (int i=0; i < chain.length; i++)
+	{
+	   X509Certificate cert = chain[i];	
+
+           long now = System.currentTimeMillis();
+           long SIX_MONTHS = 180*24*60*60*1000L;
+	   long notAfter = cert.getNotAfter().getTime();
+           if (notAfter < now) {
+             hasExpiredCert = true;
+           } else if (notAfter < now + SIX_MONTHS) {
+             hasExpiringCert = true;
+           }
+	
+	   try {
+	     cert.checkValidity();
+	   } catch (CertificateNotYetValidException cnyve) {
+             notYetValidCert = true;
+	   } catch (CertificateExpiredException cee) {
+	     hasExpiredCert = true;
+	   }
+	}
+
+	if (isUntrusted || hasExpiredCert || hasExpiringCert || notYetValidCert) {
+	      if (isUntrusted)
+	        addToDetails(R("SUntrustedCertificate"));
+              if (hasExpiredCert)
+                addToDetails(R("SHasExpiredCert"));
+              if (hasExpiringCert)
+                addToDetails(R("SHasExpiringCert"));
+              if (notYetValidCert)
+                addToDetails(R("SNotYetValidCert"));
+        }
+	return details;
+    }
+
+    private void addToDetails(String detail) {
+      if (!details.contains(detail))
+        details.add(detail);
+    }
+
+    private static String R(String key) {
+      return JNLPRuntime.getMessage(key);
+    }
+
+    public Certificate getPublisher() {
+      if (chain.length > 0)
+        return (Certificate)chain[0];
+      return null;
+    }
+
+    public Certificate getRoot() {
+      if (chain.length > 0) 
+        return (Certificate)chain[chain.length - 1];
+      return null;
+    }
+
+    public boolean getRootInCacerts() {
+	try {
+	  KeyTool kt = new KeyTool();
+          return kt.checkCacertsForCertificate(getRoot());
+        } catch (Exception e) {
+	}
+	return false;
+    }
+
+    public boolean hasSigningIssues() {
+        return false;
+    }
+
+    public boolean noSigningIssues() {
+        return false;
+    }
+
+}
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/MoreInfoPane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/MoreInfoPane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -37,15 +37,22 @@
 
 package net.sourceforge.jnlp.security;
 
-import java.awt.*;
-import javax.swing.*;
-
-import net.sourceforge.jnlp.runtime.*;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
 
-import java.util.ArrayList;
-import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
-import javax.swing.border.Border;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
 
 /**
  * Provides the UI for the More Info dialog. This dialog shows details about an
@@ -55,17 +62,15 @@
  */
 public class MoreInfoPane extends SecurityDialogUI {
 
-	public MoreInfoPane(JComponent x) {
-		super(x);
+	public MoreInfoPane(JComponent x, CertVerifier certVerifier) {
+		super(x, certVerifier);
 	}
 
 	/**
 	 * Constructs the GUI components of this UI
 	 */
 	protected void installComponents() {
-		ArrayList<String> details = 
-			((SecurityWarningDialog)optionPane)
-				.getJarSigner().getDetails();
+		ArrayList<String> details = certVerifier.getDetails();
 
 		int numLabels = details.size();
 		JPanel errorPanel = new JPanel(new GridLayout(numLabels,1));
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityDialogUI.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityDialogUI.java	Tue Feb 10 21:56:55 2009 +0000
@@ -37,18 +37,22 @@
 
 package net.sourceforge.jnlp.security;
 
-import java.awt.*;
-import javax.swing.*;
-import javax.swing.border.Border;
-import javax.swing.plaf.OptionPaneUI;
-import java.beans.PropertyChangeListener;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.ComponentOrientation;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.beans.PropertyChangeEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.ComponentAdapter;
+import java.beans.PropertyChangeListener;
 
-import net.sourceforge.jnlp.JNLPFile;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JRootPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.OptionPaneUI;
+
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
 
 /**
@@ -63,13 +67,16 @@
 
 	/** Component to receive focus when messaged with selectInitialValue. */
 	Component initialFocusComponent;
+	
+	CertVerifier certVerifier;
 
 	/** PropertyChangeListener for <code>optionPane</code> */
 	private PropertyChangeListener propertyChangeListener;
 	private Handler handler;
 
-	public SecurityDialogUI(JComponent x){
+	public SecurityDialogUI(JComponent x, CertVerifier certVerifier){
 		optionPane = (JOptionPane)x;
+		this.certVerifier = certVerifier;
 	}
 
 	/**
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityWarningDialog.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SecurityWarningDialog.java	Tue Feb 10 21:56:55 2009 +0000
@@ -38,7 +38,6 @@
 package net.sourceforge.jnlp.security;
 
 import net.sourceforge.jnlp.JNLPFile;
-import net.sourceforge.jnlp.tools.JarSigner;
 
 import java.awt.*;
 import javax.swing.*;
@@ -86,10 +85,10 @@
 	/** The type of access that this dialog is for */
 	private AccessType accessType;
 
-	/** The application file assocated with this security warning */
+	/** The application file associated with this security warning */
 	private JNLPFile file;
 
-	private JarSigner jarSigner;
+	private CertVerifier certVerifier;
 	
 	private X509Certificate cert;
 	
@@ -107,27 +106,37 @@
 		this.dialogType = dialogType;
 		this.accessType = accessType;
 		this.file = file;
-		this.jarSigner = null;
+		this.certVerifier = null;
+		initialized = true;
+		updateUI();
+	}
+	
+	public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
+			JNLPFile file, CertVerifier jarSigner) {
+		this.dialogType = dialogType;
+		this.accessType = accessType;
+		this.file = file;
+		this.certVerifier = jarSigner;
 		initialized = true;
 		updateUI();
 	}
 	
 	public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
-			JNLPFile file, JarSigner jarSigner) {
-		this.dialogType = dialogType;
-		this.accessType = accessType;
-		this.file = file;
-		this.jarSigner = jarSigner;
-		initialized = true;
-		updateUI();
+	        CertVerifier certVerifier) {
+	    this.dialogType = dialogType;
+	    this.accessType = accessType;
+	    this.file = null;
+	    this.certVerifier = certVerifier;
+	    initialized = true;
+	    updateUI();
 	}
-	
+
 	public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
 			JNLPFile file, Object[] extras) {
 		this.dialogType = dialogType;
 		this.accessType = accessType;
 		this.file = file;
-		this.jarSigner = null;
+		this.certVerifier = null;
 		initialized = true;
 		this.extras = extras;
 		updateUI();
@@ -138,7 +147,7 @@
 		this.dialogType = dialogType;
 		this.accessType = null;
 		this.file = null;
-		this.jarSigner = null;
+		this.certVerifier = null;
 		this.cert = c;
 		initialized = true;
 		updateUI();
@@ -210,7 +219,7 @@
 	 * @param jarSigner the JarSigner used to verify this application
 	 */
 	public static boolean showCertWarningDialog(AccessType accessType, 
-			JNLPFile file, JarSigner jarSigner) {
+			JNLPFile file, CertVerifier jarSigner) {
 		SecurityWarningDialog swd = 
 			new SecurityWarningDialog(DialogType.CERT_WARNING, accessType, file,
 			jarSigner);
@@ -241,7 +250,7 @@
 	 * @param parent the parent option pane
 	 */
 	public static void showMoreInfoDialog(
-		JarSigner jarSigner, JOptionPane parent) {
+		CertVerifier jarSigner, JOptionPane parent) {
 
 		SecurityWarningDialog swd =
 			new SecurityWarningDialog(DialogType.MORE_INFO, null, null,
@@ -259,7 +268,7 @@
 	 *
 	 * @param certs the certificates used in signing.
 	 */
-	public static void showCertInfoDialog(JarSigner jarSigner,
+	public static void showCertInfoDialog(CertVerifier jarSigner,
 		JOptionPane parent) {
 		SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.CERT_INFO,
 			null, null, jarSigner);
@@ -291,7 +300,7 @@
 	
 	public static int showAppletWarning() {
         	SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.APPLET_WARNING,
-            		null, null, (JarSigner) null);
+            		null, null, (CertVerifier) null);
         	JDialog dialog = swd.createDialog();
 		centerDialog(dialog);
         	swd.selectInitialValue();
@@ -382,8 +391,8 @@
 		return file;
 	}
 	
-	public JarSigner getJarSigner() {
-		return jarSigner;
+	public CertVerifier getJarSigner() {
+		return certVerifier;
 	}
 	
 	public X509Certificate getCert() {
@@ -397,17 +406,17 @@
 	public void updateUI() {
 
 		if (dialogType == DialogType.CERT_WARNING)
-			setUI((OptionPaneUI) new CertWarningPane(this));
+			setUI((OptionPaneUI) new CertWarningPane(this, this.certVerifier));
 		else if (dialogType == DialogType.MORE_INFO)
-			setUI((OptionPaneUI) new MoreInfoPane(this));
+			setUI((OptionPaneUI) new MoreInfoPane(this, this.certVerifier));
 		else if (dialogType == DialogType.CERT_INFO)
-			setUI((OptionPaneUI) new CertsInfoPane(this));
+			setUI((OptionPaneUI) new CertsInfoPane(this, this.certVerifier));
 		else if (dialogType == DialogType.SINGLE_CERT_INFO)
-			setUI((OptionPaneUI) new SingleCertInfoPane(this));
+			setUI((OptionPaneUI) new SingleCertInfoPane(this, this.certVerifier));
 		else if (dialogType == DialogType.ACCESS_WARNING)
-			setUI((OptionPaneUI) new AccessWarningPane(this, extras));
+			setUI((OptionPaneUI) new AccessWarningPane(this, extras, this.certVerifier));
 		else if (dialogType == DialogType.APPLET_WARNING)
-			setUI((OptionPaneUI) new AppletWarningPane(this));
+			setUI((OptionPaneUI) new AppletWarningPane(this, this.certVerifier));
 	}
 
 	private static void centerDialog(JDialog dialog) {
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SingleCertInfoPane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/SingleCertInfoPane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -45,10 +45,11 @@
 import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.TreeSelectionModel;
 
+
 public class SingleCertInfoPane extends CertsInfoPane {
 
-	public SingleCertInfoPane(JComponent x) {
-		super(x);
+	public SingleCertInfoPane(JComponent x, CertVerifier certVerifier) {
+		super(x, certVerifier);
 	}
 	
 	protected void buildTree() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/VariableX509TrustManager.java	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,219 @@
+/* VariableX509TrustManager.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import sun.security.validator.ValidatorException;
+
+/**
+ * This class implements an X509 Trust Manager. The certificates it trusts are 
+ * "variable", in the sense that it can dynamically, and temporarily support 
+ * different certificates that are not in the keystore.  
+ */
+
+public class VariableX509TrustManager implements X509TrustManager {
+
+    KeyStore userKeyStore = null;
+    KeyStore caKeyStore = null;
+    
+    X509TrustManager userTrustManager = null;
+    X509TrustManager caTrustManager = null;
+    
+    ArrayList<Certificate> temporarilyTrusted = new ArrayList();
+    
+    static VariableX509TrustManager instance = null;
+
+    /**
+     * Constructor initializes the system, user and custom stores
+     */
+    public VariableX509TrustManager() {
+
+        try {
+            userKeyStore = SecurityUtil.getUserKeyStore();
+            TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+            tmFactory.init(userKeyStore);
+            
+            // tm factory initialized, now get the managers so we can assign the X509 one
+            TrustManager[] trustManagers = tmFactory.getTrustManagers();
+            
+            for (int i=0; i < trustManagers.length; i++) {
+                if (trustManagers[i] instanceof X509TrustManager) {
+                    userTrustManager = (X509TrustManager) trustManagers[i];
+                }
+            }
+
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        try {
+            caKeyStore = SecurityUtil.getCacertsKeyStore();
+            TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+            tmFactory.init(caKeyStore);
+
+            // tm factory initialized, now get the managers so we can extract the X509 one
+            TrustManager[] trustManagers = tmFactory.getTrustManagers();
+
+            for (int i=0; i < trustManagers.length; i++) {
+                if (trustManagers[i] instanceof X509TrustManager) {
+                    caTrustManager = (X509TrustManager) trustManagers[i];
+                }
+            }
+
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Check if client is trusted (not support for custom here, only system/user)
+     */
+    public void checkClientTrusted(X509Certificate[] chain, String authType)
+            throws CertificateException {
+
+        // First try catrustmanager, then try usertrustmanager
+        try {
+            caTrustManager.checkClientTrusted(chain, authType);
+        } catch (Exception caex) {
+            try {
+                userTrustManager.checkClientTrusted(chain, authType);
+            } catch (Exception userex) {
+                // Do nothing here. This trust manager is intended to be used 
+                // only in the plugin instance vm, which does not act as a 
+                // server
+            }
+        }
+    }
+
+    public void checkServerTrusted(X509Certificate[] chain, String authType)
+            throws CertificateException {
+        checkServerTrusted(chain, authType, false);
+    }
+
+    /**
+     * Check if the server is trusted
+     * 
+     * @param chain The cert chain
+     * @param authType The auth type algorithm
+     * @param checkOnly Whether to "check only" i.e. no user prompt, or to prompt for permission 
+     */
+    public void checkServerTrusted(X509Certificate[] chain, String authType, boolean checkOnly) throws CertificateException {
+        try {
+            checkAllManagers(chain, authType);
+        } catch (CertificateException ce) {
+            
+            if (checkOnly) {
+                throw ce;
+            } else {
+
+                boolean b = askUser(chain,authType);
+            
+                if (b) {
+                    temporarilyTrust(chain[0]);
+                }
+
+                checkAllManagers(chain, authType);
+            }
+        }
+    }
+
+    /**
+     * Check system, user and custom trust manager  
+     */
+    private void checkAllManagers(X509Certificate[] chain, String authType) throws CertificateException {
+        // First try catrustmanager, then try usertrustmanager, and finally, check temp trusted certs
+        try {
+            caTrustManager.checkServerTrusted(chain, authType);
+        } catch (ValidatorException caex) {
+            try {
+                userTrustManager.checkServerTrusted(chain, authType);
+            } catch (ValidatorException uex) {
+                if (!temporarilyTrusted.contains(chain[0]))
+                    throw (CertificateException) uex;
+            }
+        }        
+    }
+
+    public X509Certificate[] getAcceptedIssuers() {
+        // delegate to default
+        return caTrustManager.getAcceptedIssuers();
+    }
+
+    /**
+     * Temporarily trust the given cert (runtime)
+     * 
+     * @param c The certificate to trust
+     */
+    private void temporarilyTrust(Certificate c) {
+        temporarilyTrusted.add(c);
+    }
+    
+    /**
+     * Ask user if the certificate should be trusted 
+     * 
+     * @param chain The certificate chain
+     * @param authType The authentication algorithm
+     * @return user's response
+     */
+    private boolean askUser(X509Certificate[] chain, String authType) {
+    	return SecurityWarningDialog.showCertWarningDialog(SecurityWarningDialog.AccessType.UNVERIFIED, null, new HttpsCertVerifier(this, chain, authType)); 
+    }
+
+    /**
+     * Return an instance of this singleton
+     * 
+     * @return The instance
+     */
+    public static VariableX509TrustManager getInstance() {
+        if (instance == null)
+            instance = new VariableX509TrustManager();
+        
+        return instance;
+    }
+}
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/viewer/CertificatePane.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/viewer/CertificatePane.java	Tue Feb 10 21:56:55 2009 +0000
@@ -43,38 +43,30 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.PrintStream;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Enumeration;
 
-
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JComponent;
 import javax.swing.JFileChooser;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
-import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
 import javax.swing.JTabbedPane;
 import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
-import javax.swing.plaf.OptionPaneUI;
 import javax.swing.table.DefaultTableModel;
-import javax.swing.JScrollPane;
 
-import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.CertVerifier;
+import net.sourceforge.jnlp.security.SecurityDialogUI;
 import net.sourceforge.jnlp.security.SecurityUtil;
 import net.sourceforge.jnlp.security.SecurityWarningDialog;
-import net.sourceforge.jnlp.security.SecurityDialogUI;
 import net.sourceforge.jnlp.tools.KeyTool;
 
 //import java.security.KeyStoreException;
@@ -106,7 +98,7 @@
 	private KeyStore keyStore = null;
 	
 	public CertificatePane(JComponent x) {
-		super(x);
+		super(x, null);
 		initializeKeyStore();
 	}
 	
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java	Tue Feb 10 21:56:55 2009 +0000
@@ -50,7 +50,7 @@
  * @author Jan Luehe
  */
 
-public class JarSigner {
+public class JarSigner implements CertVerifier {
 
     private static String R(String key) {
         return JNLPRuntime.getMessage(key);
@@ -145,10 +145,16 @@
     /** details of this signing */
     private ArrayList<String> details = new ArrayList<String>();
 
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getAlreadyTrustPublisher()
+     */
     public boolean getAlreadyTrustPublisher() {
     	return alreadyTrustPublisher;
     }
     
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getRootInCacerts()
+     */
     public boolean getRootInCacerts() {
     	return rootInCacerts;
     }
@@ -157,11 +163,17 @@
     	return certPath;
     }
     
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#hasSigningIssues()
+     */
     public boolean hasSigningIssues() {
         return hasExpiredCert || notYetValidCert || badKeyUsage
                || badExtendedKeyUsage || badNetscapeCertType;
     }
 
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#noSigningIssues()
+     */
     public boolean noSigningIssues() {
         return noSigningIssues;
     }
@@ -170,10 +182,16 @@
         return anyJarsSigned;
     }
 
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getDetails()
+     */
     public ArrayList<String> getDetails() {
         return details;
     }
 
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getCerts()
+     */
     public ArrayList<CertPath> getCerts() {
         return certs;
     }
@@ -366,8 +384,8 @@
     	}
     }
     
-    /** 
-     * Returns the application's publisher's certificate.
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getPublisher()
      */
     public Certificate getPublisher() {
     	if (certPath != null) {
@@ -383,10 +401,8 @@
     	}
     }
     
-    /**
-     * Returns the application's root's certificate. This
-     * may return the same certificate as getPublisher() in
-     * the event that the application is self signed.
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getRoot()
      */
     public Certificate getRoot() {
     	if (certPath != null) {
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/KeyTool.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/KeyTool.java	Tue Feb 10 21:56:55 2009 +0000
@@ -374,7 +374,6 @@
                 j++;
             }
             //return newChain;
-            System.out.println("newChain's size: " + newChain.length);
             return newChain != null;
         } else {
             throw new Exception("Failed to establish chain from reply");
--- a/patches/ecj/icedtea-pr261.patch	Tue Feb 10 21:09:31 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-diff -Nru openjdk-ecj.orig/jdk/make/java/nio/FILES_java.gmk openjdk-ecj/jdk/make/java/nio/FILES_java.gmk
---- openjdk-ecj.orig/jdk/make/java/nio/FILES_java.gmk	2008-11-20 08:44:11.000000000 +0000
-+++ openjdk-ecj/jdk/make/java/nio/FILES_java.gmk	2008-12-02 16:00:15.000000000 +0000
-@@ -32,6 +32,7 @@
- 	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 \
-@@ -42,6 +43,7 @@
- 	java/nio/channels/MembershipKey.java \
- 	java/nio/channels/MulticastChannel.java \
- 	java/nio/channels/NetworkChannel.java \
-+	java/nio/channels/Pipe.java \
- 	java/nio/channels/ReadableByteChannel.java \
- 	java/nio/channels/ScatteringByteChannel.java \
- 	java/nio/channels/SelectableChannel.java \
-diff -Nru openjdk-ecj.orig/jdk/make/java/nio/Makefile openjdk-ecj/jdk/make/java/nio/Makefile
---- openjdk-ecj.orig/jdk/make/java/nio/Makefile	2008-12-02 15:52:07.000000000 +0000
-+++ openjdk-ecj/jdk/make/java/nio/Makefile	2008-12-02 15:59:32.000000000 +0000
-@@ -85,6 +85,9 @@
- 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 @@
-         PollArrayWrapper.c
- 
- FILES_export += \
-+	sun/nio/ch/DevPollArrayWrapper.java \
-         sun/nio/ch/EPollArrayWrapper.java \
- 	sun/nio/ch/InheritedChannel.java \
- 	sun/nio/ch/NativeThread.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/hotspot/14.0b08/icedtea-format.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,48 @@
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/arguments.cpp openjdk/hotspot/src/share/vm/runtime/arguments.cpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/arguments.cpp	2009-02-03 18:08:09.000000000 +0000
++++ openjdk/hotspot/src/share/vm/runtime/arguments.cpp	2009-02-03 18:32:59.000000000 +0000
+@@ -1361,7 +1361,7 @@
+ 
+     // Feed the cache size setting into the JDK
+     char buffer[1024];
+-    sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax);
++    sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
+     add_property(buffer);
+   }
+   if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) {
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/safepoint.cpp openjdk/hotspot/src/share/vm/runtime/safepoint.cpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/safepoint.cpp	2009-01-29 15:03:07.000000000 +0000
++++ openjdk/hotspot/src/share/vm/runtime/safepoint.cpp	2009-02-03 18:30:55.000000000 +0000
+@@ -730,7 +730,7 @@
+   if (DieOnSafepointTimeout) {
+     char msg[1024];
+     VM_Operation *op = VMThread::vm_operation();
+-    sprintf(msg, "Safepoint sync time longer than %d ms detected when executing %s.",
++    sprintf(msg, "Safepoint sync time longer than " INTX_FORMAT " ms detected when executing %s.",
+             SafepointTimeoutDelay,
+             op != NULL ? op->name() : "no vm operation");
+     fatal(msg);
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/synchronizer.cpp openjdk/hotspot/src/share/vm/runtime/synchronizer.cpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/synchronizer.cpp	2009-01-29 15:03:07.000000000 +0000
++++ openjdk/hotspot/src/share/vm/runtime/synchronizer.cpp	2009-02-03 19:32:30.000000000 +0000
+@@ -424,7 +424,7 @@
+ // asserts is that error message -- often something about negative array
+ // indices -- is opaque.
+ 
+-#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @%X\n", tag); }
++#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @%p\n", tag); }
+ 
+ void ObjectMonitor::ctAsserts() {
+   CTASSERT(offset_of (ObjectMonitor, _header) == 0);
+diff -Nru openjdk.orig/hotspot/src/share/vm/utilities/vmError.cpp openjdk/hotspot/src/share/vm/utilities/vmError.cpp
+--- openjdk.orig/hotspot/src/share/vm/utilities/vmError.cpp	2009-02-03 19:10:58.000000000 +0000
++++ openjdk/hotspot/src/share/vm/utilities/vmError.cpp	2009-02-03 19:29:15.000000000 +0000
+@@ -307,7 +307,7 @@
+ 
+          strncpy(buf, file, buflen);
+          if (len + 10 < buflen) {
+-           sprintf(buf + len, ":" SIZE_FORMAT, _lineno);
++           sprintf(buf + len, ":%d", _lineno);
+          }
+          st->print(" (%s)", buf);
+        } else {
--- a/patches/icedtea-awt-window-size.patch	Tue Feb 10 21:09:31 2009 +0000
+++ b/patches/icedtea-awt-window-size.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -6,9 +6,9 @@
              Rectangle newBounds = constrainBounds(reqBounds.x, reqBounds.y, reqBounds.width, reqBounds.height);
 -            newDimensions = new WindowDimensions(newBounds, newDimensions.getInsets(), newDimensions.isClientSizeSet());
 +            Insets insets = newDimensions.getInsets();
-+            Rectangle fixedBounds = new Rectangle(newBounds.x, newBounds.y, newBounds.width - insets.left - insets.right,
++            Rectangle clientBounds = new Rectangle(newBounds.x, newBounds.y, newBounds.width - insets.left - insets.right,
 +                    newBounds.height - insets.top - insets.bottom);
-+            newDimensions = new WindowDimensions(fixedBounds, insets, newDimensions.isClientSizeSet());
++            newDimensions = new WindowDimensions(newDimensions.isClientSizeSet() ? clientBounds : newBounds , insets, newDimensions.isClientSizeSet());
          }
          XToolkit.awtLock();
          try {
--- a/patches/icedtea-cc-interp-jvmti.patch	Tue Feb 10 21:09:31 2009 +0000
+++ b/patches/icedtea-cc-interp-jvmti.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -1,16 +1,6 @@
 --- openjdk/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	2008-12-24 12:01:18.000000000 +0000
 +++ openjdk/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	2008-12-24 12:00:29.000000000 +0000
-@@ -84,7 +84,9 @@
- 
-   memset(&jc, 0, sizeof(jc));
-   jc.can_get_bytecodes = 1;
-+#ifndef CC_INTERP
-   jc.can_signal_thread = 1;
-+#endif // !CC_INTERP
-   jc.can_get_source_file_name = 1;
-   jc.can_get_line_numbers = 1;
-   jc.can_get_synthetic_attribute = 1;
-@@ -115,8 +117,10 @@
+@@ -115,8 +115,10 @@
    jvmtiCapabilities jc;
  
    memset(&jc, 0, sizeof(jc));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-doc-headers.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,181 @@
+diff -Nru openjdk.orig/jdk/make/docs/Makefile openjdk/jdk/make/docs/Makefile
+--- openjdk.orig/jdk/make/docs/Makefile	2009-02-03 13:34:38.000000000 +0000
++++ openjdk/jdk/make/docs/Makefile	2009-02-03 16:11:08.000000000 +0000
+@@ -99,36 +99,20 @@
+ 
+ TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3)
+ 
+-ifeq ($(MILESTONE), fcs)
+-    DOCTITLE_SWITCH = $(JAVADOCTITLE)
+-    WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)
+-    HEADER_SWITCH = $(JAVADOCHEADER)
+-    TOPOPTION=
+-    JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM)
+-    OVERVIEW_OPTION = -overview $(JAVADOCOVERVIEW)
+-else
+-    DOCTITLE_SWITCH = $(JAVADOCTITLE_EARLYACCESS)$(DRAFT)
+-    WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)" $(BUILD_NUMBER)"
+-    HEADER_SWITCH = $(JAVADOCHEADER)$(DRAFT)
+-    JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM_EARLYACCESS)
+-    TOPOPTION= -top $(JAVADOCTOP_EARLYACCESS)
+-    OVERVIEW_OPTION =
+-endif
++DOCTITLE_SWITCH = $(JAVADOCTITLE)
++WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)" $(BUILD_NUMBER)"
++HEADER_SWITCH = $(JAVADOCHEADER)
++TOPOPTION=
++JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM)
++OVERVIEW_OPTION = -overview $(JAVADOCOVERVIEW)
+ 
+ JAVADOCTITLE  = 'Java$(TRADEMARK) Platform, Standard Edition $(JDK_MINOR_VERSION)<br>API Specification'
+ JAVADOCWINDOWTITLE  = 'Java Platform SE $(JDK_MINOR_VERSION)'
+ JAVADOCHEADER = '<b>Java$(TRADEMARK)&nbsp;Platform<br>Standard&nbsp;Ed.&nbsp;$(JDK_MINOR_VERSION)</b>'
+-JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>For further API reference and developer documentation, see <a href="{@docroot}/../../webnotes/devdocs-vs-specs.html">Java SE Developer Documentation</a>. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All rights reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>. Also see the <a href="http://java.sun.com/docs/redist.html">documentation redistribution policy</a>.</font>'
++JAVADOCBOTTOM = '<font size="-1"><a href="http://icedtea.classpath.org/bugzilla/">Submit a bug or feature</a> <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All rights reserved. Use is subject to the terms of the <a href="http://www.gnu.org/copyleft/gpl.html">GNU General Public License</a>.</font>'
+ JAVADOCOVERVIEW = $(SHARE_SRC)/classes/overview-core.html
+ 
+ #
+-# Early access top and bottom text (for snapshots, beta and rc)
+-#
+-JAVADOCTOP_EARLYACCESS = '<div style="background-color: \#EEEEEE"> <div style="padding: 6px; margin-top: 2px; margin-bottom: 6px; margin-left: 6px; margin-right: 6px; text-align: justify; font-size: 80%; font-family: Helvetica, Arial, sans-serif; font-weight: normal;"> Please note that this documentation is not final and is subject to change. </div> </div>'
+-JAVADOCBOTTOM_EARLYACCESS = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a> <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All rights reserved. Use is subject to the terms of the <a href="http://www.gnu.org/copyleft/gpl.html">GNU General Public License</a>.</font>'
+-JAVADOCTITLE_EARLYACCESS = $(subst Specification,Documentation,$(JAVADOCTITLE))
+-
+-#
+ # Variables used by domapidocs target
+ #
+ 
+@@ -138,12 +122,11 @@
+                     -doctitle $(DOMAPI_JAVADOCTITLE)          \
+                     -windowtitle $(DOMAPI_JAVADOCWINDOWTITLE) \
+                     -header $(DOMAPI_JAVADOCHEADER)           \
+-                    -bottom $(DOMAPI_JAVADOCBOTTOM)           \
++                    -bottom $(JAVADOCBOTTOM)           \
+                     -group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP)
+ DOMAPI_JAVADOCTITLE  = 'Common DOM API'
+ DOMAPI_JAVADOCWINDOWTITLE  = 'Common DOM API'
+ DOMAPI_JAVADOCHEADER = '<b>Common DOM API</b>'
+-DOMAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A.  All Rights Reserved.</font>'
+ DOMAPI_GROUPNAME = "Packages"
+ DOMAPI_REGEXP = "com.sun.java.browser.dom:org.w3c.dom*"
+ # DOMAPI_PKGS is located in NON_CORE_PKGS.gmk
+@@ -157,13 +140,12 @@
+                     -doctitle $(MIRROR_JAVADOCTITLE)            \
+                     -windowtitle $(MIRROR_JAVADOCWINDOWTITLE)   \
+                     -header $(MIRROR_JAVADOCHEADER)             \
+-                    -bottom $(MIRROR_JAVADOCBOTTOM)             \
++                    -bottom $(JAVADOCBOTTOM)             	\
+                     -group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP) \
+                     -overview $(MIRROR_OVERVIEW)
+ MIRROR_JAVADOCTITLE = 'Mirror API'
+ MIRROR_JAVADOCWINDOWTITLE = 'Mirror API'
+ MIRROR_JAVADOCHEADER = '<b>Mirror API</b>'
+-MIRROR_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
+ MIRROR_GROUPNAME = "Packages"
+ MIRROR_OVERVIEW = $(IMPORTSRCDIR)/com/sun/mirror/overview.html
+ MIRROR_REGEXP = "com.sun.mirror.*"
+@@ -181,12 +163,11 @@
+                     -doctitle $(DOCLETAPI_JAVADOCTITLE)          \
+                     -windowtitle $(DOCLETAPI_JAVADOCWINDOWTITLE) \
+                     -header $(DOCLETAPI_JAVADOCHEADER)           \
+-                    -bottom $(DOCLETAPI_JAVADOCBOTTOM)           \
++                    -bottom $(JAVADOCBOTTOM)           		 \
+                     -group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP)
+ DOCLETAPI_JAVADOCTITLE  = 'Doclet API'
+ DOCLETAPI_JAVADOCWINDOWTITLE  = 'Doclet API'
+ DOCLETAPI_JAVADOCHEADER = '<b>Doclet API</b>'
+-DOCLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A.  All Rights Reserved.</font>'
+ DOCLETAPI_GROUPNAME = "Packages"
+ DOCLETAPI_REGEXP = "com.sun.javadoc"
+ DOCLETAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
+@@ -200,8 +181,7 @@
+ 		    -encoding ascii			        \
+                     -nonavbar                                   \
+                     -noindex                                    \
+-                    -bottom $(TAGLETAPI_JAVADOCBOTTOM)
+-TAGLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A.  All Rights Reserved.</font>'
++                    -bottom $(JAVADOCBOTTOM)
+ # TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk
+ 
+ #
+@@ -218,6 +198,7 @@
+                    -windowtitle $(JDI_WINDOWTITLE)               \
+                    -doctitle $(JDI_DOCTITLE)                     \
+                    -header $(JDI_HEADER)                         \
++                   -bottom $(JAVADOCBOTTOM)             	\
+                    -linkoffline ../../../../api $(DOCSDIR)/api/     \
+                    -overview $(JPDA_SOURCEPATH)/jdi-overview.html
+ JDI_WINDOWTITLE = "Java Debug Interface"
+@@ -242,6 +223,7 @@
+                    -windowtitle $(JAAS_WINDOWTITLE)              \
+                    -doctitle $(JAAS_DOCTITLE)                    \
+                    -header $(JAAS_JAVADOCHEADER)                 \
++                   -bottom $(JAVADOCBOTTOM)             	\
+                    -linkoffline ../../../../../api $(DOCSDIR)/api/	 \
+                    -overview $(TOPDIR)/src/share/classes/com/sun/security/auth/jaas-overview.html
+ JAAS_WINDOWTITLE = "Java Authentication and Authorization Service "
+@@ -264,6 +246,7 @@
+                    -windowtitle $(JGSS_WINDOWTITLE)             \
+                    -doctitle $(JGSS_DOCTITLE)                   \
+                    -header $(JGSS_JAVADOCHEADER)                \
++                   -bottom $(JAVADOCBOTTOM)             	\
+                    -linkoffline ../../../../../api $(DOCSDIR)/api/ \
+                    -overview $(JGSS_SOURCEPATH)/com/sun/security/jgss/jgss-overview.html
+ 
+@@ -287,6 +270,7 @@
+                    -windowtitle $(SMARTCARDIO_WINDOWTITLE)             \
+                    -doctitle $(SMARTCARDIO_DOCTITLE)                   \
+                    -header $(SMARTCARDIO_JAVADOCHEADER)                \
++                   -bottom $(JAVADOCBOTTOM)             	\
+                    -linkoffline ../../../../../api $(DOCSDIR)/api/
+ 
+ SMARTCARDIO_WINDOWTITLE = "Java Smart Card I/O"
+@@ -309,6 +293,7 @@
+                    -windowtitle $(HTTPSERVER_WINDOWTITLE)             \
+                    -doctitle $(HTTPSERVER_DOCTITLE)                   \
+                    -header $(HTTPSERVER_JAVADOCHEADER)                \
++                   -bottom $(JAVADOCBOTTOM)             	\
+                    -linkoffline ../../../../../api $(DOCSDIR)/api/
+ 
+ HTTPSERVER_WINDOWTITLE = "Java HTTP Server"
+@@ -344,6 +329,7 @@
+                      -windowtitle $(MGMT_WINDOWTITLE)              \
+                      -doctitle $(MGMT_DOCTITLE)                    \
+                      -header $(MGMT_HEADER)                        \
++                     -bottom $(JAVADOCBOTTOM)             	\
+ 		     -linkoffline ../../../../api $(DOCSDIR)/api/  \
+                      -overview $(MGMT_SOURCEPATH)/com/sun/management/mgmt-overview.html
+ MGMT_WINDOWTITLE = "Monitoring and Management Interface for the Java Platform"
+@@ -365,6 +351,7 @@
+                    -windowtitle $(ATTACH_WINDOWTITLE)               	\
+                    -doctitle $(ATTACH_DOCTITLE)                     	\
+                    -header $(ATTACH_HEADER)                         	\
++                   -bottom $(JAVADOCBOTTOM)             	\
+ 		   -linkoffline ../../../../api $(DOCSDIR)/api/
+ ATTACH_WINDOWTITLE = "Attach API"
+ ATTACH_DOCTITLE    = "Attach API"
+@@ -385,6 +372,7 @@
+                    -windowtitle $(JCONSOLE_WINDOWTITLE)               	\
+                    -doctitle $(JCONSOLE_DOCTITLE)                     	\
+                    -header $(JCONSOLE_HEADER)                         	\
++                   -bottom $(JAVADOCBOTTOM)             	\
+ 		   -linkoffline ../../../../api $(DOCSDIR)/api/
+ JCONSOLE_WINDOWTITLE = "JConsole API"
+ JCONSOLE_DOCTITLE    = "JConsole API"
+@@ -400,7 +388,7 @@
+                     -doctitle $(TREEAPI_JAVADOCTITLE)            \
+                     -windowtitle $(TREEAPI_JAVADOCWINDOWTITLE)   \
+                     -header $(TREEAPI_JAVADOCHEADER)             \
+-                    -bottom $(TREEAPI_JAVADOCBOTTOM)             \
++                    -bottom $(JAVADOCBOTTOM)                     \
+                     -group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP) 
+ #
+ #	            -overview $(TREEAPI_OVERVIEW)
+@@ -408,7 +396,6 @@
+ TREEAPI_JAVADOCTITLE = 'Compiler Tree API'
+ TREEAPI_JAVADOCWINDOWTITLE = 'Compiler Tree API'
+ TREEAPI_JAVADOCHEADER = '<b>Compiler Tree API</b>'
+-TREEAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
+ TREEAPI_GROUPNAME = "Packages"
+ TREEAPI_OVERVIEW = $(SHARE_SRC)/classes/com/sun/source/overview.html
+ TREEAPI_REGEXP = "com.sun.source.*"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-java2d-dasher.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,11 @@
+--- openjdk/jdk/src/share/classes/sun/java2d/pisces/Dasher.java.orig	2009-01-13 12:14:53.000000000 -0500
++++ openjdk/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	2009-01-13 12:15:09.000000000 -0500
+@@ -120,7 +120,7 @@
+ 
+         // Normalize so 0 <= phase < dash[0]
+         int idx = 0;
+-        dashOn = false;
++        dashOn = true;
+         int d;
+         while (phase >= (d = dash[idx])) {
+             phase -= d;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-nio2.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,2780 @@
+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/Makefile openjdk/jdk/make/docs/Makefile
+--- openjdk.orig/jdk/make/docs/Makefile	2009-02-03 16:20:38.000000000 +0000
++++ openjdk/jdk/make/docs/Makefile	2009-02-03 19:40:10.000000000 +0000
+@@ -404,6 +404,29 @@
+ # TREEAPI_PKGS is located in NON_CORE_PKGS.gmk
+ 
+ #
++# Variables used by nio2docs target
++#
++
++NIO2_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)		      \
++		    -encoding ascii			      \
++		    -d $(NIO2_DOCDIR)				\
++                    -sourcepath $(NIO2_SOURCEPATH)             	\
++                    -splitIndex                               \
++                    -doctitle $(NIO2_JAVADOCTITLE)          \
++                    -windowtitle $(NIO2_JAVADOCWINDOWTITLE) \
++                    -header $(NIO2_JAVADOCHEADER)           \
++                    -bottom $(JAVADOCBOTTOM)           \
++                    -group $(NIO2_GROUPNAME) $(NIO2_REGEXP)
++NIO2_JAVADOCTITLE  = 'NIO2 API'
++NIO2_JAVADOCWINDOWTITLE  = 'NIO2 API'
++NIO2_JAVADOCHEADER = '<b>NIO2 API</b>'
++NIO2_GROUPNAME = "Packages"
++NIO2_REGEXP = "org.classpath.icedtea.*"
++NIO2_DOCDIR      = $(DOCSDIR)/jre/api/nio2
++NIO2_SOURCEPATH  = $(TOPDIR)/src/share/classes
++# NIO2_PKGS is located in NON_CORE_PKGS.gmk
++
++#
+ # Path where javadoc should find source files for release docs
+ #
+ RELEASEDOCS_SRCPATH = "$(SHARE_SRC)/classes$(CLASSPATH_SEPARATOR)$(PLATFORM_SRC)/classes$(CLASSPATH_SEPARATOR)$(GENSRCDIR)$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/doc/stub$(CLASSPATH_SEPARATOR)$(CLOSED_SRC)/share/classes$(CLASSPATH_SEPARATOR)$(IMPORTSRCDIR)"
+@@ -429,7 +452,8 @@
+     httpserverdocs  \
+     mgmtdocs \
+     attachdocs \
+-    jconsoledocs
++    jconsoledocs \
++    nio2docs
+ 
+ ifdef LANGTOOLS_DIST
+     ALL_OTHER_TARGETS += \
+@@ -646,6 +670,14 @@
+ 		   $(TREEAPI_LINKOPT)                  \
+ 		   $(TREEAPI_PKGS)
+ 
++.PHONY: nio2docs
++nio2docs:
++	@# ######## api-nio2 ############################
++	$(RM) -r $(NIO2_DOCDIR)
++	$(MKDIR) -p $(NIO2_DOCDIR)
++	$(JAVADOC_CMD) $(NIO2_JAVADOCFLAGS)                     \
++		   $(NIO2_PKGS)
++
+ # DEBUG TARGET
+ # List the values defined in the makefile hierarchy, to make sure everything
+ # is set properly, and to help identify values we can use instead of making new ones.
+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-02-03 16:28:29.000000000 +0000
+@@ -65,6 +65,16 @@
+ HTTPSERVER_PKGS  = com.sun.net.httpserver       \
+                    com.sun.net.httpserver.spi 
+ 
++NIO2_PKGS         = org.classpath.icedtea.java.io			\
++		   org.classpath.icedtea.java.net			\
++		   org.classpath.icedtea.java.nio.channels		\
++		   org.classpath.icedtea.java.nio.channels.spi		\
++		   org.classpath.icedtea.java.nio.file    		\
++		   org.classpath.icedtea.java.nio.file.attribute	 \
++		   org.classpath.icedtea.java.nio.file.spi		 \
++		   org.classpath.icedtea.java.util
++   
++
+ DOCLETAPI_PKGS   = com.sun.javadoc
+ 
+ TAGLETAPI_FILE   = com/sun/tools/doclets/Taglet.java
+@@ -89,6 +99,7 @@
+                    $(MGMT_PKGS) \
+                    $(JAAS_PKGS) \
+                    $(JGSS_PKGS) \
++		   $(NIO2_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-19 19:13:49.000000000 +0000
+@@ -75,12 +75,13 @@
+         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 \
+ 	sun/nio/ch/IOStatus.java \
+ 	sun/nio/ch/IOVecWrapper.java \
++	sun/nio/ch/MembershipKeyImpl.java \
++	sun/nio/ch/MembershipRegistry.java \
+ 	sun/nio/ch/NativeDispatcher.java \
+ 	sun/nio/ch/NativeObject.java \
+ 	sun/nio/ch/NativeThread.java \
+@@ -100,6 +101,7 @@
+ 	sun/nio/ch/SocketAdaptor.java \
+ 	sun/nio/ch/SocketChannelImpl.java \
+ 	sun/nio/ch/SocketDispatcher.java \
++	sun/nio/ch/SocketOptionRegistry.java \
+ 	sun/nio/ch/SocketOpts.java \
+ 	sun/nio/ch/SocketOptsImpl.java \
+         sun/nio/ch/SourceChannelImpl.java \
+@@ -144,7 +146,150 @@
+ 	java/lang/StringCoding.java \
+ 	\
+ 	sun/misc/Cleaner.java \
+-	sun/util/PreHashedMap.java
++	sun/util/PreHashedMap.java \
++	\
++	org/classpath/icedtea/java/net/ProtocolFamily.java \
++	org/classpath/icedtea/java/net/SocketOption.java \
++	org/classpath/icedtea/java/net/StandardProtocolFamily.java \
++	org/classpath/icedtea/java/net/StandardSocketOption.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/Channels.java \
++	org/classpath/icedtea/java/nio/channels/CompletionHandler.java \
++	org/classpath/icedtea/java/nio/channels/DatagramChannel.java \
++	org/classpath/icedtea/java/nio/channels/FileChannel.java \
++	org/classpath/icedtea/java/nio/channels/FileLock.java \
++	org/classpath/icedtea/java/nio/channels/MembershipKey.java \
++	org/classpath/icedtea/java/nio/channels/MulticastChannel.java \
++	org/classpath/icedtea/java/nio/channels/NetworkChannel.java \
++	org/classpath/icedtea/java/nio/channels/SeekableByteChannel.java \
++	org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider.java \
++	org/classpath/icedtea/java/nio/channels/spi/SelectorProvider.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 \
++	\
++	org/classpath/icedtea/java/util/concurrent/ScheduledThreadPoolExecutor.java \
++	\
++	org/classpath/icedtea/misc/JavaUtilConcurrentThreadPoolExecutorAccess.java \
++	org/classpath/icedtea/misc/JavaNetGetIndexAccess.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,10 +408,20 @@
+ 	\
+ 	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
+ 
+-FILES_gen = $(FILES_gen_coder) $(FILES_gen_buffer) $(FILES_gen_ex) $(FILES_gen_csp)
++FILES_gen_sor = sun/nio/ch/SocketOptionRegistry.java
++
++FILES_gen = $(FILES_gen_coder) $(FILES_gen_buffer) $(FILES_gen_ex) $(FILES_gen_csp) \
++	  $(FILES_gen_sor)
+ 
+ FILES_java = $(FILES_src) $(FILES_gen)
+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-15 16:35:28.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,73 @@
+ 	  HASHER="$(BOOT_JAVA_CMD) -jar $(HASHER_JARFILE)" \
+ 	  SH="$(SH)" $(SH) -e genCharsetProvider.sh $(SCS_SRC)/standard-charsets $(SCS_GEN)
+ 
++#
++# Generated channel implementation classes.
++# C source is compiled in TEMPDIR to avoid turds left by Windows compilers.
++#
++
++GENSOR_SRC = $(SHARE_SRC)/native/sun/nio/ch/genSocketOptionRegistry.c
++
++GENSOR_EXE = $(TEMPDIR)/genSocketOptionRegistry$(EXE_SUFFIX)
++
++SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSOR_SRC) | \
++	$(NAWK) '/^.*Copyright.*Sun/ { print $$3 }') 
++
++$(TEMPDIR)/$(GENSOR_SRC) : $(GENSOR_SRC)
++	$(install-file)
++
++$(GENSOR_EXE) : $(TEMPDIR)/$(GENSOR_SRC)
++	$(prep-target)
++	($(CD) $(TEMPDIR); $(CC) $(CPPFLAGS) $(LDDFLAGS) \
++	   -o genSocketOptionRegistry$(EXE_SUFFIX) $(GENSOR_SRC))
++
++$(SCH_GEN)/SocketOptionRegistry.java: $(GENSOR_EXE)
++	$(prep-target)
++	NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(SOR_COPYRIGHT_YEARS) > $@
++	$(GENSOR_EXE) >> $@
++
++# 
++# 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-29 01:13:17.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;
+@@ -63,11 +71,24 @@
+ 		Java_sun_nio_ch_Net_socket0;
+ 		Java_sun_nio_ch_Net_bind;
+ 		Java_sun_nio_ch_Net_connect;
++		Java_sun_nio_ch_Net_bind0;
++		Java_sun_nio_ch_Net_connect0;
++		Java_sun_nio_ch_Net_listen;
+ 		Java_sun_nio_ch_Net_localPort;
+ 		Java_sun_nio_ch_Net_localInetAddress;
+ 		Java_sun_nio_ch_Net_getIntOption0;
+ 		Java_sun_nio_ch_Net_setIntOption0;
+                 Java_sun_nio_ch_Net_initIDs;
++		Java_sun_nio_ch_Net_isIPv6Available0;
++		Java_sun_nio_ch_Net_joinOrDrop4;
++		Java_sun_nio_ch_Net_blockOrUnblock4;
++		Java_sun_nio_ch_Net_joinOrDrop6;
++		Java_sun_nio_ch_Net_blockOrUnblock6;
++		Java_sun_nio_ch_Net_setInterface4;
++		Java_sun_nio_ch_Net_getInterface4;
++		Java_sun_nio_ch_Net_setInterface6;
++		Java_sun_nio_ch_Net_getInterface6;
++		Java_sun_nio_ch_Net_shutdown;
+                 Java_sun_nio_ch_PollArrayWrapper_interrupt;
+                 Java_sun_nio_ch_PollArrayWrapper_poll0;
+                 Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
+@@ -75,6 +96,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/java/net/NetworkInterface.java openjdk/jdk/src/share/classes/java/net/NetworkInterface.java
+--- openjdk.orig/jdk/src/share/classes/java/net/NetworkInterface.java	2009-01-16 04:07:15.000000000 +0000
++++ openjdk/jdk/src/share/classes/java/net/NetworkInterface.java	2009-01-19 19:12:21.000000000 +0000
+@@ -529,4 +529,15 @@
+     }
+     private static native void init();
+ 
++    // Set up JavaIODeleteOnExitAccess in SharedSecrets
++    // Added here as getIndex is package-private and SharedSecrets cannot easily access it.
++    static {
++	org.classpath.icedtea.misc.SharedSecrets.setJavaNetGetIndexAccess(
++            new org.classpath.icedtea.misc.JavaNetGetIndexAccess() {
++	      public int getIndex(NetworkInterface nf) { return nf.getIndex(); }
++	      public NetworkInterface getByIndex(int i) { return getByIndex(i); }
++            }
++        );            									    
++    }
++
+ }
+diff -Nru openjdk.orig/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java openjdk/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java
+--- openjdk.orig/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java	2009-01-13 23:54:13.000000000 +0000
++++ openjdk/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java	2009-01-15 01:21:36.000000000 +0000
+@@ -2004,4 +2004,23 @@
+             }
+         }
+     }
++
++    static {
++	org.classpath.icedtea.misc.SharedSecrets.setJavaUtilConcurrentThreadPoolExecutorAccess(
++            new org.classpath.icedtea.misc.JavaUtilConcurrentThreadPoolExecutorAccess() {
++	        public AtomicInteger getCtl(ThreadPoolExecutor e) { return e.ctl; }
++	        public void lockMainLock(ThreadPoolExecutor e) { e.mainLock.lock(); }
++	        public void unlockMainLock(ThreadPoolExecutor e) { e.mainLock.unlock(); }
++	        public void signalAll(ThreadPoolExecutor e) { e.termination.signalAll(); }
++	        public boolean isWorkQueueEmpty(ThreadPoolExecutor e) { return e.workQueue.isEmpty(); }
++	        public void rejectedExecution(Runnable command, ThreadPoolExecutor e) {
++		  e.handler.rejectedExecution(command, e); 
++		}
++	        public void interruptIdleWorkers(ThreadPoolExecutor e, boolean onlyOne) {
++		  e.interruptIdleWorkers(onlyOne); 
++		}
++            }
++        );            									    
++    }
++
+ }
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/misc/Unsafe.java openjdk/jdk/src/share/classes/sun/misc/Unsafe.java
+--- openjdk.orig/jdk/src/share/classes/sun/misc/Unsafe.java	2009-01-19 15:44:19.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/misc/Unsafe.java	2009-01-19 15:47:42.000000000 +0000
+@@ -504,9 +504,33 @@
+     /**
+      * Sets all bytes in a given block of memory to a copy of another
+      * block.
++     *
++     * <p>This method determines each block's base address by means of two parameters,
++     * and so it provides (in effect) a <em>double-register</em> addressing mode,
++     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
++     * the offset supplies an absolute base address.
++     *
++     * <p>The transfers are in coherent (atomic) units of a size determined
++     * by the address and length parameters.  If the effective addresses and
++     * length are all even modulo 8, the transfer takes place in 'long' units.
++     * If the effective addresses and length are (resp.) even modulo 4 or 2,
++     * the transfer takes place in units of 'int' or 'short'.
++     *
++     * @since 1.7
+      */
+-    public native void copyMemory(long srcAddress, long destAddress,
++    public native void copyMemory(Object srcBase, long srcOffset,
++                                  Object destBase, long destOffset,
+                                   long bytes);
++    /**
++     * Sets all bytes in a given block of memory to a copy of another
++     * block.  This provides a <em>single-register</em> addressing mode,
++     * as discussed in {@link #getInt(Object,long)}.
++     *
++     * Equivalent to <code>copyMemory(null, srcAddress, null, destAddress, bytes)</code>.
++     */
++    public void copyMemory(long srcAddress, long destAddress, long bytes) {
++        copyMemory(null, srcAddress, null, destAddress, bytes);
++    }
+ 
+     /**
+      * Disposes of a block of native memory, as obtained from {@link
+@@ -648,6 +672,10 @@
+      */
+     public native int arrayBaseOffset(Class arrayClass);
+ 
++    /** The value of {@code arrayBaseOffset(byte[].class)} */
++    public static final int ARRAY_BYTE_BASE_OFFSET
++            = theUnsafe.arrayBaseOffset(byte[].class);
++
+     /**
+      * Report the scale factor for addressing elements in the storage
+      * allocation of a given array class.  However, arrays of "narrow" types
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java openjdk/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
+--- openjdk.orig/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	2009-01-16 03:10:17.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	2009-01-19 21:04:48.000000000 +0000
+@@ -29,10 +29,28 @@
+ import java.io.IOException;
+ import java.net.*;
+ import java.nio.ByteBuffer;
+-import java.nio.channels.*;
+-import java.nio.channels.spi.*;
++
++import java.nio.channels.ClosedChannelException;
++import java.nio.channels.NotYetConnectedException;
++import java.nio.channels.SelectionKey;
++
++import java.util.Collections;
++import java.util.HashSet;
++import java.util.Set;
++
+ import java.lang.ref.SoftReference;
+ 
++import org.classpath.icedtea.java.net.ProtocolFamily;
++import org.classpath.icedtea.java.net.StandardProtocolFamily;
++import org.classpath.icedtea.java.net.SocketOption;
++import org.classpath.icedtea.java.net.StandardSocketOption;
++
++import org.classpath.icedtea.java.nio.channels.DatagramChannel;
++import org.classpath.icedtea.java.nio.channels.MembershipKey;
++
++import org.classpath.icedtea.java.nio.channels.spi.SelectorProvider;
++
++import org.classpath.icedtea.misc.SharedSecrets;
+ 
+ /**
+  * An implementation of DatagramChannels.
+@@ -53,6 +71,9 @@
+     // even after the value in the file descriptor object has been set to -1
+     int fdVal;
+ 
++    // The protocol family of the socket
++    private final ProtocolFamily family;
++
+     // IDs of native threads doing reads and writes, for signalling
+     private volatile long readerThread = 0;
+     private volatile long writerThread = 0;
+@@ -91,6 +112,9 @@
+     // Our socket adaptor, if any
+     private DatagramSocket socket = null;
+ 
++    // Multicast support
++    private MembershipRegistry registry;
++
+     // -- End of fields protected by stateLock
+ 
+ 
+@@ -98,15 +122,40 @@
+         throws IOException
+     {
+         super(sp);
++        this.family = Net.isIPv6Available() ?
++            StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
+         this.fd = Net.socket(false);
+         this.fdVal = IOUtil.fdVal(fd);
+         this.state = ST_UNCONNECTED;
+     }
+ 
++    public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) {
++        super(sp);
++        if ((family != StandardProtocolFamily.INET) &&
++            (family != StandardProtocolFamily.INET6))
++        {
++            if (family == null)
++                throw new NullPointerException("'family' is null");
++            else
++                throw new UnsupportedOperationException("Protocol family not supported");
++        }
++        if (family == StandardProtocolFamily.INET6) {
++            if (!Net.isIPv6Available()) {
++                throw new UnsupportedOperationException("IPv6 not available");
++            }
++        }
++        this.family = family;
++        this.fd = Net.socket(family, false);
++        this.fdVal = IOUtil.fdVal(fd);
++        this.state = ST_UNCONNECTED;
++    }
++
+     public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
+         throws IOException
+     {
+         super(sp);
++        this.family = Net.isIPv6Available() ?
++            StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
+         this.fd = fd;
+         this.fdVal = IOUtil.fdVal(fd);
+         this.state = ST_UNCONNECTED;
+@@ -499,7 +548,7 @@
+         }
+     }
+ 
+-    public void bind(SocketAddress local) throws IOException {
++    public DatagramChannel bind(SocketAddress local) throws IOException {
+         synchronized (readLock) {
+             synchronized (writeLock) {
+                 synchronized (stateLock) {
+@@ -515,6 +564,7 @@
+                 }
+             }
+         }
++	return this;
+     }
+ 
+     public boolean isConnected() {
+@@ -704,4 +754,350 @@
+         initIDs();
+     }
+ 
++    public SocketAddress getRemoteAddress() throws IOException {
++        synchronized (stateLock) {
++            if (!isOpen())
++                throw new ClosedChannelException();
++            return remoteAddress;
++        }
++    }
++
++    public SocketAddress getLocalAddress() throws IOException {
++        synchronized (stateLock) {
++            if (!isOpen())
++                throw new ClosedChannelException();
++            return localAddress;
++        }
++    }
++
++    public <T> DatagramChannel setOption(SocketOption<T> name, T value)
++        throws IOException
++    {
++        if (name == null)
++            throw new NullPointerException();
++        if (!supportedOptions().contains(name))
++            throw new UnsupportedOperationException("'" + name + "' not supported");
++
++        synchronized (stateLock) {
++            ensureOpen();
++
++            if (name == StandardSocketOption.IP_TOS) {
++                // IPv4 only; no-op for IPv6
++                if (family == StandardProtocolFamily.INET) {
++                    Net.setSocketOption(fd, family, name, value);
++                }
++                return this;
++            }
++
++            if (name == StandardSocketOption.IP_MULTICAST_TTL ||
++                name == StandardSocketOption.IP_MULTICAST_LOOP)
++            {
++                // options are protocol dependent
++                Net.setSocketOption(fd, family, name, value);
++                return this;
++            }
++
++            if (name == StandardSocketOption.IP_MULTICAST_IF) {
++                if (value == null)
++                    throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
++                NetworkInterface interf = (NetworkInterface)value;
++                if (family == StandardProtocolFamily.INET6) {
++		    int index = SharedSecrets.getJavaNetGetIndexAccess().getIndex(interf);
++                    if (index == -1)
++                        throw new IOException("Network interface cannot be identified");
++                    Net.setInterface6(fd, index);
++                } else {
++                    // need IPv4 address to identify interface
++                    Inet4Address target = Net.anyInet4Address(interf);
++                    if (target == null)
++                        throw new IOException("Network interface not configured for IPv4");
++                    int targetAddress = Net.inet4AsInt(target);
++                    Net.setInterface4(fd, targetAddress);
++                }
++                return this;
++            }
++
++            // remaining options don't need any special handling
++            Net.setSocketOption(fd, Net.UNSPEC, name, value);
++            return this;
++        }
++    }
++
++    @SuppressWarnings("unchecked")
++    public <T> T getOption(SocketOption<T> name)
++        throws IOException
++    {
++        if (name == null)
++            throw new NullPointerException();
++        if (!supportedOptions().contains(name))
++            throw new UnsupportedOperationException("'" + name + "' not supported");
++
++        synchronized (stateLock) {
++            ensureOpen();
++
++            if (name == StandardSocketOption.IP_TOS) {
++                // IPv4 only; always return 0 on IPv6
++                if (family == StandardProtocolFamily.INET) {
++                    return (T) Net.getSocketOption(fd, family, name);
++                } else {
++                    return (T) Integer.valueOf(0);
++                }
++            }
++
++            if (name == StandardSocketOption.IP_MULTICAST_TTL ||
++                name == StandardSocketOption.IP_MULTICAST_LOOP)
++            {
++                return (T) Net.getSocketOption(fd, family, name);
++            }
++
++            if (name == StandardSocketOption.IP_MULTICAST_IF) {
++                if (family == StandardProtocolFamily.INET) {
++                    int address = Net.getInterface4(fd);
++                    if (address == 0)
++                        return null;    // default interface
++
++                    InetAddress ia = Net.inet4FromInt(address);
++                    NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
++                    if (ni == null)
++                        throw new IOException("Unable to map address to interface");
++                    return (T) ni;
++                } else {
++                    int index = Net.getInterface6(fd);
++                    if (index == 0)
++                        return null;    // default interface
++
++                    NetworkInterface ni = SharedSecrets.getJavaNetGetIndexAccess().getByIndex(index);
++                    if (ni == null)
++                        throw new IOException("Unable to map index to interface");
++                    return (T) ni;
++                }
++            }
++
++            // no special handling
++            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
++        }
++    }
++
++    private static class LazyInitialization {
++        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
++
++        private static Set<SocketOption<?>> defaultOptions() {
++            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
++            set.add(StandardSocketOption.SO_SNDBUF);
++            set.add(StandardSocketOption.SO_RCVBUF);
++            set.add(StandardSocketOption.SO_REUSEADDR);
++            set.add(StandardSocketOption.SO_BROADCAST);
++            set.add(StandardSocketOption.IP_TOS);
++            set.add(StandardSocketOption.IP_MULTICAST_IF);
++            set.add(StandardSocketOption.IP_MULTICAST_TTL);
++            set.add(StandardSocketOption.IP_MULTICAST_LOOP);
++            return Collections.unmodifiableSet(set);
++        }
++    }
++
++    public final Set<SocketOption<?>> supportedOptions() {
++        return LazyInitialization.defaultOptions;
++    }
++
++    /**
++     * Joins channel's socket to the given group/interface and
++     * optional source address.
++     */
++    private MembershipKey innerJoin(InetAddress group,
++                                    NetworkInterface interf,
++                                    InetAddress source)
++        throws IOException
++    {
++        if (!group.isMulticastAddress())
++            throw new IllegalArgumentException("Group not a multicast address");
++
++        // check multicast address is compatible with this socket
++        if (!(group instanceof Inet4Address)) {
++            if (family == StandardProtocolFamily.INET)
++                throw new IllegalArgumentException("Group is not IPv4 address");
++            if (!(group instanceof Inet6Address))
++                throw new IllegalArgumentException("Address type not supported");
++        }
++
++        // check source address
++        if (source != null) {
++            if (source.isAnyLocalAddress())
++                throw new IllegalArgumentException("Source address is a wildcard address");
++            if (source.isMulticastAddress())
++                throw new IllegalArgumentException("Source address is multicast address");
++            if (source.getClass() != group.getClass())
++                throw new IllegalArgumentException("Source address is different type to group");
++        }
++
++        SecurityManager sm = System.getSecurityManager();
++        if (sm != null)
++            sm.checkMulticast(group);
++
++        synchronized (stateLock) {
++            if (!isOpen())
++                throw new ClosedChannelException();
++
++            // check the registry to see if we are already a member of the group
++            if (registry == null) {
++                registry = new MembershipRegistry();
++            } else {
++                // return existing membership key
++                MembershipKey key = registry.checkMembership(group, interf, source);
++                if (key != null)
++                    return key;
++            }
++
++            MembershipKeyImpl key;
++            if (family == StandardProtocolFamily.INET6) {
++                int index = SharedSecrets.getJavaNetGetIndexAccess().getIndex(interf);
++                if (index == -1)
++                    throw new IOException("Network interface cannot be identified");
++
++                // need multicast and source address as byte arrays
++                byte[] groupAddress = Net.inet6AsByteArray(group);
++                byte[] sourceAddress = (source == null) ? null :
++                    Net.inet6AsByteArray(source);
++
++                // join the group
++                int n = Net.join6(fd, groupAddress, index, sourceAddress);
++                if (n == IOStatus.UNAVAILABLE)
++                    throw new UnsupportedOperationException();
++
++                key = new MembershipKeyImpl.Type6(this, group, interf, source,
++                                                  groupAddress, index, sourceAddress);
++
++            } else {
++                // need IPv4 address to identify interface
++                Inet4Address target = Net.anyInet4Address(interf);
++                if (target == null)
++                    throw new IOException("Network interface not configured for IPv4");
++
++                int groupAddress = Net.inet4AsInt(group);
++                int targetAddress = Net.inet4AsInt(target);
++                int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source);
++
++                // join the group
++                int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress);
++                if (n == IOStatus.UNAVAILABLE)
++                    throw new UnsupportedOperationException();
++
++                key = new MembershipKeyImpl.Type4(this, group, interf, source,
++                                                  groupAddress, targetAddress, sourceAddress);
++            }
++
++            registry.add(key);
++            return key;
++        }
++    }
++
++
++    public MembershipKey join(InetAddress group,
++                              NetworkInterface interf)
++        throws IOException
++    {
++        return innerJoin(group, interf, null);
++    }
++
++
++    public MembershipKey join(InetAddress group,
++                              NetworkInterface interf,
++                              InetAddress source)
++        throws IOException
++    {
++        if (source == null)
++            throw new NullPointerException("source address is null");
++        return innerJoin(group, interf, source);
++    }
++
++    /**
++     * Block datagrams from given source if a memory to receive all
++     * datagrams.
++     */
++    void block(MembershipKeyImpl key, InetAddress source)
++        throws IOException
++    {
++        assert key.channel() == this;
++        assert key.sourceAddress() == null;
++
++        synchronized (stateLock) {
++            if (!key.isValid())
++                throw new IllegalStateException("key is no longer valid");
++            if (source.isAnyLocalAddress())
++                throw new IllegalArgumentException("Source address is a wildcard address");
++            if (source.isMulticastAddress())
++                throw new IllegalArgumentException("Source address is multicast address");
++            if (source.getClass() != key.group().getClass())
++                throw new IllegalArgumentException("Source address is different type to group");
++
++            int n;
++            if (family == StandardProtocolFamily.INET6) {
++                 MembershipKeyImpl.Type6 key6 =
++                    (MembershipKeyImpl.Type6)key;
++                n = Net.block6(fd, key6.groupAddress(), key6.index(),
++                               Net.inet6AsByteArray(source));
++            } else {
++                MembershipKeyImpl.Type4 key4 =
++                    (MembershipKeyImpl.Type4)key;
++                n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(),
++                               Net.inet4AsInt(source));
++            }
++            if (n == IOStatus.UNAVAILABLE) {
++                // ancient kernel
++                throw new UnsupportedOperationException();
++            }
++        }
++    }
++
++    /**
++     * Unblock given source.
++     */
++    void unblock(MembershipKeyImpl key, InetAddress source)
++        throws IOException
++    {
++        assert key.channel() == this;
++        assert key.sourceAddress() == null;
++
++        synchronized (stateLock) {
++            if (!key.isValid())
++                throw new IllegalStateException("key is no longer valid");
++
++            if (family == StandardProtocolFamily.INET6) {
++                MembershipKeyImpl.Type6 key6 =
++                    (MembershipKeyImpl.Type6)key;
++                Net.unblock6(fd, key6.groupAddress(), key6.index(),
++                             Net.inet6AsByteArray(source));
++            } else {
++                MembershipKeyImpl.Type4 key4 =
++                    (MembershipKeyImpl.Type4)key;
++                Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(),
++                             Net.inet4AsInt(source));
++            }
++        }
++    }
++
++    // package-private
++    void drop(MembershipKeyImpl key)
++        throws IOException
++    {
++        assert key.channel() == this;
++
++        synchronized (stateLock) {
++            if (!key.isValid())
++                return;
++
++            if (family == StandardProtocolFamily.INET6) {
++                MembershipKeyImpl.Type6 key6 =
++                    (MembershipKeyImpl.Type6)key;
++                Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
++            } else {
++                MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key;
++                Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(),
++                    key4.source());
++            }
++
++            key.invalidate();
++            registry.remove(key);
++        }
++    }
++
+ }
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java openjdk/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java
+--- openjdk.orig/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java	2009-01-20 13:37:15.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java	2009-01-27 02:33:08.000000000 +0000
+@@ -32,8 +32,15 @@
+ import java.io.IOException;
+ import java.nio.ByteBuffer;
+ import java.nio.MappedByteBuffer;
+-import java.nio.channels.*;
+-import java.nio.channels.spi.*;
++import java.nio.channels.ClosedChannelException;
++import java.nio.channels.ClosedByInterruptException;
++import java.nio.channels.FileLock;
++import java.nio.channels.FileLockInterruptionException;
++import java.nio.channels.NonReadableChannelException;
++import java.nio.channels.NonWritableChannelException;
++import java.nio.channels.OverlappingFileLockException;
++import java.nio.channels.ReadableByteChannel;
++import java.nio.channels.WritableByteChannel;
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Iterator;
+@@ -46,6 +53,7 @@
+ import sun.misc.Cleaner;
+ import sun.security.action.GetPropertyAction;
+ 
++import org.classpath.icedtea.java.nio.channels.FileChannel;
+ 
+ public class FileChannelImpl
+     extends FileChannel
+@@ -316,6 +324,10 @@
+         }
+     }
+ 
++    public FileChannel positionSBC(long newPosition) throws IOException {
++      return position(newPosition);
++    }
++
+     public long size() throws IOException {
+         ensureOpen();
+         synchronized (positionLock) {
+@@ -386,6 +398,10 @@
+         }
+     }
+ 
++    public FileChannel truncateSBC(long size) throws IOException {
++      return truncate(size);
++    }
++
+     public void force(boolean metaData) throws IOException {
+         ensureOpen();
+         int rv = -1;
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/nio/ch/Net.java openjdk/jdk/src/share/classes/sun/nio/ch/Net.java
+--- openjdk.orig/jdk/src/share/classes/sun/nio/ch/Net.java	2009-01-15 17:37:33.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/nio/ch/Net.java	2009-02-01 00:35:31.000000000 +0000
+@@ -30,6 +30,15 @@
+ import java.net.*;
+ import java.nio.channels.*;
+ 
++import java.security.AccessController;
++import java.security.PrivilegedAction;
++
++import java.util.Enumeration;
++
++import org.classpath.icedtea.java.net.ProtocolFamily;
++import org.classpath.icedtea.java.net.SocketOption;
++import org.classpath.icedtea.java.net.StandardProtocolFamily;
++import org.classpath.icedtea.java.net.StandardSocketOption;
+ 
+ class Net {                                             // package-private
+ 
+@@ -108,16 +117,24 @@
+ 
+     // -- Socket operations --
+ 
++    static native boolean isIPv6Available0();
++
+     static FileDescriptor socket(boolean stream) {
+-        return IOUtil.newFD(socket0(stream, false));
++        return socket(UNSPEC, stream);
++    }
++
++    static FileDescriptor socket(ProtocolFamily family, boolean stream) {
++        boolean preferIPv6 = isIPv6Available() &&
++            (family != StandardProtocolFamily.INET);
++        return IOUtil.newFD(socket0(preferIPv6, stream, false));
+     }
+ 
+     static FileDescriptor serverSocket(boolean stream) {
+-        return IOUtil.newFD(socket0(stream, true));
++        return IOUtil.newFD(socket0(isIPv6Available(), stream, true));
+     }
+ 
+     // Due to oddities SO_REUSEADDR on windows reuse is ignored
+-    private static native int socket0(boolean stream, boolean reuse);
++    private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
+ 
+     static native void bind(FileDescriptor fd, InetAddress addr, int port)
+         throws IOException;
+@@ -179,4 +196,314 @@
+         initIDs();
+     }
+ 
++    // From 1.7
++
++    static native void listen(FileDescriptor fd, int backlog) throws IOException;
++
++    // unspecified protocol family
++    static final ProtocolFamily UNSPEC = new ProtocolFamily() {
++        public String name() {
++            return "UNSPEC";
++        }
++    };
++
++    // -- Socket options
++
++    static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
++                                SocketOption<?> name, Object value)
++        throws IOException
++    {
++        if (value == null)
++            throw new IllegalArgumentException("Invalid option value");
++
++        // only simple values supported by this method
++        Class<?> type = name.type();
++        if (type != Integer.class && type != Boolean.class)
++            throw new AssertionError("Should not reach here");
++
++        // special handling
++        if (name == StandardSocketOption.SO_RCVBUF ||
++            name == StandardSocketOption.SO_SNDBUF)
++        {
++            int i = ((Integer)value).intValue();
++            if (i < 0)
++                throw new IllegalArgumentException("Invalid send/receive buffer size");
++        }
++        if (name == StandardSocketOption.SO_LINGER) {
++            int i = ((Integer)value).intValue();
++            if (i < 0)
++                value = Integer.valueOf(-1);
++            if (i > 65535)
++                value = Integer.valueOf(65535);
++        }
++        if (name == StandardSocketOption.IP_TOS) {
++            int i = ((Integer)value).intValue();
++            if (i < 0 || i > 255)
++                throw new IllegalArgumentException("Invalid IP_TOS value");
++        }
++        if (name == StandardSocketOption.IP_MULTICAST_TTL) {
++            int i = ((Integer)value).intValue();
++            if (i < 0 || i > 255)
++                throw new IllegalArgumentException("Invalid TTL/hop value");
++        }
++
++        // map option name to platform level/name
++        OptionKey key = SocketOptionRegistry.findOption(name, family);
++        if (key == null)
++            throw new AssertionError("Option not found");
++
++        int arg;
++        if (type == Integer.class) {
++            arg = ((Integer)value).intValue();
++        } else {
++            boolean b = ((Boolean)value).booleanValue();
++            arg = (b) ? 1 : 0;
++        }
++
++        boolean mayNeedConversion = (family == UNSPEC);
++        setIntOption1(fd, mayNeedConversion, key.level(), key.name(), arg);
++    }
++
++    static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
++                                  SocketOption<?> name)
++        throws IOException
++    {
++        Class<?> type = name.type();
++
++        // only simple values supported by this method
++        if (type != Integer.class && type != Boolean.class)
++            throw new AssertionError("Should not reach here");
++
++        // map option name to platform level/name
++        OptionKey key = SocketOptionRegistry.findOption(name, family);
++        if (key == null)
++            throw new AssertionError("Option not found");
++
++        boolean mayNeedConversion = (family == UNSPEC);
++        int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
++
++        if (type == Integer.class) {
++            return Integer.valueOf(value);
++        } else {
++            return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
++        }
++    }
++
++    private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
++                                            int level, int opt)
++        throws IOException;
++
++    private static native void setIntOption1(FileDescriptor fd, boolean mayNeedConversion,
++                                             int level, int opt, int arg)
++        throws IOException;
++
++    public final static int SHUT_RD = 0;
++    public final static int SHUT_WR = 1;
++
++    static native void shutdown(FileDescriptor fd, int how) throws IOException;
++
++    static native void setInterface6(FileDescriptor fd, int index) throws IOException;
++
++    static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
++
++    static native int getInterface4(FileDescriptor fd) throws IOException;
++
++    static native int getInterface6(FileDescriptor fd) throws IOException;
++
++    /**
++     * Returns any IPv4 address of the given network interface, or
++     * null if the interface does not have any IPv4 addresses.
++     */
++    static Inet4Address anyInet4Address(final NetworkInterface interf) {
++        return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
++            public Inet4Address run() {
++                Enumeration<InetAddress> addrs = interf.getInetAddresses();
++                while (addrs.hasMoreElements()) {
++                    InetAddress addr = addrs.nextElement();
++                    if (addr instanceof Inet4Address) {
++                        return (Inet4Address)addr;
++                    }
++                }
++                return null;
++            }
++        });
++    }
++
++    /**
++     * Returns an IPv4 address as an int.
++     */
++    static int inet4AsInt(InetAddress ia) {
++        if (ia instanceof Inet4Address) {
++            byte[] addr = ia.getAddress();
++            int address  = addr[3] & 0xFF;
++            address |= ((addr[2] << 8) & 0xFF00);
++            address |= ((addr[1] << 16) & 0xFF0000);
++            address |= ((addr[0] << 24) & 0xFF000000);
++            return address;
++        }
++        throw new AssertionError("Should not reach here");
++    }
++
++    /**
++     * Returns an InetAddress from the given IPv4 address
++     * represented as an int.
++     */
++    static InetAddress inet4FromInt(int address) {
++        byte[] addr = new byte[4];
++        addr[0] = (byte) ((address >>> 24) & 0xFF);
++        addr[1] = (byte) ((address >>> 16) & 0xFF);
++        addr[2] = (byte) ((address >>> 8) & 0xFF);
++        addr[3] = (byte) (address & 0xFF);
++        try {
++            return InetAddress.getByAddress(addr);
++        } catch (UnknownHostException uhe) {
++            throw new AssertionError("Should not reach here");
++        }
++    }
++
++    /**
++     * Returns an IPv6 address as a byte array
++     */
++    static byte[] inet6AsByteArray(InetAddress ia) {
++        if (ia instanceof Inet6Address) {
++            return ia.getAddress();
++        }
++
++        // need to construct IPv4-mapped address
++        if (ia instanceof Inet4Address) {
++            byte[] ip4address = ia.getAddress();
++            byte[] address = new byte[16];
++            address[10] = (byte)0xff;
++            address[11] = (byte)0xff;
++            address[12] = ip4address[0];
++            address[13] = ip4address[1];
++            address[14] = ip4address[2];
++            address[15] = ip4address[3];
++            return address;
++        }
++
++        throw new AssertionError("Should not reach here");
++    }
++
++    // -- Miscellaneous utilities --
++
++    private static volatile boolean checkedIPv6 = false;
++    private static volatile boolean isIPv6Available;
++
++    /**
++     * Tells whether dual-IPv4/IPv6 sockets should be used.
++     */
++    static boolean isIPv6Available() {
++        if (!checkedIPv6) {
++            isIPv6Available = isIPv6Available0();
++            checkedIPv6 = true;
++        }
++        return isIPv6Available;
++    }
++
++    /**
++     * Join IPv6 multicast group
++     */
++    static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
++        throws IOException
++    {
++        return joinOrDrop6(true, fd, group, index, source);
++    }
++
++    /**
++     * Drop membership of IPv6 multicast group
++     */
++    static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
++        throws IOException
++    {
++        joinOrDrop6(false, fd, group, index, source);
++    }
++
++    private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
++        throws IOException;
++
++    /**
++     * Block IPv6 source
++     */
++    static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
++        throws IOException
++    {
++        return blockOrUnblock6(true, fd, group, index, source);
++    }
++
++    /**
++     * Unblock IPv6 source
++     */
++    static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
++        throws IOException
++    {
++        blockOrUnblock6(false, fd, group, index, source);
++    }
++
++    static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
++        throws IOException;
++
++    /**
++     * Join IPv4 multicast group
++     */
++    static int join4(FileDescriptor fd, int group, int interf, int source)
++        throws IOException
++    {
++        return joinOrDrop4(true, fd, group, interf, source);
++    }
++
++    /**
++     * Drop membership of IPv4 multicast group
++     */
++    static void drop4(FileDescriptor fd, int group, int interf, int source)
++        throws IOException
++    {
++        joinOrDrop4(false, fd, group, interf, source);
++    }
++
++    private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
++        throws IOException;
++
++    /**
++     * Block IPv4 source
++     */
++    static int block4(FileDescriptor fd, int group, int interf, int source)
++        throws IOException
++    {
++        return blockOrUnblock4(true, fd, group, interf, source);
++    }
++
++    /**
++     * Unblock IPv4 source
++     */
++    static void unblock4(FileDescriptor fd, int group, int interf, int source)
++        throws IOException
++    {
++        blockOrUnblock4(false, fd, group, interf, source);
++    }
++
++    private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
++                                              int interf, int source)
++        throws IOException;
++
++    static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
++        throws IOException
++    {
++        return connect(UNSPEC, fd, remote, remotePort);
++    }
++
++    static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
++        throws IOException
++    {
++        boolean preferIPv6 = isIPv6Available() &&
++            (family != StandardProtocolFamily.INET);
++        return connect0(preferIPv6, fd, remote, remotePort);
++    }
++
++    private static native int connect0(boolean preferIPv6,
++                                       FileDescriptor fd,
++                                       InetAddress remote,
++                                       int remotePort)
++        throws IOException;
++
+ }
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/nio/ch/SelectorProviderImpl.java openjdk/jdk/src/share/classes/sun/nio/ch/SelectorProviderImpl.java
+--- openjdk.orig/jdk/src/share/classes/sun/nio/ch/SelectorProviderImpl.java	2009-01-16 03:01:03.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/nio/ch/SelectorProviderImpl.java	2009-01-16 03:56:55.000000000 +0000
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2000-2001 Sun Microsystems, Inc.  All Rights Reserved.
++ * 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
+@@ -29,9 +29,18 @@
+ import java.io.IOException;
+ import java.net.ServerSocket;
+ import java.net.Socket;
+-import java.nio.channels.*;
+-import java.nio.channels.spi.*;
+ 
++import java.nio.channels.Pipe;
++import java.nio.channels.ServerSocketChannel;
++import java.nio.channels.SocketChannel;
++
++import java.nio.channels.spi.AbstractSelector;
++
++import org.classpath.icedtea.java.net.ProtocolFamily;
++
++import org.classpath.icedtea.java.nio.channels.DatagramChannel;
++
++import org.classpath.icedtea.java.nio.channels.spi.SelectorProvider;
+ 
+ public abstract class SelectorProviderImpl
+     extends SelectorProvider
+@@ -41,6 +50,10 @@
+         return new DatagramChannelImpl(this);
+     }
+ 
++    public DatagramChannel openDatagramChannel(ProtocolFamily family) throws IOException {
++        return new DatagramChannelImpl(this, family);
++    }
++
+     public Pipe openPipe() throws IOException {
+         return new PipeImpl(this);
+     }
+@@ -54,5 +67,4 @@
+     public SocketChannel openSocketChannel() throws IOException {
+         return new SocketChannelImpl(this);
+     }
+-
+ }
+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";
+diff -Nru openjdk.orig/jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java openjdk/jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java
+--- openjdk.orig/jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java	2009-01-19 22:33:37.000000000 +0000
++++ openjdk/jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java	2009-01-19 22:33:01.000000000 +0000
+@@ -35,6 +35,11 @@
+ class FileDispatcher extends NativeDispatcher
+ {
+ 
++    public static final int NO_LOCK = -1;       // Failed to lock
++    public static final int LOCKED = 0;         // Obtained requested lock
++    public static final int RET_EX_LOCK = 1;    // Obtained exclusive lock
++    public static final int INTERRUPTED = 2;    // Request interrupted
++
+     static {
+         Util.load();
+         init();
+@@ -77,6 +82,28 @@
+         preClose0(fd);
+     }
+ 
++    long size(FileDescriptor fd) throws IOException {
++        return size0(fd);
++    }
++
++    int truncate(FileDescriptor fd, long size) throws IOException {
++        return truncate0(fd, size);
++    }
++
++    int force(FileDescriptor fd, boolean metaData) throws IOException {
++        return force0(fd, metaData);
++    }
++
++    int lock(FileDescriptor fd, boolean blocking, long pos, long size,
++             boolean shared) throws IOException
++    {
++        return lock0(fd, blocking, pos, size, shared);
++    }
++
++    void release(FileDescriptor fd, long pos, long size) throws IOException {
++        release0(fd, pos, size);
++    }
++
+     // -- Native methods --
+ 
+     static native int read0(FileDescriptor fd, long address, int len)
+@@ -105,4 +132,18 @@
+ 
+     static native void init();
+ 
++    static native int force0(FileDescriptor fd, boolean metaData)
++        throws IOException;
++
++    static native int truncate0(FileDescriptor fd, long size)
++        throws IOException;
++
++    static native long size0(FileDescriptor fd) throws IOException;
++
++    static native int lock0(FileDescriptor fd, boolean blocking, long pos,
++                            long size, boolean shared) throws IOException;
++
++    static native void release0(FileDescriptor fd, long pos, long size)
++        throws IOException;
++
+ }
+diff -Nru openjdk.orig/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java openjdk/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java
+--- openjdk.orig/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java	2009-01-19 13:29:01.000000000 +0000
++++ openjdk/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java	2009-01-19 13:29:27.000000000 +0000
+@@ -34,7 +34,8 @@
+ import java.nio.channels.SocketChannel;
+ import java.nio.channels.ServerSocketChannel;
+ import java.nio.channels.DatagramChannel;
+-import java.nio.channels.spi.SelectorProvider;
++
++import org.classpath.icedtea.java.nio.channels.spi.SelectorProvider;
+ 
+ class InheritedChannel {
+ 
+diff -Nru openjdk.orig/jdk/src/solaris/native/sun/nio/ch/Net.c openjdk/jdk/src/solaris/native/sun/nio/ch/Net.c
+--- openjdk.orig/jdk/src/solaris/native/sun/nio/ch/Net.c	2009-01-26 20:51:08.000000000 +0000
++++ openjdk/jdk/src/solaris/native/sun/nio/ch/Net.c	2009-02-01 01:24:41.000000000 +0000
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
++ * 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
+@@ -40,58 +40,169 @@
+ #include "java_net_SocketOptions.h"
+ #include "nio.h"
+ 
+-#ifdef __linux__
+-#include <sys/utsname.h>
++/**
++ * Definitions for source-specific multicast to allow for building
++ * with older header files.
++ */
++
++#ifdef __solaris__
++
++#ifndef IP_BLOCK_SOURCE
+ 
+-#define IPV6_MULTICAST_IF 17
+-#ifndef SO_BSDCOMPAT
+-#define SO_BSDCOMPAT  14
++#define IP_BLOCK_SOURCE                 0x15
++#define IP_UNBLOCK_SOURCE               0x16
++#define IP_ADD_SOURCE_MEMBERSHIP        0x17
++#define IP_DROP_SOURCE_MEMBERSHIP       0x18
++
++#define MCAST_BLOCK_SOURCE              0x2b
++#define MCAST_UNBLOCK_SOURCE            0x2c
++#define MCAST_JOIN_SOURCE_GROUP         0x2d
++#define MCAST_LEAVE_SOURCE_GROUP        0x2e
++
++#endif  /* IP_BLOCK_SOURCE */
++
++struct my_ip_mreq_source {
++        struct in_addr  imr_multiaddr;
++        struct in_addr  imr_sourceaddr;
++        struct in_addr  imr_interface;
++};
++
++/*
++ * Use #pragma pack() construct to force 32-bit alignment on amd64.
++ */
++#if defined(amd64)
++#pragma pack(4)
+ #endif
++
++struct my_group_source_req {
++        uint32_t                gsr_interface;  /* interface index */
++        struct sockaddr_storage gsr_group;      /* group address */
++        struct sockaddr_storage gsr_source;     /* source address */
++};
++
++#if defined(amd64)
++#pragma pack()
+ #endif
+ 
++#endif  /* __solaris__ */
++
++
++#ifdef __linux__
++
++#ifndef IP_BLOCK_SOURCE
++
++#define IP_BLOCK_SOURCE                 38
++#define IP_UNBLOCK_SOURCE               37
++#define IP_ADD_SOURCE_MEMBERSHIP        39
++#define IP_DROP_SOURCE_MEMBERSHIP       40
++
++#define MCAST_BLOCK_SOURCE              43
++#define MCAST_UNBLOCK_SOURCE            44
++#define MCAST_JOIN_SOURCE_GROUP         42
++#define MCAST_LEAVE_SOURCE_GROUP        45
++
++#endif  /* IP_BLOCK_SOURCE */
++
++struct my_ip_mreq_source {
++        struct in_addr  imr_multiaddr;
++        struct in_addr  imr_interface;
++        struct in_addr  imr_sourceaddr;
++};
++
++struct my_group_source_req {
++        uint32_t                gsr_interface;  /* interface index */
++        struct sockaddr_storage gsr_group;      /* group address */
++        struct sockaddr_storage gsr_source;     /* source address */
++};
++
++#endif   /* __linux__ */
++
++
++#define COPY_INET6_ADDRESS(env, source, target) \
++    (*env)->GetByteArrayRegion(env, source, 0, 16, target)
++
++/*
++ * Copy IPv6 group, interface index, and IPv6 source address
++ * into group_source_req structure.
++ */
++static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
++                               jbyteArray source, struct my_group_source_req* req)
++{
++    struct sockaddr_in6* sin6;
++
++    req->gsr_interface = (uint32_t)index;
++
++    sin6 = (struct sockaddr_in6*)&(req->gsr_group);
++    sin6->sin6_family = AF_INET6;
++    COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
++
++    sin6 = (struct sockaddr_in6*)&(req->gsr_source);
++    sin6->sin6_family = AF_INET6;
++    COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
++}
++
++
+ JNIEXPORT void JNICALL
+ Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
+ {
+     /* Here because Windows native code does need to init IDs */
+ }
+ 
++JNIEXPORT jboolean JNICALL
++Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
++{
++    return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
++}
++
+ JNIEXPORT int JNICALL
+-Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
+-                            jboolean reuse)
++Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
++                            jboolean stream, jboolean reuse)
+ {
+     int fd;
++    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
++    int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
+ 
+-#ifdef AF_INET6
+-    if (ipv6_available())
+-        fd = socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
+-    else
+-#endif /* AF_INET6 */
+-        fd = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
+-
++    fd = socket(domain, type, 0);
+     if (fd < 0) {
+         return handleSocketError(env, errno);
+     }
+     if (reuse) {
+         int arg = 1;
+-        if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
+-                           sizeof(arg)) < 0) {
++        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
++                       sizeof(arg)) < 0) {
++            JNU_ThrowByNameWithLastError(env,
++                                         JNU_JAVANETPKG "SocketException",
++                                         "sun.nio.ch.Net.setIntOption");
++            close(fd);
++            return -1;
++        }
++    }
++#ifdef __linux__
++    /* By default, Linux uses the route default */
++    if (domain == AF_INET6 && type == SOCK_DGRAM) {
++        int arg = 1;
++        if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
++                       sizeof(arg)) < 0) {
+             JNU_ThrowByNameWithLastError(env,
+                                          JNU_JAVANETPKG "SocketException",
+                                          "sun.nio.ch.Net.setIntOption");
++            close(fd);
++            return -1;
+         }
+     }
++#endif
+     return fd;
+ }
+ 
+ JNIEXPORT void JNICALL
+-Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */
+-                         jobject fdo, jobject ia, int port)
++Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, 
++			 jobject fdo, jobject iao, int port)
+ {
+     SOCKADDR sa;
+     int sa_len = SOCKADDR_LEN;
+     int rv = 0;
+ 
+-    if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) {
++    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) {
+       return;
+     }
+ 
+@@ -101,26 +212,53 @@
+     }
+ }
+ 
++JNIEXPORT void JNICALL
++Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
++{
++    if (listen(fdval(env, fdo), backlog) < 0)
++        handleSocketError(env, errno);
++}
++
+ JNIEXPORT jint JNICALL
+-Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz,
+-                                jobject fdo, jobject iao, jint port,
+-                                jint trafficClass)
++Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, 
++			    jobject fdo, jobject iao, jint port,
++			    jint trafficClass)
+ {
+     SOCKADDR sa;
+     int sa_len = SOCKADDR_LEN;
+     int rv;
+ 
+-    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len, JNI_TRUE) != 0) {
++    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
++                                  &sa_len, JNI_TRUE) != 0)
++    {
+       return IOS_THROWN;
+     }
+ 
+-#ifdef AF_INET6
+-#if 0
+-    if (trafficClass != 0 && ipv6_available()) { /* ## FIX */
+-        NET_SetTrafficClass((struct sockaddr *)&sa, trafficClass);
++    rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
++    if (rv != 0) {
++        if (errno == EINPROGRESS) {
++            return IOS_UNAVAILABLE;
++        } else if (errno == EINTR) {
++            return IOS_INTERRUPTED;
++        }
++        return handleSocketError(env, errno);
++    }
++    return 1;
++}
++
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
++                             jobject fdo, jobject iao, jint port)
++{
++    SOCKADDR sa;
++    int sa_len = SOCKADDR_LEN;
++    int rv;
++
++    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
++                                  &sa_len, preferIPv6) != 0)
++    {
++      return IOS_THROWN;
+     }
+-#endif
+-#endif
+ 
+     rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
+     if (rv != 0) {
+@@ -138,7 +276,7 @@
+ Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
+ {
+     SOCKADDR sa;
+-    int sa_len = SOCKADDR_LEN;
++    socklen_t sa_len = SOCKADDR_LEN;
+     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+         handleSocketError(env, errno);
+         return -1;
+@@ -150,7 +288,7 @@
+ Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
+ {
+     SOCKADDR sa;
+-    int sa_len = SOCKADDR_LEN;
++    socklen_t sa_len = SOCKADDR_LEN;
+     int port;
+     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+         handleSocketError(env, errno);
+@@ -159,119 +297,115 @@
+     return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ }
+ 
+-
+-#ifdef NEEDED
+-
+-/* ## This is gross.  We should generate platform-specific constant
+- * ## definitions into a .java file and use those directly.
+- */
+-
+-static int
+-mapOption(JNIEnv *env, int opt, int *klevel, int *kopt)
+-{
+-
+-    switch (opt) {
+-
+-    case java_net_SocketOptions_IP_TOS:
+-        *klevel = IPPROTO_IP;
+-        *kopt = IP_TOS;
+-        break;
+-
+-    case java_net_SocketOptions_SO_BROADCAST:
+-    case java_net_SocketOptions_SO_KEEPALIVE:
+-    case java_net_SocketOptions_SO_LINGER:
+-    case java_net_SocketOptions_SO_OOBINLINE:
+-    case java_net_SocketOptions_SO_RCVBUF:
+-    case java_net_SocketOptions_SO_REUSEADDR:
+-    case java_net_SocketOptions_SO_SNDBUF:
+-        *klevel = SOL_SOCKET;
+-        break;
+-
+-    case java_net_SocketOptions_TCP_NODELAY:
+-        *klevel = IPPROTO_IP;
+-        *kopt = TCP_NODELAY;
+-        return 0;
+-
+-    default:
+-        JNU_ThrowByName(env, "java/lang/IllegalArgumentException", NULL);
+-        return -1;
+-    }
+-
+-    switch (opt) {
+-
+-    case java_net_SocketOptions_SO_BROADCAST:   *kopt = SO_BROADCAST;  break;
+-    case java_net_SocketOptions_SO_KEEPALIVE:   *kopt = SO_KEEPALIVE;  break;
+-    case java_net_SocketOptions_SO_LINGER:      *kopt = SO_LINGER;  break;
+-    case java_net_SocketOptions_SO_OOBINLINE:   *kopt = SO_OOBINLINE;  break;
+-    case java_net_SocketOptions_SO_RCVBUF:      *kopt = SO_RCVBUF;  break;
+-    case java_net_SocketOptions_SO_REUSEADDR:   *kopt = SO_REUSEADDR;  break;
+-    case java_net_SocketOptions_SO_SNDBUF:      *kopt = SO_SNDBUF;  break;
+-
+-    default:
+-        return -1;
+-    }
+-
+-    return 0;
+-}
+-#endif
+-
+-
+ JNIEXPORT jint JNICALL
+-Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
+-                                  jobject fdo, jint opt)
++Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
++                                  jboolean mayNeedConversion, jint level, jint opt)
+ {
+-    int klevel, kopt;
+     int result;
+     struct linger linger;
++    u_char carg;
+     void *arg;
+-    int arglen;
++    int arglen, n;
+ 
+-    if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
+-        JNU_ThrowByNameWithLastError(env,
+-                                     JNU_JAVANETPKG "SocketException",
+-                                     "Unsupported socket option");
+-        return -1;
++    /* Option value is an int except for a few specific cases */
++
++    arg = (void *)&result;
++    arglen = sizeof(result);
++
++    if (level == IPPROTO_IP &&
++        (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
++        arg = (void*)&carg;
++        arglen = sizeof(carg);
+     }
+ 
+-    if (opt == java_net_SocketOptions_SO_LINGER) {
++    if (level == SOL_SOCKET && opt == SO_LINGER) {
+         arg = (void *)&linger;
+         arglen = sizeof(linger);
+-    } else {
+-        arg = (void *)&result;
+-        arglen = sizeof(result);
+     }
+ 
+-    if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
++    if (mayNeedConversion) {
++        n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
++    } else {
++        n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
++    }
++    if (n < 0) {
+         JNU_ThrowByNameWithLastError(env,
+                                      JNU_JAVANETPKG "SocketException",
+                                      "sun.nio.ch.Net.getIntOption");
+         return -1;
+     }
+ 
+-    if (opt == java_net_SocketOptions_SO_LINGER)
+-        return linger.l_onoff ? linger.l_linger : -1;
+-    else
+-        return result;
++    if (level == IPPROTO_IP &&
++        (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
++    {
++        return (jint)carg;
++    }
++
++    if (level == SOL_SOCKET && opt == SO_LINGER)
++        return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
++
++    return (jint)result;
+ }
+ 
+ JNIEXPORT void JNICALL
+ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
+                                   jobject fdo, jint opt, jint arg)
+ {
+-    int klevel, kopt;
++  int klevel, kopt;
++  int result;
++  struct linger linger;
++  void *parg;
++  int arglen;
++ 
++  if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
++    JNU_ThrowByNameWithLastError(env,
++				 JNU_JAVANETPKG "SocketException",
++				 "Unsupported socket option");
++    return;
++  }
++ 
++  if (opt == java_net_SocketOptions_SO_LINGER) {
++    parg = (void *)&linger;
++    arglen = sizeof(linger);
++    if (arg >= 0) {
++             linger.l_onoff = 0;
++             linger.l_linger = 0;
++         }
++    } else {
++        parg = (void *)&arg;
++        arglen = sizeof(arg);
++     }
++ 
++    if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
++      JNU_ThrowByNameWithLastError(env,
++				   JNU_JAVANETPKG "SocketException",
++				   "sun.nio.ch.Net.setIntOption");
++    }
++}
++
++JNIEXPORT void JNICALL
++Java_sun_nio_ch_Net_setIntOption1(JNIEnv *env, jclass clazz, jobject fdo,
++                                  jboolean mayNeedConversion, jint level, jint opt, jint arg)
++{
+     int result;
+     struct linger linger;
++    u_char carg;
+     void *parg;
+-    int arglen;
++    int arglen, n;
+ 
+-    if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
+-        JNU_ThrowByNameWithLastError(env,
+-                                     JNU_JAVANETPKG "SocketException",
+-                                     "Unsupported socket option");
+-        return;
++    /* Option value is an int except for a few specific cases */
++
++    parg = (void*)&arg;
++    arglen = sizeof(arg);
++
++    if (level == IPPROTO_IP &&
++        (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
++        parg = (void*)&carg;
++        arglen = sizeof(carg);
++        carg = (u_char)arg;
+     }
+ 
+-    if (opt == java_net_SocketOptions_SO_LINGER) {
++    if (level == SOL_SOCKET && opt == SO_LINGER) {
+         parg = (void *)&linger;
+         arglen = sizeof(linger);
+         if (arg >= 0) {
+@@ -281,19 +415,199 @@
+             linger.l_onoff = 0;
+             linger.l_linger = 0;
+         }
+-    } else {
+-        parg = (void *)&arg;
+-        arglen = sizeof(arg);
+     }
+ 
+-    if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
++    if (mayNeedConversion) {
++        n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
++    } else {
++        n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
++    }
++    if (n < 0) {
+         JNU_ThrowByNameWithLastError(env,
+                                      JNU_JAVANETPKG "SocketException",
+                                      "sun.nio.ch.Net.setIntOption");
+     }
+ }
+ 
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
++                                jint group, jint interf, jint source)
++{
++    struct ip_mreq mreq;
++    struct my_ip_mreq_source mreq_source;
++    int opt, n, optlen;
++    void* optval;
++
++    if (source == 0) {
++        mreq.imr_multiaddr.s_addr = htonl(group);
++        mreq.imr_interface.s_addr = htonl(interf);
++        opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
++        optval = (void*)&mreq;
++        optlen = sizeof(mreq);
++    } else {
++        mreq_source.imr_multiaddr.s_addr = htonl(group);
++        mreq_source.imr_sourceaddr.s_addr = htonl(source);
++        mreq_source.imr_interface.s_addr = htonl(interf);
++        opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
++        optval = (void*)&mreq_source;
++        optlen = sizeof(mreq_source);
++    }
++
++    n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
++    if (n < 0) {
++        if (join && (errno == ENOPROTOOPT))
++            return IOS_UNAVAILABLE;
++        handleSocketError(env, errno);
++    }
++    return 0;
++}
++
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
++                                    jint group, jint interf, jint source)
++{
++    struct my_ip_mreq_source mreq_source;
++    int n;
++    int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
++
++    mreq_source.imr_multiaddr.s_addr = htonl(group);
++    mreq_source.imr_sourceaddr.s_addr = htonl(source);
++    mreq_source.imr_interface.s_addr = htonl(interf);
++
++    n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
++                   (void*)&mreq_source, sizeof(mreq_source));
++    if (n < 0) {
++        if (block && (errno == ENOPROTOOPT))
++            return IOS_UNAVAILABLE;
++        handleSocketError(env, errno);
++    }
++    return 0;
++}
++
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
++                                jbyteArray group, jint index, jbyteArray source)
++{
++    struct ipv6_mreq mreq6;
++    struct my_group_source_req req;
++    int opt, n, optlen;
++    void* optval;
++
++    if (source == NULL) {
++        COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
++        mreq6.ipv6mr_interface = (int)index;
++        opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
++        optval = (void*)&mreq6;
++        optlen = sizeof(mreq6);
++    } else {
++#ifdef __linux__
++        /* Include-mode filtering broken on Linux at least to 2.6.24 */
++        return IOS_UNAVAILABLE;
++#else
++        initGroupSourceReq(env, group, index, source, &req);
++        opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
++        optval = (void*)&req;
++        optlen = sizeof(req);
++#endif
++    }
++
++    n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
++    if (n < 0) {
++        if (join && (errno == ENOPROTOOPT))
++            return IOS_UNAVAILABLE;
++        handleSocketError(env, errno);
++    }
++    return 0;
++}
++
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
++                                    jbyteArray group, jint index, jbyteArray source)
++{
++    struct my_group_source_req req;
++    int n;
++    int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
++
++    initGroupSourceReq(env, group, index, source, &req);
++
++    n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
++        (void*)&req, sizeof(req));
++    if (n < 0) {
++        if (block && (errno == ENOPROTOOPT))
++            return IOS_UNAVAILABLE;
++        handleSocketError(env, errno);
++    }
++    return 0;
++}
++
++JNIEXPORT void JNICALL
++Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
++{
++    struct in_addr in;
++    int arglen = sizeof(struct in_addr);
++    int n;
++
++    in.s_addr = htonl(interf);
++
++    n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
++                   (void*)&(in.s_addr), arglen);
++    if (n < 0) {
++        handleSocketError(env, errno);
++    }
++}
++
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
++{
++    struct in_addr in;
++    int arglen = sizeof(struct in_addr);
++    int n;
++
++    n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
++    if (n < 0) {
++        handleSocketError(env, errno);
++        return -1;
++    }
++    return ntohl(in.s_addr);
++}
++
++JNIEXPORT void JNICALL
++Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
++{
++    int value = (jint)index;
++    int arglen = sizeof(value);
++    int n;
++
++    n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
++                   (void*)&(index), arglen);
++    if (n < 0) {
++        handleSocketError(env, errno);
++    }
++}
++
++JNIEXPORT jint JNICALL
++Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
++{
++    int index;
++    int arglen = sizeof(index);
++    int n;
++
++    n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
++    if (n < 0) {
++        handleSocketError(env, errno);
++        return -1;
++    }
++    return (jint)index;
++}
+ 
++JNIEXPORT void JNICALL
++Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
++{
++    int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
++        (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
++    if (shutdown(fdval(env, fdo), how) < 0)
++        handleSocketError(env, errno);
++}
+ 
+ /* Declared in nio_util.h */
+ 
+diff -Nru openjdk.orig/jdk/src/solaris/native/sun/nio/ch/nio_util.h openjdk/jdk/src/solaris/native/sun/nio/ch/nio_util.h
+--- openjdk.orig/jdk/src/solaris/native/sun/nio/ch/nio_util.h	2009-01-26 22:44:30.000000000 +0000
++++ openjdk/jdk/src/solaris/native/sun/nio/ch/nio_util.h	2009-01-26 22:44:22.000000000 +0000
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2001-2002 Sun Microsystems, Inc.  All Rights Reserved.
++ * 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
+@@ -27,8 +27,15 @@
+ #include "jni_util.h"
+ #include "jvm.h"
+ #include "jlong.h"
++#include <errno.h>
+ #include <sys/types.h>
+ 
++#define RESTARTABLE(_cmd, _result) do { \
++  do { \
++    _result = _cmd; \
++  } while((_result == -1) && (errno == EINTR)); \
++} while(0)
++
+ 
+ /* NIO utility procedures */
+ 
+diff -Nru openjdk.orig/jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java openjdk/jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java
+--- openjdk.orig/jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java	2009-01-19 22:35:32.000000000 +0000
++++ openjdk/jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java	2009-01-19 22:37:37.000000000 +0000
+@@ -36,6 +36,11 @@
+ class FileDispatcher extends NativeDispatcher
+ {
+ 
++    public static final int NO_LOCK = -1;       // Failed to lock
++    public static final int LOCKED = 0;         // Obtained requested lock
++    public static final int RET_EX_LOCK = 1;    // Obtained exclusive lock
++    public static final int INTERRUPTED = 2;    // Request interrupted
++
+     static {
+         Util.load();
+     }
+@@ -78,6 +83,28 @@
+         close0(fd);
+     }
+ 
++    int force(FileDescriptor fd, boolean metaData) throws IOException {
++        return force0(fd, metaData);
++    }
++
++    int truncate(FileDescriptor fd, long size) throws IOException {
++        return truncate0(fd, size);
++    }
++
++    long size(FileDescriptor fd) throws IOException {
++        return size0(fd);
++    }
++
++    int lock(FileDescriptor fd, boolean blocking, long pos, long size,
++             boolean shared) throws IOException
++    {
++        return lock0(fd, blocking, pos, size, shared);
++    }
++
++    void release(FileDescriptor fd, long pos, long size) throws IOException {
++        release0(fd, pos, size);
++    }
++
+     //-- Native methods
+ 
+     static native int read0(FileDescriptor fd, long address, int len)
+@@ -102,4 +129,17 @@
+ 
+     static native void closeByHandle(long fd) throws IOException;
+ 
++    static native int force0(FileDescriptor fd, boolean metaData)
++        throws IOException;
++
++    static native int truncate0(FileDescriptor fd, long size)
++        throws IOException;
++
++    static native long size0(FileDescriptor fd) throws IOException;
++
++    static native int lock0(FileDescriptor fd, boolean blocking, long pos,
++                            long size, boolean shared) throws IOException;
++
++    static native void release0(FileDescriptor fd, long pos, long size)
++        throws IOException;
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-pr261.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -0,0 +1,59 @@
+diff -Nru openjdk-ecj.orig/jdk/make/java/nio/FILES_java.gmk openjdk-ecj/jdk/make/java/nio/FILES_java.gmk
+--- openjdk.orig/jdk/make/java/nio/FILES_java.gmk	2008-11-20 08:44:11.000000000 +0000
++++ openjdk/jdk/make/java/nio/FILES_java.gmk	2008-12-02 16:00:15.000000000 +0000
+@@ -32,6 +32,7 @@
+ 	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 \
+@@ -42,6 +43,7 @@
+ 	java/nio/channels/MembershipKey.java \
+ 	java/nio/channels/MulticastChannel.java \
+ 	java/nio/channels/NetworkChannel.java \
++	java/nio/channels/Pipe.java \
+ 	java/nio/channels/ReadableByteChannel.java \
+ 	java/nio/channels/ScatteringByteChannel.java \
+ 	java/nio/channels/SelectableChannel.java \
+diff -Nru openjdk-ecj.orig/jdk/make/java/nio/Makefile openjdk-ecj/jdk/make/java/nio/Makefile
+--- openjdk.orig/jdk/make/java/nio/Makefile	2008-12-02 15:52:07.000000000 +0000
++++ openjdk/jdk/make/java/nio/Makefile	2008-12-02 15:59:32.000000000 +0000
+@@ -85,6 +85,9 @@
+ 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 @@
+         PollArrayWrapper.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 \
--- a/patches/icedtea-version.patch	Tue Feb 10 21:09:31 2009 +0000
+++ b/patches/icedtea-version.patch	Tue Feb 10 21:56:55 2009 +0000
@@ -6,9 +6,8 @@
  # Default names
  ifdef OPENJDK
 -  LAUNCHER_NAME = openjdk
--  PRODUCT_NAME = OpenJDK
 +  LAUNCHER_NAME = java
-+  PRODUCT_NAME = IcedTea
+   PRODUCT_NAME = OpenJDK
    PRODUCT_SUFFIX = Runtime Environment
    JDK_RC_PLATFORM_NAME = Platform
    COMPANY_NAME = N/A
--- a/patches/icedtea-visualvm.patch	Tue Feb 10 21:09:31 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
---- pp	2008-10-31 11:24:42.000000000 -0400
-+++ visualvm/visualvm/jvm/nbproject/platform.properties	2008-10-31 11:24:48.000000000 -0400
-@@ -16,8 +16,8 @@
-     org.openide.compat,\
-     org.openide.util.enumerations
- enabled.clusters=\
--    platform7,\
--    profiler2
-+    platform8,\
-+    profiler3
- nbjdk.active=default
- nbplatform.active=NetBeans_Platform_Dev_(Build_200711261600)
- suite.dir=${basedir}
---- pp2	2008-10-31 11:50:40.000000000 -0400
-+++ visualvm/visualvm/nbproject/platform.properties	2008-10-31 11:50:47.000000000 -0400
-@@ -14,8 +14,8 @@
-     org.openide.compat,\
-     org.openide.util.enumerations
- enabled.clusters=\
--    platform7,\
--    profiler2
-+    platform8,\
-+    profiler3
- nbjdk.active=default
- nbplatform.active=NetBeans_Platform_6.0.1_(Build_200801291616)
- suite.dir=${basedir}
--- a/plugin/icedtea/sun/applet/AppletSecurityContextManager.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/AppletSecurityContextManager.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 import java.security.AccessControlContext;
--- a/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java	Tue Feb 10 21:56:55 2009 +0000
@@ -55,6 +55,7 @@
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Hashtable;
 import java.util.List;
 
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
@@ -224,7 +225,7 @@
 
 public class PluginAppletSecurityContext {
 	
-	public static HashMap<ClassLoader, String> classLoaders = new HashMap<ClassLoader, String>();
+	public static Hashtable<ClassLoader, String> classLoaders = new Hashtable<ClassLoader, String>();
 
 	// FIXME: make private
 	public PluginObjectStore store = new PluginObjectStore();
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,4 +1,41 @@
- /*
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat 
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+/*
   * Copyright 1995-2004 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
@@ -176,7 +213,7 @@
          AccessController.doPrivileged(new PrivilegedAction() {
              public Object run() {
             	 	try {
-            	 		panel = new NetxPanel(doc, atts, true);
+            	 		panel = new NetxPanel(doc, atts, false);
             	 		AppletViewerPanel.debug("Using NetX panel");
             	 		PluginDebug.debug(atts.toString());
             	 	} catch (Exception ex) {
@@ -612,8 +649,14 @@
 
                  // try to fetch it locally
                  if (panel instanceof NetxPanel) {
+
                      URL localURL = null;
-                     localURL = ((NetxPanel) panel).getAppletClassLoader().getResource(originalURL.substring(codeBase.length()));
+                     
+                     String resourceName = originalURL.substring(codeBase.length()); 
+                     JNLPClassLoader loader = (JNLPClassLoader) ((NetxPanel) panel).getAppletClassLoader(); 
+
+                     if (loader.resourceAvailableLocally(resourceName))
+                         localURL = loader.getResource(resourceName);
 
                      url = localURL != null ? localURL : url;
                  }
@@ -630,7 +673,7 @@
                  return ref;
              }
          } catch (Exception e) {
-             System.err.println("Error occurred wgen trying to fetch image:");
+             System.err.println("Error occurred when trying to fetch image:");
              e.printStackTrace();
              return null;
          }
--- a/plugin/icedtea/sun/applet/PluginCallRequestFactory.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginCallRequestFactory.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 
--- a/plugin/icedtea/sun/applet/PluginClassLoader.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginClassLoader.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 public class PluginClassLoader extends ClassLoader {
--- a/plugin/icedtea/sun/applet/PluginDebug.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginDebug.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 import java.io.*;
--- a/plugin/icedtea/sun/applet/PluginException.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginException.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 
--- a/plugin/icedtea/sun/applet/PluginMain.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginMain.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,40 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
 /*
  * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -34,6 +71,14 @@
 import java.util.Enumeration;
 import java.util.Properties;
 
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import net.sourceforge.jnlp.security.VariableX509TrustManager;
+
 /**
  * The main entry point into PluginAppletViewer.
  */
@@ -152,7 +197,19 @@
 		// INSTALL THE PROPERTY LIST
 		System.setProperties(avProps);
 
-		// REMIND: Create and install a socket factory!
+
+		try {
+		    SSLSocketFactory sslSocketFactory;
+		    SSLContext context = SSLContext.getInstance("SSL");
+		    TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() };
+		    context.init(null, trust, null);
+		    sslSocketFactory = context.getSocketFactory();
+		    
+		    HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
+		} catch (Exception e) {
+		    System.err.println("Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway...");
+		    e.printStackTrace();
+		}
 	}
 
     static boolean messageAvailable() {
--- a/plugin/icedtea/sun/applet/PluginMessageConsumer.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginMessageConsumer.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 import java.util.ArrayList;
--- a/plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 
--- a/plugin/icedtea/sun/applet/PluginStreamHandler.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/PluginStreamHandler.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 import java.io.BufferedReader;
--- a/plugin/icedtea/sun/applet/RequestQueue.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/plugin/icedtea/sun/applet/RequestQueue.java	Tue Feb 10 21:56:55 2009 +0000
@@ -1,3 +1,41 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
 package sun.applet;
 
 
@@ -36,4 +74,4 @@
     public int size() {
     	return size;
     }
-}
\ No newline at end of file
+}
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 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
@@ -292,15 +292,39 @@
   // Set up the Java frame anchor  
   thread->set_last_Java_frame();
 
-  // Change the thread state to native
+  // Change the thread state to _thread_in_native
   ThreadStateTransition::transition_from_java(thread, _thread_in_native);
 
   // Make the call
   intptr_t result[4 - LogBytesPerWord];
   ffi_call(handler->cif(), (void (*)()) function, result, arguments);
 
-  // Change the thread state back to Java
-  ThreadStateTransition::transition_from_native(thread, _thread_in_Java);
+  // Change the thread state back to _thread_in_Java.
+  // ThreadStateTransition::transition_from_native() cannot be used
+  // here because it does not check for asynchronous exceptions.
+  // We have to manage the transition ourself.
+  thread->set_thread_state(_thread_in_native_trans);
+
+  // Make sure new state is visible in the GC thread
+  if (os::is_MP()) {
+    if (UseMembar) {
+      OrderAccess::fence();
+    }
+    else {
+      InterfaceSupport::serialize_memory(thread);
+    }
+  }
+
+  // Handle safepoint operations, pending suspend requests,
+  // and pending asynchronous exceptions.
+  if (SafepointSynchronize::do_call_back() ||
+      thread->has_special_condition_for_native_trans()) {
+    JavaThread::check_special_condition_for_native_trans(thread);
+    CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops());
+  }
+
+  // Finally we can change the thread state to _thread_in_Java.
+  thread->set_thread_state(_thread_in_Java);
   fixup_after_potential_safepoint();
 
   // Clear the frame anchor
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 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
@@ -41,11 +41,7 @@
   // accessors for the instance variables
   intptr_t* fp() const
   {
-#ifdef PRODUCT
-    ShouldNotCallThis();
-#else
-    return (intptr_t *) -1; // make frame::print_value_on work
-#endif // !PRODUCT
+    return (intptr_t *) -1;
   }
 
 #ifdef CC_INTERP
--- a/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * Copyright 2008, 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
@@ -37,13 +37,13 @@
   {
     intptr_t *lo_addr = thread->zero_stack()->sp();
     if (!lo_addr) {
-      _st->print(" stack not set up");
+      _st->print_cr(" stack not set up");
       return;
     }
 
     intptr_t *hi_addr = (intptr_t *) thread->top_zero_frame();
     if (!hi_addr) {
-      _st->print("no frames pushed"); 
+      _st->print_cr("no frames pushed"); 
       return;
     }
     assert(hi_addr >= lo_addr, "corrupted stack");
@@ -250,3 +250,24 @@
       _st->print_cr(PTR_FORMAT, *addr);    
   }
 };
+
+#ifndef PRODUCT
+extern "C" {
+  void print_zero_threads() {
+    char buf[O_BUFLEN];
+    ZeroStackPrinter zsp(tty, buf, sizeof(buf));
+
+    for (JavaThread *t = Threads::first(); t; t = t->next()) {
+      tty->print(PTR_FORMAT, t);
+      tty->print(" ");
+      t->print_on_error(tty, buf, sizeof(buf));
+      tty->cr();
+      tty->cr();
+
+      zsp.print(t);
+      if (t->next())
+        tty->cr();
+    }
+  }
+}
+#endif // !PRODUCT
--- a/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -142,7 +142,7 @@
   };
 
   enum FrameType {
-    ENTRY_FRAME = 1,
+    ENTRY_FRAME = 0xCAFEBABE,
     INTERPRETER_FRAME,
     SHARK_FRAME,
     DEOPTIMIZER_FRAME
--- a/ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2005 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * Copyright 2008, 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
@@ -27,5 +27,5 @@
 #include "incls/_stubRoutines_zero.cpp.incl"
 
 #ifdef IA32
-address StubRoutines::i486::_call_stub_compiled_return = NULL;
+address StubRoutines::x86::_call_stub_compiled_return = NULL;
 #endif // IA32
--- a/ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2005 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 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
@@ -45,7 +45,7 @@
   };                     // them if that happens.
 
 #ifdef IA32
-  class i486
+  class x86
   {
     friend class VMStructs;
 
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -23,6 +23,24 @@
  *
  */
 
+#ifdef __PPC
+
+#define READ_MEM_BARRIER __asm __volatile ("isync":::"memory")
+#ifdef __NO_LWSYNC__
+#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory")
+#else
+#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory")
+#endif
+
+#else // PPC
+
+#define READ_MEM_BARRIER __asm __volatile ("":::"memory")
+#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory")
+
+#endif // PPC
+
+
+
 inline void OrderAccess::loadload()   { acquire(); }
 inline void OrderAccess::storestore() { release(); }
 inline void OrderAccess::loadstore()  { acquire(); }
@@ -30,12 +48,12 @@
 
 inline void OrderAccess::acquire()
 {
-  __sync_synchronize();
+  READ_MEM_BARRIER;
 }
 
 inline void OrderAccess::release()
 {
-  __sync_synchronize();
+  WRITE_MEM_BARRIER;
 }
 
 inline void OrderAccess::fence()
@@ -43,49 +61,71 @@
   __sync_synchronize();
 }
 
-inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
-inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { return *p; }
-inline jint     OrderAccess::load_acquire(volatile jint*    p) { return *p; }
+inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { jbyte data = *p; acquire(); return data; }
+inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { jshort data = *p; acquire(); return data; }
+inline jint     OrderAccess::load_acquire(volatile jint*    p) { jint data = *p; acquire(); return data; }
 inline jlong    OrderAccess::load_acquire(volatile jlong*   p)
 {
   jlong tmp;
   os::atomic_copy64(p, &tmp);
+  acquire();
   return tmp;
 }
-inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { return *p; }
-inline jushort  OrderAccess::load_acquire(volatile jushort* p) { return *p; }
-inline juint    OrderAccess::load_acquire(volatile juint*   p) { return *p; }
+inline jubyte    OrderAccess::load_acquire(volatile jubyte*   p) { jubyte data = *p; acquire(); return data; }
+inline jushort   OrderAccess::load_acquire(volatile jushort*  p) { jushort data = *p; acquire(); return data; }
+inline juint     OrderAccess::load_acquire(volatile juint*    p) { juint data = *p; acquire(); return data; }
 inline julong   OrderAccess::load_acquire(volatile julong*  p)
 {
   julong tmp;
   os::atomic_copy64(p, &tmp);
+  acquire();
   return tmp;
 }
-inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { return *p; }
+inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { jfloat data = *p; acquire(); return data; }
 inline jdouble  OrderAccess::load_acquire(volatile jdouble* p)
 {
   jdouble tmp;
   os::atomic_copy64(p, &tmp);
+  acquire();
   return tmp;
 }
 
-inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t*   p) { return *p; }
-inline void*    OrderAccess::load_ptr_acquire(volatile void*       p) { return *(void* volatile *)p; }
-inline void*    OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; }
+inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t*   p) 
+{ 
+  intptr_t data = *p; 
+  acquire();
+  return data; 
+}
+inline void*    OrderAccess::load_ptr_acquire(volatile void*       p) 
+{ 
+  void *data = *(void* volatile *)p;
+  acquire();
+  return data; 
+}
+inline void*    OrderAccess::load_ptr_acquire(const volatile void* p) 
+{
+  void *data = *(void* const volatile *)p; 
+  acquire(); 
+  return data;
+}
 
-inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { os::atomic_copy64(&v, p); }
-inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
-inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { os::atomic_copy64(&v, p); }
-inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { os::atomic_copy64(&v, p); }
+inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) 
+{ release(); os::atomic_copy64(&v, p); }
+inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v)
+{ release(); os::atomic_copy64(&v, p); }
+inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v)
+{ release(); os::atomic_copy64(&v, p); }
 
-inline void     OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
-inline void     OrderAccess::release_store_ptr(volatile void*     p, void*    v) { *(void* volatile *)p = v; }
+inline void     OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; }
+inline void     OrderAccess::release_store_ptr(volatile void*     p, void*    v)
+{ release(); *(void* volatile *)p = v; }
 
 inline void     OrderAccess::store_fence(jbyte*   p, jbyte   v) { *p = v; fence(); }
 inline void     OrderAccess::store_fence(jshort*  p, jshort  v) { *p = v; fence(); }
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -95,6 +95,15 @@
   }
 
  public:
+  // Check for pending suspend requests and pending asynchronous
+  // exceptions.  There are separate accessors for these, but
+  // _suspend_flags is volatile so using them would be unsafe.
+  bool has_special_condition_for_native_trans()
+  {
+    return _suspend_flags != 0;
+  }
+
+ public:
   bool pd_get_top_frame_for_signal_handler(frame* fr_addr,
                                            void* ucontext,
                                            bool isInJava)
--- a/ports/hotspot/src/share/vm/includeDB_shark	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/includeDB_shark	Tue Feb 10 21:56:55 2009 +0000
@@ -112,6 +112,7 @@
 sharkBuilder.hpp                        sizes.hpp
 sharkBuilder.hpp                        sharkType.hpp
 sharkBuilder.hpp                        sharkValue.inline.hpp
+sharkBuilder.hpp                        sharkEntry.hpp
 
 sharkBytecodeTracer.cpp                 sharkBytecodeTracer.hpp
 sharkBytecodeTracer.cpp                 sharkState.inline.hpp
@@ -269,3 +270,4 @@
 sharkValue.inline.hpp                   ciType.hpp
 sharkValue.inline.hpp                   llvmHeaders.hpp
 sharkValue.inline.hpp                   sharkValue.hpp
+
--- a/ports/hotspot/src/share/vm/shark/llvmHeaders.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/llvmHeaders.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -36,6 +36,10 @@
 #include <llvm/ModuleProvider.h>
 #include <llvm/Support/IRBuilder.h>
 #include <llvm/Type.h>
+#include <llvm/ExecutionEngine/JITMemoryManager.h>
+#include <llvm/Support/CommandLine.h>
+
+#include <map>
 
 #ifdef assert
   #undef assert
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * Copyright 2008, 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
@@ -992,7 +992,7 @@
   if (value->is_jobject()) {
     call_vm_nocheck(
       SharkRuntime::throw_NullPointerException(),
-      LLVMValue::intptr_constant((intptr_t) __FILE__),
+      builder()->pointer_constant(__FILE__),
       LLVMValue::jint_constant(__LINE__));
   }
   else {
@@ -1021,7 +1021,7 @@
   SharkTrackingState *saved_state = current_state()->copy();
   call_vm_nocheck(
     SharkRuntime::throw_ArrayIndexOutOfBoundsException(),
-    LLVMValue::intptr_constant((intptr_t) __FILE__),
+    builder()->pointer_constant(__FILE__),
     LLVMValue::jint_constant(__LINE__),
     index->jint_value());
   handle_exception(function()->CreateGetPendingException());
@@ -1141,8 +1141,7 @@
 
   Value *state = builder()->CreateLoad(
     builder()->CreateIntToPtr(
-      LLVMValue::intptr_constant(
-        (intptr_t) SafepointSynchronize::address_of_state()),
+      builder()->pointer_constant(SafepointSynchronize::address_of_state()),
       PointerType::getUnqual(SharkType::jint_type())),
     "state");
 
@@ -2238,13 +2237,13 @@
     builder()->SetInsertPoint(heap_alloc);
 
     Value *top_addr = builder()->CreateIntToPtr(
-      LLVMValue::intptr_constant((intptr_t) Universe::heap()->top_addr()),
+	builder()->pointer_constant(Universe::heap()->top_addr()),
       PointerType::getUnqual(SharkType::intptr_type()),
       "top_addr");
 
     Value *end = builder()->CreateLoad(
       builder()->CreateIntToPtr(
-        LLVMValue::intptr_constant((intptr_t) Universe::heap()->end_addr()),
+        builder()->pointer_constant(Universe::heap()->end_addr()),
         PointerType::getUnqual(SharkType::intptr_type())),
       "end");
 
@@ -2473,7 +2472,10 @@
 void SharkBlock::do_monitorexit()
 {
   SharkValue *lockee = pop();
-  check_null(lockee);
+  // The monitorexit can't throw an NPE because the verifier checks
+  // that the monitor operations are block structured before we
+  // compile.
+  // check_null(lockee);
   Value *object = lockee->jobject_value();
 
   // Find the monitor associated with this object
@@ -2513,5 +2515,8 @@
   // Release the lock
   builder()->SetInsertPoint(got_monitor);
   monitor->release(this);
-  check_pending_exception();
+  // The monitorexit can't throw an NPE because the verifier checks
+  // that the monitor operations are block structured before we
+  // compile.
+  // check_pending_exception();
 }
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -28,12 +28,15 @@
 
 using namespace llvm;
 
+std::map<const llvm::Function*, SharkEntry*> SharkBuilder::sharkEntry;
+
 SharkBuilder::SharkBuilder()
   : IRBuilder<>(),
       _module("shark"),
       _module_provider(module()),
-      _execution_engine(ExecutionEngine::create(&_module_provider))
-{
+      _execution_engine(ExecutionEngine::createJIT
+			(&_module_provider, NULL, new MyJITMemoryManager(),
+			 /* Fast */ false)) {
   init_external_functions();
 }
 
@@ -152,7 +155,7 @@
 {
   return CreateCall2(
     SharkRuntime::unimplemented(),
-    LLVMValue::intptr_constant((intptr_t) file),
+    pointer_constant(file),
     LLVMValue::jint_constant(line));
 }
 
@@ -160,7 +163,7 @@
 {
   return CreateCall2(
     SharkRuntime::should_not_reach_here(),
-    LLVMValue::intptr_constant((intptr_t) file),
+    pointer_constant(file),
     LLVMValue::jint_constant(line));
 }
 
@@ -174,3 +177,16 @@
     ConstantInt::get(Type::Int1Ty, 0)};
   return CreateCall(llvm_memory_barrier_fn(), args, args + 5);
 }
+
+void SharkBuilder::MyJITMemoryManager::endFunctionBody
+  (const llvm::Function *F, unsigned char *FunctionStart,
+   unsigned char *FunctionEnd) 
+{
+  mm->endFunctionBody(F, FunctionStart, FunctionEnd);
+#ifndef PRODUCT
+  SharkEntry *e = sharkEntry[F];
+  if (e)
+    e->setBounds(FunctionStart, FunctionEnd);
+#endif // !PRODUCT
+}
+
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -27,11 +27,76 @@
  public:
   SharkBuilder();
 
+  static std::map<const llvm::Function*, SharkEntry*> sharkEntry;
+
  private:
   llvm::Module                 _module;
   llvm::ExistingModuleProvider _module_provider;
   llvm::ExecutionEngine*       _execution_engine;
 
+  // MyJITMemoryManager wraps the JIT Memory Manager: this allows us
+  // to run our own memory allocation policies, but the purpose here
+  // is to allow us to intercept JITMemoryManager::endFunctionBody.
+  class MyJITMemoryManager : public llvm::JITMemoryManager {
+
+    llvm::JITMemoryManager *mm;
+
+  public:
+
+    MyJITMemoryManager()
+    {
+      mm = llvm::JITMemoryManager::CreateDefaultMemManager();
+    }
+
+    virtual void AllocateGOT() {
+      mm->AllocateGOT();
+    }
+
+    virtual unsigned char *getGOTBase() const {
+      return mm->getGOTBase();
+    }
+
+    virtual unsigned char *startFunctionBody(const llvm::Function *F,
+					     uintptr_t &ActualSize) {
+      return mm->startFunctionBody(F, ActualSize);
+    }
+
+    virtual unsigned char *allocateStub(const llvm::GlobalValue* F,
+					unsigned StubSize,
+					unsigned Alignment) {
+      return mm->allocateStub(F, StubSize, Alignment);
+    }
+
+    void endFunctionBody(const llvm::Function *F, unsigned char *FunctionStart,
+			 unsigned char *FunctionEnd);
+
+    virtual void deallocateMemForFunction(const llvm::Function *F) {
+      return mm->deallocateMemForFunction(F);
+    }
+
+    virtual unsigned char* startExceptionTable(const llvm::Function* F,
+					       uintptr_t &ActualSize) {
+      return mm->startExceptionTable(F, ActualSize);
+    }
+
+    virtual void endExceptionTable(const llvm::Function *F,
+				   unsigned char *TableStart,
+				   unsigned char *TableEnd,
+				   unsigned char* FrameRegister) {
+      mm->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
+    }
+
+    virtual void setMemoryWritable() {
+      mm->setMemoryWritable();
+    }
+
+    virtual void setMemoryExecutable() {
+      mm->setMemoryExecutable();
+    }
+  };
+
+  MyJITMemoryManager *MemMgr;
+
  public:
   llvm::Module* module()
   {
@@ -125,9 +190,37 @@
                                 const llvm::FunctionType* sig,
                                 const char*               name);
 
+  llvm::Constant* pointer_constant(const void *ptr)
+  {
+    // Create a pointer constant that points at PTR.  We do this by
+    // creating a GlobalVariable mapped at PTR.  This is a workaround
+    // for http://www.llvm.org/bugs/show_bug.cgi?id=2920
+
+    using namespace llvm;
+
+    // This might be useful but it returns a const pointer that can't
+    // be used for anything.  Go figure...
+//     {
+//       const GlobalValue *value
+// 	= execution_engine()->getGlobalValueAtAddress(const_cast<void*>(ptr));
+//       if (value)
+// 	return ConstantExpr::getPtrToInt(value, SharkType::intptr_type());
+//     }
+
+    char name[128];
+    snprintf(name, sizeof name - 1, "pointer_constant_%p", ptr);
+
+    GlobalVariable *value = new GlobalVariable(SharkType::intptr_type(),
+      false, GlobalValue::ExternalLinkage,
+      NULL, name, module());
+    execution_engine()->addGlobalMapping(value, const_cast<void*>(ptr));
+
+    return ConstantExpr::getPtrToInt(value, SharkType::intptr_type());
+  }
+
   // Helper for making pointers
  public:
-  llvm::Constant* make_pointer(intptr_t addr, const llvm::Type* type) const
+  llvm::Constant* make_pointer(intptr_t addr, const llvm::Type* type)
   {
     return llvm::ConstantExpr::getIntToPtr(
       LLVMValue::intptr_constant(addr),
@@ -193,8 +286,7 @@
       LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
       CreateIntToPtr(
         CreateAdd(
-          LLVMValue::intptr_constant(
-            (intptr_t) ((CardTableModRefBS *) bs)->byte_map_base),
+          pointer_constant(((CardTableModRefBS *) bs)->byte_map_base),
           CreateLShr(
             CreatePtrToInt(field, SharkType::intptr_type()),
             LLVMValue::intptr_constant(CardTableModRefBS::card_shift))),
--- a/ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -89,7 +89,7 @@
     break;
 
   case T_ADDRESS:
-    *dst = LLVMValue::intptr_constant(value->returnAddress_value());
+    *dst = builder->pointer_constant((const void*)value->returnAddress_value());
     break;
 
   default:
--- a/ports/hotspot/src/share/vm/shark/sharkEntry.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkEntry.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -41,30 +41,6 @@
 // Lots of the stuff down here is machine- and LLVM-specific.
 // It's only debug stuff though, and none of it's critical.
 
-address SharkEntry::code_start() const
-{
-  return (address) entry_point();
-}
-
-address SharkEntry::code_limit() const
-{
-#ifdef PPC
-  // LLVM seems to insert three junk instructions and a null after
-  // every function.  Only the first junk instruction seems to be
-  // kept after the next function is generated, however, so this
-  // method will only work before you generate another function.
-  // I wish there was a nicer way to do this, but that's life...
-  uint32_t *limit = (uint32_t *) code_start();
-  while (*limit)
-    limit++;
-  assert(limit[-1] == 0xd143cfec && limit[-2] == 0xd143cfec, "should be");
-  limit -= 3;
-  return (address) limit;
-#else
-  Unimplemented();
-#endif // PPC
-}
-
 void SharkEntry::print_pd_statistics(address start, address limit) const
 {
 #ifdef PPC
--- a/ports/hotspot/src/share/vm/shark/sharkEntry.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkEntry.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -48,8 +48,24 @@
 
 #ifndef PRODUCT
  private:
-  address code_start() const;
-  address code_limit() const;
+  address code_start() const
+  {
+    return start;
+  }
+  address code_limit() const
+  {
+    return limit;
+  }
   void print_pd_statistics(address start, address limit) const;
+
+  address start, limit;
+
+public:
+  void setBounds(unsigned char *FunctionStart, unsigned char *FunctionEnd)
+  {
+    start = (address)FunctionStart;
+    limit = (address)FunctionEnd;
+  }
+
 #endif // !PRODUCT
 };
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Tue Feb 10 21:56:55 2009 +0000
@@ -26,6 +26,8 @@
 #include "incls/_precompiled.incl"
 #include "incls/_sharkFunction.cpp.incl"
 
+#include <fnmatch.h>
+
 using namespace llvm;
 
 void SharkFunction::initialize()
@@ -37,6 +39,11 @@
   // Create the function
   _function = builder()->CreateFunction();
   entry->set_llvm_function(function());
+#ifndef PRODUCT
+  // FIXME: there should be a mutex when updating sharkEntry in case
+  // there are multiple compilation threads.
+  builder()->sharkEntry[function()] = entry;
+#endif // !PRODUCT
 
   // Create the list of blocks
   set_block_insertion_point(NULL);
@@ -122,10 +129,25 @@
 
   // Dump the bitcode, if requested
   if (SharkPrintBitcodeOf != NULL) {
-    if (!strcmp(SharkPrintBitcodeOf, name()))
+    if (!fnmatch(SharkPrintBitcodeOf, name(), 0))
       function()->dump();
   }
 
+  if (SharkPrintAsmOf != NULL) {
+#if defined (__x86_64) || defined (__i386)
+      std::vector<const char*> Args;
+      Args.push_back(""); // program name
+      if (!fnmatch(SharkPrintAsmOf, name(), 0))
+	// Oh, yuck.  The LLVM name for this debugging dump is
+	// target-specific.
+	Args.push_back("-debug-only=" "x86-emitter");
+      else
+	Args.push_back("-debug-only=");
+      Args.push_back(0);  // Null terminator.
+      cl::ParseCommandLineOptions(Args.size()-1, (char**)&Args[0]);
+#endif
+  }
+
   // Compile to native code
   void *code = builder()->execution_engine()->getPointerToFunction(function());
   entry->set_entry_point((ZeroEntry::method_entry_t) code);
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -232,6 +232,8 @@
 
   // OopMap support
  public:
+  // Every time a new, distinct pc is required, an extra byte is
+  // emitted into the codebuffer
   int code_offset() const
   {
     int offset = masm()->offset();
--- a/ports/hotspot/src/share/vm/shark/shark_globals.hpp	Tue Feb 10 21:09:31 2009 +0000
+++ b/ports/hotspot/src/share/vm/shark/shark_globals.hpp	Tue Feb 10 21:56:55 2009 +0000
@@ -48,6 +48,9 @@
   develop(ccstr, SharkPrintBitcodeOf, NULL,                                   \
           "Print the LLVM bitcode of the specified method")                   \
                                                                               \
+  develop(ccstr, SharkPrintAsmOf, NULL,                                   \
+          "Print the asm of the specified method")                   \
+                                                                              \
   develop(bool, SharkTraceBytecodes, false,                                   \
           "Trace bytecode compilation")                                       \
                                                                               \
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Tue Feb 10 21:56:55 2009 +0000
@@ -55,9 +55,6 @@
 
 	private byte[] data = null;
 
-	private boolean muted;
-	private float volume;
-
 	// these are frame indices. so counted from 0
 	// the current frame index
 	private int currentFrame = 0;
@@ -206,7 +203,6 @@
 		this.supportedFormats = formats;
 		this.defaultFormat = defaultFormat;
 		this.currentFormat = defaultFormat;
-		this.volume = PulseAudioVolumeControl.MAX_VOLUME;
 		this.streamName = DEFAULT_CLIP_NAME;
 
 		clipThread = new ClipThread();
@@ -416,12 +412,7 @@
 
 		PulseAudioVolumeControl volumeControl = new PulseAudioVolumeControl(
 				this, eventLoop);
-		PulseAudioMuteControl muteControl = new PulseAudioMuteControl(this,
-				volumeControl);
 		controls.add(volumeControl);
-		controls.add(muteControl);
-		volume = volumeControl.getValue();
-		muted = muteControl.getValue();
 
 		PulseAudioMixer mixer = PulseAudioMixer.getInstance();
 		mixer.addSourceLine(this);
@@ -433,28 +424,22 @@
 
 	// FIXME
 	@Override
-	public byte[] native_setVolume(float value) {
-		return stream.native_setVolume(value);
+	public byte[] native_set_volume(float value) {
+		return stream.native_set_volume(value);
 	}
 
-	@Override
-	public boolean isMuted() {
-		return muted;
+	public byte[] native_update_volume() {
+		return stream.native_update_volume();
 	}
 
 	@Override
-	public void setMuted(boolean value) {
-		muted = value;
+	public float getCachedVolume() {
+		return stream.getCachedVolume();
 	}
 
 	@Override
-	public float getVolume() {
-		return this.volume;
-	}
-
-	@Override
-	public void setVolume(float value) {
-		this.volume = value;
+	public void setCachedVolume(float value) {
+		stream.setCachedVolume(value);
 
 	}
 
@@ -536,12 +521,8 @@
 
 	@Override
 	public void start() {
-		if (!isOpen) {
-			throw new IllegalStateException("Line not open");
-		}
-
 		if (isStarted) {
-			throw new IllegalStateException("already started");
+			return;
 		}
 
 		super.start();
@@ -562,8 +543,9 @@
 			throw new IllegalStateException("Line not open");
 		}
 
+		/* do what start does and ignore if called at the wrong time */
 		if (!isStarted) {
-			throw new IllegalStateException("not started, so cant stop");
+			return;
 		}
 
 		if (clipThread.isAlive()) {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMuteControl.java	Tue Feb 10 21:09:31 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/* PulseAudioMuteControl.java
-   Copyright (C) 2008 Red Hat, Inc.
-
-This file is part of IcedTea.
-
-IcedTea is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 2.
-
-IcedTea is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with IcedTea; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version.
- */
-
-package org.classpath.icedtea.pulseaudio;
-
-import javax.sound.sampled.BooleanControl;
-
-final class PulseAudioMuteControl extends BooleanControl {
-
-	private PulseAudioVolumeControl volumeControl;
-	private PulseAudioPlaybackLine line;
-
-	protected PulseAudioMuteControl(PulseAudioPlaybackLine line,
-			PulseAudioVolumeControl volumeControl) {
-		super(BooleanControl.Type.MUTE, false, "Volume muted", "Volume on");
-		this.volumeControl = volumeControl;
-		this.line = line;
-	}
-
-	public synchronized void setValue(boolean value) {
-		if (!line.isOpen()) {
-			return;
-		}
-
-		if (value == true) {
-			line.setMuted(true);
-			volumeControl.setStreamVolume(0);
-		} else {
-			line.setMuted(false);
-			float newValue = volumeControl.getValue();
-			volumeControl.setStreamVolume(newValue);
-		}
-	}
-
-	public synchronized boolean getValue() {
-		return line.isMuted();
-	}
-
-}
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPlaybackLine.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPlaybackLine.java	Tue Feb 10 21:56:55 2009 +0000
@@ -37,18 +37,49 @@
 
 package org.classpath.icedtea.pulseaudio;
 
+/**
+ * Represents a Line that supports changing the volume
+ */
 interface PulseAudioPlaybackLine {
 
-	byte[] native_setVolume(float value);
-
-	boolean isMuted();
+	/**
+	 * Set the volume of the Line (ie, sink input, source, or sink)
+	 * 
+	 * @return an Operation object which can be used to check if the operation
+	 *         has completed
+	 */
+	byte[] native_set_volume(float value);
 
-	void setMuted(boolean mute);
+	/**
+	 * 
+	 * Update the volume information of a Line (sink input, source or sink)
+	 * 
+	 * @return an Operation object which can be used to check if the operation
+	 *         has been completed
+	 */
+	byte[] native_update_volume();
+	
+	
+	/**
+	 * Gets the cached volume. To get the current volume, call
+	 * native_update_volume, and then call this method to get the updated
+	 * volume.
+	 * 
+	 * @return the cached volume of the Line
+	 */
+	float getCachedVolume();
 
-	float getVolume();
+	/**
+	 * Set the cached value of a line
+	 * 
+	 */
+	void setCachedVolume(float volume);
 
-	void setVolume(float volume);
-
+	/**
+	 * Check if a line is open
+	 * 
+	 * @return <code>true</code> if line is open
+	 */
 	boolean isOpen();
 
 }
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java	Tue Feb 10 21:56:55 2009 +0000
@@ -57,10 +57,8 @@
 
 	private EventLoop eventLoop;
 
-	private float volume;
-	private boolean muted;
+	private float cachedVolume;
 
-	private PulseAudioMuteControl muteControl;
 	private PulseAudioVolumeControl volumeControl;
 
 	static {
@@ -76,72 +74,67 @@
 
 		volumeControl = new PulseAudioVolumeControl(this, eventLoop);
 		controls.add(volumeControl);
-		muteControl = new PulseAudioMuteControl(this, volumeControl);
-		controls.add(muteControl);
 
 		/*
 		 * unlike other lines, Ports must either be open or close
 		 * 
 		 * close = no sound. open = sound
-		 * 
 		 */
 		open();
 
 		// System.out.println("Opened Target Port " + name);
 	}
 
-	
 	// FIXME why public
 	@Override
-	public abstract byte[] native_setVolume(float newValue);
+	public abstract byte[] native_set_volume(float newValue);
 
+	/**
+	 * 
+	 * @see {@link update_channels_and_volume}
+	 */
 	// FIXME why public
-	public abstract byte[] native_updateVolumeInfo();
+	public abstract byte[] native_update_volume();
 
 	@Override
-	public boolean isMuted() {
-		return muted;
+	public float getCachedVolume() {
+		return this.cachedVolume;
 	}
 
 	@Override
-	public void setMuted(boolean value) {
-		muted = value;
-	}
-
-	@Override
-	public float getVolume() {
-
-		// FIXME need to query system for volume
-		return this.volume;
-	}
-
-	@Override
-	public void setVolume(float value) {
-		this.volume = value;
+	public void setCachedVolume(float value) {
+		this.cachedVolume = value;
 
 	}
 
-	// FIXME
-	public synchronized void updateVolumeInfo() {
+	private void updateVolumeInfo() {
 		Operation op;
 		synchronized (eventLoop.threadLock) {
-			op = new Operation(native_updateVolumeInfo());
+			op = new Operation(native_update_volume());
 		}
 
 		op.waitForCompletion();
 		op.releaseReference();
 	}
 
-	// FIXME
-	public void update_channels_and_volume(int channels, float volume) {
+	/**
+	 * Callback used by JNI when native_update_volume completes
+	 * 
+	 * @param channels
+	 *            the number of channels
+	 * @param cachedVolume
+	 *            the new volume
+	 */
+	@SuppressWarnings("unused")
+	void update_channels_and_volume(int channels, float volume) {
 		this.channels = channels;
-		this.volume = volume;
+		this.cachedVolume = volume;
 	}
 
 	@Override
 	public void close() {
 
-		native_setVolume((float) 0);
+		native_set_volume((float) 0);
 		isOpen = false;
 		fireLineEvent(new LineEvent(this, LineEvent.Type.CLOSE,
 				AudioSystem.NOT_SPECIFIED));
@@ -155,7 +148,7 @@
 		if (isOpen) {
 			return;
 		}
-		native_setVolume(volume);
+		native_set_volume(cachedVolume);
 		isOpen = true;
 		fireLineEvent(new LineEvent(this, LineEvent.Type.OPEN,
 				AudioSystem.NOT_SPECIFIED));
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Tue Feb 10 21:56:55 2009 +0000
@@ -51,10 +51,7 @@
 public final class PulseAudioSourceDataLine extends PulseAudioDataLine
 		implements SourceDataLine, PulseAudioPlaybackLine {
 
-	private PulseAudioMuteControl muteControl;
 	private PulseAudioVolumeControl volumeControl;
-	private boolean muted;
-	private float volume;
 
 	public static final String DEFAULT_SOURCEDATALINE_NAME = "Audio Stream";
 
@@ -67,7 +64,6 @@
 		this.lineListeners = new ArrayList<LineListener>();
 		this.defaultFormat = defaultFormat;
 		this.currentFormat = defaultFormat;
-		this.volume = PulseAudioVolumeControl.MAX_VOLUME;
 		this.streamName = DEFAULT_SOURCEDATALINE_NAME;
 
 	}
@@ -80,8 +76,6 @@
 
 		volumeControl = new PulseAudioVolumeControl(this, eventLoop);
 		controls.add(volumeControl);
-		muteControl = new PulseAudioMuteControl(this, volumeControl);
-		controls.add(muteControl);
 
 		PulseAudioMixer parentMixer = PulseAudioMixer.getInstance();
 		parentMixer.addSourceLine(this);
@@ -97,32 +91,26 @@
 	}
 
 	// FIXME
-	public byte[] native_setVolume(float value) {
+	public byte[] native_set_volume(float value) {
 		synchronized (eventLoop.threadLock) {
-			return stream.native_setVolume(value);
+			return stream.native_set_volume(value);
 		}
 	}
 
-	// FIXME
+	public byte[] native_update_volume() {
+		synchronized (eventLoop.threadLock) {
+			return stream.native_update_volume();
+		}
+	}
+	
 	@Override
-	public boolean isMuted() {
-		return muted;
+	public float getCachedVolume() {
+		return stream.getCachedVolume();
 	}
 
 	@Override
-	public void setMuted(boolean value) {
-		muted = value;
-	}
-
-	@Override
-	public float getVolume() {
-		return this.volume;
-	}
-
-	@Override
-	synchronized public void setVolume(float value) {
-		this.volume = value;
-
+	synchronized public void setCachedVolume(float value) {
+		stream.setCachedVolume(value);
 	}
 
 	@Override
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java	Tue Feb 10 21:56:55 2009 +0000
@@ -82,10 +82,10 @@
 	}
 
 	// FIXME
-	public native byte[] native_setVolume(float newValue);
+	public native byte[] native_set_volume(float newValue);
 
 	// FIXME
-	public synchronized native byte[] native_updateVolumeInfo();
+	public native byte[] native_update_volume();
 
 	@Override
 	public Line.Info getLineInfo() {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java	Tue Feb 10 21:56:55 2009 +0000
@@ -49,7 +49,6 @@
 	}
 
 	PulseAudioTargetPort(String name) {
-
 		super(name);
 	}
 
@@ -75,12 +74,11 @@
 		super.close();
 	}
 
-	
 	// FIXME
-	public native byte[] native_setVolume(float newValue);
+	public native byte[] native_set_volume(float newValue);
 
 	// FIXME
-	public synchronized native byte[] native_updateVolumeInfo();
+	public native byte[] native_update_volume();
 
 	@Override
 	public Line.Info getLineInfo() {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.java	Tue Feb 10 21:56:55 2009 +0000
@@ -46,8 +46,12 @@
 
 	protected PulseAudioVolumeControl(PulseAudioPlaybackLine line,
 			EventLoop eventLoop) {
+
+		/*
+		 * the initial volume is ignored by pulseaudio.
+		 */
 		super(FloatControl.Type.VOLUME, MIN_VOLUME, MAX_VOLUME, 1, -1, line
-				.getVolume(), "pulseaudio units", "Volume Off",
+				.getCachedVolume(), "pulseaudio units", "Volume Off",
 				"Default Volume", "Full Volume");
 		this.line = line;
 		this.eventLoop = eventLoop;
@@ -66,17 +70,15 @@
 			return;
 		}
 
-		if (!line.isMuted()) {
-			setStreamVolume(newValue);
-		}
+		setStreamVolume(newValue);
 
-		line.setVolume(newValue);
+		line.setCachedVolume(newValue);
 	}
 
 	protected synchronized void setStreamVolume(float newValue) {
 		Operation op;
 		synchronized (eventLoop.threadLock) {
-			op = new Operation(line.native_setVolume(newValue));
+			op = new Operation(line.native_set_volume(newValue));
 		}
 
 		op.waitForCompletion();
@@ -85,7 +87,15 @@
 	}
 
 	public synchronized float getValue() {
-		return line.getVolume();
+		Operation op;
+		synchronized (eventLoop.threadLock) {
+			op = new Operation(line.native_update_volume());
+		}
+
+		op.waitForCompletion();
+		op.releaseReference();
+
+		return line.getCachedVolume();
 	}
 
 }
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java	Tue Feb 10 21:56:55 2009 +0000
@@ -115,6 +115,7 @@
 	}
 
 	private Format format;
+	private float cachedVolume;
 
 	private List<StateListener> stateListeners;
 	private List<WriteListener> writeListeners;
@@ -222,7 +223,9 @@
 
 	private native byte[] native_pa_stream_update_sample_rate(int rate);
 
-	native byte[] native_setVolume(float newValue);
+	native byte[] native_set_volume(float newValue);
+
+	native byte[] native_update_volume();
 
 	/*
 	 * pa_operation pa_stream_proplist_update (pa_streams, pa_update_mode_t
@@ -777,4 +780,16 @@
 		native_pa_stream_unref();
 	}
 
+	float getCachedVolume() {
+		return this.cachedVolume;
+	}
+
+	void setCachedVolume(float volume) {
+		this.cachedVolume = volume;
+	}
+
+	void update_channels_and_volume(int channels, float volume) {
+		this.cachedVolume = volume;
+	}
+
 }
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Tue Feb 10 21:56:55 2009 +0000
@@ -295,69 +295,3 @@
 
 }
 
-static void sink_input_volume_change_complete(pa_context* contest, int success,
-		void* userdata) {
-	// userdata is the pointer to the int containing the new volume 
-
-	assert(userdata);
-	free(userdata);
-	assert(success);
-
-}
-
-static void sink_input_change_volume(pa_context* c,
-		const pa_sink_input_info* i, int eol, void* userdata) {
-	assert(c);
-
-	if (eol) {
-		return;
-	}
-
-	assert(i);
-	assert(userdata);
-	int volume = *((int*)userdata);
-
-	int j = 0;
-	//	printf("changing sink input volume\n");
-	pa_cvolume* new_volume = malloc(sizeof(pa_cvolume));
-
-	//	printf("allocated memory\n");
-	new_volume->channels = i->volume.channels;
-	//	printf("set the number of channels\n");
-	for (j = 0; j < new_volume->channels; j++) {
-		new_volume->values[j] = volume;
-	}
-
-	//	printf("calling set_sick_input_volume\n");
-	pa_operation* o = pa_context_set_sink_input_volume(c, i->index, new_volume,
-			sink_input_volume_change_complete, new_volume);
-	if (o != NULL) {
-		pa_operation_unref(o);
-	}
-
-	//	printf("done setup for changing volume\n");
-}
-
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_EventLoop
- * Method:    native_set_sink_volume
- * Signature: ([BI)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1set_1sink_1volume
-(JNIEnv* env, jobject obj, jbyteArray streamPointer, jint volume) {
-
-	pa_stream* stream = (pa_stream*) convertJavaPointerToNative(env, streamPointer);
-	assert(stream);
-	pa_context* context = (pa_context*) getJavaPointer(env, obj, "contextPointer");
-	assert(context);
-
-	int* new_volume = malloc(sizeof(int));
-	*new_volume = volume;
-
-	int stream_id = pa_stream_get_index(stream);
-	pa_operation* o = pa_context_get_sink_input_info(context, stream_id,sink_input_change_volume, new_volume);
-	pa_operation_unref(o);
-	return;
-}
-
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioSourcePort.c	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioSourcePort.c	Tue Feb 10 21:56:55 2009 +0000
@@ -22,7 +22,7 @@
 	assert(pulse_thread_env);
 	
 	if (eol == 0) {
-		// printf("%s\n", i->name); 
+		// printf("%s\n", i->name);
 		jobject obj = (jobject) userdata;
 		assert(obj);
 		jclass cls = (*pulse_thread_env)->GetObjectClass(pulse_thread_env, obj);
@@ -39,10 +39,10 @@
 
 /*
  * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourcePort
- * Method:    native_updateVolumeInfo
+ * Method:    native_update_volume
  * Signature: ()[B
  */
-JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1updateVolumeInfo
+JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1update_1volume
 (JNIEnv *env, jobject obj) {
 	jclass cls = (*env)->GetObjectClass(env, obj);
 	assert(cls);
@@ -65,10 +65,10 @@
 
 /*
  * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourcePort
- * Method:    native_setVolume
+ * Method:    native_set_volume
  * Signature: (F)[B
  */
-JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1setVolume
+JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourcePort_native_1set_1volume
 (JNIEnv *env, jobject obj, jfloat value) {
 	jclass cls = (*env)->GetObjectClass(env, obj);
 	assert(cls);
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioTargetPort.c	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_PulseAudioTargetPort.c	Tue Feb 10 21:56:55 2009 +0000
@@ -11,17 +11,17 @@
 
 extern JNIEnv* pulse_thread_env;
 
-void sink_callback(pa_context *context, int success, void *userdata) {
+static void sink_callback(pa_context *context, int success, void *userdata) {
 	notifyWaitingOperations(pulse_thread_env);
 }
 
-void get_sink_volume_callback(pa_context *context, const pa_sink_info *i,
+static void get_sink_volume_callback(pa_context *context, const pa_sink_info *i,
 		int eol, void *userdata) {
 	assert(context);
 	assert(pulse_thread_env);
 
 	if (eol == 0) {
-		// printf("%s\n", i->name); 
+		// printf("%s\n", i->name);
 		jobject obj = (jobject) userdata;
 		assert(obj);
 		jclass cls = (*pulse_thread_env)->GetObjectClass(pulse_thread_env, obj);
@@ -40,10 +40,10 @@
 
 /*
  * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetPort
- * Method:    native_updateVolumeInfo
+ * Method:    native_update_volume
  * Signature: ()[B
  */
-JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1updateVolumeInfo
+JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1update_1volume
 (JNIEnv *env, jobject obj) {
 	jclass cls = (*env)->GetObjectClass(env, obj);
 	assert(cls);
@@ -72,10 +72,10 @@
 
 /*
  * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetPort
- * Method:    native_setVolume
+ * Method:    native_set_volume
  * Signature: (F)[B
  */
-JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1setVolume
+JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetPort_native_1set_1volume
 (JNIEnv *env, jobject obj, jfloat value) {
 	jclass cls = (*env)->GetObjectClass(env, obj);
 	assert(cls);
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c	Tue Feb 10 21:56:55 2009 +0000
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #define STREAM_POINTER "streamPointer"
+#define CONTEXT_POINTER "contextPointer"
 
 typedef struct java_context {
 	JNIEnv* env;
@@ -297,10 +298,10 @@
 	setJavaPointer(env, obj, "streamPointer", stream);
 
 	/*
-	 * 
-	 * The stream has been created; now setup the callbacks 
+	 *
+	 * The stream has been created; now setup the callbacks
 	 * so we can do somethig about them
-	 * 
+	 *
 	 */
 
 	pa_stream_set_state_callback (stream, stream_state_callback, j_context);
@@ -966,12 +967,12 @@
 
 /*
  * Class:     org_classpath_icedtea_pulseaudio_Stream
- * Method:    native_setVolume
+ * Method:    native_set_volume
  * Signature: (F)[B
  */
-JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_native_1setVolume
+JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_native_1set_1volume
 (JNIEnv *env, jobject obj, jfloat new_volume) {
-	
+
 	pa_stream *stream = getJavaPointer(env, obj, STREAM_POINTER);
 	assert(stream);
 	pa_context *context = pa_stream_get_context(stream);
@@ -988,6 +989,55 @@
 
 }
 
+
+static void get_sink_input_volume_callback(pa_context *context, const pa_sink_input_info *i,
+		int eol, void *userdata) {
+
+	JNIEnv* env = pulse_thread_env;
+
+	assert(context);
+	assert(env);
+	jobject obj = (jobject) userdata;
+	assert(obj);
+
+	if (eol == 0) {
+		jclass cls = (*pulse_thread_env)->GetObjectClass(pulse_thread_env, obj);
+		assert(cls);
+		jmethodID mid1 = (*pulse_thread_env)->GetMethodID(pulse_thread_env, cls,
+				"update_channels_and_volume", "(IF)V");
+		assert(mid1);
+		(*pulse_thread_env)->CallVoidMethod(pulse_thread_env, obj, mid1,
+				(int) (i->volume).channels, (float) (i->volume).values[0]) ;
+	} else {
+		notifyWaitingOperations(pulse_thread_env);
+		(*env)->DeleteGlobalRef(env, obj);
+	}
+}
+
+/*
+ * Class:     org_classpath_icedtea_pulseaudio_Stream
+ * Method:    native_update_volume
+ * Signature: ()[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_native_1update_1volume
+(JNIEnv* env, jobject obj) {
+
+	pa_stream* stream = getJavaPointer(env, obj, STREAM_POINTER);
+	assert(stream);
+
+	int sink_input_index = pa_stream_get_index(stream);
+
+	pa_context* context = pa_stream_get_context(stream);
+	assert(context);
+
+	obj = (*env)->NewGlobalRef(env, obj);
+	pa_operation *o = pa_context_get_sink_input_info(context, sink_input_index , get_sink_input_volume_callback, obj);
+	assert(o);
+	return convertNativePointerToJava(env, o);
+
+
+}
+
 JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_bytesInBuffer(JNIEnv *env, jobject obj) {
 	pa_stream *stream = getJavaPointer(env, obj, STREAM_POINTER);
 	assert(stream);
@@ -1000,7 +1050,7 @@
 JNIEXPORT jbyteArray JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1updateTimingInfo(JNIEnv* env, jobject obj) {
 	pa_stream *stream = getJavaPointer(env, obj, STREAM_POINTER);
 	assert(stream);
-	pa_operation* o = pa_stream_update_timing_info(stream, update_timing_info_callback, NULL); 
+	pa_operation* o = pa_stream_update_timing_info(stream, update_timing_info_callback, NULL);
 	assert(o);
 	return convertNativePointerToJava(env, o);
 
--- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java	Tue Feb 10 21:56:55 2009 +0000
@@ -447,7 +447,7 @@
 
 		Control[] controls = clip.getControls();
 		Assert.assertNotNull(controls);
-		Assert.assertTrue(controls.length >= 2);
+		Assert.assertTrue(controls.length >= 1);
 		for (Control control : controls) {
 			Assert.assertNotNull(control);
 		}
--- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineRawTest.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineRawTest.java	Tue Feb 10 21:56:55 2009 +0000
@@ -43,7 +43,6 @@
 import javax.sound.sampled.AudioFormat;
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
-import javax.sound.sampled.BooleanControl;
 import javax.sound.sampled.DataLine;
 import javax.sound.sampled.FloatControl;
 import javax.sound.sampled.Line;
@@ -195,7 +194,7 @@
 	}
 
 	@Test
-	public void testVolumeAndMute() throws Exception {
+	public void testVolume() throws Exception {
 
 		Mixer selectedMixer = mixer;
 		SourceDataLine line = (SourceDataLine) selectedMixer
@@ -211,14 +210,9 @@
 		line.start();
 		PulseAudioVolumeControl volume = (PulseAudioVolumeControl) line
 				.getControl(FloatControl.Type.VOLUME);
-		PulseAudioMuteControl mute = (PulseAudioMuteControl) line
-				.getControl(BooleanControl.Type.MUTE);
 
-		mute.setValue(true);
 		volume.setValue(PulseAudioVolumeControl.MAX_VOLUME);
 
-		mute.setValue(false);
-
 		byte[] abData = new byte[1000];
 		int bytesRead = 0;
 
--- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java	Tue Feb 10 21:56:55 2009 +0000
@@ -287,6 +287,7 @@
 		sourceDataLine.write(buffer, 1, buffer.length);
 	}
 
+	// FIXME
 	@Test
 	public void testWriteWithoutStart() throws UnsupportedAudioFileException,
 			IOException, LineUnavailableException, InterruptedException {
@@ -805,13 +806,11 @@
 		sourceDataLine.open();
 		Assert.assertTrue(sourceDataLine
 				.isControlSupported(FloatControl.Type.VOLUME));
-		Assert.assertTrue(sourceDataLine
-				.isControlSupported(BooleanControl.Type.MUTE));
 		sourceDataLine.close();
 	}
 
 	@Test
-	public void testVolumeAndMute() throws Exception {
+	public void testVolume() throws Exception {
 
 		Mixer selectedMixer = mixer;
 		sourceDataLine = (SourceDataLine) selectedMixer.getLine(new Line.Info(
@@ -827,14 +826,9 @@
 		sourceDataLine.start();
 		FloatControl volume = (FloatControl) sourceDataLine
 				.getControl(FloatControl.Type.VOLUME);
-		BooleanControl mute = (BooleanControl) sourceDataLine
-				.getControl(BooleanControl.Type.MUTE);
 
-		mute.setValue(true);
 		volume.setValue(volume.getMaximum());
 
-		mute.setValue(false);
-
 		byte[] abData = new byte[1000];
 		int bytesRead = 0;
 
--- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourcePortTest.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourcePortTest.java	Tue Feb 10 21:56:55 2009 +0000
@@ -40,7 +40,6 @@
 import static org.junit.Assert.assertNotNull;
 
 import javax.sound.sampled.AudioSystem;
-import javax.sound.sampled.BooleanControl;
 import javax.sound.sampled.FloatControl;
 import javax.sound.sampled.Line;
 import javax.sound.sampled.LineUnavailableException;
@@ -103,10 +102,6 @@
 				FloatControl volumeControl = (FloatControl) port
 						.getControl(FloatControl.Type.VOLUME);
 				volumeControl.setValue(60000);
-				BooleanControl muteControl = (BooleanControl) port
-						.getControl(BooleanControl.Type.MUTE);
-				muteControl.setValue(true);
-				muteControl.setValue(false);
 				port.close();
 			}
 		}
--- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetPortTest.java	Tue Feb 10 21:09:31 2009 +0000
+++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetPortTest.java	Tue Feb 10 21:56:55 2009 +0000
@@ -40,7 +40,6 @@
 import static org.junit.Assert.assertNotNull;
 
 import javax.sound.sampled.AudioSystem;
-import javax.sound.sampled.BooleanControl;
 import javax.sound.sampled.FloatControl;
 import javax.sound.sampled.Line;
 import javax.sound.sampled.LineUnavailableException;
@@ -103,10 +102,6 @@
 				FloatControl volumeControl = (FloatControl) port
 						.getControl(FloatControl.Type.VOLUME);
 				volumeControl.setValue(60000);
-				BooleanControl muteControl = (BooleanControl) port
-						.getControl(BooleanControl.Type.MUTE);
-				muteControl.setValue(true);
-				muteControl.setValue(false);
 				port.close();
 			}
 		}
--- a/visualvm.desktop	Tue Feb 10 21:09:31 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-[Desktop Entry]
-Name=OpenJDK VisualVM
-Comment=Integrates commandline JDK tools and profiling capabilites.
-Exec=/usr/bin/jvisualvm
-Icon=java
-Terminal=false
-Type=Application
-Categories=Development;Java;
-Version=1.0