/*
*
*
* Copyright 1990-2009 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 javax.microedition.io;
import java.lang.ClassNotFoundException;
import java.lang.IllegalStateException;
import java.lang.IllegalArgumentException;
import java.lang.String;
import java.io.IOException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import com.sun.midp.io.Util;
import com.sun.midp.io.j2me.push.PushRegistryImpl;
/**
* The <code>PushRegistry</code> 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
* <code>registerConnection</code> method.
* <P> 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
* <code>MIDlet</code>, the AMS will start the <code>MIDlet</code>
* via the normal invocation of <code>MIDlet.startApp</code>
* method.</P>
*
* <H3> Installation Handling of Declared Connections </H3>
*
* <P>
* To avoid collisions on inbound generic connections, the application
* descriptor file MUST include information about static connections
* that are needed by the <code>MIDlet</code> 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 <em>Over The Air User Initiated Provisioning
* Specification</em> 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 <code>MIDlet</code> class that is not listed in
* the <code>MIDlet-<n></code> attributes of the same
* application descriptor.
*
* If the <code>MIDlet</code> 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 <code>PushRegistry</code>.
* </P>
* <P>
* A conflict-free installation reserves each requested connection for
* the exclusive use of the
* <code>MIDlets</code> in the suite. While the suite is
* installed, any attempt by other applications to open one of the
* reserved connections will fail with an
* <code>IOException</code>. A call from a
* <code>MIDlet</code> to
* <code>Connector.open()</code>
* on a connection reserved for its suite will always
* succeed, assuming the suite does not already have the connection open.
* </P>
*
* <P>
* If two <code>MIDlet</code> 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.
* </P>
* <H3> <A NAME="PushAttr"></A>Push Registration Attribute </H3>
* <P>
* Each push registration entry contains the following information :
* <CODE><BLOCKQUOTE>
* <strong>MIDlet-Push-</strong><n>: <ConnectionURL>,
* <MIDletClassName>, <AllowedSender>
* </BLOCKQUOTE>
* </CODE> where :
* <UL>
* <LI> <code>MIDlet-Push-<n></code> =
* the Push registration attribute name. Multiple push
* registrations can be provided in a <code>MIDlet</code>
* 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.
* </LI>
* <LI><code>ConnectionURL</code> =
* the connection string used in <code>Connector.open()</code></LI>
* <LI><code>MIDletClassName</code> =
* the <code>MIDlet</code> that is responsible for the connection.
* The named <code>MIDlet</code> MUST be registered in the
* descriptor file or the jar file manifest with a
* <code>MIDlet-<n></code> 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 privileges for the application.)
* If the named <code>MIDlet</code> appears more than once in the
* suite, the first matching entry is used. </LI>
* <LI>
* <code>AllowedSender</code> = a designated filter that restricts which
* senders are valid for launching the requested <code>MIDlet</code>.
*
* The syntax and semantics of the <code>AllowedSender</code> 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:
* <UL>
* <LI> "*" matches any string, including an empty string </LI>
* <LI> "?" matches any single character </LI>
* </UL>
* When the value of this field is just the wildcard character "*",
* connections will be accepted from any originating source.
*
* For Push attributes using the <CODE>datagram</CODE> and
* <CODE>socket</CODE> 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 <CODE>datagram</CODE> and
* <CODE>socket</CODE> connections.
* </LI>
* </UL>
* <P>
* The MIDP specification defines the syntax for
* <code>datagram</code> and <code>socket</code> 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.
* </P>
* <H4> Example Descriptor File Declarative Notation </H4>
*
* <P>
* 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 <a href="http://www.iana.org/numbers.html#P">
* IANA Port Number Registry</a>]
* </P>
*
* <CODE>
* <PRE>
* MIDlet-Push-1: socket://:79, com.sun.example.SampleChat, *
* MIDlet-Push-2: datagram://:50000, com.sun.example.SampleChat, *
* </PRE>
* </CODE>
* <H3> Buffered Messages </H3>
* <P>
* 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 <code>MIDlet</code> when the
* <code>MIDlet</code> is started and it opens the related
* <code>Connection</code> that it has registered for Push.
* </P>
* <P>
* When datagram connections are supported with Push, the
* implementation MUST guarantee that when a <code>MIDlet</code>
* registered for datagram Push is started in response to an incoming
* datagram, at least the datagram that caused the startup of the
* <code>MIDlet</code> is buffered by the implementation and will be
* available to the <code>MIDlet</code> when the <code>MIDlet</code>
* opens the <code>UDPDatagramConnection</code> after startup.
* </P>
* <P>
* When socket connections are supported with Push, the
* implementation MUST guarantee that when a <code>MIDlet</code>
* registered for socket Push is started in response to
* an incoming socket connection, this connection can
* be accepted by the <code>MIDlet</code> by opening the
* <code>ServerSocketConnection</code> after startup, provided
* that the connection hasn't timed out meanwhile.
* </P>
*
* <H3> Connection vs Push Registration Support </H3>
* <P>
* 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 <code>MIDlet</code>,
* but might not support inbound socket connections for push
* launch capability.
* A <code>ConnectionNotFoundException</code> is thrown from
* the <code>registerConnection</code> and from the
* <code>registerAlarm</code> methods, when the platform
* does not support that optional capability.
* </P>
*
* <H3> AMS Connection Handoff </H3>
* <P>
* Responsibility for registered push connections is shared between
* the AMS and the <code>MIDlet</code> 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
* <code>Connector.open()</code>
* until it calls <code>Connection.close()</code>.
* </P>
* <P>
* 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
* <A HREF="package-summary.html#push">Security of PushRegistry</A>
* and presenting notifications (if any) to the user before invoking
* the MIDlet suite.
*</P>
* <P>
* The AMS is responsible for the shutdown of any running
* applications (if necessary) prior to the invocation of
* the push <code>MIDlet</code> method.
* </P>
* <P>
* After the AMS has started the push application, the
* <code>MIDlet</code> 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.
* </P>
* <P>
* If an application has finished with all inbound data
* it MAY <code>close()</code> 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.
* </P>
* <P>
* When the application is destroyed, the AMS resumes its
* responsibility to watch for inbound connections.
* </P>
* <P>
* 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.)
* </P>
* <H3>Dynamic Connections Registered from a Running MIDlet</H3>
*
* <P>
* 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 <code>MIDlet</code> and server application.
* </P>
*
* <P>
* To accommodate 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
* <code>MIDlet</code>.
* </P>
* <P>
* For instance, if a <a href="UDPDatagramConnection.html">
* <code>UDPDatagramConnection</code></a>
* 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 <code>PushRegistry.registerConnection()</code> the
* <code>MIDlet</code> informs the AMS that it is the target for
* inbound communication, even
* after the <code>MIDlet</code> has been destroyed (See
* <code>MIDlet</code> life cycle for
* definition of "destroyed" state). If the application is deleted from the
* phone, then its dynamic communication connections are unregistered
* automatically.
* </P>
* <H3>AMS Runtime Handling - Implementation Notes</H3>
*
* <P>
* During installation each <code>MIDlet</code> 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 <em>Installation
* notification message</em> has been successfully transmitted, the
* application is officially installed.)
* the <code>MIDlet</code> MAY then receive inbound communication.
* e.g. the push notification event.
* </P>
*
* <P>
* 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
* <code>MIDlet</code>.
* The <code>MIDlet</code> then opens
* the connection with <code>Connector.open()</code> method to
* perform whatever I/O operations are needed for the particular
* connection type. e.g. for a server socket the application
* uses <code>acceptAndOpen()</code> to get the socket connected
* and for a datagram connection the application uses
* <code>receive()</code> to read the delivered message.
* </P>
* <P>
* For message oriented transports the inbound message MAY be
* read by the AMS and saved for delivery to the <code>MIDlet</code>
* 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.
* </P>
* <P>
* When a <code>MIDlet</code> is started in response to a registered
* push connection notification, it is platform dependent what
* happens to the current running application. The <code>MIDlet</code>
* life cycle defines the expected behaviors that an interrupted
* <code>MIDlet</code> could see from a call to <code>pauseApp()</code>
* or from <code>destroyApp()</code>.
* </P>
* <H2>Sample Usage Scenarios</H2>
* <P>
* <strong>Usage scenario 1:</strong>
* The suite includes a <code>MIDlet</code> with a well
* known port for communication.
* During the <code>startApp</code> 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
* <code>MIDlet</code> is destroyed.
* </P>
*
* <H4>Sample Chat Descriptor File -</H4>
* <P> In this sample, the descriptor file includes
* a static push
* connection registration. It also includes
* an indication that this <code>MIDlet</code>
* requires permission to use a datagram connection
* for inbound push messages.
* (See <A HREF="package-summary.html#push">
* Security of Push Functions</A> in the package
* overview for details about <code>MIDlet</code> permissions.)
* <strong>Note:</strong> this sample is appropriate for bursts of
* datagrams.
* It is written to loop on the connection, processing
* received messages.
* </P>
* <CODE>
* <PRE>
* 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
* </PRE>
* </CODE>
*
* <H4>Sample Chat MIDlet Processing -</H4>
* <CODE>
* <PRE>
* 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) {
* ...
* }
* ...
* </PRE>
* </CODE>
* <P>
* <strong>Usage scenario 2:</strong>
* The suite includes a <code>MIDlet</code>
* that dynamically allocates port the first time
* it is started.
* </P>
*
*
* <H4>Sample Ping Descriptor File -</H4>
* <P> 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.
* </P>
* <CODE>
* <PRE>
* 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
* </PRE>
* </CODE>
*
* <H4>Sample Ping MIDlet Processing -</H4>
* <CODE>
* <PRE>
* 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
* }
* }
* ...
* </PRE>
* </CODE>
*/
public class PushRegistry {
/** Prevent instantiation of the push registry. */
private PushRegistry() { };
/**
* Register a dynamic connection with the
* application management software. Once registered,
* the dynamic connection acts just like a
* connection preallocated from the descriptor file.
*
* <P> The arguments for the dynamic connection registration are the
* same as the <A HREF="#PushAttr">Push Registration Attribute</A>
* used for static registrations.
* </P>
* <P> If the <code>connection</code> or <code>filter</code>
* arguments are <code>null</code>,
* then an <code>IllegalArgumentException</code> will be thrown.
* If the <code>midlet</code> argument is <code>null</code> a
* <code>ClassNotFoundException</code> will be thrown. </P>
*
* @param connection generic connection <em>protocol</em>, <em>host</em>
* and <em>port number</em>
* (optional parameters may be included
* separated with semi-colons (;))
* @param midlet class name of the <code>MIDlet</code> to be launched,
* when new external data is available.
* The named <code>MIDlet</code> 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.
* @param filter a connection URL string indicating which senders
* are allowed to cause the <code>MIDlet</code> to be launched
* @exception IllegalArgumentException if the connection string is not
* valid, or if the filter string is not valid
* @exception ConnectionNotFoundException if the runtime system does not
* support push delivery for the requested
* connection protocol
* @exception IOException if the connection is already
* registered or if there are insufficient resources
* to handle the registration request
* @exception ClassNotFoundException if the <code>MIDlet</code>
* class name can not be found in the current <code>MIDlet</code>
* suite or if this class is not included in any of the
* MIDlet-<n> records in the descriptor file or the jar file
* manifest
* @exception SecurityException if the <code>MIDlet</code> does not
* have permission to register a connection
* @see #unregisterConnection
*/
public static void registerConnection(String connection, String midlet,
String filter)
throws ClassNotFoundException,
IOException {
PushRegistryImpl
.registerConnection(connection, midlet, filter);
}
/**
* Remove a dynamic connection registration.
*
* @param connection generic connection <em>protocol</em>,
* <em>host</em> and <em>port number</em>
* @exception SecurityException if the connection was
* registered by another <code>MIDlet</code>
* suite
* @return <code>true</code> if the unregistration was successful,
* <code>false</code> if the connection was not registered
* or if the connection argument was <code>null</code>
* @see #registerConnection
*/
public static boolean unregisterConnection(String connection) {
return PushRegistryImpl.unregisterConnection(connection);
}
/**
* Return a list of registered connections for the current
* <code>MIDlet</code> suite.
*
* @param available if <code>true</code>, only return the list of
* connections with input available, otherwise return the
* complete list of registered connections for the current
* <code>MIDlet</code> suite
* @return array of registered connection strings, where each connection
* is represented by the generic connection <em>protocol</em>,
* <em>host</em> and <em>port number</em> identification
*/
public static String[] listConnections(boolean available) {
return PushRegistryImpl.listConnections(available);
}
/**
* Retrieve the registered <code>MIDlet</code> for a requested connection.
*
* @param connection generic connection <em>protocol</em>, <em>host</em>
* and <em>port number</em>
* (optional parameters may be included
* separated with semi-colons (;))
* @return class name of the <code>MIDlet</code> to be launched,
* when new external data is available, or
* <code>null</code> if the connection was not
* registered by the current <code>MIDlet</code> suite
* or if the connection argument was <code>null</code>
* @see #registerConnection
*/
public static String getMIDlet(String connection) {
// Delegate to implementation class for native lookup
return PushRegistryImpl.getMIDlet(connection);
}
/**
* Retrieve the registered filter for a requested connection.
*
* @param connection generic connection <em>protocol</em>, <em>host</em>
* and <em>port number</em>
* (optional parameters may be included
* separated with semi-colons (;))
* @return a filter string indicating which senders
* are allowed to cause the <code>MIDlet</code> to be
* launched or <code>null</code>, if the connection was not
* registered by the current <code>MIDlet</code> suite
* or if the connection argument was <code>null</code>
* @see #registerConnection
*/
public static String getFilter(String connection) {
// Delegate to implementation class for native lookup
return PushRegistryImpl.getFilter(connection);
}
/**
* Register a time to launch the specified application. The
* <code>PushRegistry</code> supports one outstanding wake up
* time per <code>MIDlet</code> in the current suite. An application
* is expected to use a <code>TimerTask</code> for notification
* of time based events while the application is running.
* <P>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. </P>
*
* @param midlet class name of the <code>MIDlet</code> within the
* current running <code>MIDlet</code> suite
* to be launched,
* when the alarm time has been reached.
* The named <code>MIDlet</code> 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.
* @param time time at which the <code>MIDlet</code> is to be executed
* in the format returned by <code>Date.getTime()</code>
* @return the time at which the most recent execution of this
* <code>MIDlet</code> was scheduled to occur,
* in the format returned by <code>Date.getTime()</code>
* @exception ConnectionNotFoundException if the runtime system does not
* support alarm based application launch
* @exception ClassNotFoundException if the <code>MIDlet</code>
* class name can not be found in the current <code>MIDlet</code>
* 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 <code>midlet</code> argument is
* <code>null</code>
* @exception SecurityException if the <code>MIDlet</code> does not
* have permission to register an alarm
* @see Date#getTime()
* @see Timer
* @see TimerTask
*/
public static long registerAlarm(String midlet, long time)
throws ClassNotFoundException, ConnectionNotFoundException {
// Delegate to implementation class for native registration
return PushRegistryImpl.registerAlarm(midlet, time);
}
}