Overview | Package | Class | Use | Tree | Deprecated | Index | Help
| IM Profile
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## javax.microedition.io
Class PushRegistry

    java.lang.Object
      javax.microedition.io.PushRegistry

public class PushRegistry
extends Object

The `PushRegistry` maintains a list of inbound connections. An application can register the inbound connections with an entry in the application descriptor file or dynamically by calling the `registerConnection` method.

While an application is running, it is responsible for all I/O operations associated with the inbound connection. When the application is not running, the application management software(AMS) listens for inbound notification requests. When a notification arrives for a registered `MIDlet`, the AMS will start the `MIDlet` via the normal invocation of `MIDlet.startApp` method.

### Installation Handling of Declared Connections

To avoid collisions on inbound generic connections, the application descriptor file MUST include information about static connections that are needed by the `MIDlet` suite. If all the static Push declarations in the application descriptor can not be fulfilled during the installation, the user MUST be notified that there are conflicts and the MIDlet suite MUST NOT be installed. (See Over The Air User Initiated Provisioning Specification section for errors reported in the event of conflicts.) Conditions when the declarations can not be fulfilled include: syntax errors in the Push attributes, declaration for a connection end point (e.g. port number) that is already reserved in the device, declaration for a protocol that is not supported for Push in the device, and declaration referencing a `MIDlet` class that is not listed in the `MIDlet-<n>` attributes of the same application descriptor. If the `MIDlet` suite can function meaningfully even if a Push registration can't be fulfilled, it MUST register the Push connections using the dynamic registration methods in the `PushRegistry`.

A conflict-free installation reserves each requested connection for the exclusive use of the `MIDlets` in the suite. While the suite is installed, any attempt by other applications to open one of the reserved connections will fail with an `IOException`. A call from a `MIDlet` to `Connector.open()` on a connection reserved for its suite will always succeed, assuming the suite does not already have the connection open.

If two `MIDlet` suites have a static push connection in common, they cannot be installed together and both function correctly. The end user would typically have to uninstall one before being able to successfully install the other.

### Push Registration Attribute

Each push registration entry contains the following information : ``

> MIDlet-Push-<n>: <ConnectionURL>, <MIDletClassName>, <AllowedSender>

where :

- `MIDlet-Push-<n>` = the Push registration attribute name. Multiple push registrations can be provided in a `MIDlet` suite. The numeric value for <n> starts from 1 and MUST use consecutive ordinal numbers for additional entries. The first missing entry terminates the list. Any additional entries are ignored.
- `ConnectionURL` = the connection string used in `Connector.open()`
- `MIDletClassName` = the `MIDlet` that is responsible for the connection. The named `MIDlet` MUST be registered in the descriptor file or the jar file manifest with a `MIDlet-<n>` record. (This information is needed when displaying messages to the user about the application when push connections are detected, or when the user grants/revokes priveleges for the application.) If the named `MIDlet` appears more than once in the suite, the first matching entry is used.
- `AllowedSender` = a designated filter that restricts which senders are valid for launching the requested `MIDlet`. The syntax and semantics of the `AllowedSender` field depend on the addressing format used for the protocol. However, every syntax for this field MUST support using the wildcard characters "*" and "?". The semantics of those wildcard are:
  - "*" matches any string, including an empty string
  - "?" matches any single character
  When the value of this field is just the wildcard character "*", connections will be accepted from any originating source. For Push attributes using the `datagram` and `socket` URLs (if supported by the platform), this field contains a numeric IP address in the same format for IPv4 and IPv6 as used in the respective URLs (IPv6 address including the square brackets as in the URL). It is possible to use the wildcards also in these IP addresses, e.g. "129.70.40.*" would allow subnet resolution. Note that the port number is not part of the filter for `datagram` and `socket` connections.

The MIDP 2.0 specification defines the syntax for `datagram` and `socket` inbound connections. When other specifications define push semantics for additional connection types, they must define the expected syntax for the filter field, as well as the expected format for the connection URL string.

#### Example Descriptor File Declarative Notation

The following is a sample descriptor file entry that would reserve a stream socket at port 79 and a datagram connection at port 50000. (Port numbers are maintained by IANA and cover well-known, user-registered and dynamic port numbers) [See IANA Port Number Registry]

`

      MIDlet-Push-1: socket://:79, com.sun.example.SampleChat, *
      MIDlet-Push-2: datagram://:50000, com.sun.example.SampleChat, *

`

### Buffered Messages

The requirements for buffering of messages are specific to each protocol used for Push and are defined separately for each protocol. There is no general requirement related to buffering that would apply to all protocols. If the implementation buffers messages, these messages MUST be provided to the `MIDlet` when the `MIDlet` is started and it opens the related `Connection` that it has registered for Push.

When datagram connections are supported with Push, the implementation MUST guarantee that when a `MIDlet` registered for datagram Push is started in response to an incoming datagram, at least the datagram that caused the startup of the `MIDlet` is buffered by the implementation and will be available to the `MIDlet` when the `MIDlet` opens the `UDPDatagramConnection` after startup.

When socket connections are supported with Push, the implementation MUST guarantee that when a `MIDlet` registered for socket Push is started in response to an incoming socket connection, this connection can be accepted by the `MIDlet` by opening the `ServerSocketConnection` after startup, provided that the connection hasn't timed out meanwhile.

### Connection vs Push Registration Support

Not all generic connections will be appropriate for use as push application transport. Even if a protocol is supported on the device as an inbound connection type, it is not required to be enabled as a valid push mechanism. e.g. a platform might support server socket connections in a `MIDlet`, but might not support inbound socket connections for push launch capability. A `ConnectionNotFoundException` is thrown from the `registerConnection` and from the `registerAlarm` methods, when the platform does not support that optional capability.

### AMS Connection Handoff

Responsibility for registered push connections is shared between the AMS and the `MIDlet` that handles the I/O operations on the inbound connection. To prevent any data from being lost, an application is responsible for all I/O operations on the connection from the time it calls `Connector.open()` until it calls `Connection.close()`.

The AMS listens for inbound connection notifications. This MAY be handled via a native callback or polling mechanism looking for new inbound data. The AMS is responsible for enforcing the Security of PushRegistry and presenting notifications (if any) to the user before invoking the MIDlet suite.

The AMS is responsible for the shutdown of any running applications (if necessary) prior to the invocation of the push `MIDlet` method.

After the AMS has started the push application, the `MIDlet` is responsible for opening the connections and for all subsequent I/O operations. An application that needs to perform blocking I/O operations SHOULD use a separate thread to allow for interactive user operations. Once the application has been started and the connection has been opened, the AMS is no longer responsible for listening for push notifications for that connection. The application is responsible for reading all inbound data.

If an application has finished with all inbound data it MAY `close()` the connection. If the connection is closed, then neither the AMS nor the application will be listening for push notifications. Inbound data could be lost, if the application closes the connection before all data has been received.

When the application is destroyed, the AMS resumes its responsiblity to watch for inbound connections.

A push application SHOULD behave in a predictable manner when handling asynchronous data via the push mechanism. A well behaved application SHOULD inform the user that data has been processed. (While it is possible to write applications that do not use any user visible interfaces, this could lead to a confused end user experience to launch an application that only performs a background function.)

### Dynamic Connections Registered from a Running MIDlet

There are cases when defining a well known port registered with IANA is not necessary. Simple applications may just wish to exchange data using a private protocol between a `MIDlet` and server application.

To accomodate this type of application, a mechanism is provided to dynamically allocate a connection and to register that information, as if it was known, when the application was installed. This information can then be sent to an agent on the network to use as the mechanism to communicate with the registered `MIDlet`.

For instance, if a `UDPDatagramConnection` is opened and a port number, was not specified, then the application is requesting a dynamic port to be allocated from the ports that are currently available. By calling `PushRegistry.registerConnection()` the `MIDlet` informs the AMS that it is the target for inbound communication, even after the `MIDlet` has been destroyed (See `MIDlet` life cycle for definition of "destroyed" state). If the application is deleted from the phone, then its dynamic communication connections are unregistered automatically.

### AMS Runtime Handling - Implementation Notes

During installation each `MIDlet` that is expecting inbound communication on a well known address has the information recorded with the AMS from the push registration attribute in the manifest or application descriptor file. Once the installation has been successfully completed, (e.g. For the OTA recommended practices - when the Installation notification message has been successfully transmitted, the application is officially installed.) the `MIDlet` MAY then receive inbound communication. e.g. the push notification event.

When the AMS is started, it checks the list of registered connections and begins listening for inbound communication. When a notification arrives the AMS starts the registered `MIDlet`. The `MIDlet` then opens the connection with `Connector.open()` method to perform whatever I/O operations are needed for the particular connection type. e.g. for a server socket the application uses `acceptAndOpen()` to get the socket connected and for a datagram connection the application uses `receive()` to read the delivered message.

For message oriented transports the inbound message MAY be read by the AMS and saved for delivery to the `MIDlet` when it requests to read the data. For stream oriented transports the connection MAY be lost if the connection is not accepted before the server end of the connection request timeouts.

When a `MIDlet` is started in response to a registered push connection notification, it is platform dependent what happens to the current running application. The `MIDlet` life cycle defines the expected behaviors that an interrupted `MIDlet` could see from a call to `pauseApp()` or from `destroyApp()`.

## Sample Usage Scenarios

Usage scenario 1: The suite includes a `MIDlet` with a well known port for communication. During the `startApp` processing a thread is launched to handle the incoming data. Using a separate thread is the recommended practice for avoiding conflicts between blocking I/O operations and the normal user interaction events. The thread continues to receive messages until the `MIDlet` is destroyed.

#### Sample Chat Descriptor File -

In this sample, the descriptor file includes a static push connection registration. It also includes an indication that this `MIDlet` requires permission to use a datagram connection for inbound push messages. (See Security of Push Functions in the package overview for details about `MIDlet` permissions.) Note: this sample is appropriate for bursts of datagrams. It is written to loop on the connection, processing received messages.

`

      MIDlet-Name: SunNetwork - Chat Demo
      MIDlet-Version: 1.0
      MIDlet-Vendor: Sun Microsystems, Inc.
      MIDlet-Description: Network demonstration programs for MIDP
      MicroEdition-Profile: MIDP-2.0
      MicroEdition-Configuration: CLDC-1.0
      MIDlet-1: InstantMessage, /icons/Chat.png, example.chat.SampleChat, *
      MIDlet-Push-1: datagram://:79,  example.chat.SampleChat, *
      MIDlet-Permissions: javax.microedition.io.PushRegistry, \\
                          javax.microedition.io.Connector.datagramreceiver

`

#### Sample Chat MIDlet Processing -

`

     public class SampleChat extends MIDlet {
         // Current inbound message connection.
         DatagramConnection conn;
         // Flag to terminate the message reading thread.
         boolean done_reading;

         public void startApp() {
             // List of active connections.
             String connections[];

             // Check to see if this session was started due to
             // inbound connection notification.
             connections = PushRegistry.listConnections(true);

             // Start an inbound message thread for available
             // inbound messages for the statically configured
             // connection in the descriptor file.
             for (int i=0; i < connections.length; i++) {
               Thread t = new Thread (new MessageHandler(
                                connections[i]));
               t.start();
             }

             ...
            }
         }

         // Stop reading inbound messages and release the push
         // connection to the AMS listener.
         public void destroyApp(boolean conditional) {
            done_reading = true;
            if (conn != null)
                conn.close();
            // Optionally, notify network service that we're
            // done with the current session.
            ...
         }

         // Optionally, notify network service.
         public void pauseApp() {
             ...
         }

      // Inner class to handle inbound messages on a separate thread.
      class MessageHandler implements Runnable {
          String connUrl ;
          MessageHandler(String url) {
               connUrl = url ;
          }
          // Fetch messages in a blocking receive loop.
          public void run() {
            try {
              // Get a connection handle for inbound messages
              // and a buffer to hold the inbound message.
              DatagramConnection conn = (DatagramConnection)
                   Connector.open(connUrl);
              Datagram data = conn.newDatagram(conn.getMaximumLength());

              // Read the inbound messages
              while (!done_reading) {
                 conn.receive(data);
                ...
              }
             } catch (IOException ioe) {
             ...
          }
          ...

`

Usage scenario 2: The suite includes a `MIDlet` that dynamically allocates port the first time it is started.

#### Sample Ping Descriptor File -

In this sample, the descriptor file includes an entry indicating that the application will need permission to use the datagram connection for inbound push messages. The dynamic connection is allocated in the constructor the first time it is run. The open connection is used during this session and can be reopened in a subsequent session in response to a inbound connection notification.

`

      MIDlet-Name: SunNetwork - Demos
      MIDlet-Version: 1.0
      MIDlet-Vendor: Sun Microsystems, Inc.
      MIDlet-Description: Network demonstration programs for MIDP
      MicroEdition-Profile: MIDP-2.0
      MicroEdition-Configuration: CLDC-1.0
      MIDlet-1: JustCallMe, /icons/Ping.png, example.ping.SamplePingMe, *
      MIDlet-Permissions: javax.microedition.io.PushRegistry, \\
                          javax.microedition.io.Connector.datagramreceiver

`

#### Sample Ping MIDlet Processing -

`

     public class SamplePingMe extends MIDlet {
        // Name of the current application for push registration.
        String myName = "example.chat.SamplePingMe";
        // List of registered push connections.
        String connections[];
        // Inbound datagram connection
        UDPDatagramConnection dconn;

        public SamplePingMe() {

            // Check to see if the ping connection has been registered.
            // This is a dynamic connection allocated on first
            // time execution of this MIDlet.
            connections = PushRegistry.listConnections(false);

            if (connections.length == 0) {
                // Request a dynamic port for out-of-band notices.
                // (Omitting the port number let's the system allocate
                //  an available port number.)
                try {
                    dconn = (UDPDatagramConnection)
                            Connector.open("datagram://");
                    String dport = "datagram://:"  + dconn.getLocalPort();

                    // Register the port so the MIDlet will wake up, if messages
                    // are posted after the MIDlet exits.
                    PushRegistry.registerConnection(dport, myName, "*");

                    // Post my datagram address to the network
                      ...
                } catch (IOException ioe) {
                    ...
                } catch (ClassNotFoundException cnfe) {
                    ...
                }
        }

        public void startApp() {
           // Open the connection if it's not already open.
           if (dconn == null) {
               // This is not the first time this is run, because the
               // dconn hasn't been opened by the constructor.

              // Check if the startup has been due to an incoming
              // datagram.
              connections = PushRegistry.listConnections(true);

              if (connections.length > 0) {
                 // There is a pending datagram that can be received.
                 dconn = (UDPDatagramConnection)
                     Connector.open(connections[0]);

                 // Read the datagram
                 Datagram d = dconn.newDatagram(dconn.getMaximumLength());
                 dconn.receive(d);
              } else {
                 // There are not any pending datagrams, but open
                 // the connection for later use.
                 connections = PushRegistry.listConnections(false);
                 if (connections.length > 0) {
                         dconn = (UDPDatagramConnection)
                             Connector.open(connections[0]);
                 }
             }
          }

        public void destroyApp(boolean unconditional) {
            // Close the connection before exiting
            if(dconn != null){
               dconn.close()
               dconn = null
            }
        }
        ...

`

Since:
  MIDP 2.0

Method Summary
`static String` | `getFilter(String connection)` Retrieve the registered filter for a requested connection.
`static String` | `getMIDlet(String connection)` Retrieve the registered `MIDlet` for a requested connection.
`static String[]` | `listConnections(boolean available)` Return a list of registered connections for the current `MIDlet` suite.
`static long` | `registerAlarm(String midlet, long time)` Register a time to launch the specified application.
`static void` | `registerConnection(String connection, String midlet, String filter)` Register a dynamic connection with the application management software.
`static boolean` | `unregisterConnection(String connection)` Remove a dynamic connection registration.

Methods inherited from class java.lang.Object
`equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Method Detail

### registerConnection

    public static void registerConnection(String connection,
                                          String midlet,
                                          String filter)
                                   throws ClassNotFoundException,
                                          IOException

  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 arguments for the dynamic connection registration are the same as the Push Registration Attribute used for static registrations.

  If the `connection` or `filter` arguments are `null`, then an `IllegalArgumentException` will be thrown. If the `midlet` argument is `null` a `ClassNotFoundException` will be thrown.

  Parameters:
    `connection` - generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
    `midlet` - class name of the `MIDlet` to be launched, when new external data is available. The named `MIDlet` MUST be registered in the descriptor file or the jar file manifest with a MIDlet-<n> record. This parameter has the same semantics as the MIDletClassName in the Push registration attribute defined above in the class description.
    `filter` - a connection URL string indicating which senders are allowed to cause the `MIDlet` to be launched
  Throws:
    `IllegalArgumentException` - if the connection string is not valid, or if the filter string is not valid
    `ConnectionNotFoundException` - if the runtime system does not support push delivery for the requested connection protocol
    `IOException` - if the connection is already registered or if there are insufficient resources to handle the registration request
    `ClassNotFoundException` - if the `MIDlet` class name can not be found in the current `MIDlet` suite or if this class is not included in any of the MIDlet-<n> records in the descriptor file or the jar file manifest
    `SecurityException` - if the `MIDlet` does not have permission to register a connection
  See Also:
    `unregisterConnection(java.lang.String)`

### unregisterConnection

    public static boolean unregisterConnection(String connection)

  Remove a dynamic connection registration.

  Parameters:
    `connection` - generic connection protocol, host and port number
  Returns:
    `true` if the unregistration was successful, `false` if the connection was not registered or if the connection argument was `null`
  Throws:
    `SecurityException` - if the connection was registered by another `MIDlet` suite
  See Also:
    `registerConnection(java.lang.String, java.lang.String, java.lang.String)`

### listConnections

    public static String[] listConnections(boolean available)

  Return a list of registered connections for the current `MIDlet` suite.

  Parameters:
    `available` - if `true`, only return the list of connections with input available, otherwise return the complete list of registered connections for the current `MIDlet` suite
  Returns:
    array of registered connection strings, where each connection is represented by the generic connection protocol, host and port number identification

### getMIDlet

    public static String getMIDlet(String connection)

  Retrieve the registered `MIDlet` for a requested connection.

  Parameters:
    `connection` - generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
  Returns:
    class name of the `MIDlet` to be launched, when new external data is available, or `null` if the connection was not registered by the current `MIDlet` suite or if the connection argument was `null`
  See Also:
    `registerConnection(java.lang.String, java.lang.String, java.lang.String)`

### getFilter

    public static String getFilter(String connection)

  Retrieve the registered filter for a requested connection.

  Parameters:
    `connection` - generic connection protocol, host and port number (optional parameters may be included separated with semi-colons (;))
  Returns:
    a filter string indicating which senders are allowed to cause the `MIDlet` to be launched or `null`, if the connection was not registered by the current `MIDlet` suite or if the connection argument was `null`
  See Also:
    `registerConnection(java.lang.String, java.lang.String, java.lang.String)`

### registerAlarm

    public static long registerAlarm(String midlet,
                                     long time)
                              throws ClassNotFoundException,
                                     ConnectionNotFoundException

  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.

  Parameters:
    `midlet` - class name of the `MIDlet` within the current running `MIDlet` suite to be launched, when the alarm time has been reached. The named `MIDlet` MUST be registered in the descriptor file or the jar file manifest with a MIDlet-<n> record. This parameter has the same semantics as the MIDletClassName in the Push registration attribute defined above in the class description.
    `time` - time at which the `MIDlet` is to be executed in the format returned by `Date.getTime()`
  Returns:
    the time at which the most recent execution of this `MIDlet` was scheduled to occur, in the format returned by `Date.getTime()`
  Throws:
    `ConnectionNotFoundException` - if the runtime system does not support alarm based application launch
    `ClassNotFoundException` - if the `MIDlet` class name can not be found in the current `MIDlet` suite or if this class is not included in any of the MIDlet-<n> records in the descriptor file or the jar file manifest or if the `midlet` argument is `null`
    `SecurityException` - if the `MIDlet` does not have permission to register an alarm
  See Also:
    `Date.getTime()`, `Timer`, `TimerTask`

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
| IM Profile
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Submit a comment or suggestion Version 2.0 of IM Profile Specification
Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries. Copyright (c) 1993-2002 Sun Microsystems, Inc. 901 San Antonio Road,Palo Alto, California, 94303, U.S.A. All Rights Reserved.