FileDocCategorySizeDatePackage
ASClientSocketImpl.javaAPI DocGlassfish v2 API18433Tue May 29 01:53:52 BST 2007com.sun.enterprise.server.ss.provider

ASClientSocketImpl

public final class ASClientSocketImpl extends SocketImpl
NIO based SocketImpl implementation used by java.net.Socket. The implementation is used always in the non-blocking mode.

Fields Summary
private static final Logger
logger
private SocketChannel
sc
private Socket
sock
private InputStream
is
private boolean
usePlainSockets
private ASPlainSocketImpl
ps
Constructors Summary
Methods Summary
public voidaccept(java.net.SocketImpl si)

	throw new UnsupportedOperationException(
		    "accept() not supported in ASClientSocketImpl");
    
public intavailable()


         
        if (usePlainSockets) {
            return getPlainSocket().available();
        }
        return 0;
    
public voidbind(java.net.InetAddress ia, int port)

        if (usePlainSockets) {
            getPlainSocket().bind(ia, port);
            return;
        }
        InetSocketAddress isa = new InetSocketAddress(ia, port);
        getClientSocket().bind(isa);
    
public voidclose()
Apart from closing the internal socket ant it's channel, we need to shutdown the output also. This is necessary because 1) A normal socket's InputStream will get an EOF, when its remote socket closes. 2) But in case of non blocking IO, if a selector is registered on the channel with OP_WRITE key, the output of the socket doesnt get shutdown immediately even when the socket/channel is closed. This could lead to its corrsponding InputStream longer to get closed. We explicitely shutdown to fix this problem. Note that, if a program, expects its output stream to be open for a few microseconds after the socket is closed and try to do some smart stuff, may not work correctly. But that is a very very very rare case.

        if (usePlainSockets) {
            getPlainSocket().close();
            return;
        }
        if (sock != null) {
            try {
                sock.shutdownOutput();
            } catch (Exception e) {
                if ( logger.isLoggable(Level.FINER) ) {
                    logger.log(Level.FINER, "" + e.getMessage(), e);
                }
            }
            try {
	        sock.close();
                sc.close();
            } catch (IOException ie) {
                if ( logger.isLoggable(Level.FINER) ) {
                    logger.log(Level.FINER, "" + ie.getMessage(), ie);
                }
                //throw ie;
            } catch (Error er) {
                if ( logger.isLoggable(Level.FINE) ) {
                    logger.log(Level.FINE, "" + er.getMessage(), er);
                }
                // This ideally should not happen...
            }
            is = null;
        }
    
public voidconnect(java.lang.String host, int port)

        if (usePlainSockets) {
            getPlainSocket().connect(host, port);
            return;
        }
        InetSocketAddress isa = new InetSocketAddress(host, port);
        if ( logger.isLoggable(Level.FINE) ) {
            logger.fine("In ASClientSocketImpl.connect, host = "+host
	 					     +" port = "+port);
        }
        connect(isa);
    
public voidconnect(java.net.InetAddress ia, int port)

        if (usePlainSockets) {
            getPlainSocket().connect(ia, port);
            return;
        }
        InetSocketAddress isa = new InetSocketAddress(ia, port);
        if ( logger.isLoggable(Level.FINE) ) {
	    logger.fine("In ASClientSocketImpl.connect, host = "+ia.getHostName()
							       +" port = "+port);
        }
        connect(isa);
    
private voidconnect(java.net.InetSocketAddress isa)

        connect(isa,0);
    
public voidconnect(java.net.SocketAddress sa, int timeout)

        if (usePlainSockets) {
            getPlainSocket().connect(sa, timeout);
            return;
        }
        if (sa == null || !(sa instanceof InetSocketAddress)) {
            throw new IllegalArgumentException("unsupported address type");
	}
	
        InetSocketAddress addr = (InetSocketAddress) sa;
        if (addr.isUnresolved()) {
            throw new UnknownHostException(addr.getHostName());
	}
        this.port = addr.getPort();
        this.address = addr.getAddress();

        // Check whether the socketservice is notified. If it is not, then
        // this is the first connection to the service. This will trigger
        // the startup. So, this connection should be serviced only after
        // the completion of service startup.
        boolean waitForStartupReqd = ! ASSocketFacadeUtils.getASSocketService().
                                      socketServiceNotified(this.port);

        SocketChannel ch = getClientSocketChannel();
        boolean connected = ch.connect(sa);
	if ( !connected ) {
	    waitForSelect(timeout);
	    if (ch.finishConnect() == false) {
		throw new IOException("Connection timed out");
	    }
	}

        if (ASSocketFacadeUtils.getASSocketService().
        isLocalClient(address) == false) {
            return;
        }

	// Inform the ASSocketService about this socket, so that it can
	// correctly block remote sockets while allowing local loopback sockets.
	// Note: this needs to be called when NIO sockets are created too,
	// for now we dont do it because the Windows NIO impl does not allow 
	// SocketChannel to be wrapped (it casts the SocketChannel to an
	// internal class).
        Socket connectedSocket = sc.socket();
        if (waitForStartupReqd) {
            ASSocketFacadeUtils.getASSocketService().
            waitOnClientConnection(connectedSocket.getPort());
        }
	ASSocketFacadeUtils.getASSocketService().clientSocketConnected(
             connectedSocket.getPort(), connectedSocket.getLocalPort());
    
public voidcreate(boolean stream)

        if (usePlainSockets) {
            getPlainSocket().create(stream);
        }
    
private voidcreateSocket()

	sc = SocketChannel.open();
        sc.configureBlocking(false);
	sock = sc.socket();
    
protected voidfinalize()

        try {
            close();
        } catch (Throwable t) {}
    
private java.net.SocketgetClientSocket()

	if ( sock == null ) {
            createSocket();
	}
	return sock;
    
private java.nio.channels.SocketChannelgetClientSocketChannel()

	if ( sc == null ) {
            createSocket();
	}
	return sc;
    
public java.net.InetAddressgetInetAddress()

        if (usePlainSockets) {
            return getPlainSocket().getInetAddress();
        }
        try {
            return getClientSocket().getInetAddress();
        } catch (IOException ie) {
            if ( logger.isLoggable(Level.FINE) ) {
                 logger.log(Level.FINE, "" + ie.getMessage(), ie);
            }
            // Typically this will never be executed.
            return super.getInetAddress();
        }
    
public java.io.InputStreamgetInputStream()

        if (usePlainSockets) {
            return getPlainSocket().getInputStream();
        }
        if (this.is == null) {
            this.is = new ASInputStream(getClientSocketChannel(), getClientSocket()); 
        }
        return this.is;
    
public intgetLocalPort()

        if (usePlainSockets) {
            return getPlainSocket().getLocalPort();
        }
        try {
            return getClientSocket().getLocalPort();
        } catch (IOException ie) {
            if ( logger.isLoggable(Level.FINE) ) {
                 logger.log(Level.FINE, "" + ie.getMessage(), ie);
            }
            // Typically this will never be executed.
            return super.getLocalPort();
        }
    
public java.lang.ObjectgetOption(int opt)

        if (usePlainSockets) {
            return getPlainSocket().getOption(opt);
        }
        try {
            switch (opt) {
                case SO_LINGER:
                    return new Integer(getClientSocket().getSoLinger());
                case SO_TIMEOUT:
                    return new Integer(getClientSocket().getSoTimeout());
                case IP_TOS:
                    return new Integer(getClientSocket().getTrafficClass());
                case SO_BINDADDR:
	            return getClientSocket().getInetAddress();
                case TCP_NODELAY:
                    return new Boolean(getClientSocket().getTcpNoDelay());
                case SO_SNDBUF:
                    return new Integer(getClientSocket().getSendBufferSize());
                case SO_RCVBUF:
                    return 
                    new Integer(getClientSocket().getReceiveBufferSize());
                case SO_KEEPALIVE:
                    return new Boolean(getClientSocket().getKeepAlive());
                case SO_OOBINLINE:
                    return new Boolean(getClientSocket().getOOBInline());
                case SO_REUSEADDR:
                    return new Boolean(getClientSocket().getReuseAddress());
                default:
                    throw 
                    new SocketException("unrecognized TCP option: " + opt);
            }
        } catch (SocketException se) {
            throw se;
        } catch (IOException ie) {
            throw (SocketException)
            (new SocketException(ie.getMessage())).initCause(ie);
        }
    
public java.io.OutputStreamgetOutputStream()

        if (usePlainSockets) {
            return getPlainSocket().getOutputStream();
        }
        return new ASOutputStream(getClientSocketChannel(), getClientSocket());
    
ASPlainSocketImplgetPlainSocket()
The plain socket implementation will be used for any outbound communication will use this socketimpl.

        if (ps == null) {
            ps = new ASPlainSocketImpl();
        }
        return ps;
    
public intgetPort()


        if (usePlainSockets) {
            return getPlainSocket().getPort();
        }

        try {
            return getClientSocket().getPort();
        } catch (IOException ie) {
            if ( logger.isLoggable(Level.FINE) ) {
                 logger.log(Level.FINE, "" + ie.getMessage(), ie);
            }
            // Typically this will never be executed.
            return super.getPort();
        }
    
public voidlisten(int i)

	throw new UnsupportedOperationException(
		    "listen() not supported in ASClientSocketImpl");
    
public voidsendUrgentData(int i)

        if (usePlainSockets) {
            getPlainSocket().sendUrgentData(i);
            return;
        }
        getClientSocket().sendUrgentData(i);
    
voidsetClientSocket(java.net.Socket s)

        usePlainSockets = false;
	sock = s;
	sc = sock.getChannel();
        sc.configureBlocking(false);
        localport = sock.getLocalPort();
        port = sock.getPort();
        address = sock.getInetAddress();
    
public voidsetOption(int opt, java.lang.Object val)

        if (usePlainSockets) {
            getPlainSocket().setOption(opt, val);
            return;
        }
	try {
	    switch (opt) {
	    case SO_LINGER:
		if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
		    throw new SocketException("Bad parameter for option");
		if (val instanceof Boolean) {
		    if ( ((Boolean)val).booleanValue() == true )
			throw new SocketException("Bad parameter for option");
		    getClientSocket().setSoLinger( false, 0); 
		} else {
		    getClientSocket().setSoLinger( true, ((Integer) val).intValue());
		}
		break;
	    case SO_TIMEOUT:
		if (val == null || (!(val instanceof Integer)))
		    throw new SocketException("Bad parameter for SO_TIMEOUT");
		int tmp = ((Integer) val).intValue();
		if (tmp < 0)
		    throw new IllegalArgumentException("timeout < 0");
		//timeout = tmp;
		getClientSocket().setSoTimeout( tmp );
		break;
	    case IP_TOS:
		 if (val == null || !(val instanceof Integer)) {
		     throw new SocketException("bad argument for IP_TOS");
		 }
		 int trafficClass = ((Integer)val).intValue();
		 getClientSocket().setTrafficClass( trafficClass );
		 break;
	    case SO_BINDADDR:
		throw new SocketException("Cannot re-bind socket");
	    case TCP_NODELAY:
		if (val == null || !(val instanceof Boolean))
		    throw new SocketException("bad parameter for TCP_NODELAY");
		
		getClientSocket().setTcpNoDelay( ((Boolean)val).booleanValue() );
		break;
	    case SO_SNDBUF:
		if (val == null || !(val instanceof Integer) ||
		    !(((Integer)val).intValue() > 0)) {
		    throw new SocketException("bad parameter for SO_SNDBUF " );
		}
		getClientSocket().setSendBufferSize( ((Integer) val).intValue() );
		break;
	    case SO_RCVBUF:
		if (val == null || !(val instanceof Integer) ||
		    !(((Integer)val).intValue() > 0)) {
		    throw new SocketException("bad parameter for SO_SNDBUF " +
					      "or SO_RCVBUF");
		}
		getClientSocket().setReceiveBufferSize( ((Integer) val).intValue() );
		break;
	    case SO_KEEPALIVE:
		if (val == null || !(val instanceof Boolean))
		    throw new SocketException("bad parameter for SO_KEEPALIVE");
		getClientSocket().setKeepAlive( ((Boolean)val).booleanValue() );
		break;
	    case SO_OOBINLINE:
		if (val == null || !(val instanceof Boolean))
		    throw new SocketException("bad parameter for SO_OOBINLINE");
		getClientSocket().setOOBInline( ((Boolean)val).booleanValue() );
		break;
	    case SO_REUSEADDR:
		if (val == null || !(val instanceof Boolean)) 
		    throw new SocketException("bad parameter for SO_REUSEADDR");
		getClientSocket().setReuseAddress( ((Boolean)val).booleanValue() );
		break;
	    default:
		throw new SocketException("unrecognized TCP option: " + opt);
	    }

	} catch ( IOException ioex ) {
	    if ( ioex instanceof SocketException )
		throw ((SocketException)ioex);
	    else
		throw (SocketException)(new SocketException()).initCause(ioex);
	}
    
public voidshutdownInput()

        if (usePlainSockets) {
            getPlainSocket().shutdownInput();
            return;
        }
        getClientSocket().shutdownInput();
    
public voidshutdownOutput()

        if (usePlainSockets) {
            getPlainSocket().shutdownOutput();
            return;
        }
        getClientSocket().shutdownOutput();
    
public booleansupportsUrgentData()

        if (usePlainSockets) {
            return getPlainSocket().supportsUrgentData();
        }
        return true;
    
private voidwaitForSelect(long timeout)

        Selector selector = Selector.open();
        this.sc.register(selector, SelectionKey.OP_CONNECT); 
        
        selectorblock:
            while (true) {
                try {
                    int n = selector.select(timeout);
                    if (n==0 && this.sc.finishConnect()) {
                        break;
                    }
                    Iterator it = selector.selectedKeys().iterator();
                    while (it.hasNext()) {
                        SelectionKey selKey = (SelectionKey)it.next();
                        if (selKey.isValid() && selKey.isConnectable()) {
                            it.remove();
                            break selectorblock;
                        }
                    }
                } catch (Exception e) {
                    throw (IOException) (new IOException()).initCause(e);
                }
            }
        try {
            selector.close();
        } catch (IOException ie) {
            if ( logger.isLoggable(Level.FINE) ) {
                logger.log(Level.FINE, ie.getMessage(), ie);
            }
        }