FileDocCategorySizeDatePackage
CBSMessageConnection.javaAPI DocphoneME MR2 API (J2ME)12186Wed May 02 18:00:32 BST 2007com.sun.tck.wma.cbs

CBSMessageConnection.java

/*
 *   
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */

package com.sun.tck.wma.cbs;

import com.sun.tck.wma.PropLoader;
import com.sun.tck.wma.Message;
import com.sun.tck.wma.MessageConnection;
import com.sun.tck.wma.MessageTransportConstants;
import com.sun.tck.wma.BinaryMessage;
import com.sun.tck.wma.TextMessage;
import com.sun.tck.wma.sms.BinaryObject;
import com.sun.tck.wma.sms.TextObject;
import com.sun.midp.io.j2me.sms.TextEncoder;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Properties;

import java.io.IOException;

/**
 * CBS message connection handler.
 */
public class CBSMessageConnection extends PropLoader
    implements MessageConnection {

    /** Machine name - the parsed target address from the URL. */
    protected String host = null;

    /** Message ID from the URL connection string. */
    protected String msgID = null;

    /** Datagram host for sending CBS messages. */
    protected String clientHost;

    /** Datagram transport for sending. */
    protected int portOut;

    /** Phone number of the message sender. */
    protected String phoneNumber;

    /** Datagram server connection. */
    DatagramSocket dgc; 

    /** Datagram buffer. */
    byte [] buf = new byte[MessageTransportConstants.DATAGRAM_PACKET_SIZE];

    /** Datagram envelope for sending or receiving messages. */
    DatagramPacket mess =
        new DatagramPacket(buf, MessageTransportConstants.DATAGRAM_PACKET_SIZE);

    /**
     * Open flag indicates when the connection is closed. When a connection is
     * closed, subsequent operations throw an exception.
     */
    protected boolean open;


    /**
     * Construct a new CBS message connection handler.
     */
    public CBSMessageConnection() {

        /* 
         * Configurable parameters for low level transport.
         * e.g. cbs://:11100 maps to datagram://129.148.70.80:123
         */

        clientHost = "localhost";
        portOut = 22200;
        phoneNumber = "+5551234";

        /* 
         * Check for overrides in the "connections.prop"
         * configuration file.
         */

        
        clientHost = getProp("localhost", "JSR_205_DATAGRAM_HOST",
            "connections.prop", "DatagramHost");

        portOut = getIntProp(22200, "JSR_205_CBS_OUT_PORT",
            "connections.prop", "CBSDatagramPortOut");

        phoneNumber = getProp("+5551234", "JSR_205_PHONE_NUMBER",
            "connections.prop", "PhoneNumber");

    }

    /**
     * Opens a connection. This method is called from
     * <code>Connector.open()</code> method to obtain the destination address
     * given in the <code>name</code> parameter.
     * <p>
     * The format for the <code>name</code> string for this method is:
     * <code>cbs://<em>phone_number</em>:<em>port</em></code> where the
     * <em>phone_number:</em> is optional. If the <em>phone_number</em>
     * 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.  
     * <p>
     * The connection that is opened is to a low-level transport mechanism
     * which can be any of the following:
     * <ul>
     * <li>A datagram Short Message Peer to Peer (SMPP) to a service
     * center.
     * <li>A <code>comm</code> connection to a phone device with AT-commands.
     * <li>a native CBS stack.
     * </ul>
     *
     * @param name The target of the connection.
     *
     * @return This connection.
     *
     * @throws IOException if the connection is closed or unavailable.
     */
    public MessageConnection openPrim(String name)
        throws IOException {

        /*
         * If <code>host == null</code>, then we are a server endpoint at
         * the supplied <code>port</code>.
         *
         * If <code>host != null</code> we are a client endpoint at a port
         * decided by the system and the default address for
         * CBS messages to be sent is <code>cbs://host:port</code> .
         */

        if (name.charAt(0) != '/' || name.charAt(1) != '/') {
            throw new IllegalArgumentException(
                           "Missing protocol separator.");
        }
        
        int colon = name.indexOf(':');
        if (colon > 0) {
            if (colon != 2) {
                host = name.substring(2, colon);
            }
            msgID = name.substring(colon + 1);
        } else {
            if (name.length() > 2) {
                host = name.substring(2); 
            }
        }

        open = true;
        return this;
    }

    /**
     * Constructs a new message object of a text or binary type. When the 
     * <code>TEXT_MESSAGE</code> constant is passed in, the created 
     * object implements the <code>TextMessage</code> interface.
     * When the <code>BINARY_MESSAGE</code> constant is passed in, the 
     * created object implements the <code>BinaryMessage</code> 
     * interface. 
     * <p>
     * If this method is called in a sending mode, a new <code>Message</code>
     * object is requested from the connection. For example:
     * <p>
     * <code>Message msg = conn.newMessage(TEXT_MESSAGE);</code>
     * <p>
     * The newly created <code>Message</code> does not have the destination
     * address set. It must be set by the application before 
     * the message is sent.
     * <p>
     * If it is called in receiving mode, the <code>Message</code> object does
     * have its address set. The application can act on the object to extract
     * the address and message data. 
     * <p>
     * <!-- The <code>type</code> parameter indicates the number of bytes 
     * that should be
     * allocated for the message. No restrictions are placed on the application 
     * for the value of <code>size</code>.
     * A value of <code>null</code> is permitted and creates a 
     * <code>Message</code> object 
     * with a 0-length message. -->
     * 
     * @param  type either TEXT_MESSAGE or BINARY_MESSAGE.
     * @return      a new message
     */
    public Message newMessage(String type) {
        return newMessage(type, null);
    }

    /**
     * Constructs a new message object of a text or binary type and specifies
     * a destination address.
     * When the 
     * <code>TEXT_MESSAGE</code> constant is passed in, the created 
     * object implements the <code>TextMessage</code> interface.
     * When the <code>BINARY_MESSAGE</code> constant is passed in, the 
     * created object implements the <code>BinaryMessage</code> 
     * interface. 
     * <p>
     * The destination address <code>addr</code> has the following format:
     * <code>cbs://</code><em>phone_number</em>:<em>port</em>.
     *
     * @param  type either TEXT_MESSAGE or BINARY_MESSAGE.
     * @param  addr the destination address of the message.
     * @return      a new <code>Message</code> object.
     */
    public Message newMessage(String type, String addr)  {
        /* Return the appropriate type of sub message. */
        if (type == MessageConnection.TEXT_MESSAGE) {
            return  new TextObject(addr); 
        } else if (type == MessageConnection.BINARY_MESSAGE) {
            return  new BinaryObject(addr);
        }
        return null; /* message type not supported */
    }

    /**
     * Sends a message over the connection. This method extracts
     * the data payload from 
     * the <code>Message</code> object so that it
     * can be sent as a datagram. 
     *
     * @param dmsg a <code>Message</code> object.
     * @exception ConnectionNotFoundException  if the address is 
     *    invalid or if no address is found in the message.
     * @exception IOException  if an I/O error occurs.
     */
    public void send(Message dmsg) throws IOException {

        byte[] buffer = null;
        String type = null;
        if (dmsg instanceof TextMessage) {
            type = MessageConnection.TEXT_MESSAGE;
            buffer = ((TextObject)dmsg).getPayloadData();
        } else if (dmsg instanceof BinaryMessage) {
            type = MessageConnection.BINARY_MESSAGE;
            buffer = ((BinaryObject)dmsg).getPayloadData();
        }

        /*
         * For text messages choose between UCS-2 or GSM 7-bit
         * encoding.
         */
        int encodingType = MessageTransportConstants.GSM_BINARY;
        if (type.equals(MessageConnection.TEXT_MESSAGE)) {
            byte[] gsm7bytes = TextEncoder.encode(buffer);
            if (gsm7bytes != null) {
                encodingType = MessageTransportConstants.GSM_TEXT;
                buffer = gsm7bytes;
            } else {
                encodingType = MessageTransportConstants.GSM_UCS2;
            }
        }


        /* Datagram envelope for sending messages. */
        mess = new DatagramPacket(buf,
                   MessageTransportConstants.DATAGRAM_PACKET_SIZE);

        /* Set the address and port to which the datagram is being sent. */
        mess.setAddress(InetAddress.getByName(clientHost));
        mess.setPort(portOut);

        /* Create the special CBS packet. */
        CBSPacket cbsPacket = new CBSPacket();
        cbsPacket.setEncodingType(encodingType);
	if (msgID != null) {
            cbsPacket.setMessageID(Integer.parseInt(msgID));
	} else {
            cbsPacket.setMessageID(0);
	}
        cbsPacket.setMessageLength(buffer.length);
        cbsPacket.setMessage(buffer);

        debug("CBS PACKET: encoding type = " + encodingType);
        debug("CBS PACKET: msgID = " + msgID);
        debug("CBS PACKET: address = " + dmsg.getAddress());
        debug("CBS PACKET: message length = " + buffer.length);
        debug("CBS PACKET: message:" + new String(buffer));

        /* Make the CBS packet the payload for the datagram, and send it. */
        byte[] buf = cbsPacket.getData();
        mess.setData(buf, 0, buf.length);

        /* Open the outbound datagram connection. */
        dgc = new DatagramSocket();
        dgc.send(mess);
        dgc.close();
        dgc = null;
    }
    
    /**
     * Not supported. Normally, this would receive bytes that have been sent
     * over the connection.
     * 
     * @exception IOException  Always thrown to indicate that this features is
     *     not supported.
     *
     * @return Message  This object is never returned.
     */
    public synchronized Message receive() throws IOException {
        throw new IOException("Server-Side receive not supported.");
    }


    /**
     * Closes the connection. Reset the connection is open flag
     * so methods can be checked to throws an appropriate exception
     * for operations on a closed connection.
     *
     * @exception IOException  if an I/O error occurs.
     */
    public void close() throws IOException {

        if (open) {
            open = false;
        }
    }

    /**
     * Show a debug message.
     *
     * @param text  The text to be displayed after a mandatory prefix.
     */
    private void debug(String text) {
        System.out.println("CBSMessageConnection: " + text);
    }

}