SendState.java

/*
 * Copyright © 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners. 
 * See LICENSE.TXT for license information.
 */ 
package com.nokia.example.bcexchanger.comm;

import java.io.IOException;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.obex.ClientSession;
import javax.obex.HeaderSet;
import javax.obex.Operation;
import javax.obex.ResponseCodes;

/**
 * This class implements business card sending state. In this state a client
 * OBEX PUT operation is performed. No OBEX server commands are served.
 * 
 * This class extends ExchangerState abstract class. 
 * 
 * @see bcexchanger.comm.ExchangerState Design Patterns: State
 */
public class SendState extends ExchangerState {

    // Instance variables
    private ClientSession connection = null;
    private String url = null;
    private Operation operation = null;
    private boolean cancelInvoked = false;

    /**
     * Constructor
     * 
     * @param _parent -
     *            the class which is nesting the current state of the state
     *            machine
     * @param _url -
     *            a URL of the remote OBEX service. This state is responsible
     *            for establishing the connection
     */
    public SendState(ExchangerStateParent _parent, String _url) {
        super(_parent);

        url = _url;
    }

    /*
     * SendState does not allow to start any other business card exchange
     * process.
     * 
     * @see bcexchanger.comm.ExchangerState#startSending()
     */
    public void startSending(int o) throws IOException {
        throw new IOException(
                "Sending is in progress. Sending has to be canceled before starting new sending process");
    }

    /*
     * SendState allows to cancel sending process.
     * 
     * @see bcexchanger.comm.ExchangerState#cancelSending()
     */
    public void cancelSending() {
        cancelInvoked = true;

        try { // cancel any active OBEX operation
            operation.abort();
        } catch (Exception e) { // catch NullPointer exception also
            // Ignore, aborting anyway
        }

        try { // send DISCONNECT to the remote peer

            connection.disconnect(null);
        } catch (Exception e1) { // catch NullPointer exception also
            // Ignore, disconnecting anyway
        }

        try { // close the connection
            connection.close(); // 

        } catch (Exception e2) { // catch NullPointer exception also
            // Ignore, closing anyway
        }
    }

    /*
     * This method implements the logic for sending a
     * business card
     * 
     */
    public void doSend() {
        try {
            connection = (ClientSession) Connector.open(url);
            HeaderSet response = connection.connect(null);

            // Initiate the PUT request
            operation = connection.put(null);
            OutputStream out = operation.openOutputStream();
            //getting the own card
            byte[] vCard = parent.getListener().getOwnBC();
            int vlen = vCard.length;
            byte[] tmpBuf = new byte[vlen + 4];
            System.arraycopy(vCard, 0, tmpBuf, 4, vlen);
            tmpBuf[0] = (byte) ((vlen >>> 24) & 0xff);
            tmpBuf[1] = (byte) ((vlen >>> 16) & 0xff);
            tmpBuf[2] = (byte) ((vlen >>> 8) & 0xff);
            tmpBuf[3] = (byte) ((vlen >>> 0) & 0xff);
            //sending data
            out.write(tmpBuf);
            out.close();
            int responseCode = operation.getResponseCode();

            operation.close();

            if (cancelInvoked) {
                throw new Exception(
                        "Cancel did not invoke any exception; throw exception then");
            }

            // send is done
            try {
                parent.setState(new IdleState(parent));
            } catch (Exception e) {
            }
        } catch (Exception e1) {
            parent.setState(new IdleState(parent));
            if (cancelInvoked) { // if exception is caused by cancellation
                parent.getListener().onSendComplete(ExchangerComm.CANCELED);
            } else { // if exception is caused by error
                parent.setState(new IdleState(parent));
                parent.getListener().onSendComplete(ExchangerComm.ERROR);
            }
        } finally {
            try { // finalizing operation
                operation.close();
            } catch (IOException e3) {
            }

            try { // sending DISCONNECT command
                connection.disconnect(null);
                connection.close();
            } catch (IOException e2) {
                // Ignore, disconnecting anyway
            }
        }
    }

    /*
     * Server OBEX GET command is supported only in IdleState
     * 
     * @see bcexchanger.comm.ExchangerState#onGet(javax.obex.Operation)
     */
    public int onGet(Operation op) {
        return ResponseCodes.OBEX_HTTP_CONFLICT;
    }

    /*
     * Server OBEX PUT command is supported only in IdleState
     * 
     * @see bcexchanger.comm.ExchangerState#onPut(javax.obex.Operation)
     */
    public int onPut(Operation op) {
        return ResponseCodes.OBEX_HTTP_CONFLICT;
    }
}