changeset 1576:913512a256bd

Fix UNIX sun.nio.ch and shared sun.nio.fs classes. 2009-01-19 Andrew John Hughes <gnu_andrew@member.fsf.org> * 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.
author Andrew John Hughes <gnu_andrew@member.fsf.org>
date Tue, 20 Jan 2009 00:06:18 +0000
parents fb3c68368b7f
children 721c79ccc804
files ChangeLog overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.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/SimpleAsynchronousFileChannelImpl.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/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/FileOwnerAttributeViewImpl.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/UnixAsynchronousServerSocketChannelImpl.java overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java patches/icedtea-nio2.patch
diffstat 19 files changed, 1133 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jan 19 14:25:02 2009 +0000
+++ b/ChangeLog	Tue Jan 20 00:06:18 2009 +0000
@@ -1,3 +1,79 @@
+2009-01-19  Andrew John Hughes  <gnu_andrew@member.fsf.org>
+
+	* 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  <gnu_andrew@member.fsf.org>
 
 	* generated/sun/nio/ch/SocketOptionRegistry.java:
--- a/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/misc/JavaNetGetIndexAccess.java	Tue Jan 20 00:06:18 2009 +0000
@@ -42,4 +42,5 @@
 public interface JavaNetGetIndexAccess
 {
   int getIndex(NetworkInterface nf);
+  NetworkInterface getByIndex(int i);
 }
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,11 +25,11 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.*;
 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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java	Tue Jan 20 00:06:18 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 Jan 20 00:06:18 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();
+                }
+            }
+        }
+    }
+}
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,14 +25,22 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.*;
 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.
@@ -60,7 +68,7 @@
     }
 
     // Used to make native read and write calls
-    private static final FileDispatcher nd = new FileDispatcherImpl();
+    private static final FileDispatcher nd = new FileDispatcher();
 
     // Thread-safe set of IDs of native threads, for signalling
     private final NativeThreadSet threads = new NativeThreadSet(2);
@@ -209,7 +217,7 @@
             throw new NonWritableChannelException();
 
         // add to lock table
-        final FileLockImpl fli = addToFileLockTable(position, size, shared);
+        final AsynchronousFileLockImpl fli = addToFileLockTable(position, size, shared);
         if (fli == null) {
             CompletedFuture<FileLock,A> result = CompletedFuture
                 .withFailure(this, new ClosedChannelException(), attachment);
@@ -270,7 +278,7 @@
             throw new NonWritableChannelException();
 
         // add to lock table
-        FileLockImpl fli = addToFileLockTable(position, size, shared);
+        AsynchronousFileLockImpl fli = addToFileLockTable(position, size, shared);
         if (fli == null)
             throw new ClosedChannelException();
 
@@ -301,7 +309,7 @@
     }
 
 
-    void release(FileLockImpl fli) throws IOException {
+    void release(AsynchronousFileLockImpl fli) throws IOException {
         try {
             begin();
             nd.release(fdObj, fli.position(), fli.size());
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java	Tue Jan 20 00:06:18 2009 +0000
@@ -28,6 +28,7 @@
 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;
 
@@ -72,7 +73,7 @@
     }
 
 
-    public final Map<String,?> readAttributes(String first, String[] rest)
+    public final Map<String,?> readAttributes(String first, String... rest)
         throws IOException
     {
         boolean acl = false;
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java	Tue Jan 20 00:06:18 2009 +0000
@@ -200,7 +200,7 @@
     }
 
 
-    public Map<String,?> readAttributes(String first, String[] rest)
+    public Map<String,?> readAttributes(String first, String... rest)
         throws IOException
     {
         AttributesBuilder builder = AttributesBuilder.create(first, rest);
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java	Tue Jan 20 00:06:18 2009 +0000
@@ -69,7 +69,7 @@
     }
 
 
-    public final Map<String,?> readAttributes(String first, String[] rest)
+    public final Map<String,?> readAttributes(String first, String... rest)
         throws IOException
     {
         boolean total = false;
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,12 +25,18 @@
 
 package sun.nio.fs;
 
-import java.nio.file.*;
 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
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java	Tue Jan 20 00:06:18 2009 +0000
@@ -27,6 +27,7 @@
 
 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;
 
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java	Tue Jan 20 00:06:18 2009 +0000
@@ -28,6 +28,9 @@
 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;
 
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java	Tue Jan 20 00:06:18 2009 +0000
@@ -28,7 +28,11 @@
 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
@@ -75,7 +79,7 @@
     }
 
 
-    public Map<String,?> readAttributes(String first, String[] rest) throws IOException {
+    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());
--- a/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,13 +25,14 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.spi.AsynchronousChannelProvider;
 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.
  */
--- a/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,12 +25,17 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.*;
 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
--- a/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/Port.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/Port.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,16 +25,19 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.spi.AsynchronousChannelProvider;
-import java.nio.channels.*;
 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.
  */
--- a/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,17 +25,23 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.*;
 import java.util.concurrent.*;
 import java.io.IOException;
 import java.io.FileDescriptor;
 import java.net.InetSocketAddress;
+import java.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
  */
--- a/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Mon Jan 19 14:25:02 2009 +0000
+++ b/overlays/nio2/openjdk/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Tue Jan 20 00:06:18 2009 +0000
@@ -25,8 +25,11 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.*;
 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;
@@ -35,6 +38,10 @@
 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
  */
--- a/patches/icedtea-nio2.patch	Mon Jan 19 14:25:02 2009 +0000
+++ b/patches/icedtea-nio2.patch	Tue Jan 20 00:06:18 2009 +0000
@@ -52,8 +52,8 @@
  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-16 19:47:40.000000000 +0000
-@@ -75,7 +75,6 @@
++++ 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 \
@@ -61,7 +61,14 @@
  	sun/nio/ch/FileKey.java \
  	sun/nio/ch/Interruptible.java \
  	sun/nio/ch/IOUtil.java \
-@@ -100,6 +99,7 @@
+ 	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 \
@@ -69,7 +76,7 @@
  	sun/nio/ch/SocketOpts.java \
  	sun/nio/ch/SocketOptsImpl.java \
          sun/nio/ch/SourceChannelImpl.java \
-@@ -144,7 +144,150 @@
+@@ -144,7 +146,150 @@
  	java/lang/StringCoding.java \
  	\
  	sun/misc/Cleaner.java \
@@ -221,7 +228,7 @@
  
  # Generated coder classes
  #
-@@ -263,10 +406,20 @@
+@@ -263,10 +408,20 @@
  	\
  	java/nio/charset/CharacterCodingException.java \
  	java/nio/charset/IllegalCharsetNameException.java \
@@ -807,8 +814,8 @@
  
 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-16 04:08:41.000000000 +0000
-@@ -529,4 +529,14 @@
++++ 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();
  
@@ -818,6 +825,7 @@
 +	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); }
 +            }
 +        );            									    
 +    }
@@ -850,10 +858,59 @@
 +    }
 +
  }
+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 13:34:41.000000000 +0000
-@@ -29,10 +29,27 @@
++++ 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;
@@ -876,6 +933,7 @@
 +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;
 +
@@ -883,7 +941,7 @@
  
  /**
   * An implementation of DatagramChannels.
-@@ -53,6 +70,9 @@
+@@ -53,6 +71,9 @@
      // even after the value in the file descriptor object has been set to -1
      int fdVal;
  
@@ -893,7 +951,17 @@
      // IDs of native threads doing reads and writes, for signalling
      private volatile long readerThread = 0;
      private volatile long writerThread = 0;
-@@ -98,15 +118,40 @@
+@@ -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);
@@ -934,7 +1002,24 @@
          this.fd = fd;
          this.fdVal = IOUtil.fdVal(fd);
          this.state = ST_UNCONNECTED;
-@@ -704,4 +749,86 @@
+@@ -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();
      }
  
@@ -946,6 +1031,14 @@
 +        }
 +    }
 +
++    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
 +    {
@@ -999,6 +1092,61 @@
 +        }
 +    }
 +
++    @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();
 +
@@ -1020,10 +1168,211 @@
 +        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/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-01-19 13:37:55.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/nio/ch/Net.java	2009-01-19 23:21:37.000000000 +0000
 @@ -30,6 +30,15 @@
  import java.net.*;
  import java.nio.channels.*;
@@ -1068,7 +1417,7 @@
  
      static native void bind(FileDescriptor fd, InetAddress addr, int port)
          throws IOException;
-@@ -179,4 +196,164 @@
+@@ -179,4 +196,314 @@
          initIDs();
      }
  
@@ -1182,6 +1531,10 @@
 +
 +    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.
@@ -1216,6 +1569,47 @@
 +        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;
@@ -1232,6 +1626,111 @@
 +        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
@@ -1292,6 +1791,69 @@
  
      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
@@ -1305,3 +1867,65 @@
  
  class InheritedChannel {
  
+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;
+ }