test/jdk/java/net/SocketImpl/CustomSocketImpls.java
branchniosocketimpl-branch
changeset 57199 88a41734ddbe
child 57200 4446b7c9bc1f
equal deleted inserted replaced
57191:de9dd71ef18c 57199:88a41734ddbe
       
     1 /*
       
     2  * Copyright (c) 2019, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /**
       
    25  * @test
       
    26  * @modules java.base/java.net:+open java.base/sun.nio.ch:+open
       
    27  * @run testng/othervm CustomSocketImpls
       
    28  * @run testng/othervm -Djdk.net.usePlainSocketImpl CustomSocketImpls
       
    29  */
       
    30 
       
    31 import java.io.FileDescriptor;
       
    32 import java.io.IOException;
       
    33 import java.io.InputStream;
       
    34 import java.io.OutputStream;
       
    35 import java.lang.reflect.Field;
       
    36 import java.net.InetAddress;
       
    37 import java.net.InetSocketAddress;
       
    38 import java.net.Proxy;
       
    39 import java.net.ServerSocket;
       
    40 import java.net.Socket;
       
    41 import java.net.SocketAddress;
       
    42 import java.net.SocketImpl;
       
    43 import java.net.SocketImplFactory;
       
    44 import java.nio.channels.ServerSocketChannel;
       
    45 import java.nio.channels.SocketChannel;
       
    46 import java.util.function.Consumer;
       
    47 
       
    48 import org.testng.annotations.Test;
       
    49 import static org.testng.Assert.*;
       
    50 
       
    51 @Test
       
    52 public class CustomSocketImpls {
       
    53 
       
    54     /**
       
    55      * Test ServerSocket is created with the expected SocketImpl.
       
    56      */
       
    57     public void testServerSocketSocketImpl() throws Exception {
       
    58         try (ServerSocket ss = new ServerSocket()) {
       
    59             SocketImpl si = getSocketImpl(ss);
       
    60             assertTrue(isPlatformSocketImpl(si));
       
    61         }
       
    62 
       
    63         SocketImpl impl = new CustomSocketImpl(true);
       
    64         try (ServerSocket ss = new ServerSocket(impl){}) {
       
    65             SocketImpl si = getSocketImpl(ss);
       
    66             assertTrue(si instanceof CustomSocketImpl);
       
    67         }
       
    68 
       
    69         setSocketFactory(() -> new CustomSocketImpl(true));
       
    70         try (ServerSocket ss = new ServerSocket()) {
       
    71             SocketImpl si = getSocketImpl(ss);
       
    72             assertTrue(si instanceof CustomSocketImpl);
       
    73         } finally {
       
    74             setSocketFactory(null);
       
    75         }
       
    76     }
       
    77 
       
    78     /**
       
    79      * Test Socket is created with the expected SocketImpl.
       
    80      */
       
    81     public void tesSocketSocketImpl() throws Exception {
       
    82         try (Socket s = new Socket()) {
       
    83             SocketImpl si = getSocketImpl(s);
       
    84             assertTrue(isSocksSocketImpl(si));
       
    85             SocketImpl delegate = getDelegate(si);
       
    86             assertTrue(isPlatformSocketImpl(delegate));
       
    87         }
       
    88 
       
    89         try (Socket s = new Socket((SocketImpl) null){}) {
       
    90             assertTrue(getSocketImpl(s) == null);
       
    91         }
       
    92 
       
    93         try (Socket s = new Socket(Proxy.NO_PROXY)) {
       
    94             SocketImpl si = getSocketImpl(s);
       
    95             assertTrue(isPlatformSocketImpl(si));
       
    96         }
       
    97 
       
    98         var address = new InetSocketAddress("127.0.0.1", 1000);
       
    99         var socksProxy = new Proxy(Proxy.Type.SOCKS, address);
       
   100         try (Socket s = new Socket(socksProxy)) {
       
   101             SocketImpl si = getSocketImpl(s);
       
   102             assertTrue(isSocksSocketImpl(si));
       
   103             SocketImpl delegate = getDelegate(si);
       
   104             assertTrue(isPlatformSocketImpl(delegate));
       
   105         }
       
   106 
       
   107         var httpProxy = new Proxy(Proxy.Type.HTTP, address);
       
   108         try (Socket s = new Socket(httpProxy)) {
       
   109             SocketImpl si = getSocketImpl(s);
       
   110             assertTrue(isHttpConnectSocketImpl(si));
       
   111             SocketImpl delegate = getDelegate(si);
       
   112             assertTrue(isPlatformSocketImpl(delegate));
       
   113         }
       
   114 
       
   115         try (Socket s = new Socket(new CustomSocketImpl(false)){}) {
       
   116             SocketImpl si = getSocketImpl(s);
       
   117             assertTrue(si instanceof CustomSocketImpl);
       
   118         }
       
   119 
       
   120         setSocketImplFactory(() -> new CustomSocketImpl(false));
       
   121         try (Socket s = new Socket()) {
       
   122             SocketImpl si = getSocketImpl(s);
       
   123             assertTrue(si instanceof CustomSocketImpl);
       
   124         } finally {
       
   125             setSocketImplFactory(null);
       
   126         }
       
   127     }
       
   128 
       
   129     /**
       
   130      * ServerSocket using default SocketImpl. Test accept returning a Socket
       
   131      * that initially doesn't have a SocketImpl.
       
   132      */
       
   133     public void test1() throws Exception {
       
   134         var socket = new Socket((SocketImpl) null) { };
       
   135         assertTrue(getSocketImpl(socket) == null);
       
   136         testAccept(socket, s -> {
       
   137             assertTrue(s == socket);
       
   138             SocketImpl si = getSocketImpl(s);
       
   139             assertTrue(isPlatformSocketImpl(si));
       
   140             checkFields(si);
       
   141         });
       
   142     }
       
   143 
       
   144     /**
       
   145      * ServerSocket using default SocketImpl. Test accept returning a Socket
       
   146      * that has an existing default SocketImpl.
       
   147      */
       
   148     public void test2() throws Exception {
       
   149         var socket = new Socket();
       
   150         SocketImpl si = getSocketImpl(socket);
       
   151         assertTrue(isSocksSocketImpl(si));
       
   152         SocketImpl delegate = getDelegate(si);
       
   153         assertTrue(isPlatformSocketImpl(delegate));
       
   154         testAccept(socket, s -> {
       
   155             assertTrue(s == socket);
       
   156             assertTrue(getSocketImpl(s) == si);
       
   157             assertTrue(getDelegate(si) == delegate);
       
   158             checkFields(delegate);
       
   159         });
       
   160     }
       
   161 
       
   162     /**
       
   163      * ServerSocket using default SocketImpl. A SocketImplFactory is set to
       
   164      * return a custom SocketImpl. Test accept returning a Socket that initially
       
   165      * doesn't have a SocketImpl.
       
   166      */
       
   167     public void test3() throws Exception {
       
   168         var socket = new Socket((SocketImpl) null) { };
       
   169         assertTrue(getSocketImpl(socket) == null);
       
   170         testAccept(socket, () -> new CustomSocketImpl(false), s -> {
       
   171             assertTrue(s == socket);
       
   172             SocketImpl si = getSocketImpl(s);
       
   173             assertTrue(si instanceof CustomSocketImpl);
       
   174             checkFields(si);
       
   175         });
       
   176     }
       
   177 
       
   178     /**
       
   179      * ServerSocket using default SocketImpl. Test accept returning a Socket
       
   180      * that has an existing custom SocketImpl.
       
   181      */
       
   182     public void test4() throws Exception {
       
   183         SocketImpl si = new CustomSocketImpl(false);
       
   184         Socket socket = new Socket(si) { };
       
   185         assertTrue(getSocketImpl(socket) == si);
       
   186         testAccept(socket, s -> {
       
   187             assertTrue(s == socket);
       
   188             assertTrue(getSocketImpl(s) == si);
       
   189             checkFields(si);
       
   190         });
       
   191     }
       
   192 
       
   193     /**
       
   194      * ServerSocket using a custom SocketImpl. Test accept returning a Socket
       
   195      * that initially doesn't have a SocketImpl.
       
   196      */
       
   197     public void test5() throws Exception {
       
   198         SocketImpl impl = new CustomSocketImpl(true);
       
   199         Socket socket = new Socket((SocketImpl) null) { };
       
   200         assertTrue(getSocketImpl(socket) == null);
       
   201         testAccept(impl, socket, s -> {
       
   202             assertTrue(s == socket);
       
   203             SocketImpl si = getSocketImpl(s);
       
   204             assertTrue(isPlatformSocketImpl(si));
       
   205             checkFields(si);
       
   206         });
       
   207     }
       
   208 
       
   209     /**
       
   210      * ServerSocket using a custom SocketImpl. Test accept returning a Socket
       
   211      * that has an existing default SocketImpl.
       
   212      */
       
   213     public void test6() throws Exception {
       
   214         SocketImpl impl = new CustomSocketImpl(true);
       
   215         var socket = new Socket();
       
   216         SocketImpl si = getSocketImpl(socket);
       
   217         assertTrue(isSocksSocketImpl(si));
       
   218         SocketImpl delegate = getDelegate(si);
       
   219         assertTrue(isPlatformSocketImpl(delegate));
       
   220         testAccept(impl, socket, s -> {
       
   221             assertTrue(s == socket);
       
   222             assertTrue(getSocketImpl(s) == si);
       
   223             assertTrue(getDelegate(si) == delegate);
       
   224             checkFields(delegate);
       
   225         });
       
   226     }
       
   227 
       
   228     /**
       
   229      * ServerSocket using a custom SocketImpl. A SocketImplFactory is set to
       
   230      * return a custom SocketImpl. Test accept returning a Socket that initially
       
   231      * doesn't have a SocketImpl.
       
   232      */
       
   233     public void test7() throws Exception {
       
   234         var socket = new Socket((SocketImpl) null) { };
       
   235         assertTrue(getSocketImpl(socket) == null);
       
   236         Socket s1 = null;
       
   237         Socket s2 = null;
       
   238         try (ServerSocket ss = prepareToAccept(new CustomSocketImpl(true), socket)) {
       
   239             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   240             setSocketImplFactory(() -> new CustomSocketImpl(false));
       
   241             try {
       
   242                 s2 = ss.accept();
       
   243                 SocketImpl si = getSocketImpl(s2);
       
   244                 assertTrue(si instanceof CustomSocketImpl);
       
   245                 checkFields(si);
       
   246             } finally {
       
   247                 setSocketImplFactory(null);
       
   248             }
       
   249         } finally {
       
   250             if (s1 != null) s1.close();
       
   251             if (s2 != null) s1.close();
       
   252         }
       
   253     }
       
   254 
       
   255     /**
       
   256      * ServerSocket using a custom SocketImpl. A SocketImplFactory is set to
       
   257      * return a custom SocketImpl. Test accept returning a Socket has an existing
       
   258      * custom SocketImpl.
       
   259      */
       
   260     public void test8() throws Exception {
       
   261         SocketImpl si = new CustomSocketImpl(false);
       
   262         Socket socket = new Socket(si) { };
       
   263         assertTrue(getSocketImpl(socket) == si);
       
   264         Socket s1 = null;
       
   265         Socket s2 = null;
       
   266         try (ServerSocket ss = prepareToAccept(new CustomSocketImpl(true), socket)) {
       
   267             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   268             setSocketImplFactory(() -> new CustomSocketImpl(false));
       
   269             try {
       
   270                 s2 = ss.accept();
       
   271                 assertTrue(getSocketImpl(s2) == si);
       
   272                 checkFields(si);
       
   273             } finally {
       
   274                 setSocketImplFactory(null);
       
   275             }
       
   276         } finally {
       
   277             if (s1 != null) s1.close();
       
   278             if (s2 != null) s1.close();
       
   279         }
       
   280     }
       
   281 
       
   282     /**
       
   283      * Creates a ServerSocket that returns the given Socket from accept.
       
   284      * The consumer is invoked with the accepted socket.
       
   285      */
       
   286     static void testAccept(Socket socket, Consumer<Socket> consumer)
       
   287         throws IOException
       
   288     {
       
   289         Socket s1 = null;
       
   290         Socket s2 = null;
       
   291         try (ServerSocket ss = prepareToAccept(socket)) {
       
   292             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   293             s2 = ss.accept();
       
   294             consumer.accept(s2);
       
   295         } finally {
       
   296             if (s1 != null) s1.close();
       
   297             if (s2 != null) s1.close();
       
   298         }
       
   299     }
       
   300 
       
   301     /**
       
   302      * Creates a ServerSocket that returns the given Socket from accept. The
       
   303      * given SocketImplFactory is set during the accept and the consumer is
       
   304      * invoked when the accepted socket.
       
   305      */
       
   306     static void testAccept(Socket socket, SocketImplFactory factory, Consumer<Socket> consumer)
       
   307         throws IOException
       
   308     {
       
   309         Socket s1 = null;
       
   310         Socket s2 = null;
       
   311         try (ServerSocket ss = prepareToAccept(socket)) {
       
   312             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   313             setSocketImplFactory(factory);
       
   314             try {
       
   315                 s2 = ss.accept();
       
   316             } finally {
       
   317                 setSocketImplFactory(null);
       
   318             }
       
   319             consumer.accept(s2);
       
   320         } finally {
       
   321             if (s1 != null) s1.close();
       
   322             if (s2 != null) s1.close();
       
   323         }
       
   324     }
       
   325 
       
   326     /**
       
   327      * Creates a ServerSocket with a SocketImpl that returns the given Socket
       
   328      * from accept. The consumer is invoked with the accepted socket.
       
   329      */
       
   330     static void testAccept(SocketImpl impl, Socket socket, Consumer<Socket> consumer)
       
   331         throws IOException
       
   332     {
       
   333         Socket s1 = null;
       
   334         Socket s2 = null;
       
   335         try (ServerSocket ss = prepareToAccept(impl, socket)) {
       
   336             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   337             s2 = ss.accept();
       
   338             consumer.accept(s2);
       
   339         } finally {
       
   340             if (s1 != null) s1.close();
       
   341             if (s2 != null) s1.close();
       
   342         }
       
   343     }
       
   344 
       
   345     /**
       
   346      * Creates a ServerSocket that returns the given Socket from accept.
       
   347      */
       
   348     static ServerSocket prepareToAccept(Socket s) throws IOException {
       
   349         return new ServerSocket(0) {
       
   350             @Override
       
   351             public Socket accept() throws IOException {
       
   352                 implAccept(s);
       
   353                 return s;
       
   354             }
       
   355         };
       
   356     }
       
   357 
       
   358     /**
       
   359      * Creates a ServerSocket with a SocketImpl that returns the given Socket
       
   360      * from accept.
       
   361      */
       
   362     static ServerSocket prepareToAccept(SocketImpl impl, Socket s) throws IOException {
       
   363         ServerSocket ss = new ServerSocket(impl) {
       
   364             @Override
       
   365             public Socket accept() throws IOException {
       
   366                 implAccept(s);
       
   367                 return s;
       
   368             }
       
   369         };
       
   370         ss.bind(new InetSocketAddress(0));
       
   371         return ss;
       
   372     }
       
   373 
       
   374     /**
       
   375      * Returns the socket's SocketImpl
       
   376      */
       
   377     static SocketImpl getSocketImpl(Socket s) {
       
   378         try {
       
   379             Field f = Socket.class.getDeclaredField("impl");
       
   380             f.setAccessible(true);
       
   381             return (SocketImpl) f.get(s);
       
   382         } catch (Exception e) {
       
   383             throw new RuntimeException(e);
       
   384         }
       
   385     }
       
   386 
       
   387     /**
       
   388      * Returns the server socket's SocketImpl
       
   389      */
       
   390     static SocketImpl getSocketImpl(ServerSocket ss) {
       
   391         try {
       
   392             Field f = ServerSocket.class.getDeclaredField("impl");
       
   393             f.setAccessible(true);
       
   394             return (SocketImpl) f.get(ss);
       
   395         } catch (Exception e) {
       
   396             throw new RuntimeException(e);
       
   397         }
       
   398     }
       
   399 
       
   400     /**
       
   401      * Returns the SocketImpl that the given SocketImpl delegates to
       
   402      */
       
   403     static SocketImpl getDelegate(SocketImpl si) {
       
   404         try {
       
   405             Class<?> clazz = Class.forName("java.net.DelegatingSocketImpl");
       
   406             Field f = clazz.getDeclaredField("delegate");
       
   407             f.setAccessible(true);
       
   408             return (SocketImpl) f.get(si);
       
   409         } catch (Exception e) {
       
   410             throw new RuntimeException(e);
       
   411         }
       
   412     }
       
   413 
       
   414     /**
       
   415      * Returns the value of a SocketImpl field
       
   416      */
       
   417     static <T> T get(SocketImpl si, String name) {
       
   418         try {
       
   419             Field f = SocketImpl.class.getDeclaredField(name);
       
   420             f.setAccessible(true);
       
   421             return (T) f.get(si);
       
   422         } catch (Exception e) {
       
   423             throw new RuntimeException(e);
       
   424         }
       
   425     }
       
   426 
       
   427     /**
       
   428      * Sets the value of SocketImpl field
       
   429      */
       
   430     static void set(SocketImpl si, String name, Object value) {
       
   431         try {
       
   432             Field f = SocketImpl.class.getDeclaredField(name);
       
   433             f.setAccessible(true);
       
   434             f.set(si, value);
       
   435         } catch (Exception e) {
       
   436             throw new RuntimeException(e);
       
   437         }
       
   438     }
       
   439 
       
   440     /**
       
   441      * Returns true if the SocketImpl is a PlatformSocketImpl
       
   442      */
       
   443     static boolean isPlatformSocketImpl(SocketImpl si) {
       
   444         try {
       
   445             Class<?> clazz = Class.forName("sun.net.PlatformSocketImpl");
       
   446             return clazz.isInstance(si);
       
   447         } catch (Exception e) {
       
   448             throw new RuntimeException(e);
       
   449         }
       
   450     }
       
   451 
       
   452     /**
       
   453      * Returns true if the SocketImpl is a SocksSocketImpl
       
   454      */
       
   455     static boolean isSocksSocketImpl(SocketImpl si) {
       
   456         try {
       
   457             Class<?> clazz = Class.forName("java.net.SocksSocketImpl");
       
   458             return clazz.isInstance(si);
       
   459         } catch (Exception e) {
       
   460             throw new RuntimeException(e);
       
   461         }
       
   462     }
       
   463 
       
   464     /**
       
   465      * Returns true if the SocketImpl is a HttpConnectSocketImpl
       
   466      */
       
   467     static boolean isHttpConnectSocketImpl(SocketImpl si) {
       
   468         try {
       
   469             Class<?> clazz = Class.forName("java.net.HttpConnectSocketImpl");
       
   470             return clazz.isInstance(si);
       
   471         } catch (Exception e) {
       
   472             throw new RuntimeException(e);
       
   473         }
       
   474     }
       
   475 
       
   476     /**
       
   477      * Socket.setSocketImplFactory
       
   478      */
       
   479     static void setSocketImplFactory(SocketImplFactory factory) {
       
   480         try {
       
   481             Field f = Socket.class.getDeclaredField("factory");
       
   482             f.setAccessible(true);
       
   483             f.set(null, factory);
       
   484         } catch (Exception e) {
       
   485             throw new RuntimeException(e);
       
   486         }
       
   487     }
       
   488 
       
   489     /**
       
   490      * ServerSocket.setSocketFactory
       
   491      */
       
   492     static void setSocketFactory(SocketImplFactory factory) {
       
   493         try {
       
   494             Field f = ServerSocket.class.getDeclaredField("factory");
       
   495             f.setAccessible(true);
       
   496             f.set(null, factory);
       
   497         } catch (Exception e) {
       
   498             throw new RuntimeException(e);
       
   499         }
       
   500     }
       
   501 
       
   502     /**
       
   503      * Checks the 4 protected fields of a SocketImpl to make sure that they
       
   504      * have been initialized.
       
   505      */
       
   506     static void checkFields(SocketImpl si) {
       
   507         FileDescriptor fd = get(si, "fd");
       
   508         InetAddress address = get(si, "address");
       
   509         int port = get(si, "port");
       
   510         int localport = get(si, "localport");
       
   511         assertTrue(fd.valid() && address != null && port != 0 && localport != 0);
       
   512     }
       
   513 
       
   514     /**
       
   515      * Custom SocketImpl that is layed on a SocketChannel or ServerSocketChannel
       
   516      */
       
   517     static class CustomSocketImpl extends SocketImpl {
       
   518         private final boolean server;
       
   519         private ServerSocketChannel ssc;
       
   520         private SocketChannel sc;
       
   521 
       
   522         CustomSocketImpl(boolean server) {
       
   523             this.server = server;
       
   524         }
       
   525 
       
   526         @Override
       
   527         protected void create(boolean stream) throws IOException {
       
   528             if (server) {
       
   529                 ssc = ServerSocketChannel.open();
       
   530             } else {
       
   531                 sc = SocketChannel.open();
       
   532             }
       
   533         }
       
   534 
       
   535         @Override
       
   536         protected void connect(String host, int port) throws IOException {
       
   537             connect(new InetSocketAddress(host, port), 0);
       
   538         }
       
   539 
       
   540         @Override
       
   541         protected void connect(InetAddress address, int port) throws IOException {
       
   542             connect(new InetSocketAddress(address, port), 0);
       
   543         }
       
   544 
       
   545         @Override
       
   546         protected void connect(SocketAddress remote, int timeout) throws IOException {
       
   547             sc.connect(remote);
       
   548             super.address = ((InetSocketAddress) remote).getAddress();
       
   549             super.port = ((InetSocketAddress) remote).getPort();
       
   550         }
       
   551 
       
   552         @Override
       
   553         protected void bind(InetAddress address, int port) throws IOException {
       
   554             if (server) {
       
   555                 ssc.bind(new InetSocketAddress(address, port));
       
   556             } else {
       
   557                 sc.bind(new InetSocketAddress(address, port));
       
   558             }
       
   559             super.address = address;
       
   560             super.localport = ssc.socket().getLocalPort();
       
   561         }
       
   562 
       
   563         @Override
       
   564         protected void listen(int backlog) {
       
   565             // do nothing
       
   566         }
       
   567 
       
   568         @Override
       
   569         protected void accept(SocketImpl si) throws IOException {
       
   570             SocketChannel peer = ssc.accept();
       
   571             FileDescriptor fd;
       
   572             try {
       
   573                 Class<?> clazz = Class.forName("sun.nio.ch.SocketChannelImpl");
       
   574                 Field f = clazz.getDeclaredField("fd");
       
   575                 f.setAccessible(true);
       
   576                 fd = (FileDescriptor) f.get(peer);
       
   577             } catch (Exception e) {
       
   578                 throw new RuntimeException(e);
       
   579             }
       
   580             set(si, "fd", fd);
       
   581             set(si, "address", peer.socket().getInetAddress());
       
   582             set(si, "port", peer.socket().getPort());
       
   583             set(si, "localport", peer.socket().getLocalPort());
       
   584         }
       
   585 
       
   586         @Override
       
   587         protected InputStream getInputStream() {
       
   588             throw new RuntimeException();
       
   589         }
       
   590 
       
   591         @Override
       
   592         protected OutputStream getOutputStream() {
       
   593             throw new RuntimeException();
       
   594         }
       
   595 
       
   596         @Override
       
   597         protected int available() {
       
   598             return 0;
       
   599         }
       
   600 
       
   601         @Override
       
   602         protected void close() {
       
   603         }
       
   604 
       
   605         @Override
       
   606         protected void sendUrgentData(int data) {
       
   607             throw new RuntimeException();
       
   608         }
       
   609 
       
   610         @Override
       
   611         public void setOption(int option, Object value) {
       
   612             throw new RuntimeException();
       
   613         }
       
   614 
       
   615         @Override
       
   616         public Object getOption(int option) {
       
   617             throw new RuntimeException();
       
   618         }
       
   619     }
       
   620 }