FileDocCategorySizeDatePackage
ClientOperation.javaAPI DocphoneME MR2 API (J2ME)21953Wed May 02 18:00:32 BST 2007com.sun.kvem.jsr082.obex

ClientOperation

public final class ClientOperation extends Object implements javax.obex.Operation
The class implements client side of put/get operation.

Fields Summary
private static final boolean
DEBUG
Debug information, should be false for RR.
private ClientSessionImpl
stream
private HeaderSetImpl
recvHeaders
private HeaderSetImpl
sentHeaders
private byte[]
head
private Object
lock
private boolean
inputStreamOpened
private boolean
inputStreamClosed
private boolean
outputStreamOpened
private boolean
outputStreamClosed
private boolean
inputStreamEof
private boolean
firstDataBlock
private int
openObjects
private OperationInputStream
is
private OperationOutputStream
os
private boolean
isGet
True if this operation is get operation. Otherwise it is put operation.
private boolean
requestEnd
Output stream finished, receiving data from input stream.
private boolean
operationEnd
private boolean
operationClosed
private boolean
restartable
private boolean
restarting
private boolean
abortingOperation
Determines whether aborting of operation is in progress. If true any read/write calls are denied.
Constructors Summary
ClientOperation(ClientSessionImpl stream, HeaderSetImpl sendHeaders, boolean isGet)


       
                
        if (DEBUG) {
            System.out.println("clientOperation.constructor(): isGet = "
                    + isGet);
        }
        this.isGet = isGet;
        head = new byte[] {
            isGet ? (byte) ObexPacketStream.OPCODE_GET
                  : (byte) ObexPacketStream.OPCODE_PUT,
            0, 0};

        stream.operation = this;
        stream.isEof = false;
        this.stream = stream;
        this.sentHeaders = sendHeaders == null ?
            new HeaderSetImpl(HeaderSetImpl.OWNER_CLIENT) : sendHeaders;
        recvHeaders = new HeaderSetImpl(HeaderSetImpl.OWNER_CLIENT);
        is = new OperationInputStream();
        os = new OperationOutputStream();

        // starting send process, fill in send buffer
        stream.packetBegin(head);
        if (sendHeaders == null
                || sendHeaders.getHeader(HeaderSet.TARGET) == null) {

            // early TARGET vs CONNECTION ID conflict check
            stream.packetAddConnectionID(
                    stream.getConnectionID(), sendHeaders);
        }
        stream.packetAddAuthResponses();
        stream.packetAddHeaders(sendHeaders);

        // if buffer is overflowed - begining to send packets
        while (stream.challengesToSend || !stream.queuedHeaders.isEmpty()) {
            if (!packetExchange()) {
                // Some headers may be lost if server early finish the
                // operation.
                return;
            }
        }
    
Methods Summary
public voidabort()

        abortingOperation = true;
        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: abort()");
            }
            if (operationClosed) {
                throw new IOException("operation closed");
            }
            try {
                if (operationEnd) {
                    throw new IOException(
                            "operation already finished");
                }
                sendAbortPacket();
            } finally {
                operationClosed = true;
                openObjects = 0;
                stream.operation = null;
            }
        }
    
public voidclose()

        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: op.close()");
            }
            if (!operationClosed) {
                operationClosed = true;
                terminate();
            }
        }
    
public java.lang.StringgetEncoding()

        return null; // acording to docs
    
public longgetLength()

        Long res = (Long)recvHeaders.getHeader(HeaderSetImpl.LENGTH);
        if (res == null) {
            return -1;
        }
        return res.longValue();
    
public javax.obex.HeaderSetgetReceivedHeaders()

        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: getReceivedHeaders()");
            }
            if (operationClosed) {
                throw new IOException("operation closed");
            }

            HeaderSetImpl res = new HeaderSetImpl(recvHeaders);
            res.packetType = ObexPacketStream.validateStatus(res.packetType);
            return res;
        }
    
public intgetResponseCode()

        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: getResponseCodes()");
            }
            if (operationClosed) {
                throw new IOException("operation closed");
            }

            requestEnd();

	    inputStreamOpened  = false;
            outputStreamOpened = false;
	    
	    
	    inputStreamClosed = true;
            outputStreamClosed = true;

	    openObjects = 1;

            return ObexPacketStream.validateStatus(recvHeaders.packetType);
        }
    
public java.lang.StringgetType()

        return (String)recvHeaders.getHeader(HeaderSetImpl.TYPE);
    
private voidnotRestartable()

        restartable = false;
        sentHeaders = null;
    
public java.io.DataInputStreamopenDataInputStream()

        return new DataInputStream(openInputStream());
    
public java.io.DataOutputStreamopenDataOutputStream()

        return new DataOutputStream(openOutputStream());
    
public java.io.InputStreamopenInputStream()

        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: openInputStream()");
            }
            if (operationClosed) {
                throw new IOException("operation closed");
            }
            if (inputStreamOpened) {
                throw new IOException("no more input streams available");
            }
            inputStreamOpened = true;
            openObjects++;
            if (!isGet) {
                return new FakeInputStream();
            }

            // flush rest of headers and data
            requestEnd();

            return is;
        }
    
public java.io.OutputStreamopenOutputStream()

        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: openOutputStream()");
            }
            if (operationClosed) {
                throw new IOException("operation closed");
            }
            if (outputStreamOpened) {
                throw new IOException("no more output streams available");
            }
            if (requestEnd) {
                throw new IOException("too late to open output stream");
            }
            outputStreamOpened = true;
            openObjects++;
            return os;
        }
    
private booleanpacketExchange()
Finish and send packet, received response, start new packet.

return
packetType == OPCODE_CONTINUE.

        if (DEBUG) {
            System.out.println("client: packetExchange()");
        }
        if (operationEnd) {
            if (requestEnd && stream.shouldSendAuthResponse()
                    && restartOperation()) {
                return true;
            }
            return false;
        }
        if (!requestEnd) {
            // finish packet end send it
            stream.packetEndStripConnID();

            // receive packet
            stream.recvPacket();
            operationEnd =
                stream.packetType != ObexPacketStream.OPCODE_CONTINUE;
            synchronized (recvHeaders) {
                stream.parsePacketHeaders(recvHeaders, 3);
            }

            // check code
            if (operationEnd) {
                if (stream.shouldSendAuthResponse() && restartOperation()) {
                    return true;
                }
                operationEnd = requestEnd = true;
                return false;
            }

            // begin new packet
            stream.packetBegin(head);
            stream.packetAddAuthResponses();
            stream.packetAddHeaders(null);
            return true;
        }

        // requestEnd = true

        stream.parseEnd();
        stream.sendPacket(head, -1, null, false);
        stream.recvPacket();
        operationEnd = stream.packetType != ObexPacketStream.OPCODE_CONTINUE;

        // check of errorcode should be done before after data parsing
        stream.parsePacketDataBegin(recvHeaders, 3);
        return true;
    
private voidrequestEnd()

        if (DEBUG) {
            System.out.println("client: requestEnd()");
        }
        synchronized (lock) {
            if (requestEnd) {
                return;
            }
            requestEnd = true;
        }
        head[0] |= ObexPacketStream.OPCODE_FINAL;

        if (operationEnd) {
            return;
        }

        if (outputStreamOpened) {
            boolean res = stream.packetEOFBody();
            if (!res) { // error adding EOFB previous packet too long
                if (!packetExchange()) {
                    return;
                }
                stream.packetEOFBody();
            }
        }

        stream.packetMarkFinal();
        stream.packetEndStripConnID();
        stream.recvPacket();
        operationEnd = stream.packetType != ObexPacketStream.OPCODE_CONTINUE;

        if (!isGet) {
            stream.parsePacketHeaders(recvHeaders, 3);
            return;
        }

        stream.parsePacketDataBegin(recvHeaders, 3);

        while (true) {
            // special request to check data availability
            int hasData = stream.parsePacketData(recvHeaders, null, 0, 0);
            if (hasData == 1 || stream.isEof) break;

            if (stream.shouldSendAuthResponse() && restartOperation()) {
                return;
            }
            if (!packetExchange()) {
                return;
            }
        }
    
private booleanrestartOperation()

        if (DEBUG) {
            System.out.println("client: restartOperation()");
        }
        if (!restartable) {
            return false;
        }
        HeaderSetImpl headers = sentHeaders;
        notRestartable();
        operationEnd = false;
        boolean prevRequestEnd = requestEnd;
        requestEnd = false;
        head[0] = isGet ? (byte) ObexPacketStream.OPCODE_GET
                        : (byte) ObexPacketStream.OPCODE_PUT;

        recvHeaders = new HeaderSetImpl(HeaderSetImpl.OWNER_CLIENT);
        stream.queuedHeaders.removeAllElements();
        stream.isEof = false;

        // starting send process, fill in send buffer
        stream.packetBegin(head);
        stream.packetAddConnectionID(stream.getConnectionID(), headers);
        stream.packetAddAuthResponses();
        stream.packetAddHeaders(headers);

        // if buffer is overflowed - begining to send packets
        while (!stream.queuedHeaders.isEmpty()) {
            if (!packetExchange()) {
                return true;
            }
        }
        if (prevRequestEnd) {
            requestEnd();
        }
        restarting = true;
        return true;
    
private voidsendAbortPacket()

        if (operationEnd) {
            return;
        }

        inputStreamClosed = true;
        outputStreamClosed = true;
        operationEnd = true;
        requestEnd = true;
        stream.queuedHeaders.removeAllElements();
        stream.sendPacket(ObexPacketStream.PACKET_ABORT, -1, null, true);
        stream.recvPacket();
        stream.parsePacketHeaders(recvHeaders, 3);

        if (stream.packetType != ResponseCodes.OBEX_HTTP_OK) {
            stream.brokenLink();
        }
    
public voidsendHeaders(javax.obex.HeaderSet headers)

        synchronized (lock) {
            if (DEBUG) {
                System.out.println("client: sendHeaders()");
            }
            if (operationClosed) {
                throw new IOException("operation closed");
            }
            if (headers == null) {
                throw new NullPointerException("null headerset");
            }
            if (!(headers instanceof HeaderSetImpl)) {
                throw new IllegalArgumentException("wrong headerset class");
            }
            HeaderSetImpl headersImpl = (HeaderSetImpl) headers;
            if (!headersImpl.isSendable()) {
                throw new IllegalArgumentException(
                        "not created with createHeaderSet");
            }
            if (operationEnd) {
                throw new IOException("operation finished");
            }

            if (restartable) {
                // store the headers to accumulated headers
                sentHeaders.merge(headersImpl);
            }

            stream.packetAddHeaders(headersImpl);

            if (requestEnd) {
                return;
            }

            if (!stream.queuedHeaders.isEmpty()) {
                if (!packetExchange()) {
                    throw new IOException(
                            "server finished operation, not all headers sent");
                }
            }
        }
    
private voidterminate()

        if (DEBUG) {
            System.out.println("client: terminate() = "
                    + (openObjects - 1));
        }
        openObjects--;
        if (openObjects != 0) {
            return;
        }

        // all closed what was opened.
        sendAbortPacket();
        stream.operation = null;