FileDocCategorySizeDatePackage
Protocol.javaAPI DocphoneME MR2 API (J2ME)25158Wed May 02 18:00:32 BST 2007com.sun.midp.io.j2me.cbs

Protocol

public class Protocol extends com.sun.midp.io.j2me.ProtocolBase
CBS message connection implementation. Cell Broadcast message connections are receive only.

Fields Summary
protected static Vector
openConnections
Currently opened connections.
private int
m_imsgid
Local handle for port number.
protected String
url
Name of current connection.
protected static final int
GSM_TEXT
DCS: GSM Alphabet
protected static final int
GSM_BINARY
DCS: Binary
protected static final int
GSM_UCS2
DCS: Unicode UCS-2
Constructors Summary
public Protocol()
Creates a message connection protocol handler.


           
      
        super();
        ADDRESS_PREFIX = "cbs://";
    
Methods Summary
protected voidcheckReceivePermission()
Checks the internal setting of the receive permission. Called from the receive and setMessageListener methods.

exception
InterruptedIOException if permission dialog was pre-empted.


        /* Check if we have permission to receive. */
        if (readPermission == false) {
            try {
                midletSuite.checkForPermission(Permissions.CBS_RECEIVE,
                                               "cbs:receive");
                readPermission = true;
            } catch (InterruptedException ie) {
                throw new InterruptedIOException("Interrupted while trying " +
                                               "to ask the user permission.");
            }
        }
    
public voidclose()
Closes the connection. Resets the connection open flag to false. Subsequent operations on a closed connection should throw an appropriate exception.

exception
IOException if an I/O error occurs


        /*
         * Set m_imsgid to 0, in order to quit out of the while loop
         * in the receiver thread.
         */
        int save_imsgid = m_imsgid;
        m_imsgid = 0;

        synchronized (closeLock) {
            if (open) {
                /*
                 * Reset open flag early to prevent receive0 executed by
                 * concurrent thread to operate on partially closed
                 * connection
                 */
                open = false;
                /* Close the connection and unregister the application ID. */
                close0(save_imsgid, connHandle, 1);

                setMessageListener(null);

                /*
                 * Reset handle and other params to default
                 * values. Multiple calls to close() are allowed
                 * by the spec and the resetting would prevent any
                 * strange behaviour.
                 */
                connHandle = 0;
                m_mode = 0;

                /*
                 * Remove this connection from the list of open connections.
                 */
                for (int i = 0, n = openConnections.size(); i < n; i++) {
                    if (openConnections.elementAt(i) == this) {
                        openConnections.removeElementAt(i);
                        break;
                    }
                }
            }
        }
    
private native intclose0(int port, int handle, int deRegister)
Native function to close cbs connection

param
port The port number to close.
param
handle The CBS handle returned by open0.
param
deRegister Deregistration appID when parameter is 1.
return
0 on success, -1 on failure.

protected intclose00(int connHandle, int deRegister)
Close connection.

param
connHandle handle returned by open0
param
deRegister Deregistration appID when parameter is 1.
return
0 on success, -1 on failure

        return close0(m_imsgid, connHandle, deRegister);
    
private native voidfinalize()
Native finalizer

protected java.lang.StringgetAppID()
Gets the connection parameter in string mode.

return
string that contains a parameter

        if (m_imsgid > 0) {
            return new String(Integer.toString(m_imsgid));
        } else {
            return null;
        }
    
public javax.wireless.messaging.MessagenewMessage(java.lang.String type)
Constructs a new message object of a binary or text type. If the TEXT_MESSAGE constant is passed in, the TextMessage interface is implemented by the created object. If the BINARY_MESSAGE constant is passed in, the BinaryMessage interface is implemented by the created object.

If this method is called in a sending mode, a new Message object is requested from the connection. For example:

Message msg = conn.newMessage(TEXT_MESSAGE);

The Message object that was created doesn't have the destination address set. It's the application's responsibility to set it before the message is sent.

If this method is called in receiving mode, the Message object does have its address set. The application can act on the object to extract the address and message data.

param
type TEXT_MESSAGE or BINARY_MESSAGE.
return
A new CBS Message object.


        /* Create the CBS-formatted URL. */
        String address = ADDRESS_PREFIX;
        if (m_imsgid != 0) {
            address = address + ":" + String.valueOf(m_imsgid);
        }

        return newMessage(type, address);
    
public javax.wireless.messaging.MessagenewMessage(java.lang.String type, java.lang.String addr)
Constructs a new message object of a text or binary type and specifies a destination address. If the TEXT_MESSAGE constant is passed in, the TextMessage interface is implemented by the created object. If the BINARY_MESSAGE constant is passed in, the BinaryMessage interface is implemented by the created object.

The destination address addr has the following format:

cbs://phone_number:port

param
type TEXT_MESSAGE or BINARY_MESSAGE.
param
addr The destination address of the message.
return
A new CBS Message object.

        Message msg = null;

        if (type.equals(MessageConnection.TEXT_MESSAGE)) {
            msg = new TextObject(addr);

        } else if (type.equals(MessageConnection.BINARY_MESSAGE)) {
            msg = new BinaryObject(addr);

        } else {
            throw new IllegalArgumentException("Message type not supported.");
        }

        return msg;
    
public intnumberOfSegments(javax.wireless.messaging.Message message)
Returns the number of segments required to send the given Message.

Note: The message is not actually sent. The number of protocol segments is simply computed.

This method calculates the number of segments required when this message is split into the protocol segments utilizing the underlying protocol's features. Possible implementation's limitations that may limit the number of segments that can be sent using it are not taken into account. These limitations are protocol specific. They are documented with that protocol's adapter definition.

param
message The message to be used for the computation.
return
The number of protocol segments needed for sending the message. Returns 0 if the Message object cannot be sent using the underlying protocol.


        /* When a message is present, there is always just one segment. */
        return (message != null) ? 1 : 0;
    
private native intopen0(int msgID, int msid)
Native function to open a CBS connection.

param
msgID The message ID to be matched against incoming messages.
param
msid Midlet Suite ID.
return
returns handle to the open CBS connection.

public java.io.DataInputStreamopenDataInputStream()
Open and return a data input stream for a connection. This method always throw IllegalArgumentException. a

return
An input stream.
exception
IOException if an I/O error occurs.
exception
IllegalArgumentException is thrown for all requests.


        throw new IllegalArgumentException("Not supported");
    
public java.io.DataOutputStreamopenDataOutputStream()
Open and return a data output stream for a connection. This method always throw IllegalArgumentException.

return
An output stream.
exception
IOException if an I/O error occurs.
exception
IllegalArgumentException is thrown for all requests.


        throw new IllegalArgumentException("Not supported");
    
public java.io.InputStreamopenInputStream()
Open and return an input stream for a connection. This method always throw IllegalArgumentException.

return
An input stream.
exception
IOException if an I/O error occurs.
exception
IllegalArgumentException is thrown for all requests.


        throw new IllegalArgumentException("Not supported");
    
public java.io.OutputStreamopenOutputStream()
Open and return an output stream for a connection. This method always throw IllegalArgumentException.

return
An output stream.
exception
IOException if an I/O error occurs.
exception
IllegalArgumentException is thrown for all requests.


        throw new IllegalArgumentException("Not supported");
    
public javax.microedition.io.ConnectionopenPrim(java.lang.String name, int mode, boolean timeouts)
Opens a CBS connection. This method is called from the Connector.open() method to obtain the destination address given in the name parameter.

The format for the name string for this method is:

cbs://[phone_number:][port_number]

where the phone_number: is optional. If the phone_number parameter is present, the connection is being opened in client mode. This means that messages can be sent. If the parameter is absent, the connection is being opened in server mode. This means that messages can be sent and received.

The connection that is opened is to a low-level transport mechanism which can be any of the following:

  • a datagram Short Message Peer-to-Peer (SMPP) to a service center
  • a comm connection to a phone device with AT-commands
  • .
  • a native CBS stack
Currently, the mode and timeouts parameters are ignored.

param
name the target of the connection
param
mode indicates whether the caller intends to write to the connection. Currently, this parameter is ignored.
param
timeouts indicates whether the caller wants timeout exceptions. Currently, this parameter is ignored.
return
this connection
exception
IOException if the connection is closed or unavailable


        return openPrimInternal(name, mode, timeouts);
    
public synchronized javax.microedition.io.ConnectionopenPrimInternal(java.lang.String name, int mode, boolean timeouts)
Opens a CBS connection. This is the internal entry point that allows the CBS protocol handler to use the reserved port for CBS emulated messages.

param
name The name of the connection, which as a format of "//:portNumber" for CBS connections.
param
mode Must be READ, only.
param
timeouts Indicates whether the caller wants time-out exceptions. Currently ignored.
return
the successfully opened connection.
exception
IOException if the connection is closed or unavailable.


        // The connection must not be WRITE-only. A form of READ is OK.
        if (mode == Connector.WRITE) {
            throw new IllegalArgumentException("WRITE not supported.");
        }

        // Check the I/O constraint.
        if ((mode != Connector.READ) &&
            (mode != Connector.READ_WRITE)) {
            throw new IllegalArgumentException("Invalid I/O constraint.");
        }

        /*
         * The general form of a CBS address is <code>cbs://host:port</code>.
         * CBS is receive-only, so the <code>host</code> must not be present
         * making the address form: <code>cbs://:port</code>.
         */
        if (name.charAt(0) != '/" || name.charAt(1) != '/") {
            throw new IllegalArgumentException("Missing protocol separator.");
        }

        /* Ensure no host name before extracting the port number text. */
        int colon = name.indexOf(':");
        if (colon != 2) {
            throw new IllegalArgumentException("Host not supported.");
        }
        String msgIDText = name.substring(colon + 1);

        /* Verify that the message ID is in range. */
        int msgID = 0;

        try {
            msgID = Integer.parseInt(msgIDText);
            if ((msgID > 65535) || (msgID < 0)) {
                throw new IllegalArgumentException("Message ID out of range.");
            }
        } catch (NumberFormatException nfe) {
            throw new IllegalArgumentException("Message ID formatted badly.");
        }

        /*
         * Perform a one-time check to see if the application has the permission
         * to use this connection type.
         */
        if (openPermission == false) {
            try {
                midletSuite.checkForPermission(Permissions.CBS_SERVER,
                                               "cbs:open");
                openPermission = true;
            } catch (InterruptedException ie) {
                throw new InterruptedIOException("Interrupted while trying " +
                                                "to ask the user permission.");
            }
        }

        /* See if the connection is already open. */
        for (int i = 0, n = openConnections.size(); i < n; i++) {
            if (((Protocol)openConnections.elementAt(i)).url.equals(name)) {
                throw new IOException("Connection already open.");
            }
        }

        /* Set up URL and port information, first. */
        url = name;
        m_imsgid = 0;
        if (msgIDText != null) {
            m_imsgid = msgID;
        }

        try {
            connHandle = open0(m_imsgid, midletSuite.getID());
        } catch (IOException ioexcep) {
            m_mode = 0;
            throw new IOException("Unable to open CBS connection.");
        } catch (OutOfMemoryError oomexcep) {
            m_mode = 0;
            throw new IOException("Unable to open CBS connection.");
        }

        /* Save this connection, which is now populated with URL and port. */
        openConnections.addElement(this);

        m_mode = mode;  /* This should always be READ. */
        open = true;

        return this;
    
public synchronized javax.wireless.messaging.Messagereceive()
Receives the bytes that have been sent over the connection, constructs a Message object, and returns it.

If there are no Messages waiting on the connection, this method will block until the MessageConnection is closed, or a message is received.

return
a Message object
exception
java.io.IOException if an error occurs while receiving a message.
exception
java.io.InterruptedIOException if this MessageConnection object is closed during the call of this method.
exception
java.lang.SecurityException if the application doesn't have permission to receive messages on the given port.


        checkReceivePermission();

        /* Make sure the connection is still open. */
        ensureOpen();

        /* The connection must be read-only with no host address. */
        if (m_mode == Connector.WRITE) {
            throw new IOException("Invalid connection mode.");
        }

        /* No message received yet. */
        Message msg = null;
        int length = 0;

        try {

            CBSPacket cbsPacket = new CBSPacket();

            /*
             * Packet has been received and deleted from inbox.
             * Time to wake up receive thread.
             */
                // Pick up the CBS message from the message pool.
            length = receive0(m_imsgid, midletSuite.getID(),
                              connHandle, cbsPacket);

            if (length < 0) {
                throw new InterruptedIOException("Connection closed.");
            }

            /* Messages other than binary are assumed to be text. */
            String type = MessageConnection.TEXT_MESSAGE;
            boolean isTextMessage = true;
            if (cbsPacket.encodingType == GSM_BINARY)  {
                type = MessageConnection.BINARY_MESSAGE;
                isTextMessage = false;
            }

            /* Construct a message with proper encoding type and address. */
            msg = newMessage(type,
                new String(ADDRESS_PREFIX + ":" + cbsPacket.msgID));

            /* Set message payload as text or binary. Message can be null. */
            if (isTextMessage) {

                String text = null;
                if (cbsPacket.message != null) {
                    if (cbsPacket.encodingType == GSM_TEXT) {
                        text = new String(TextEncoder.toString(
                            TextEncoder.decode(cbsPacket.message)));
                    } else {
                        text = new String(TextEncoder.toString(
                            cbsPacket.message));

                    }
                } else {
                    // null message. Set to empty string
                    text = new String("");
                }
                ((TextObject)msg).setPayloadText(text);
            } else {

                if (cbsPacket.message != null) {
                    ((BinaryObject)msg).setPayloadData(cbsPacket.message);
                } else {
                    // null message. Set to empty byte array
                    ((BinaryObject)msg).setPayloadData(new byte[0]);
                }
            }

        } catch (InterruptedIOException ex) {
            throw new InterruptedIOException("MessageConnection closed.");
        } catch (IOException ex) {
            io2InterruptedIOExc(ex, "receiving");
        }

        return msg;
    
private native intreceive0(int port, int msid, int handle, com.sun.midp.io.j2me.cbs.Protocol$CBSPacket cbsPacket)
Receives a CBS message.

param
port The port used for incoming messages.
param
msid Midlet Suite ID.
param
handle The handle used to open the CBS connection.
param
cbsPacket The received packet.
return
The number of bytes received.
exception
IOException if an I/O error occurs

public voidsend(javax.wireless.messaging.Message msg)
Cell broadcast connections are read-only connections. Calling this method causes an IOException to be thrown.

param
msg Placeholder: A Message object.
exception
IOException always thrown.

        throw new IOException("Send not supported.");
    
protected voidsetAppID(java.lang.String newValue)
Sets the connection parameter in string mode.

param
newValue new value of connection parameter

        try {
            m_imsgid = Integer.parseInt(newValue);
        } catch (NumberFormatException exc) {
            m_imsgid = 0;
        }
    
protected intunblock00(int msid)
Unblock the receive thread.

param
msid The MIDlet suite ID.
return
returns handle to the connection.

        return open0(0, msid);
    
private native intwaitUntilMessageAvailable0(int port, int handle)
Waits until message available

param
port The port used for incoming messages.
param
handle The handle to the CBS connection.
return
0 on success, -1 on failure
exception
IOException if an I/O error occurs

protected intwaitUntilMessageAvailable00(int handle)
Waits until message available

param
handle handle to connection
return
0 on success, -1 on failure
exception
IOException if an I/O error occurs

        return waitUntilMessageAvailable0(m_imsgid, handle);