Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]
    1   /*
    2    * Copyright 2000-2006 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package sun.nio.ch;
   27   
   28   import java.io;
   29   import java.lang.ref;
   30   import java.net;
   31   import java.nio;
   32   import java.nio.channels;
   33   import java.security.AccessController;
   34   import java.security.PrivilegedExceptionAction;
   35   import java.util;
   36   
   37   
   38   // Make a socket channel look like a socket.
   39   //
   40   // The only aspects of java.net.Socket-hood that we don't attempt to emulate
   41   // here are the interrupted-I/O exceptions (which our Solaris implementations
   42   // attempt to support) and the sending of urgent data.  Otherwise an adapted
   43   // socket should look enough like a real java.net.Socket to fool most of the
   44   // developers most of the time, right down to the exception message strings.
   45   //
   46   // The methods in this class are defined in exactly the same order as in
   47   // java.net.Socket so as to simplify tracking future changes to that class.
   48   //
   49   
   50   public class SocketAdaptor
   51       extends Socket
   52   {
   53   
   54       // The channel being adapted
   55       private final SocketChannelImpl sc;
   56   
   57       // Option adaptor object, created on demand
   58       private volatile OptionAdaptor opts = null;
   59   
   60       // Timeout "option" value for reads
   61       private volatile int timeout = 0;
   62   
   63       // Traffic-class/Type-of-service
   64       private volatile int trafficClass = 0;
   65   
   66   
   67       // ## super will create a useless impl
   68       private SocketAdaptor(SocketChannelImpl sc) {
   69           this.sc = sc;
   70       }
   71   
   72       public static Socket create(SocketChannelImpl sc) {
   73           return new SocketAdaptor(sc);
   74       }
   75   
   76       public SocketChannel getChannel() {
   77           return sc;
   78       }
   79   
   80       // Override this method just to protect against changes in the superclass
   81       //
   82       public void connect(SocketAddress remote) throws IOException {
   83           connect(remote, 0);
   84       }
   85   
   86       public void connect(SocketAddress remote, int timeout) throws IOException {
   87           if (remote == null)
   88               throw new IllegalArgumentException("connect: The address can't be null");
   89           if (timeout < 0)
   90               throw new IllegalArgumentException("connect: timeout can't be negative");
   91   
   92           synchronized (sc.blockingLock()) {
   93               if (!sc.isBlocking())
   94                   throw new IllegalBlockingModeException();
   95   
   96               try {
   97   
   98                   if (timeout == 0) {
   99                       sc.connect(remote);
  100                       return;
  101                   }
  102   
  103                   // Implement timeout with a selector
  104                   SelectionKey sk = null;
  105                   Selector sel = null;
  106                   sc.configureBlocking(false);
  107                   try {
  108                       if (sc.connect(remote))
  109                           return;
  110                       sel = Util.getTemporarySelector(sc);
  111                       sk = sc.register(sel, SelectionKey.OP_CONNECT);
  112                       long to = timeout;
  113                       for (;;) {
  114                           if (!sc.isOpen())
  115                               throw new ClosedChannelException();
  116                           long st = System.currentTimeMillis();
  117                           int ns = sel.select(to);
  118                           if (ns > 0 &&
  119                               sk.isConnectable() && sc.finishConnect())
  120                               break;
  121                           sel.selectedKeys().remove(sk);
  122                           to -= System.currentTimeMillis() - st;
  123                           if (to <= 0) {
  124                               try {
  125                                   sc.close();
  126                               } catch (IOException x) { }
  127                               throw new SocketTimeoutException();
  128                           }
  129                       }
  130                   } finally {
  131                       if (sk != null)
  132                           sk.cancel();
  133                       if (sc.isOpen())
  134                           sc.configureBlocking(true);
  135                       if (sel != null)
  136                           Util.releaseTemporarySelector(sel);
  137                   }
  138   
  139               } catch (Exception x) {
  140                   Net.translateException(x, true);
  141               }
  142           }
  143   
  144       }
  145   
  146       public void bind(SocketAddress local) throws IOException {
  147           try {
  148               if (local == null)
  149                   local = new InetSocketAddress(0);
  150               sc.bind(local);
  151           } catch (Exception x) {
  152               Net.translateException(x);
  153           }
  154       }
  155   
  156       public InetAddress getInetAddress() {
  157           if (!sc.isConnected())
  158               return null;
  159           return Net.asInetSocketAddress(sc.remoteAddress()).getAddress();
  160       }
  161   
  162       public InetAddress getLocalAddress() {
  163           if (!sc.isBound())
  164               return new InetSocketAddress(0).getAddress();
  165           return Net.asInetSocketAddress(sc.localAddress()).getAddress();
  166       }
  167   
  168       public int getPort() {
  169           if (!sc.isConnected())
  170               return 0;
  171           return Net.asInetSocketAddress(sc.remoteAddress()).getPort();
  172       }
  173   
  174       public int getLocalPort() {
  175           if (!sc.isBound())
  176               return -1;
  177           return Net.asInetSocketAddress(sc.localAddress()).getPort();
  178       }
  179   
  180       private class SocketInputStream
  181           extends ChannelInputStream
  182       {
  183           private SocketInputStream() {
  184               super(sc);
  185           }
  186   
  187           protected int read(ByteBuffer bb)
  188               throws IOException
  189           {
  190               synchronized (sc.blockingLock()) {
  191                   if (!sc.isBlocking())
  192                       throw new IllegalBlockingModeException();
  193                   if (timeout == 0)
  194                       return sc.read(bb);
  195   
  196                   // Implement timeout with a selector
  197                   SelectionKey sk = null;
  198                   Selector sel = null;
  199                   sc.configureBlocking(false);
  200                   try {
  201                       int n;
  202                       if ((n = sc.read(bb)) != 0)
  203                           return n;
  204                       sel = Util.getTemporarySelector(sc);
  205                       sk = sc.register(sel, SelectionKey.OP_READ);
  206                       long to = timeout;
  207                       for (;;) {
  208                           if (!sc.isOpen())
  209                               throw new ClosedChannelException();
  210                           long st = System.currentTimeMillis();
  211                           int ns = sel.select(to);
  212                           if (ns > 0 && sk.isReadable()) {
  213                               if ((n = sc.read(bb)) != 0)
  214                                   return n;
  215                           }
  216                           sel.selectedKeys().remove(sk);
  217                           to -= System.currentTimeMillis() - st;
  218                           if (to <= 0)
  219                               throw new SocketTimeoutException();
  220                       }
  221                   } finally {
  222                       if (sk != null)
  223                           sk.cancel();
  224                       if (sc.isOpen())
  225                           sc.configureBlocking(true);
  226                       if (sel != null)
  227                           Util.releaseTemporarySelector(sel);
  228                   }
  229   
  230               }
  231           }
  232       }
  233   
  234       private InputStream socketInputStream = null;
  235   
  236       public InputStream getInputStream() throws IOException {
  237           if (!sc.isOpen())
  238               throw new SocketException("Socket is closed");
  239           if (!sc.isConnected())
  240               throw new SocketException("Socket is not connected");
  241           if (!sc.isInputOpen())
  242               throw new SocketException("Socket input is shutdown");
  243           if (socketInputStream == null) {
  244               try {
  245                   socketInputStream = AccessController.doPrivileged(
  246                       new PrivilegedExceptionAction<InputStream>() {
  247                           public InputStream run() throws IOException {
  248                               return new SocketInputStream();
  249                           }
  250                       });
  251               } catch (java.security.PrivilegedActionException e) {
  252                   throw (IOException)e.getException();
  253               }
  254           }
  255           return socketInputStream;
  256       }
  257   
  258       public OutputStream getOutputStream() throws IOException {
  259           if (!sc.isOpen())
  260               throw new SocketException("Socket is closed");
  261           if (!sc.isConnected())
  262               throw new SocketException("Socket is not connected");
  263           if (!sc.isOutputOpen())
  264               throw new SocketException("Socket output is shutdown");
  265           OutputStream os = null;
  266           try {
  267               os = AccessController.doPrivileged(
  268                   new PrivilegedExceptionAction<OutputStream>() {
  269                       public OutputStream run() throws IOException {
  270                           return Channels.newOutputStream(sc);
  271                       }
  272                   });
  273           } catch (java.security.PrivilegedActionException e) {
  274               throw (IOException)e.getException();
  275           }
  276           return os;
  277       }
  278   
  279       private OptionAdaptor opts() {
  280           if (opts == null)
  281               opts = new OptionAdaptor(sc);
  282           return opts;
  283       }
  284   
  285       public void setTcpNoDelay(boolean on) throws SocketException {
  286           opts().setTcpNoDelay(on);
  287       }
  288   
  289       public boolean getTcpNoDelay() throws SocketException {
  290           return opts().getTcpNoDelay();
  291       }
  292   
  293       public void setSoLinger(boolean on, int linger) throws SocketException {
  294           opts().setSoLinger(on, linger);
  295       }
  296   
  297       public int getSoLinger() throws SocketException {
  298           return opts().getSoLinger();
  299       }
  300   
  301       public void sendUrgentData(int data) throws IOException {
  302           throw new SocketException("Urgent data not supported");
  303       }
  304   
  305       public void setOOBInline(boolean on) throws SocketException {
  306           opts().setOOBInline(on);
  307       }
  308   
  309       public boolean getOOBInline() throws SocketException {
  310           return opts().getOOBInline();
  311       }
  312   
  313       public void setSoTimeout(int timeout) throws SocketException {
  314           if (timeout < 0)
  315               throw new IllegalArgumentException("timeout can't be negative");
  316           this.timeout = timeout;
  317       }
  318   
  319       public int getSoTimeout() throws SocketException {
  320           return timeout;
  321       }
  322   
  323       public void setSendBufferSize(int size) throws SocketException {
  324           opts().setSendBufferSize(size);
  325       }
  326   
  327       public int getSendBufferSize() throws SocketException {
  328           return opts().getSendBufferSize();
  329       }
  330   
  331       public void setReceiveBufferSize(int size) throws SocketException {
  332           opts().setReceiveBufferSize(size);
  333       }
  334   
  335       public int getReceiveBufferSize() throws SocketException {
  336           return opts().getReceiveBufferSize();
  337       }
  338   
  339       public void setKeepAlive(boolean on) throws SocketException {
  340           opts().setKeepAlive(on);
  341       }
  342   
  343       public boolean getKeepAlive() throws SocketException {
  344           return opts().getKeepAlive();
  345       }
  346   
  347       public void setTrafficClass(int tc) throws SocketException {
  348           opts().setTrafficClass(tc);
  349           trafficClass = tc;
  350       }
  351   
  352       public int getTrafficClass() throws SocketException {
  353           int tc = opts().getTrafficClass();
  354           if (tc < 0) {
  355               tc = trafficClass;
  356           }
  357           return tc;
  358       }
  359   
  360       public void setReuseAddress(boolean on) throws SocketException {
  361           opts().setReuseAddress(on);
  362       }
  363   
  364       public boolean getReuseAddress() throws SocketException {
  365           return opts().getReuseAddress();
  366       }
  367   
  368       public void close() throws IOException {
  369           try {
  370               sc.close();
  371           } catch (Exception x) {
  372               Net.translateToSocketException(x);
  373           }
  374       }
  375   
  376       public void shutdownInput() throws IOException {
  377           try {
  378               sc.shutdownInput();
  379           } catch (Exception x) {
  380               Net.translateException(x);
  381           }
  382       }
  383   
  384       public void shutdownOutput() throws IOException {
  385           try {
  386               sc.shutdownOutput();
  387           } catch (Exception x) {
  388               Net.translateException(x);
  389           }
  390       }
  391   
  392       public String toString() {
  393           if (sc.isConnected())
  394               return "Socket[addr=" + getInetAddress() +
  395                   ",port=" + getPort() +
  396                   ",localport=" + getLocalPort() + "]";
  397           return "Socket[unconnected]";
  398       }
  399   
  400       public boolean isConnected() {
  401           return sc.isConnected();
  402       }
  403   
  404       public boolean isBound() {
  405           return sc.isBound();
  406       }
  407   
  408       public boolean isClosed() {
  409           return !sc.isOpen();
  410       }
  411   
  412       public boolean isInputShutdown() {
  413           return !sc.isInputOpen();
  414       }
  415   
  416       public boolean isOutputShutdown() {
  417           return !sc.isOutputOpen();
  418       }
  419   
  420   }

Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]