Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package sun.nio.ch;
     27 
     28 import java.io.*;
     29 import java.net.*;
     30 import java.nio.channels.*;
     31 
     32 
     33 // Make a server-socket channel look like a server socket.
     34 //
     35 // The methods in this class are defined in exactly the same order as in
     36 // java.net.ServerSocket so as to simplify tracking future changes to that
     37 // class.
     38 //
     39 
     40 public class ServerSocketAdaptor                        // package-private
     41     extends ServerSocket
     42 {
     43 
     44     // The channel being adapted
     45     private final ServerSocketChannelImpl ssc;
     46 
     47     // Timeout "option" value for accepts
     48     private volatile int timeout = 0;
     49 
     50     public static ServerSocket create(ServerSocketChannelImpl ssc) {
     51         try {
     52             return new ServerSocketAdaptor(ssc);
     53         } catch (IOException x) {
     54             throw new Error(x);
     55         }
     56     }
     57 
     58     // ## super will create a useless impl
     59     private ServerSocketAdaptor(ServerSocketChannelImpl ssc)
     60         throws IOException
     61     {
     62         this.ssc = ssc;
     63     }
     64 
     65 
     66     public void bind(SocketAddress local) throws IOException {
     67         bind(local, 50);
     68     }
     69 
     70     public void bind(SocketAddress local, int backlog) throws IOException {
     71         if (local == null)
     72             local = new InetSocketAddress(0);
     73         try {
     74             ssc.bind(local, backlog);
     75         } catch (Exception x) {
     76             Net.translateException(x);
     77         }
     78     }
     79 
     80     public InetAddress getInetAddress() {
     81         if (!ssc.isBound())
     82             return null;
     83         return Net.getRevealedLocalAddress(ssc.localAddress()).getAddress();
     84 
     85     }
     86 
     87     public int getLocalPort() {
     88         if (!ssc.isBound())
     89             return -1;
     90         return Net.asInetSocketAddress(ssc.localAddress()).getPort();
     91     }
     92 
     93 
     94     public Socket accept() throws IOException {
     95         synchronized (ssc.blockingLock()) {
     96             if (!ssc.isBound())
     97                 throw new IllegalBlockingModeException();
     98             try {
     99                 if (timeout == 0) {
    100                     SocketChannel sc = ssc.accept();
    101                     if (sc == null && !ssc.isBlocking())
    102                         throw new IllegalBlockingModeException();
    103                     return sc.socket();
    104                 }
    105 
    106                 // Implement timeout with a selector
    107                 SelectionKey sk = null;
    108                 Selector sel = null;
    109                 ssc.configureBlocking(false);
    110                 try {
    111                     SocketChannel sc;
    112                     if ((sc = ssc.accept()) != null)
    113                         return sc.socket();
    114                     sel = Util.getTemporarySelector(ssc);
    115                     sk = ssc.register(sel, SelectionKey.OP_ACCEPT);
    116                     long to = timeout;
    117                     for (;;) {
    118                         if (!ssc.isOpen())
    119                             throw new ClosedChannelException();
    120                         long st = System.currentTimeMillis();
    121                         int ns = sel.select(to);
    122                         if (ns > 0 &&
    123                             sk.isAcceptable() && ((sc = ssc.accept()) != null))
    124                             return sc.socket();
    125                         sel.selectedKeys().remove(sk);
    126                         to -= System.currentTimeMillis() - st;
    127                         if (to <= 0)
    128                             throw new SocketTimeoutException();
    129                     }
    130                 } finally {
    131                     if (sk != null)
    132                         sk.cancel();
    133                     if (ssc.isOpen())
    134                         ssc.configureBlocking(true);
    135                     if (sel != null)
    136                         Util.releaseTemporarySelector(sel);
    137                 }
    138 
    139             } catch (Exception x) {
    140                 Net.translateException(x);
    141                 assert false;
    142                 return null;            // Never happens
    143             }
    144         }
    145     }
    146 
    147     public void close() throws IOException {
    148         ssc.close();
    149     }
    150 
    151     public ServerSocketChannel getChannel() {
    152         return ssc;
    153     }
    154 
    155     public boolean isBound() {
    156         return ssc.isBound();
    157     }
    158 
    159     public boolean isClosed() {
    160         return !ssc.isOpen();
    161     }
    162 
    163     public void setSoTimeout(int timeout) throws SocketException {
    164         this.timeout = timeout;
    165     }
    166 
    167     public int getSoTimeout() throws SocketException {
    168         return timeout;
    169     }
    170 
    171     public void setReuseAddress(boolean on) throws SocketException {
    172         try {
    173             ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on);
    174         } catch (IOException x) {
    175             Net.translateToSocketException(x);
    176         }
    177     }
    178 
    179     public boolean getReuseAddress() throws SocketException {
    180         try {
    181             return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue();
    182         } catch (IOException x) {
    183             Net.translateToSocketException(x);
    184             return false;       // Never happens
    185         }
    186     }
    187 
    188     public String toString() {
    189         if (!isBound())
    190             return "ServerSocket[unbound]";
    191         return "ServerSocket[addr=" + getInetAddress() +
    192             //          ",port=" + getPort() +
    193                 ",localport=" + getLocalPort()  + "]";
    194     }
    195 
    196     public void setReceiveBufferSize(int size) throws SocketException {
    197         // size 0 valid for ServerSocketChannel, invalid for ServerSocket
    198         if (size <= 0)
    199             throw new IllegalArgumentException("size cannot be 0 or negative");
    200         try {
    201             ssc.setOption(StandardSocketOptions.SO_RCVBUF, size);
    202         } catch (IOException x) {
    203             Net.translateToSocketException(x);
    204         }
    205     }
    206 
    207     public int getReceiveBufferSize() throws SocketException {
    208         try {
    209             return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue();
    210         } catch (IOException x) {
    211             Net.translateToSocketException(x);
    212             return -1;          // Never happens
    213         }
    214     }
    215 
    216 }
    217