diff -r b43cc3b9ef40 -r 13b67c1420b8 src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java Thu Apr 25 09:12:40 2019 +0200 +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java Thu Apr 25 10:41:49 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, 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 @@ -32,12 +32,14 @@ import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; -import java.net.SocketTimeoutException; +import java.net.SocketOption; import java.net.StandardSocketOptions; import java.nio.channels.IllegalBlockingModeException; -import java.nio.channels.NotYetBoundException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; +import java.util.Set; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; // Make a server-socket channel look like a server socket. @@ -56,23 +58,21 @@ // Timeout "option" value for accepts private volatile int timeout; - public static ServerSocket create(ServerSocketChannelImpl ssc) { - try { - return new ServerSocketAdaptor(ssc); - } catch (IOException x) { - throw new Error(x); - } + static ServerSocket create(ServerSocketChannelImpl ssc) { + return new ServerSocketAdaptor(ssc); } - // ## super will create a useless impl - private ServerSocketAdaptor(ServerSocketChannelImpl ssc) throws IOException { + private ServerSocketAdaptor(ServerSocketChannelImpl ssc) { + super(DummySocketImpl.create()); this.ssc = ssc; } + @Override public void bind(SocketAddress local) throws IOException { bind(local, 50); } + @Override public void bind(SocketAddress local, int backlog) throws IOException { if (local == null) local = new InetSocketAddress(0); @@ -83,6 +83,7 @@ } } + @Override public InetAddress getInetAddress() { InetSocketAddress local = ssc.localAddress(); if (local == null) { @@ -92,6 +93,7 @@ } } + @Override public int getLocalPort() { InetSocketAddress local = ssc.localAddress(); if (local == null) { @@ -101,65 +103,65 @@ } } + @Override public Socket accept() throws IOException { - synchronized (ssc.blockingLock()) { - try { - if (!ssc.isBound()) - throw new NotYetBoundException(); - - long to = this.timeout; - if (to == 0) { - // for compatibility reasons: accept connection if available - // when configured non-blocking - SocketChannel sc = ssc.accept(); - if (sc == null && !ssc.isBlocking()) - throw new IllegalBlockingModeException(); - return sc.socket(); + SocketChannel sc = null; + try { + int timeout = this.timeout; + if (timeout > 0) { + long nanos = MILLISECONDS.toNanos(timeout); + sc = ssc.blockingAccept(nanos); + } else { + // accept connection if possible when non-blocking (to preserve + // long standing behavior) + sc = ssc.accept(); + if (sc == null) { + throw new IllegalBlockingModeException(); } - - if (!ssc.isBlocking()) - throw new IllegalBlockingModeException(); - for (;;) { - long st = System.currentTimeMillis(); - if (ssc.pollAccept(to)) - return ssc.accept().socket(); - to -= System.currentTimeMillis() - st; - if (to <= 0) - throw new SocketTimeoutException(); - } - - } catch (Exception x) { - Net.translateException(x); - assert false; - return null; // Never happens } + } catch (Exception e) { + Net.translateException(e); } + return sc.socket(); } + @Override public void close() throws IOException { ssc.close(); } + @Override public ServerSocketChannel getChannel() { return ssc; } + @Override public boolean isBound() { return ssc.isBound(); } + @Override public boolean isClosed() { return !ssc.isOpen(); } + @Override public void setSoTimeout(int timeout) throws SocketException { + if (!ssc.isOpen()) + throw new SocketException("Socket is closed"); + if (timeout < 0) + throw new IllegalArgumentException("timeout < 0"); this.timeout = timeout; } + @Override public int getSoTimeout() throws SocketException { + if (!ssc.isOpen()) + throw new SocketException("Socket is closed"); return timeout; } + @Override public void setReuseAddress(boolean on) throws SocketException { try { ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on); @@ -168,6 +170,7 @@ } } + @Override public boolean getReuseAddress() throws SocketException { try { return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue(); @@ -177,6 +180,7 @@ } } + @Override public String toString() { if (!isBound()) return "ServerSocket[unbound]"; @@ -184,6 +188,7 @@ ",localport=" + getLocalPort() + "]"; } + @Override public void setReceiveBufferSize(int size) throws SocketException { // size 0 valid for ServerSocketChannel, invalid for ServerSocket if (size <= 0) @@ -195,6 +200,7 @@ } } + @Override public int getReceiveBufferSize() throws SocketException { try { return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue(); @@ -203,4 +209,20 @@ return -1; // Never happens } } + + @Override + public ServerSocket setOption(SocketOption name, T value) throws IOException { + ssc.setOption(name, value); + return this; + } + + @Override + public T getOption(SocketOption name) throws IOException { + return ssc.getOption(name); + } + + @Override + public Set> supportedOptions() { + return ssc.supportedOptions(); + } }