jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java
changeset 2 90ce3da70b43
child 1152 29d6145d1097
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2000-2005 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.io.*;
+import java.net.*;
+import java.nio.channels.*;
+
+
+// Make a server-socket channel look like a server socket.
+//
+// The methods in this class are defined in exactly the same order as in
+// java.net.ServerSocket so as to simplify tracking future changes to that
+// class.
+//
+
+public class ServerSocketAdaptor                        // package-private
+    extends ServerSocket
+{
+
+    // The channel being adapted
+    private final ServerSocketChannelImpl ssc;
+
+    // Option adaptor object, created on demand
+    private volatile OptionAdaptor opts = null;
+
+    // Timeout "option" value for accepts
+    private volatile int timeout = 0;
+
+    public static ServerSocket create(ServerSocketChannelImpl ssc) {
+        try {
+            return new ServerSocketAdaptor(ssc);
+        } catch (IOException x) {
+            throw new Error(x);
+        }
+    }
+
+    // ## super will create a useless impl
+    private ServerSocketAdaptor(ServerSocketChannelImpl ssc)
+        throws IOException
+    {
+        this.ssc = ssc;
+    }
+
+
+    public void bind(SocketAddress local) throws IOException {
+        bind(local, 50);
+    }
+
+    public void bind(SocketAddress local, int backlog) throws IOException {
+        if (local == null)
+            local = new InetSocketAddress(0);
+        try {
+            ssc.bind(local, backlog);
+        } catch (Exception x) {
+            Net.translateException(x);
+        }
+    }
+
+    public InetAddress getInetAddress() {
+        if (!ssc.isBound())
+            return null;
+        return Net.asInetSocketAddress(ssc.localAddress()).getAddress();
+    }
+
+    public int getLocalPort() {
+        if (!ssc.isBound())
+            return -1;
+        return Net.asInetSocketAddress(ssc.localAddress()).getPort();
+    }
+
+
+    public Socket accept() throws IOException {
+        synchronized (ssc.blockingLock()) {
+            if (!ssc.isBound())
+                throw new IllegalBlockingModeException();
+            try {
+                if (timeout == 0) {
+                    SocketChannel sc = ssc.accept();
+                    if (sc == null && !ssc.isBlocking())
+                        throw new IllegalBlockingModeException();
+                    return sc.socket();
+                }
+
+                // Implement timeout with a selector
+                SelectionKey sk = null;
+                Selector sel = null;
+                ssc.configureBlocking(false);
+                try {
+                    SocketChannel sc;
+                    if ((sc = ssc.accept()) != null)
+                        return sc.socket();
+                    sel = Util.getTemporarySelector(ssc);
+                    sk = ssc.register(sel, SelectionKey.OP_ACCEPT);
+                    long to = timeout;
+                    for (;;) {
+                        if (!ssc.isOpen())
+                            throw new ClosedChannelException();
+                        long st = System.currentTimeMillis();
+                        int ns = sel.select(to);
+                        if (ns > 0 &&
+                            sk.isAcceptable() && ((sc = ssc.accept()) != null))
+                            return sc.socket();
+                        sel.selectedKeys().remove(sk);
+                        to -= System.currentTimeMillis() - st;
+                        if (to <= 0)
+                            throw new SocketTimeoutException();
+                    }
+                } finally {
+                    if (sk != null)
+                        sk.cancel();
+                    if (ssc.isOpen())
+                        ssc.configureBlocking(true);
+                    if (sel != null)
+                        Util.releaseTemporarySelector(sel);
+                }
+
+            } catch (Exception x) {
+                Net.translateException(x);
+                assert false;
+                return null;            // Never happens
+            }
+        }
+    }
+
+    public void close() throws IOException {
+        try {
+            ssc.close();
+        } catch (Exception x) {
+            Net.translateException(x);
+        }
+    }
+
+    public ServerSocketChannel getChannel() {
+        return ssc;
+    }
+
+    public boolean isBound() {
+        return ssc.isBound();
+    }
+
+    public boolean isClosed() {
+        return !ssc.isOpen();
+    }
+
+    public void setSoTimeout(int timeout) throws SocketException {
+        this.timeout = timeout;
+    }
+
+    public int getSoTimeout() throws SocketException {
+        return timeout;
+    }
+
+    private OptionAdaptor opts() {
+        if (opts == null)
+            opts = new OptionAdaptor(ssc);
+        return opts;
+    }
+
+    public void setReuseAddress(boolean on) throws SocketException {
+        opts().setReuseAddress(on);
+    }
+
+    public boolean getReuseAddress() throws SocketException {
+        return opts().getReuseAddress();
+    }
+
+    public String toString() {
+        if (!isBound())
+            return "ServerSocket[unbound]";
+        return "ServerSocket[addr=" + getInetAddress() +
+            //          ",port=" + getPort() +
+                ",localport=" + getLocalPort()  + "]";
+    }
+
+    public void setReceiveBufferSize(int size) throws SocketException {
+        opts().setReceiveBufferSize(size);
+    }
+
+    public int getReceiveBufferSize() throws SocketException {
+        return opts().getReceiveBufferSize();
+    }
+
+}