FileDocCategorySizeDatePackage
Transport.javaAPI DocJCIFS 1.3.17 API9499Tue Oct 18 15:26:24 BST 2011jcifs.util.transport

Transport

public abstract class Transport extends Object implements Runnable
This class simplifies communication for protocols that support multiplexing requests. It encapsulates a stream and some protocol knowledge (provided by a concrete subclass) so that connecting, disconnecting, sending, and receiving can be syncronized properly. Apparatus is provided to send and receive requests concurrently.

Fields Summary
static int
id
static jcifs.util.LogStream
log
int
state
String
name
Thread
thread
TransportException
te
protected HashMap
response_map
Constructors Summary
Methods Summary
public synchronized voidconnect(long timeout)

        try {
            switch (state) {
                case 0:
                    break;
                case 3:
                    return; // already connected
                case 4:
                    state = 0;
                    throw new TransportException( "Connection in error", te );
                default:
                    TransportException te = new TransportException( "Invalid state: " + state );
                    state = 0;
                    throw te;
            }

            state = 1;
            te = null;
            thread = new Thread( this, name );
            thread.setDaemon( true );

            synchronized (thread) {
                thread.start();
                thread.wait( timeout );          /* wait for doConnect */

                switch (state) {
                    case 1: /* doConnect never returned */
                        state = 0;
                        thread = null;
                        throw new TransportException( "Connection timeout" );
                    case 2:
                        if (te != null) { /* doConnect throw Exception */
                            state = 4;                        /* error */
                            thread = null;
                            throw te;
                        }
                        state = 3;                         /* Success! */
                        return;
                }
            }
        } catch( InterruptedException ie ) {
            state = 0;
            thread = null;
            throw new TransportException( ie );
        } finally {
            /* This guarantees that we leave in a valid state
             */
            if (state != 0 && state != 3 && state != 4) {
                if (log.level >= 1)
                    log.println("Invalid state: " + state);
                state = 0;
                thread = null;
            }
        }
    
public synchronized voiddisconnect(boolean hard)

        IOException ioe = null;

        switch (state) {
            case 0: /* not connected - just return */
                return;
            case 2:
                hard = true;
            case 3: /* connected - go ahead and disconnect */
                if (response_map.size() != 0 && !hard) {
                    break; /* outstanding requests */
                }
                try {
                    doDisconnect( hard );
                } catch (IOException ioe0) {
                    ioe = ioe0;
                }
            case 4: /* in error - reset the transport */
                thread = null;
                state = 0;
                break;
            default:
                if (log.level >= 1)
                    log.println("Invalid state: " + state);
                thread = null;
                state = 0;
                break;
        }

        if (ioe != null)
            throw ioe;
    
protected abstract voiddoConnect()

protected abstract voiddoDisconnect(boolean hard)

protected abstract voiddoRecv(Response response)

protected abstract voiddoSend(Request request)

protected abstract voiddoSkip()

private voidloop()

        while( thread == Thread.currentThread() ) {
            try {
                Request key = peekKey();
                if (key == null)
                    throw new IOException( "end of stream" );
                synchronized (this) {
                    Response response = (Response)response_map.get( key );
                    if (response == null) {
                        if (log.level >= 4)
                            log.println( "Invalid key, skipping message" );
                        doSkip();
                    } else {
                        doRecv( response );
                        response.isReceived = true;
                        notifyAll();
                    }
                }
            } catch( Exception ex ) {
                String msg = ex.getMessage();
                boolean timeout = msg != null && msg.equals( "Read timed out" );
                /* If just a timeout, try to disconnect gracefully
                 */
                boolean hard = timeout == false;

                if (!timeout && log.level >= 3)
                    ex.printStackTrace( log );

                try {
                    disconnect( hard );
                } catch( IOException ioe ) {
                    ioe.printStackTrace( log );
                }
            }
        }
    
protected abstract voidmakeKey(Request request)

protected abstract RequestpeekKey()

public static intreadn(java.io.InputStream in, byte[] b, int off, int len)


         
                 
                 
                     
        int i = 0, n = -5;

        while (i < len) {
            n = in.read( b, off + i, len - i );
            if (n <= 0) {
                break;
            }
            i += n;
        }

        return i;
    
public voidrun()

        Thread run_thread = Thread.currentThread();
        Exception ex0 = null;

        try {
            /* We cannot synchronize (run_thread) here or the caller's
             * thread.wait( timeout ) cannot reaquire the lock and
             * return which would render the timeout effectively useless.
             */
            doConnect();
        } catch( Exception ex ) {
            ex0 = ex; // Defer to below where we're locked
            return;
        } finally {
            synchronized (run_thread) {
                if (run_thread != thread) {
                    /* Thread no longer the one setup for this transport --
                     * doConnect returned too late, just ignore.
                     */
                    if (ex0 != null) {
                        if (log.level >= 2)
                            ex0.printStackTrace(log);
                    }
                    return;
                }
                if (ex0 != null) {
                    te = new TransportException( ex0 );
                }
                state = 2; // run connected
                run_thread.notify();
            }
        }

        /* Proccess responses
         */
        loop();
    
public synchronized voidsendrecv(Request request, Response response, long timeout)


            
         
            
            
         

         
                     
                         
            makeKey( request );
            response.isReceived = false;
            try {
                response_map.put( request, response );
                doSend( request );
                response.expiration = System.currentTimeMillis() + timeout;
                while (!response.isReceived) {
                    wait( timeout );
                    timeout = response.expiration - System.currentTimeMillis();
                    if (timeout <= 0) {
                        throw new TransportException( name +
                                " timedout waiting for response to " +
                                request );
                    }
                }
            } catch( IOException ioe ) {
                if (log.level > 2)
                    ioe.printStackTrace( log );
                try {
                    disconnect( true );
                } catch( IOException ioe2 ) {
                    ioe2.printStackTrace( log );
                }
                throw ioe;
            } catch( InterruptedException ie ) {
                throw new TransportException( ie );
            } finally {
                response_map.remove( request );
            }
    
public java.lang.StringtoString()

        return name;