src/java.base/share/classes/java/net/ServerSocket.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 57382 14e01d39c01a
child 58679 9c3209ff7550
--- a/src/java.base/share/classes/java/net/ServerSocket.java	Thu Oct 17 20:27:44 2019 +0100
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Thu Oct 17 20:53:35 2019 +0100
@@ -27,17 +27,12 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.nio.channels.ServerSocketChannel;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
 import java.util.Objects;
 import java.util.Set;
 import java.util.Collections;
 
-import jdk.internal.access.JavaNetSocketAccess;
-import jdk.internal.access.SharedSecrets;
+import sun.security.util.SecurityConstants;
 import sun.net.PlatformSocketImpl;
 
 /**
@@ -79,17 +74,29 @@
      *
      * @throws     NullPointerException if impl is {@code null}.
      *
+     * @throws     SecurityException if a security manager is set and
+     *             its {@code checkPermission} method doesn't allow
+     *             {@code NetPermission("setSocketImpl")}.
      * @since 12
      */
     protected ServerSocket(SocketImpl impl) {
         Objects.requireNonNull(impl);
+        checkPermission();
         this.impl = impl;
     }
 
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
+        }
+        return null;
+    }
+
     /**
      * Creates an unbound server socket.
      *
-     * @exception IOException IO error when opening the socket.
+     * @throws    IOException IO error when opening the socket.
      * @revised 1.4
      */
     public ServerSocket() throws IOException {
@@ -106,9 +113,10 @@
      * request to connect) is set to {@code 50}. If a connection
      * indication arrives when the queue is full, the connection is refused.
      * <p>
-     * If the application has specified a server socket factory, that
-     * factory's {@code createSocketImpl} method is called to create
-     * the actual socket implementation. Otherwise a "plain" socket is created.
+     * If the application has specified a server socket implementation
+     * factory, that factory's {@code createSocketImpl} method is called to
+     * create the actual socket implementation. Otherwise a system-default
+     * socket implementation is created.
      * <p>
      * If there is a security manager,
      * its {@code checkListen} method is called
@@ -120,11 +128,11 @@
      * @param      port  the port number, or {@code 0} to use a port
      *                   number that is automatically allocated.
      *
-     * @exception  IOException  if an I/O error occurs when opening the socket.
-     * @exception  SecurityException
+     * @throws     IOException  if an I/O error occurs when opening the socket.
+     * @throws     SecurityException
      * if a security manager exists and its {@code checkListen}
      * method doesn't allow the operation.
-     * @exception  IllegalArgumentException if the port parameter is outside
+     * @throws     IllegalArgumentException if the port parameter is outside
      *             the specified range of valid port values, which is between
      *             0 and 65535, inclusive.
      *
@@ -150,9 +158,10 @@
      * a connection indication arrives when the queue is full, the
      * connection is refused.
      * <p>
-     * If the application has specified a server socket factory, that
-     * factory's {@code createSocketImpl} method is called to create
-     * the actual socket implementation. Otherwise a "plain" socket is created.
+     * If the application has specified a server socket implementation
+     * factory, that factory's {@code createSocketImpl} method is called to
+     * create the actual socket implementation. Otherwise a system-default
+     * socket implementation is created.
      * <p>
      * If there is a security manager,
      * its {@code checkListen} method is called
@@ -172,11 +181,11 @@
      * @param      backlog  requested maximum length of the queue of incoming
      *                      connections.
      *
-     * @exception  IOException  if an I/O error occurs when opening the socket.
-     * @exception  SecurityException
+     * @throws     IOException  if an I/O error occurs when opening the socket.
+     * @throws     SecurityException
      * if a security manager exists and its {@code checkListen}
      * method doesn't allow the operation.
-     * @exception  IllegalArgumentException if the port parameter is outside
+     * @throws     IllegalArgumentException if the port parameter is outside
      *             the specified range of valid port values, which is between
      *             0 and 65535, inclusive.
      *
@@ -225,7 +234,7 @@
      * its {@code checkListen} method doesn't allow the operation.
      *
      * @throws  IOException if an I/O error occurs when opening the socket.
-     * @exception  IllegalArgumentException if the port parameter is outside
+     * @throws     IllegalArgumentException if the port parameter is outside
      *             the specified range of valid port values, which is between
      *             0 and 65535, inclusive.
      *
@@ -472,13 +481,19 @@
      * as its arguments to ensure the operation is allowed.
      * This could result in a SecurityException.
      *
-     * @exception  IOException  if an I/O error occurs when waiting for a
+     * @implNote
+     * An instance of this class using a system-default {@code SocketImpl}
+     * accepts sockets with a {@code SocketImpl} of the same type, regardless
+     * of the {@linkplain Socket#setSocketImplFactory(SocketImplFactory)
+     * client socket implementation factory}, if one has been set.
+     *
+     * @throws     IOException  if an I/O error occurs when waiting for a
      *               connection.
-     * @exception  SecurityException  if a security manager exists and its
+     * @throws     SecurityException  if a security manager exists and its
      *             {@code checkAccept} method doesn't allow the operation.
-     * @exception  SocketTimeoutException if a timeout was previously set with setSoTimeout and
+     * @throws     SocketTimeoutException if a timeout was previously set with setSoTimeout and
      *             the timeout has been reached.
-     * @exception  java.nio.channels.IllegalBlockingModeException
+     * @throws     java.nio.channels.IllegalBlockingModeException
      *             if this socket has an associated channel, the channel is in
      *             non-blocking mode, and there is no connection ready to be
      *             accepted
@@ -501,15 +516,33 @@
     /**
      * Subclasses of ServerSocket use this method to override accept()
      * to return their own subclass of socket.  So a FooServerSocket
-     * will typically hand this method an <i>empty</i> FooSocket.  On
-     * return from implAccept the FooSocket will be connected to a client.
+     * will typically hand this method a newly created, unbound, FooSocket.
+     * On return from implAccept the FooSocket will be connected to a client.
+     *
+     * <p> The behavior of this method is unspecified when invoked with a
+     * socket that is not newly created and unbound. Any socket options set
+     * on the given socket prior to invoking this method may or may not be
+     * preserved when the connection is accepted. It may not be possible to
+     * accept a connection when this socket has a {@code SocketImpl} of one
+     * type and the given socket has a {@code SocketImpl} of a completely
+     * different type.
+     *
+     * @implNote
+     * An instance of this class using a system-default {@code SocketImpl}
+     * can accept a connection with a Socket using a {@code SocketImpl} of
+     * the same type: {@code IOException} is thrown if the Socket is using
+     * a custom {@code SocketImpl}. An instance of this class using a
+     * custom {@code SocketImpl} cannot accept a connection with a Socket
+     * using a system-default {@code SocketImpl}.
      *
      * @param s the Socket
      * @throws java.nio.channels.IllegalBlockingModeException
      *         if this socket has an associated channel,
      *         and the channel is in non-blocking mode
      * @throws IOException if an I/O error occurs when waiting
-     * for a connection.
+     *         for a connection, or if it is not possible for this socket
+     *         to accept a connection with the given socket
+     *
      * @since   1.1
      * @revised 1.4
      * @spec JSR-51
@@ -654,7 +687,7 @@
      * <p> If this socket has an associated channel then the channel is closed
      * as well.
      *
-     * @exception  IOException  if an I/O error occurs when closing the socket.
+     * @throws     IOException  if an I/O error occurs when closing the socket.
      * @revised 1.4
      * @spec JSR-51
      */
@@ -690,6 +723,10 @@
 
     /**
      * Returns the binding state of the ServerSocket.
+     * <p>
+     * If the socket was bound prior to being {@linkplain #close closed},
+     * then this method will continue to return {@code true}
+     * after the socket is closed.
      *
      * @return true if the ServerSocket successfully bound to an address
      * @since 1.4
@@ -739,7 +776,7 @@
      * Retrieve setting for {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}.
      * 0 returns implies that the option is disabled (i.e., timeout of infinity).
      * @return the {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} value
-     * @exception IOException if an I/O error occurs
+     * @throws    IOException if an I/O error occurs
      * @since   1.1
      * @see #setSoTimeout(int)
      */
@@ -782,7 +819,7 @@
      * is not defined.
      *
      * @param on  whether to enable or disable the socket option
-     * @exception SocketException if an error occurs enabling or
+     * @throws    SocketException if an error occurs enabling or
      *            disabling the {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR}
      *            socket option, or the socket is closed.
      * @since 1.4
@@ -802,7 +839,7 @@
      *
      * @return a {@code boolean} indicating whether or not
      *         {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} is enabled.
-     * @exception SocketException if there is an error
+     * @throws    SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
      * @since   1.4
      * @see #setReuseAddress(boolean)
@@ -817,7 +854,8 @@
      * Returns the implementation address and implementation port of
      * this socket as a {@code String}.
      * <p>
-     * If there is a security manager set, its {@code checkConnect} method is
+     * If there is a security manager set, and this socket is
+     * {@linkplain #isBound bound}, its {@code checkConnect} method is
      * called with the local address and {@code -1} as its arguments to see
      * if the operation is allowed. If the operation is not allowed,
      * an {@code InetAddress} representing the
@@ -831,7 +869,7 @@
             return "ServerSocket[unbound]";
         InetAddress in;
         if (System.getSecurityManager() != null)
-            in = InetAddress.getLoopbackAddress();
+            in = getInetAddress();
         else
             in = impl.getInetAddress();
         return "ServerSocket[addr=" + in +
@@ -860,10 +898,10 @@
      * This could result in a SecurityException.
      *
      * @param      fac   the desired factory.
-     * @exception  IOException  if an I/O error occurs when setting the
+     * @throws     IOException  if an I/O error occurs when setting the
      *               socket factory.
-     * @exception  SocketException  if the factory has already been defined.
-     * @exception  SecurityException  if a security manager exists and its
+     * @throws     SocketException  if the factory has already been defined.
+     * @throws     SecurityException  if a security manager exists and its
      *             {@code checkSetFactory} method doesn't allow the operation.
      * @see        java.net.SocketImplFactory#createSocketImpl()
      * @see        SecurityManager#checkSetFactory
@@ -903,13 +941,13 @@
      * requested value but the TCP receive window in sockets accepted from
      * this ServerSocket will be no larger than 64K bytes.
      *
-     * @exception SocketException if there is an error
+     * @throws    SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
      *
      * @param size the size to which to set the receive buffer
      * size. This value must be greater than 0.
      *
-     * @exception IllegalArgumentException if the
+     * @throws    IllegalArgumentException if the
      * value is 0 or is negative.
      *
      * @since 1.4
@@ -933,7 +971,7 @@
      * calling {@link Socket#getReceiveBufferSize()}.
      * @return the value of the {@link SocketOptions#SO_RCVBUF SO_RCVBUF}
      *         option for this {@code Socket}.
-     * @exception SocketException if there is an error
+     * @throws    SocketException if there is an error
      *            in the underlying protocol, such as a TCP error.
      * @see #setReceiveBufferSize(int)
      * @since 1.4
@@ -1089,27 +1127,4 @@
         }
         return options;
     }
-
-    static {
-        SharedSecrets.setJavaNetSocketAccess(
-            new JavaNetSocketAccess() {
-                @Override
-                public ServerSocket newServerSocket(SocketImpl impl) {
-                    return new ServerSocket(impl);
-                }
-
-                @Override
-                public SocketImpl newSocketImpl(Class<? extends SocketImpl> implClass) {
-                    try {
-                        Constructor<? extends SocketImpl> ctor =
-                            implClass.getDeclaredConstructor();
-                        return ctor.newInstance();
-                    } catch (NoSuchMethodException | InstantiationException |
-                             IllegalAccessException | InvocationTargetException e) {
-                        throw new AssertionError(e);
-                    }
-                }
-            }
-        );
-    }
 }