FileDocCategorySizeDatePackage
BTSPPNotifierImpl.javaAPI DocphoneME MR2 API (J2ME)16026Wed May 02 18:00:30 BST 2007com.sun.midp.io.j2me.btspp

BTSPPNotifierImpl

public class BTSPPNotifierImpl extends com.sun.kvem.jsr082.bluetooth.BluetoothNotifier implements javax.microedition.io.StreamConnectionNotifier
Bluetooth Serial Port Profile notifier implementation.

Fields Summary
private int
handle
Identidies this connection at native layer, -1 if connection is not open.
int
peerHandle
Temporary stores peer's native handle for accepted connection. Used by doAccept method.
byte[]
peerAddress
Temporary stores remote device address for accepted connection.
private boolean
isListenMode
Indicates whether notifier is listening for incoming connections.
private int
cid
Channel Id.
private DataElement
CHANNEL_ID
Keeps channel id for service record validation.
static final DataElement
L2CAP_UUID
Keeps L2CAP UUID for service record validation.
static final DataElement
RFCOMM_UUID
Keeps RFCOMM UUID for service record validation.
static final DataElement
SPP_UUID
Keeps SPP UUID for service record validation.
private int
pushHandle
Bluetooth PushRegistry handle, used in native methods only.
Constructors Summary
BTSPPNotifierImpl(com.sun.midp.io.BluetoothUrl url, int mode)
Creates instance of BTSPPNotifierImpl.

param
url BluetoothUrl that represents server connection string to create notifier for.
param
mode I/O access mode
throws
IOException if there is no available channels to open connection
throws
ServiceRegistrationException if there is no available channel


                                                        
         
                
        super(url, mode);
        MIDletSuite suite = MIDletStateHandler.getMidletStateHandler().
                getMIDletSuite();
        String connUrl = "btspp:" + url.caseSensitiveUrl;
        if (suite != null && pushCheckout(connUrl, suite.getID())) {
            serviceRec = BluetoothPush.getServiceRecord(this, connUrl);
            checkServiceRecord();
        } else {
            serviceRec = createServiceRecord(this, url, doCreate(url));
        }
    
Methods Summary
private native intaccept0()
Accepts incoming client connection request. Note: the method gets native connection handle directly from handle field of BTSPPNotifierImpl object. Note: new native connection handle to work with accepted incoming client connection is setted directly to handle field of appropriate BTSPPConnectionImpl object.

return
0 if incoming client connection was successfully accepted; -1 if there is no pending incoming connections
throws
IOException if an I/O error occurs

public javax.microedition.io.StreamConnectionacceptAndOpen()
Accepts client connection to the service this notifier is assigned to. Adds corresponding service record to the SDDB, blocks until a successfull connection to a client is established, retrieves the connection.

return
bi-directional connection to a client just accepted.
throws
IOException if notifier is closed or device is not in connectable mode.

        ensureConnectable();

        // switch on listen mode if it has not been done yet
        doListen();

        // adds the record only if is not yet in SDDB
        SDDB.getInstance().updateServiceRecord(serviceRec);

        StreamConnection client;
        do {
            ensureConnectable();

            // accept incoming connections if any
            client = doAccept();
        } while (client == null);

        return client;
    
protected voidcheckServiceRecord()
Ensures that the service record is valid.

throws
ServiceRegistrationException if the structure of the srvRecord is missing any mandatory service attributes, or if an attempt has been made to change any of the values described as fixed

        synchronized (serviceRec) {
            // check if the ServiceClassIDList is not missing
            if (serviceRec.getAttributeValue(
                    ServiceRecordImpl.SERVICE_CLASS_ATTR_ID) == null) {
                throw new ServiceRegistrationException(
                        "ServiceClassIDList is missing.");
            }
            // check the ProtocolList is not missed
            DataElement protocolList = serviceRec.getAttributeValue(
                    ServiceRecordImpl.PROTOCOL_DESCRIPTOR_LIST);
            if (protocolList == null) {
                throw new ServiceRegistrationException(
                        "ProtocolDescriptorList is missing.");
            }
            Enumeration protocolListEnum =
                    (Enumeration)protocolList.getValue();
            boolean l2cap = false;
            boolean rfcomm = false;
            while (protocolListEnum.hasMoreElements()) {
                Enumeration protocolEnum = (Enumeration)((DataElement)
                        protocolListEnum.nextElement()).getValue();
                // check that L2CAP/RFCOMM UUIDs are not missing, check the CN
                // is not missing and the value has not changed
                while (protocolEnum.hasMoreElements()) {
                    DataElement element = (DataElement)protocolEnum.
                            nextElement();
                    if (compareDataElements(element, L2CAP_UUID)) {
                        l2cap = true;
                    }
                    if (compareDataElements(element, RFCOMM_UUID)) {
                        rfcomm = true;
                        if (!protocolEnum.hasMoreElements() ||
                                !compareDataElements((DataElement)protocolEnum.
                                nextElement(), CHANNEL_ID)) {
                            throw new ServiceRegistrationException(
                                    "Channel value has changed.");
                        }
                    }
                    if (l2cap && rfcomm) {
                        return;
                    }
                }
            }
        }
        throw new ServiceRegistrationException("L2CAP UUID is missing.");
    
public voidclose()
Closes this notifier making corresponding service record inaccessible. updates the information on the communication server.

throws
IOException if an error occured lower in Bluetooth stack.

        if (isClosed) {
            return;
        }
        isClosed = true;

        SDDB.getInstance().removeServiceRecord(serviceRec);

        doClose();
    
private native voidclose0()
Closes this server connection. Releases all native resources (such as sockets) owned by this notifier. Note: the method gets native connection handle directly from handle field of BTSPPNotifierImpl object.

throws
IOException IOException if an I/O error occurs

private native intcreate0(boolean auth, boolean authz, boolean enc, boolean master)
Creates a server connection. Note: the method sets native connection handle directly to handle field of BTSPPNotifierImpl object.

param
auth true if authication is required
param
authz true if authorization is required
param
enc true indicates what connection must be encrypted
param
master true if client requires to be a connection's master
return
selected channel number to listen for incoming connections on
throws
IOException IOException if an I/O error occurs

public static com.sun.kvem.jsr082.bluetooth.ServiceRecordImplcreateServiceRecord(com.sun.midp.io.j2me.btspp.BTSPPNotifierImpl notifier, com.sun.midp.io.BluetoothUrl url, int cn)
Creates an empty service record for the given URL and channel value.

param
notifier SPP notifier object to be associated with the record
param
url URL from which a new record is constructed
param
cn channel value assigned to the notifier
return
a new service record instance

        DataElement serviceList = new DataElement(DataElement.DATSEQ);
        serviceList.addElement(new DataElement(DataElement.UUID,
                new UUID(url.uuid, false)));
        serviceList.addElement(SPP_UUID);
        DataElement protocolList = new DataElement(DataElement.DATSEQ);
        DataElement protocol = new DataElement(DataElement.DATSEQ);
        protocol.addElement(L2CAP_UUID);
        protocolList.addElement(protocol);
        protocol = new DataElement(DataElement.DATSEQ);
        protocol.addElement(RFCOMM_UUID);
        if (notifier != null) {
            notifier.CHANNEL_ID = new DataElement(DataElement.U_INT_1, cn);
            protocol.addElement(notifier.CHANNEL_ID);
        } else {
            protocol.addElement(new DataElement(DataElement.U_INT_1, cn));
        }
        protocolList.addElement(protocol);
        int[] attrIDs;
        DataElement[] attrVals;
        if (url.name != null) {
            DataElement name = new DataElement(DataElement.STRING, url.name);
            attrIDs = new int[] {
                ServiceRecordImpl.SERVICE_CLASS_ATTR_ID,
                ServiceRecordImpl.PROTOCOL_DESCRIPTOR_LIST,
                ServiceRecordImpl.NAME_ATTR_ID
            };
            attrVals = new DataElement[] { serviceList, protocolList, name };
        } else {
            attrIDs = new int[] {
                ServiceRecordImpl.SERVICE_CLASS_ATTR_ID,
                ServiceRecordImpl.PROTOCOL_DESCRIPTOR_LIST
            };
            attrVals = new DataElement[] { serviceList, protocolList };
        }
        return new ServiceRecordImpl(notifier, attrIDs, attrVals);
    
public static com.sun.kvem.jsr082.bluetooth.ServiceRecordImplcreateServiceRecord(java.lang.String url)
Creates an empty service record for the given URL

param
url URL from which a new record is constructed
return
a new service record instance

        return createServiceRecord(null, new BluetoothUrl(url), 0);
    
private javax.microedition.io.StreamConnectiondoAccept()
Advertises acception by calling underlying stack methods.

return
BTSPPConnection instance to work with accepted client

        if (!isListenMode) {
            throw new BluetoothStateException("Device is not in listen mode");
        }

        /*
         * Note: native handle is set to peerHandleID field directly
         * by accept0 method and retrieved by L2CAPConnectionImpl constructor.
         */
        accept0();

        return new BTSPPConnectionImpl(url, mode, this);
    
private voiddoClose()
Closes this notifier at native layer.

        close0();
    
private intdoCreate(com.sun.midp.io.BluetoothUrl url)
Creates an instanse of server connection at native layer.

param
url BluetoothUrl that represents server connection string to create notifier for
return
selected channel number to listen for incoming connections

        return create0(url.authenticate, url.authorize,
                url.encrypt, url.master);
    
private voiddoListen()
Force listen mode by calling underlying stack methods.

throws
IOException if an error occured

        // force listening if it had not been done yet
        if (!isListenMode) {
            listen0();

            isListenMode = true;
        }
    
private voidensureConnectable()
Ensures that this notifier can accept connections.

throws
IOException if notifier is closed or device is not in connectable mode
throws
ServiceRegistrationException if the service record is not valid

        if (isClosed) {
            throw new BluetoothConnectionException(
                    BluetoothConnectionException.FAILED_NOINFO,
                    "Notifier is closed.");
        }
        if (!BCC.getInstance().isConnectable()) {
            throw new BluetoothStateException("The device is not connectable.");
        }
        checkServiceRecord();
    
private native voidfinalize()
Native finalizer. Releases all native resources used by this connection.

private static native voidinitialize()
Native static class initializer.

private native voidlisten0()
Force Bluetooth stack to listen for incoming client connections. Note: the method gets native connection handle directly from handle field of BTSPPNotifierImpl object.

throws
IOException if an I/O error occurs

private native booleanpushCheckout(java.lang.String url, int suiteId)
Checks out (takes ownership of) an active server connection maintained by push subsystem.

param
url URL used during registration of the push entry
param
suiteId suite id
return
true if the operation succeeds, false otherwise