FileDocCategorySizeDatePackage
ConnectionRegistry.javaAPI DocphoneME MR2 API (J2ME)30291Wed May 02 18:00:00 BST 2007com.sun.midp.io.j2me.push

ConnectionRegistry

public final class ConnectionRegistry extends Object implements MIDletProxyListListener, Runnable
CLDC implementation of ConnectionRegistry.

Fields Summary
static final int
PUSH_OPT_WHEN_ONLY_APP
Push option to only launch this suite when not other applications are running.
private static com.sun.midp.security.SecurityToken
classSecurityToken
This class has a different security domain than the MIDlet suite.
static boolean
pushEnabled
Flag to control when push launching is permitted. This flag is set to false by the AMS when installing or removing MIDlets, when an interruption could compromise the integrity of the operation.
static boolean
mvmSingleMidletMode
This flag is set to true by the AMS when running in MVM singal MIDlet mode. In this mode the current MIDlet that is not the application manager should be destroyed before the next MIDlet is started.
private MIDletProxyList
midletProxyList
MIDlet proxy list reference.
private static com.sun.midp.midletsuite.MIDletSuiteStorage
storage
Cached reference to the midlet suite storage instance.
Constructors Summary
private ConnectionRegistry()
Keeps an object of this class from being created out of the startListening method. Will throw a security exception if called by any thing other than the MIDletSuiteLoader.

        /*
         * Will throw a security exception if called by any thing other
         * than the MIDletSuiteLoader.
         */
        midletProxyList =
            MIDletProxyList.getMIDletProxyList(classSecurityToken);
        midletProxyList.addListener(this);

        if (storage == null) {
            storage = MIDletSuiteStorage.getMIDletSuiteStorage(
                classSecurityToken);
        }
    
Methods Summary
private static native intadd0(byte[] connection)
Native connection registry add connection function.

param
connection string to register
return
0 if successful, -1 if failed

private static native longaddAlarm0(byte[] midlet, long time)
Native connection registry add alarm function.

param
midlet string to register
param
time
return
0 if unregistered, otherwise the time of the previous registered alarm

private static native voidcheckInByHandle0(int handle)
Native connection registry check in connection function.

param
handle native handle of the connection

private static native voidcheckInByMidlet0(int suiteId, byte[] className)
Native connection registry method to check in connections that are in launch pending state for a specific MIDlet.

param
suiteId Suite ID of the MIDlet array
param
className Class name of the MIDlet as zero terminated ASCII byte array

private static native intcheckInByName0(byte[] connection)
Native connection registry check in connection function.

param
connection string to register
return
0 if successful, -1 if failed

static booleancheckInConnectionInternal(java.lang.String connection)
Check in a push connection into AMS so the owning MIDlet can get launched next time data is pushed. This method is used when a MIDlet will not be able to get the connection and close (check in) the connection for some reason. (normally because the user denied a permission)

For datagram connections this function will discard the cached message.

For server socket connections this function will close the accepted connection.

param
connection generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
exception
IllegalArgumentException if the connection string is not valid
exception
SecurityException if the MIDlet does not have permission to clear a connection
return
true if the check in was successful, false the connection was not registered.
see
#unregisterConnection


        /* Verify that the connection requested is valid. */
        if (connection == null || connection.length() == 0) {
            throw new IllegalArgumentException("Connection missing");
        }

        byte[] asciiRegistration = Util.toCString(connection);

        return checkInByName0(asciiRegistration) != -1;
    
static voidcheckRegistration(Connection connection, java.lang.String midlet, java.lang.String filter)
Check the registration arguments.

param
connection preparsed connection to check
param
midlet class name of the MIDlet to be launched, when new external data is available
param
filter a connection URL string indicating which senders are allowed to cause the MIDlet to be launched
exception
IllegalArgumentException if connection or filter is not valid
exception
ConnectionNotFoundException if PushRegistry doesn't support this kind of connections

        final String c = connection.getConnection();
        ProtocolPush.getInstance(c).checkRegistration(c, midlet, filter);
    
private static java.lang.String[]connectionsToArray(java.lang.String connections)
Converts connections as string into string array.

param
connections Connections to convert
return
array of connections

        if (connections == null) {
            return new String[0];
        }

        /* Count the commas in the returned string */
        int count = 0;
        int offset = 0;

        do {
            offset = connections.indexOf(',", offset + 1);
            count ++;
        } while (offset > 0);

        /* Now parse out the connections for easier access by caller. */
        String[] ret = new String[count];
        int start = 0;
        for (int i = 0; i < count; i++) {
            offset = connections.indexOf(',", start);
            if (offset > 0) {
                /* Up to the next comma */
                ret[i] = connections.substring(start, offset);
            } else {
                /* From the last comma to the end of the string. */
                ret[i] = connections.substring(start);
            }
            start = offset + 1;
        }

        return ret;
    
private static native intdel0(byte[] connection, byte[] storage)
Native connection registry del connection function.

param
connection string to register
param
storage current suite storage name
return
0 if successful, -1 if failed

static native voiddelAllForSuite0(int id)
Native connection registry delete a suite's connections function.

param
id suite's ID

private voiddestroyAppMidlets()
Destroy every MIDlet except the application manager midlet. This should only be used in MVM Signal MIDlet Mode.

        Enumeration midlets = midletProxyList.getMIDlets();

        while (midlets.hasMoreElements()) {
            MIDletProxy midlet = (MIDletProxy)midlets.nextElement();

            if (midlet.getSuiteId() == MIDletSuite.INTERNAL_SUITE_ID &&
                    midlet.getClassName().indexOf("Manager") != -1) {
                continue;
            }

            midlet.destroyMidlet();
        }
    
private static native intgetEntry0(byte[] connection, byte[] regentry, int entrysz)
Native connection registry lookup registry entry from a specific connection.

param
connection registered connection string
param
regentry registered entry
param
entrysz maximum string that will be accepted
return
0 if successful, -1 if failed

public static java.lang.StringgetFilter(java.lang.String connection)
Retrieve the registered filter for a requested connection.

param
connection generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
return
a filter string indicating which senders are allowed to cause the MIDlet to be launched or null if the connection was not registered
see
#registerConnection


        String filter = null;
        byte[] asciiConn = Util.toCString(connection);
        byte[] registryEntry = new byte[512];

        if (getEntry0(asciiConn, registryEntry, 512) == 0) {
            String name = Util.toJavaString(registryEntry);
            try {
                int comma1 = name.indexOf(',", 0);
                int comma2 = name.indexOf(',", comma1 + 1);
                int comma3 = name.indexOf(',", comma2 + 1);

                filter = name.substring(comma2+1, comma3).trim();
            } catch (Exception e) {
                if (Logging.TRACE_ENABLED) {
                    Logging.trace(e, null);
                }
            }
        }
        return  filter;
    
public static java.lang.StringgetMIDlet(java.lang.String connection)
Retrieve the registered MIDlet for a requested connection.

param
connection generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
return
class name of the MIDlet to be launched, when new external data is available, or null if the connection was not registered
see
#registerConnection


        String midlet = null;
        byte[] asciiConn = Util.toCString(connection);
        byte[] registryEntry = new byte[512];

        if (getEntry0(asciiConn, registryEntry, 512) == 0) {
            String name = Util.toJavaString(registryEntry);
            try {
                int comma1 = name.indexOf(',", 0);
                int comma2 = name.indexOf(',", comma1 + 1);

                midlet = name.substring(comma1+1, comma2).trim();
            } catch (Exception e) {
                if (Logging.TRACE_ENABLED) {
                    Logging.trace(e, null);
                }
            }
        }
        return  midlet;
    
private static native intgetMIDlet0(int handle, byte[] regentry, int entrysz)
Native connection registry lookup for MIDlet name from file descriptor.

param
handle file descriptor of registered active connection
param
regentry registered entry
param
entrysz maximum string that will be accepted
return
0 if successful, -1 if failed

public static voidinitSecurityToken(com.sun.midp.security.SecurityToken token)
Initializes the security token for this class, so it can perform actions that a normal MIDlet Suite cannot.

param
token security token for this class.

        if (classSecurityToken == null) {
            classSecurityToken = token;
        }
    
private voidlaunchEntry(java.lang.String name)
Parse the registration entry and launch the associated MIDlet.

param
name registration string for connection and MIDlet to be launched

        String conn;
        String midlet;
        String filter;
        String strSuiteId;
        int id;
        MIDletSuite next = null;

        /*
         * Parse the comma separated values  -
         *  " connection, midlet,  filter, id"
         *  "  midlet,  wakeup, midlet suite ID"
         */
        int comma1 = name.indexOf(',", 0);
        int comma2 = name.indexOf(',", comma1 + 1);
        int comma3 = name.indexOf(',", comma2 + 1);

        if (comma3 == -1) {
            /* Alarm was triggered */
            conn = null;
            midlet = name.substring(0, comma1).trim();
            strSuiteId = name.substring(comma2+1).trim();
        } else {
            conn = name.substring(0, comma1).trim();
            midlet = name.substring(comma1+1, comma2).trim();
            filter = name.substring(comma2+1, comma3).trim();
            strSuiteId = name.substring(comma3+1).trim();
        }

        try {
            /*
             * IMPL_NOTE: here it's assumed that when a suiteId is converted
             * to string the padding zeroes are placed _before_ the value,
             * for ex., suiteId 3 is converted into "00000003".
             * MIDletSuiteStorage.stringToSuiteId() API should be added later.
             */
            id = Integer.parseInt(strSuiteId);
        } catch (NumberFormatException nfe) {
            id = MIDletSuite.UNUSED_SUITE_ID;
        }

        try {
            /*
             * Check to see if the MIDlet is already started.
             */
            if (midletProxyList.isMidletInList(id, midlet)) {
                if (conn != null) {
                    checkInConnectionInternal(conn);
                }

                return;
            }

            next = storage.getMIDletSuite(id, false);
            if (next == null) {
                if (conn != null) {
                    checkInConnectionInternal(conn);
                }

                return;
            }

            if ((next.getPushOptions() & PUSH_OPT_WHEN_ONLY_APP) != 0 &&
                    !onlyAppManagerRunning()) {
                if (conn != null) {
                    checkInConnectionInternal(conn);
                }

                return;
            }

            if (!next.permissionToInterrupt(conn)) {
                // user does not want the interruption
                if (conn != null) {
                    checkInConnectionInternal(conn);
                }

                return;
            }

            if (MIDletSuiteUtils.execute(classSecurityToken, id, midlet,
                                          null)) {
                /* We are in SVM mode, destroy all running MIDlets. */
                MIDletStateHandler.getMidletStateHandler().destroySuite();
            } else if (mvmSingleMidletMode) {
                destroyAppMidlets();
            }
        } catch (Throwable e) {
            // Could not launch requested push entry
            if (conn != null) {
                checkInConnectionInternal(conn);
            }

            if (Logging.TRACE_ENABLED) {
                Logging.trace(e, null);
            }
        } finally {
            if (next != null) {
                next.close();
            }
        }
    
private static native intlist0(byte[] midlet, boolean available, byte[] connectionlist, int listsz)
Native connection registry list connection function.

param
midlet string to register
param
available if true, only return the list of connections with input available
param
connectionlist comma separated string of connections
param
listsz maximum string that will be accepted in connectionlist
return
0 if successful, -1 if failed

public static java.lang.String[]listConnections(com.sun.midp.midlet.MIDletSuite midletSuite, boolean available)
Return a list of registered connections for the current MIDlet suite.

param
midletSuite MIDlet suite to list connections for
param
available if true, only return the list of connections with input available
return
array of connection strings, where each connection is represented by the generic connection protocol, host and port number identification


        return connectionsToArray(listConnections(midletSuite.getID(),
                               available));
    
static java.lang.StringlistConnections(int id, boolean available)
Return a list of registered connections for given MIDlet suite. AMS permission is required.

param
id identifies the specific MIDlet suite to be launched
param
available if true, only return the list of connections with input available
return
array of connection strings, where each connection is represented by the generic connection protocol, host and port number identification

        byte[] nativeID;
        String connections = null;
        byte[] connlist;

        nativeID = Util.toCString(suiteIdToString(id));
        connlist = new byte[512];

        if (list0(nativeID, available, connlist, 512) == 0) {
            connections = Util.toJavaString(connlist);
        }

        return connections;
    
public voidmidletAdded(MIDletProxy midlet)
Called when a MIDlet is added to the list, not used by this class.

param
midlet The proxy of the MIDlet being added

public voidmidletRemoved(MIDletProxy midlet)
Called when a MIDlet is removed from the list, the connections in "launch pending" state for this MIDlet will be checked in.

param
midlet The proxy of the removed MIDlet

        byte[] asciiClassName = Util.toCString(midlet.getClassName());

        checkInByMidlet0(midlet.getSuiteId(), asciiClassName);
    
public voidmidletStartError(int externalAppId, int suiteId, java.lang.String className, int errorCode, java.lang.String errorDetails)
Called when error occurred while starting a MIDlet object. The connections in "launch pending" state for this MIDlet will be checked in.

param
externalAppId ID assigned by the external application manager
param
suiteId Suite ID of the MIDlet
param
className Class name of the MIDlet
param
errorCode start error code
param
errorDetails start error code

        byte[] asciiClassName = Util.toCString(className);

        checkInByMidlet0(suiteId, asciiClassName);
    
public voidmidletUpdated(MIDletProxy midlet, int fieldId)
Called when the state of a MIDlet in the list is updated.

param
midlet The proxy of the MIDlet that was updated
param
fieldId code for which field of the proxy was updated

private booleanonlyAppManagerRunning()
Check to see if only the application manager MIDlet is running.

return
true if only the application manager is running

        Enumeration midlets = midletProxyList.getMIDlets();

        while (midlets.hasMoreElements()) {
            MIDletProxy midlet = (MIDletProxy)midlets.nextElement();

            if (midlet.getSuiteId() != MIDletSuite.INTERNAL_SUITE_ID ||
                    midlet.getClassName().indexOf("Manager") == -1) {
                return false;
            }
        }

        return true;
    
private native intpoll0(long time)
Native function to test registered inbound connections for new connection notification.

param
time current time to use for alarm checks
return
handle for the connection with inbound connection pending.

public static longregisterAlarm(com.sun.midp.midlet.MIDletSuite midletSuite, java.lang.String midlet, long time)
Register a time to launch the specified application. The PushRegistry supports one outstanding wake up time per MIDlet in the current suite. An application is expected to use a TimerTask for notification of time based events while the application is running.

If a wakeup time is already registered, the previous value will be returned, otherwise a zero is returned the first time the alarm is registered.

param
midletSuite MIDlet suite to register alarm for
param
midlet class name of the MIDlet within the current running MIDlet suite to be launched, when the alarm time has been reached
param
time time at which the MIDlet is to be executed in the format returned by Date.getTime()
return
the time at which the most recent execution of this MIDlet was scheduled to occur, in the format returned by Date.getTime()
exception
ConnectionNotFoundException if the runtime system does not support alarm based application launch


        byte[] asciiName = Util.toCString(midlet + ","
                  + time + ","
                  + suiteIdToString(midletSuite));
        return addAlarm0(asciiName, time);
    
public static voidregisterConnection(com.sun.midp.midlet.MIDletSuite midletSuite, Connection connection, java.lang.String midlet, java.lang.String filter)
Register a dynamic connection.

param
midletSuite MIDlet suite to register connection for
param
connection generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
param
midlet class name of the MIDlet to be launched, when new external data is available
param
filter a connection URL string indicating which senders are allowed to cause the MIDlet to be launched
exception
ClassNotFoundException if the MIDlet class name can not be found in the current MIDlet suite
exception
IOException if the connection is already registered or if there are insufficient resources to handle the registration request
see
#unregisterConnection


        registerConnectionInternal(midletSuite,
                            connection.getConnection(), midlet, filter, true);
    
static voidregisterConnectionInternal(com.sun.midp.midlet.MIDletSuite midletSuite, java.lang.String connection, java.lang.String midlet, java.lang.String filter, boolean registerConnection)
Register a dynamic connection with the application management software. Once registered, the dynamic connection acts just like a connection preallocated from the descriptor file. The internal implementation includes the storage name that uniquely identifies the MIDlet. This method bypasses the class loader specific checks needed by the Installer.

param
midletSuite MIDlet suite for the suite registering, the suite only has to implement isRegistered, checkForPermission, and getID.
param
connection generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
param
midlet class name of the MIDlet to be launched, when new external data is available
param
filter a connection URL string indicating which senders are allowed to cause the MIDlet to be launched
param
registerConnection if true, register a connection with a protocol, used by the installer when redo old connections during an aborted update
exception
ClassNotFoundException if the MIDlet class name can not be found in the current MIDlet suite
exception
IOException if the connection is already registered or if there are insufficient resources to handle the registration request
see
#unregisterConnection


        if (registerConnection) {
            /*
             * No need to register connection when bypassChecks: restoring
             * RFC: why add0 below?
             */
            ProtocolPush.getInstance(connection)
                .registerConnection(midletSuite, connection, midlet, filter);
        }

        byte[] asciiRegistration = Util.toCString(connection
                  + "," + midlet
                  + "," + filter
                  + "," + suiteIdToString(midletSuite));

        if (add0(asciiRegistration) == -1) {
            // in case of Bluetooth URL, unregistration within Bluetooth
            // PushRegistry was already performed by add0()
            throw new IOException("Connection already registered");
        }
    
public voidrun()
Run the polling loop to check for inbound connections.

        int fd = -1;
        int ret = 0;
        while (true) {
            try {
                fd = poll0(System.currentTimeMillis());
                if (fd != -1) {
                    if (pushEnabled) {
                        byte[] registryEntry = new byte[512];
                        if ((ret = getMIDlet0(fd, registryEntry, 512)) == 0) {
                            String name = Util.toJavaString(registryEntry);
                            launchEntry(name);
                        }
                    } else {
                        checkInByHandle0(fd);
                    }
                }
            } catch (Exception e) {
                if (Logging.TRACE_ENABLED) {
                    Logging.trace(e, null);
                }
            }
        }
    
static voidstartListening()
Start listening for push notifications. Will throw a security exception if called by any thing other than the MIDletSuiteLoader.


                            
       
        (new Thread(new ConnectionRegistry())).start();
    
private static java.lang.StringsuiteIdToString(int suiteId)
Converts MIDlet suite ID into a string.

param
suiteId MIDlet suite to convert ID of
return
string representation

        // assert storage != null; // Listener should be started before
        return storage.suiteIdToString(suiteId);
    
private static java.lang.StringsuiteIdToString(com.sun.midp.midlet.MIDletSuite midletSuite)
Converts MIDlet suite ID into a string.

param
midletSuite MIDlet suite to convert ID of
return
string representation

        // assert midletSuite != null;
        return suiteIdToString(midletSuite.getID());
    
public static booleanunregisterConnection(com.sun.midp.midlet.MIDletSuite midletSuite, java.lang.String connection)
Remove a dynamic connection registration.

param
midletSuite MIDlet suite to unregister connection for
param
connection generic connection protocol, host and port number
exception
SecurityException if the connection was not registered by the current MIDlet suite
return
true if the unregistration was successful, false the connection was not registered.
see
#registerConnection


        byte[] asciiRegistration = Util.toCString(connection);
        byte[] asciiStorage = Util.toCString(suiteIdToString(midletSuite));
        int ret =  del0(asciiRegistration, asciiStorage);
        if (ret == -2) {
            throw new SecurityException("wrong suite");
        }
        return ret != -1;