changeset 771:f62d24530d08

getLocalAddress/getRemoteAddress not consistent with other methods when channel is closed Misc. fixes to AsynchronousDatagramChannel spec
author alanb
date Mon, 20 Oct 2008 20:26:27 +0100
parents 2b9ea59279b9
children 84214f4a00a6
files src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java src/share/classes/java/nio/channels/AsynchronousSocketChannel.java src/share/classes/java/nio/channels/DatagramChannel.java src/share/classes/java/nio/channels/NetworkChannel.java src/share/classes/java/nio/channels/SocketChannel.java src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java src/share/classes/sun/nio/ch/DatagramChannelImpl.java src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java src/share/classes/sun/nio/ch/SocketChannelImpl.java src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java test/java/nio/channels/etc/NetworkChannelTests.java
diffstat 13 files changed, 80 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Mon Oct 20 20:26:27 2008 +0100
@@ -241,9 +241,11 @@
      * then the return value from this method is of type {@link
      * java.net.InetSocketAddress}.
      *
-     * @return  The remote address; {@code null} if the channel is not {@link
-     *          #isOpen open} or the channel's socket is not 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
      */
@@ -267,9 +269,9 @@
      * datagrams to be received from and sent to, respectively, the given
      * remote address.
      *
-     * <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>
+     * <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
@@ -300,8 +302,9 @@
      * on read or write operations that are already in progress at the moment
      * that it is invoked.
      *
-     * <p> If this channel's socket is not connected, or if the channel is
-     * closed, then invoking this method has no effect.  </p>
+     * <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
      *
@@ -352,6 +355,8 @@
      *
      * @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,
@@ -382,6 +387,8 @@
      *
      * @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,
@@ -463,6 +470,8 @@
      * @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,
@@ -506,6 +515,8 @@
      * @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,
@@ -589,6 +600,8 @@
      *          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,
@@ -599,6 +612,8 @@
     /**
      * @throws  NotYetConnectedException
      *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
      */
     @Override
     public final <A> Future<Integer> read(ByteBuffer dst,
@@ -656,6 +671,8 @@
      *          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,
@@ -665,6 +682,8 @@
     /**
      * @throws  NotYetConnectedException
      *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
      */
     @Override
     public final <A> Future<Integer> write(ByteBuffer src,
--- a/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java	Mon Oct 20 20:26:27 2008 +0100
@@ -259,9 +259,11 @@
      * 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 is not {@link
-     *          #isOpen open} or the channel's socket is not 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
      */
--- a/src/share/classes/java/nio/channels/DatagramChannel.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/java/nio/channels/DatagramChannel.java	Mon Oct 20 20:26:27 2008 +0100
@@ -320,9 +320,11 @@
      * {@note new}
      * Returns the remote address to which this channel's socket is connected.
      *
-     * @return  The remote address; {@code null} if the channel is not {@link
-     *          #isOpen open} or the channel's socket is not 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
      *
--- a/src/share/classes/java/nio/channels/NetworkChannel.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/java/nio/channels/NetworkChannel.java	Mon Oct 20 20:26:27 2008 +0100
@@ -95,9 +95,10 @@
      * java.net.InetSocketAddress}.
      *
      * @return  The socket address that the socket is bound to, or {@code null}
-     *          if the channel is not {@link #isOpen open} or the channel's socket
-     *          is not bound
+     *          if the channel's socket is not bound
      *
+     * @throws  ClosedChannelException
+     *          If the channel is closed
      * @throws  IOException
      *          If an I/O error occurs
      */
--- a/src/share/classes/java/nio/channels/SocketChannel.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/java/nio/channels/SocketChannel.java	Mon Oct 20 20:26:27 2008 +0100
@@ -436,9 +436,11 @@
      * 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 is not {@link
-     *          #isOpen open} or the channel's socket is not 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
      *
--- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -26,7 +26,6 @@
 package sun.nio.ch;
 
 import java.nio.channels.*;
-import java.net.SocketOption;
 import java.net.SocketAddress;
 import java.net.SocketOption;
 import java.net.StandardSocketOption;
@@ -50,7 +49,7 @@
     protected final FileDescriptor fd;
 
     // the local address to which the channel's socket is bound
-    private volatile SocketAddress localAddress = null;
+    protected volatile SocketAddress localAddress = null;
 
     // need this lock to set local address
     private final Object stateLock = new Object();
@@ -143,8 +142,10 @@
     }
 
     @Override
-    public final SocketAddress getLocalAddress() {
-        return isOpen() ? localAddress : null;
+    public final SocketAddress getLocalAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return localAddress;
     }
 
     @Override
@@ -206,11 +207,10 @@
         if (!isOpen())
             sb.append("closed");
         else {
-            SocketAddress local = getLocalAddress();
-            if (local == null) {
+            if (localAddress == null) {
                 sb.append("unbound");
             } else {
-                sb.append(local.toString());
+                sb.append(localAddress.toString());
             }
         }
         sb.append(']');
--- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -314,9 +314,8 @@
                 if (writeShutdown) {
                     closed = true;
                 } else {
-                    if (hasDataToWrite) {
+                    if (hasDataToWrite)
                         writing = true;
-                    }
                 }
             }
         } else {
@@ -396,8 +395,10 @@
     }
 
     @Override
-    public final SocketAddress getLocalAddress() {
-        return (isOpen()) ? localAddress : null;
+    public final SocketAddress getLocalAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return localAddress;
     }
 
     @Override
@@ -455,8 +456,10 @@
 
     @Override
     @SuppressWarnings("unchecked")
-    public final SocketAddress getRemoteAddress() {
-        return (isOpen()) ? remoteAddress : null;
+    public final SocketAddress getRemoteAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return remoteAddress;
     }
 
     @Override
@@ -500,10 +503,10 @@
         StringBuffer sb = new StringBuffer();
         sb.append(this.getClass().getSuperclass().getName());
         sb.append('[');
-        if (!isOpen())
-            sb.append("closed");
-        else {
-            synchronized (stateLock) {
+        synchronized (stateLock) {
+            if (!isOpen()) {
+                sb.append("closed");
+            } else {
                 switch (state) {
                 case ST_UNCONNECTED:
                     sb.append("unconnected");
@@ -519,15 +522,13 @@
                         sb.append(" oshut");
                     break;
                 }
-                SocketAddress local = getLocalAddress();
-                if (local != null) {
+                if (localAddress != null) {
                     sb.append(" local=");
-                    sb.append(local.toString());
+                    sb.append(localAddress.toString());
                 }
-                SocketAddress remote = getRemoteAddress();
-                if (remote != null) {
+                if (remoteAddress != null) {
                     sb.append(" remote=");
-                    sb.append(remote.toString());
+                    sb.append(remoteAddress.toString());
                 }
             }
         }
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -153,7 +153,7 @@
     public SocketAddress getLocalAddress() throws IOException {
         synchronized (stateLock) {
             if (!isOpen())
-                return null;
+                throw new ClosedChannelException();
             return localAddress;
         }
     }
@@ -162,7 +162,7 @@
     public SocketAddress getRemoteAddress() throws IOException {
         synchronized (stateLock) {
             if (!isOpen())
-                return null;
+                throw new ClosedChannelException();
             return remoteAddress;
         }
     }
--- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -27,12 +27,9 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.lang.reflect.*;
 import java.net.*;
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.*;
 
 
@@ -111,7 +108,7 @@
     public SocketAddress getLocalAddress() throws IOException {
         synchronized (stateLock) {
             if (!isOpen())
-                return null;
+                throw new ClosedChannelException();
             return localAddress;
         }
     }
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -128,7 +128,7 @@
     public SocketAddress getLocalAddress() throws IOException {
         synchronized (stateLock) {
             if (!isOpen())
-                return null;
+                throw new ClosedChannelException();
             return localAddress;
         }
     }
@@ -137,7 +137,7 @@
     public SocketAddress getRemoteAddress() throws IOException {
         synchronized (stateLock) {
             if (!isOpen())
-                return null;
+                throw new ClosedChannelException();
             return remoteAddress;
         }
     }
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -235,7 +235,7 @@
             Invoker.invokeIndirectly(handler, result);
             return result;
         }
-        if (getLocalAddress() == null)
+        if (localAddress == null)
             throw new NotYetBoundException();
 
         // cancel was invoked with pending accept so connection may have been
--- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Mon Oct 20 20:26:27 2008 +0100
@@ -301,7 +301,7 @@
             throw new RuntimeException("Accept not allowed due to cancellation");
 
         // ensure channel is bound to local address
-        if (getLocalAddress() == null)
+        if (localAddress == null)
             throw new NotYetBoundException();
 
         // create the socket that will be accepted. The creation of the socket
--- a/test/java/nio/channels/etc/NetworkChannelTests.java	Mon Oct 20 19:22:05 2008 +0100
+++ b/test/java/nio/channels/etc/NetworkChannelTests.java	Mon Oct 20 20:26:27 2008 +0100
@@ -103,9 +103,10 @@
 
         // closed
         ch.close();
-        if (ch.getLocalAddress() != null) {
-            throw new RuntimeException("Local address return when closed");
-        }
+        try {
+            ch.getLocalAddress();
+            throw new RuntimeException("ClosedChannelException expected");
+        } catch (ClosedChannelException e) { }
     }
 
     /**
@@ -132,8 +133,10 @@
 
         // closed
         sc.close();
-        if (sc.getRemoteAddress() != null)
-            throw new RuntimeException("getRemoteAddress returned address when closed");
+        try {
+            sc.getRemoteAddress();
+            throw new RuntimeException("ClosedChannelException expected");
+        } catch (ClosedChannelException e) { }
 
         ssc.close();
     }