# HG changeset patch # User vtewari # Date 1457025668 0 # Node ID a16a22218e232a78f5f1ee3e0cc77c3b3673691f # Parent 0149fa1848eb1843c42abf273a248f626b55f649 8148609: socket impl supportedOptions() should return an immutable set Reviewed-by: alanb, chegar diff -r 0149fa1848eb -r a16a22218e23 jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Thu Mar 03 14:29:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Thu Mar 03 17:21:08 2016 +0000 @@ -27,9 +27,7 @@ import java.io.FileDescriptor; import java.io.IOException; -import java.io.InterruptedIOException; import java.util.Set; -import java.util.HashSet; /** * Abstract datagram and multicast socket implementation base class. @@ -352,32 +350,32 @@ } } - private static final Set> dgSocketOptions = - new HashSet<>(); + private static final Set> dgSocketOptions; - private static final Set> mcSocketOptions = - new HashSet<>(); + private static final Set> mcSocketOptions; static { - dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF); - dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - dgSocketOptions.add(StandardSocketOptions.IP_TOS); + dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS); - mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF); - mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - mcSocketOptions.add(StandardSocketOptions.IP_TOS); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP); - }; + mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS, + StandardSocketOptions.IP_MULTICAST_IF, + StandardSocketOptions.IP_MULTICAST_TTL, + StandardSocketOptions.IP_MULTICAST_LOOP); + } /** * Returns a set of SocketOptions supported by this impl * and by this impl's socket (DatagramSocket or MulticastSocket) * * @return a Set of SocketOptions + * + * @since 9 */ protected Set> supportedOptions() { if (getDatagramSocket() instanceof MulticastSocket) { diff -r 0149fa1848eb -r a16a22218e23 jdk/src/java.base/share/classes/java/net/SocketImpl.java --- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java Thu Mar 03 14:29:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java Thu Mar 03 17:21:08 2016 +0000 @@ -30,8 +30,6 @@ import java.io.OutputStream; import java.io.FileDescriptor; import java.util.Set; -import java.util.HashSet; -import java.util.Collections; /** * The abstract class {@code SocketImpl} is a common superclass @@ -445,31 +443,31 @@ } } - private static final Set> socketOptions = - new HashSet<>(); + private static final Set> socketOptions; - private static final Set> serverSocketOptions = - new HashSet<>(); + private static final Set> serverSocketOptions; static { - socketOptions.add(StandardSocketOptions.SO_KEEPALIVE); - socketOptions.add(StandardSocketOptions.SO_SNDBUF); - socketOptions.add(StandardSocketOptions.SO_RCVBUF); - socketOptions.add(StandardSocketOptions.SO_REUSEADDR); - socketOptions.add(StandardSocketOptions.SO_LINGER); - socketOptions.add(StandardSocketOptions.IP_TOS); - socketOptions.add(StandardSocketOptions.TCP_NODELAY); + socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE, + StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.SO_LINGER, + StandardSocketOptions.IP_TOS, + StandardSocketOptions.TCP_NODELAY); - serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - serverSocketOptions.add(StandardSocketOptions.IP_TOS); - }; + serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS); + } /** * Returns a set of SocketOptions supported by this impl * and by this impl's socket (Socket or ServerSocket) * * @return a Set of SocketOptions + * + * @since 9 */ protected Set> supportedOptions() { if (getSocket() != null) { diff -r 0149fa1848eb -r a16a22218e23 jdk/test/java/net/SocketOption/ImmutableOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/SocketOption/ImmutableOptions.java Thu Mar 03 17:21:08 2016 +0000 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8148609 + * @run testng/othervm ImmutableOptions + * @summary Assert that the set of socket options are immutable + */ +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.util.Set; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +public class ImmutableOptions { + + @BeforeTest + void setupServerSocketFactory() throws IOException { + ServerSocket.setSocketFactory(new ServerSocketImplFactory()); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void socketThrows() throws IOException { + CustomSocketImpl impl = new CustomSocketImpl(); + Socket socket = new CustomSocket(impl); + socket.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void socketImplThrows() throws IOException { + CustomSocketImpl impl = new CustomSocketImpl(); + impl.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void serverSocketThrows() throws IOException { + ServerSocket ss = new ServerSocket(); + ss.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void serverSocketImplThrows() throws IOException { + ServerSocket ss = new ServerSocket(); + ServerSocketImplFactory.mostRecentlyCreated.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void datagramSocketThrows() throws IOException { + CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl(); + DatagramSocket socket = new CustomDatagramSocket(impl); + socket.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void datagramSocketImplThrows() throws IOException { + CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl(); + impl.supportedOptions().clear(); + } + + + // Socket descendants + static class CustomSocket extends Socket { + public CustomSocket(SocketImpl impl) throws IOException { + super(impl); + } + } + + static class CustomDatagramSocket extends DatagramSocket { + public CustomDatagramSocket(DatagramSocketImpl impl) { + super(impl); + } + } + + static class ServerSocketImplFactory implements SocketImplFactory { + static volatile CustomSocketImpl mostRecentlyCreated; + + @Override public SocketImpl createSocketImpl() { + return mostRecentlyCreated = new CustomSocketImpl(); + } + } + + // Custom impl's + static class CustomSocketImpl extends SocketImpl { + // The only method interesting to this test. + @Override public Set> supportedOptions() { + return super.supportedOptions(); + } + + public void create(boolean stream) throws IOException { } + + public void connect(String host, int port) throws IOException { } + + public void connect(InetAddress addr, int port) throws IOException { } + + public void connect(SocketAddress addr, int timeout) throws IOException { } + + public void bind(InetAddress host, int port) throws IOException { } + + public void listen(int backlog) throws IOException { } + + public void accept(SocketImpl s) throws IOException { } + + public InputStream getInputStream() throws IOException { return null; } + + public OutputStream getOutputStream() throws IOException { return null; } + + public int available() throws IOException { return 0; } + + public void close() throws IOException { } + + public void sendUrgentData(int data) throws IOException { } + + public Object getOption(int i) throws SocketException { return null; } + + public void setOption(int i, Object o) throws SocketException { } + } + + static class CustomDatagramSocketImpl extends DatagramSocketImpl { + // The only method interesting to this test. + @Override public Set> supportedOptions() { + return super.supportedOptions(); + } + + protected void create() throws SocketException { } + + protected void bind(int lport, InetAddress laddr) throws SocketException { } + + protected void send(DatagramPacket p) throws IOException { } + + protected int peek(InetAddress i) throws IOException { return 0; } + + protected int peekData(DatagramPacket p) throws IOException { return 0; } + + protected void receive(DatagramPacket p) throws IOException { } + + protected void setTTL(byte ttl) throws IOException { } + + protected byte getTTL() throws IOException { return 0; } + + protected void setTimeToLive(int ttl) throws IOException { } + + protected int getTimeToLive() throws IOException { return 0; } + + protected void join(InetAddress inetaddr) throws IOException { } + + protected void leave(InetAddress inetaddr) throws IOException { } + + protected void joinGroup(SocketAddress x, NetworkInterface y) + throws IOException { } + + protected void leaveGroup(SocketAddress x, NetworkInterface y) + throws IOException { } + + protected void close() { } + + public void setOption(int optID, Object value) throws SocketException { } + + public Object getOption(int optID) throws SocketException { return null; } + } +}