1 /*
   2  * Copyright (c) 2010, 2014, 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 com.oracle.net;
  27 
  28 import java.net.Socket;
  29 import java.net.ServerSocket;
  30 import java.net.SocketImpl;
  31 import java.net.SocketImplFactory;
  32 import java.net.SocketException;
  33 import java.nio.channels.SocketChannel;
  34 import java.nio.channels.ServerSocketChannel;
  35 import java.io.IOException;
  36 import java.io.FileDescriptor;
  37 import java.security.AccessController;
  38 import java.security.PrivilegedAction;
  39 import java.lang.reflect.Constructor;
  40 import java.lang.reflect.AccessibleObject;
  41 import java.lang.reflect.InvocationTargetException;
  42 
  43 import sun.net.sdp.SdpSupport;
  44 
  45 /**
  46  * This class consists exclusively of static methods that Sockets or Channels to
  47  * sockets that support the InfiniBand Sockets Direct Protocol (SDP).
  48  */
  49 
  50 public final class Sdp {
  51     private Sdp() { }
  52 
  53     /**
  54      * The package-privage ServerSocket(SocketImpl) constructor
  55      */
  56     private static final Constructor<ServerSocket> serverSocketCtor;
  57     static {
  58         try {
  59             serverSocketCtor =
  60                 ServerSocket.class.getDeclaredConstructor(SocketImpl.class);
  61             setAccessible(serverSocketCtor);
  62         } catch (NoSuchMethodException e) {
  63             throw new AssertionError(e);
  64         }
  65     }
  66 
  67     /**
  68      * The package-private SdpSocketImpl() constructor
  69      */
  70     private static final Constructor<SocketImpl> socketImplCtor;
  71     static {
  72         try {
  73             Class<?> cl = Class.forName("java.net.SdpSocketImpl", true, null);
  74             socketImplCtor = (Constructor<SocketImpl>)cl.getDeclaredConstructor();
  75             setAccessible(socketImplCtor);
  76         } catch (ClassNotFoundException e) {
  77             throw new AssertionError(e);
  78         } catch (NoSuchMethodException e) {
  79             throw new AssertionError(e);
  80         }
  81     }
  82 
  83     private static void setAccessible(final AccessibleObject o) {
  84         AccessController.doPrivileged(new PrivilegedAction<Void>() {
  85             public Void run() {
  86                 o.setAccessible(true);
  87                 return null;
  88             }
  89         });
  90     }
  91 
  92     /**
  93      * SDP enabled Socket.
  94      */
  95     private static class SdpSocket extends Socket {
  96         SdpSocket(SocketImpl impl) throws SocketException {
  97             super(impl);
  98         }
  99     }
 100 
 101     /**
 102      * Creates a SDP enabled SocketImpl
 103      */
 104     private static SocketImpl createSocketImpl() {
 105         try {
 106             return socketImplCtor.newInstance();
 107         } catch (InstantiationException x) {
 108             throw new AssertionError(x);
 109         } catch (IllegalAccessException x) {
 110             throw new AssertionError(x);
 111         } catch (InvocationTargetException x) {
 112             throw new AssertionError(x);
 113         }
 114     }
 115 
 116     /**
 117      * Creates an unconnected and unbound SDP socket. The {@code Socket} is
 118      * associated with a {@link java.net.SocketImpl} of the system-default type.
 119      *
 120      * @return  a new Socket
 121      *
 122      * @throws  UnsupportedOperationException
 123      *          If SDP is not supported
 124      * @throws  IOException
 125      *          If an I/O error occurs
 126      */
 127     public static Socket openSocket() throws IOException {
 128         SocketImpl impl = createSocketImpl();
 129         return new SdpSocket(impl);
 130     }
 131 
 132     /**
 133      * Creates an unbound SDP server socket. The {@code ServerSocket} is
 134      * associated with a {@link java.net.SocketImpl} of the system-default type.
 135      *
 136      * @return  a new ServerSocket
 137      *
 138      * @throws  UnsupportedOperationException
 139      *          If SDP is not supported
 140      * @throws  IOException
 141      *          If an I/O error occurs
 142      */
 143     public static ServerSocket openServerSocket() throws IOException {
 144         // create ServerSocket via package-private constructor
 145         SocketImpl impl = createSocketImpl();
 146         try {
 147             return serverSocketCtor.newInstance(impl);
 148         } catch (IllegalAccessException x) {
 149             throw new AssertionError(x);
 150         } catch (InstantiationException x) {
 151             throw new AssertionError(x);
 152         } catch (InvocationTargetException x) {
 153             Throwable cause = x.getCause();
 154             if (cause instanceof IOException)
 155                 throw (IOException)cause;
 156             if (cause instanceof RuntimeException)
 157                 throw (RuntimeException)cause;
 158             throw new RuntimeException(x);
 159         }
 160     }
 161 
 162     /**
 163      * Opens a socket channel to a SDP socket.
 164      *
 165      * <p> The channel will be associated with the system-wide default
 166      * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
 167      *
 168      * @return  a new SocketChannel
 169      *
 170      * @throws  UnsupportedOperationException
 171      *          If SDP is not supported or not supported by the default selector
 172      *          provider
 173      * @throws  IOException
 174      *          If an I/O error occurs.
 175      */
 176     public static SocketChannel openSocketChannel() throws IOException {
 177         FileDescriptor fd = SdpSupport.createSocket();
 178         return sun.nio.ch.Secrets.newSocketChannel(fd);
 179     }
 180 
 181     /**
 182      * Opens a socket channel to a SDP socket.
 183      *
 184      * <p> The channel will be associated with the system-wide default
 185      * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
 186      *
 187      * @return  a new ServerSocketChannel
 188      *
 189      * @throws  UnsupportedOperationException
 190      *          If SDP is not supported or not supported by the default selector
 191      *          provider
 192      * @throws  IOException
 193      *          If an I/O error occurs
 194      */
 195     public static ServerSocketChannel openServerSocketChannel()
 196         throws IOException
 197     {
 198         FileDescriptor fd = SdpSupport.createSocket();
 199         return sun.nio.ch.Secrets.newServerSocketChannel(fd);
 200     }
 201 }