/*********************************************************************
* ____ _____ _ *
* / ___| ___ _ __ _ _ | ____|_ __(_) ___ ___ ___ ___ _ __ *
* \___ \ / _ \| '_ \| | | | | _| | '__| |/ __/ __/ __|/ _ \| '_ \ *
* ___) | (_) | | | | |_| | | |___| | | | (__\__ \__ \ (_) | | | | *
* |____/ \___/|_| |_|\__, | |_____|_| |_|\___|___/___/\___/|_| |_| *
* |___/ *
* *
*********************************************************************
* Sony Ericsson Mobile Communications AB, Lund Sweden *
* Copyright 2007 Sony Ericsson Mobile Communications AB. *
* All rights, including trade secret rights, reserved. *
*********************************************************************
*
* @file
* @ingroup JAVA
*
* @copyright_semc
* @author MIDP
*/
package javax.microedition.midlet;
import com.sonyericsson.midp.Configuration;
import com.sun.midp.io.HttpUrl;
import com.sun.midp.midlet.Scheduler;
import com.sun.midp.midlet.MIDletSuite;
import com.sun.midp.security.Permissions;
/**
* A <code>MIDlet</code> is a Mobile Information Device Profile application.
* The application must
* extend this class to allow the application management software to control the
* MIDlet and to be able to retrieve properties from the application descriptor
* and notify and request state changes. The methods of this class allow the
* application management software to create, start, and destroy a
* MIDlet. A <code>MIDlet</code> is a set of classes designed to be run and
* controlled by the application management software via this interface. The
* states allow the application management software to manage the activities of
* a <CODE>MIDlet</CODE>. It can select
* which <code>MIDlet</code> is active at a given time by starting and
* destroying them individually. The application management software maintains the
* state of the <code>MIDlet</code> and invokes methods on the
* <code>MIDlet</code> to notify the MIDlet of change states. The
* <code>MIDlet</code> implements these methods to update its internal
* activities and resource usage as directed by the application management
* software. The <code>MIDlet</code> can initiate some state changes itself
* and notifies the application management software of those state changes by
* invoking the appropriate methods.
* <p>
*
* <strong>Note:</strong> The methods on this class signal state changes.
* The state change is not considered complete until the state change method has
* returned. It is intended that these methods return quickly.
* <p>
* @since MIDP 1.0
*/
public abstract class MIDlet {
/** current state of the MIDlet */
private MIDletProxy state;
/**
* Protected constructor for subclasses. The application management software
* is responsible for creating MIDlets and creation of MIDlets is
* restricted. MIDlets should not attempt to create other MIDlets.
*
* @exception java.lang.SecurityException
* unless the application management software is creating the
* MIDlet.
* @since MIDP 2.0
*/
protected MIDlet() {
state = new MIDletProxy(this);
}
/**
* Signals the <code>MIDlet</code> that it has entered the <em>Active</em>
* state. In the
* <em>Active</EM> state the <code>MIDlet</code> may hold resources.
* The method will only be called when
* the <code>MIDlet</code> is in the <em>Paused</em> state.
* <p>
* The use of {@link MIDletStateChangeException} to delay starting a
* MIDlet is deprecated.
* If MIDletStateChangeException exception is thrown it MUST be
* handled as a RuntimeException below.
*
* <p>
* If a Runtime exception occurs during <code>startApp</code> the
* MIDlet will be destroyed immediately.
* Its <code>destroyApp</code> will be called allowing
* the MIDlet to cleanup.
*
* @exception MIDletStateChangeException is thrown
* if the <code>MIDlet</code>
* cannot start now but might be able to start at a
* later time.
* @since MIDP 1.0
*/
protected abstract void startApp() throws MIDletStateChangeException;
/**
* Pausing of MIDlets is deprecated.
* The application management software MUST NOT call the
* <code>pauseApp</code> method.
* The MIDlet is not required to implement the <code>pauseApp</code>
* method.
* Classes in a MIDlet Suite may call the <code>pauseApp</code>
* method but the state of the MIDlet MUST NOT be changed.
*
* #deprecated Previously calls to <code>pauseApp</code> did not
* provide reliable information about system state changes.
* To be informed of changes in resources available to the
* application use the listeners in the respective APIs.
* For example, to be notified that the application is not in the
* foreground register a
* {@link javax.microedition.lcdui.DisplayListener DisplayListener}.
* The {@link javax.microedition.event.EventManager} can be used
* to listen for system state changes.
*
* @since MIDP 1.0
*/
protected abstract void pauseApp();
/**
* Signals the <code>MIDlet</code> to terminate and enter the
* <em>Destroyed</em> state. In the destroyed state the
* <code>MIDlet</code> must release all resources and save any persistent
* state. This method may be called from the <em>Paused</em> or
* <em>Active</em> states.
* <p>
* <code>MIDlet</code>s should perform any operations required before
* being terminated, such as releasing resources or saving preferences or
* state.
* <p>
* The use of {@link MIDletStateChangeException} to delay destruction of a
* MIDlet is deprecated. The <code>destroyApp</code> method MUST always
* be called with <code>true</code> to force termination.
* The <code>MIDlet</code> is put in the <em>Destroyed</em>
* state regardless of how this method terminates.
*
* <p>
* If a Runtime exception occurs during <code>destroyApp</code> then the
* exception is ignored and the MIDlet is put into the <em>Destroyed</em>
* state.
*
* <p>
* When an uncaught exception occurs in a thread, the thread MUST be stopped
* in accordance with the Java Language Specification. In addition, further
* handling of the uncaught exception MAY occur as follows:
* </p>
* <ul>
* <li>If an implementation can identify the MIDlet that created the thread
* (the MIDlet to which the thread belongs), the MIDlet.destroyApp(false)
* method of this MIDlet MAY be called.</li>
* <li>If an implementation can only identify the MIDlet suite that created
* the thread (the MIDlet suite to which the thread belongs), the
* MIDlet.destroyApp(false) methods of all MIDlets from this suite MAY be
* called.</li>
* <li>If an implementation cannot identify either a MIDlet or a MIDlet
* suite that owns the offending thread, MIDlet.destroyApp(false) methods of
* all MIDlets executing in this VM instance MAY be called.</li>
* </ul>
* In all of these cases, the behavior after a call to
* MIDlet.destroyApp(false) is as follows:
* <ul>
* <li>If a MIDlet attempts to recover by throwing
* javax.microedition.midlet.MIDletStateChangeException, the implementation
* MAY allow the MIDlet to continue running.</li>
* <li>If a call to MIDlet.destroyApp(false) results in a different
* exception of any kind, the implementation MUST terminate the MIDlet</li>
* </ul>
*
* @param unconditional
* If true when this method is called, the <code>MIDlet</code>
* must cleanup and release all resources. If false the
* <code>MIDlet</code> may throw <CODE>MIDletStateChangeException</CODE>
* to indicate it does not want to be destroyed at this time.
*
* @exception MIDletStateChangeException
* is thrown if the <code>MIDlet</code> wishes to continue
* to execute (Not enter the <em>Destroyed</em> state).
* This exception is ignored and the MIDlet is destroyed.
* @since MIDP 1.0
*/
protected abstract void destroyApp(boolean unconditional) throws MIDletStateChangeException;
/**
*
* Used by an <code>MIDlet</code> to notify the application management
* software that it has entered into the <em>Destroyed</em> state. The
* application management software will not call the MIDlet's
* <code>destroyApp</code> method, and all resources held by the
* <code>MIDlet</code> will be considered eligible for reclamation. The
* <code>MIDlet</code> must have performed the same operations (clean up,
* releasing of resources etc.) it would have if the
* <code>MIDlet.destroyApp()</code> had been called.
*
* @since MIDP 1.0
*/
public final void notifyDestroyed() {
state.notifyDestroyed();
}
/**
* Pausing of MIDlets is deprecated.
* For backward compatibility and to avoid problems with existing
* MIDlets, calling <code>notifyPaused</code> in the <em>Active</em>
* state MUST cause <code>startApp</code> to be called immediately.
* The MIDlet is expecting a call to <code>startApp</code>
* to restore it to the <em>Active</em> state.
* <p>
* Invoking this method MUST NOT have any effect if the <code>MIDlet</code>
* is not in the <em>Active</em> state.
* A misbehaving MIDlet that continuously calls <code>notifyPaused</code>
* may be destroyed.
*
* #deprecated The <em>Paused</em> state is deprecated;
* the application does not need to inform the implementation
* that it is quiescent.
*
* @since MIDP 1.0
*/
public final void notifyPaused() {
state.notifyPaused();
}
/**
* Provides a <code>MIDlet</code> with a mechanism to retrieve named
* properties from the application management software. The properties are
* retrieved from the combination of the application descriptor file and the
* manifest. For trusted applications the values in the manifest MUST NOT be
* overridden by those in the application descriptor. If they differ, the
* MIDlet will not be installed on the device. For untrusted applications,
* if an attribute in the descriptor has the same name as an attribute in
* the manifest, the value from the descriptor is used and the value from the
* manifest is ignored.
*
* @param key
* the name of the property
* @return A string with the value of the property. <code>null</code> is
* returned if no value is available for the key.
* @exception NullPointerException
* is thrown if key is <code>null</code>.
* @since MIDP 1.0
*/
public final String getAppProperty(String key) {
return state.getMIDletSuite().getProperty(key);
}
/**
* Provides a mechanism to retrieve and at the same time parse application
* property values from the application descriptor and the manifest of the
* MIDlet or bound LIBlets. This method retrieves property value for a specific
* LIBlet or MIDlet, so same property name is allowed to be used by multiple
* LIBlets without ambiguity in the same binding.
*
* @param name
* name of the LIBlet or MIDlet to retrieve named property
* information from. If both name and vendor are <code> null
* </code>, this retrieves information from the MIDlet JAD/Manifest
* @param vendor
* the vendor of the LIBlet or MIDlet
* @param attributeName
* the name of the property to retrieve
* @param attributeDelimiter
* The characters in this parameter are the delimiters for
* separating the retrieved property value into tokens. Delimiter
* characters themselves will not be treated as tokens. If
* this is <code> null </code>, the value is not tokenized.
* @return
* An array of string with the value of the property tokenized.
* <code>null</code> is returned if no value is available for the
* attributeName
* @exception NullPointerException
* is thrown if attributeName is <code>null</code>.
* @since MIDP 3.0
*/
public static final String[] getAppProperty(String name, String vendor, String attributeName, String attributeDelimiter) {
// TODO: Implement this! (MIDP3)
throw new IllegalStateException("MIDP3: Not Implemented");
}
/**
* Pausing of MIDlets is deprecated.
* Invoking this method MUST have no effect.
* The application management software maintains the MIDlet in
* the <em>Active</em> state.
*
* #deprecated MIDlets will not be paused and do not need to be
* resumed.
*
* @since MIDP 1.0
*/
public final void resumeRequest() {
state.resumeRequest();
}
/**
* <p>
* Requests that the device handle (for example, display or install) the
* indicated URL.
* </p>
*
* <p>
* If the platform has the appropriate capabilities and resources available,
* it SHOULD bring the appropriate application to the foreground and let the
* user interact with the content, while keeping the MIDlet suite running in
* the background. If the platform does not have appropriate capabilities or
* resources available, it MAY wait to handle the URL request until after
* the MIDlet suite exits. In this case, when the requesting MIDlet suite
* exits, the platform MUST then bring the appropriate application (if one
* exists) to the foreground to let the user interact with the content.
* </p>
*
* <p>
* This is a non-blocking method. In addition, this method does NOT queue
* multiple requests. On platforms where the MIDlet suite must exit before
* the request is handled, the platform MUST handle only the last request
* made. On platforms where the MIDlet suite and the request can be handled
* concurrently, each request that the MIDlet suite makes MUST be passed to
* the platform software for handling in a timely fashion.
* </p>
*
* <p>
* If the URL specified refers to a MIDlet suite (either an Application
* Descriptor or a JAR file), the application handling the request MUST
* interpret it as a request to install the named package. In this case, the
* platform's normal MIDlet suite installation process SHOULD be used, and
* the user MUST be allowed to control the process (including cancelling the
* download and/or installation). If the MIDlet suite being installed is an
* <em>update</em> of the currently running MIDlet suite, the platform
* MUST first stop the currently running MIDlet suite before performing the
* update. On some platforms, the currently running MIDlet suite MAY need to
* be stopped before any installations can occur.
* </p>
*
* <p>
* If the URL specified is of the form <code>tel:<number></code>,
* as specified in <a href="http://www.ietf.org/rfc/rfc2806.txt">RFC2806</a>,
* then the platform MUST interpret this as a request to initiate a voice
* call. The request MUST be passed to the "phone" application to
* handle if one is present in the platform. The "phone"
* application, if present, MUST be able to set up local and global phone
* calls and also perform DTMF post dialing. Not all elements of RFC2806
* need be implemented, especially the area-specifier or any other
* requirement on the terminal to know its context. The isdn-subaddress,
* service-provider and future-extension may also be ignored. Pauses during
* dialing are not relevant in some telephony services.
* </p>
*
* <p>
* Devices MAY choose to support additional URL schemes beyond the
* requirements listed above.
* </p>
*
* <p>
* Many of the ways this method will be used could have a financial impact
* to the user (e.g. transferring data through a wireless network, or
* initiating a voice call). Therefore the platform MUST ask the user to
* explicitly acknowlege each request before the action is taken.
* Implementation freedoms are possible so that a pleasant user experience
* is retained. For example, some platforms may put up a dialog for each
* request asking the user for permission, while other platforms may launch
* the appropriate application and populate the URL or phone number fields,
* but not take the action until the user explicitly clicks the load or dial
* buttons.
* </p>
*
* @return true if the MIDlet suite MUST first exit before the content can
* be fetched.
*
* @param url
* The URL for the platform to load. An empty string (not null)
* cancels any pending requests.
*
* @exception javax.microedition.io.ConnectionNotFoundException
* if the platform cannot handle the URL requested.
*
* @since MIDP 2.0
*/
public final boolean platformRequest(String url) throws javax.microedition.io.ConnectionNotFoundException {
if (url != null && url.length() > 0 ) {
if (!supportedProtocol(url)) {
throw new javax.microedition.io.ConnectionNotFoundException();
}
if (!priviligedProtocol(url)) {
MIDletSuite midletSuite;
midletSuite = Scheduler.getScheduler().getMIDletSuite();
if (midletSuite == null) {
//Not in midlet context
throw new IllegalStateException();
}
if (Configuration.MIDlet.useDomainInPlatformRequest()) {
midletSuite.checkForPermission(Permissions.PLATFORM_REQUEST_URL, url);
} else {
midletSuite.checkForPermission(Permissions.PLATFORM_REQUEST_URL, "");
}
}
return state.platformRequest(url);
}
return false;
}
private static final String[] priviligedProtocols = { "tel:", "smsto:", "mmsto:", "mailto:" };
private static final String[] unpriviligedProtocols = { "http://", "https://", "rtsp://" };
private boolean supportedProtocol(String url) {
for( int i=0; i < unpriviligedProtocols.length; i++) {
if(url.startsWith(unpriviligedProtocols[i])) {
return true;
}
}
return priviligedProtocol(url);
}
private boolean priviligedProtocol(String url) {
for(int i=0; i < priviligedProtocols.length; i++) {
if(url.startsWith(priviligedProtocols[i])) {
return true;
}
}
return false;
}
/**
* The Named Permissions of MIDP 2.x have been deprecated.
* For MIDP 3.0 applications, calling <code>checkPermission</code> throws
* an exception.
* For MIDP 2.x applications, the implementation must implement
* <code>checkPermission</code>.
* <p>
* Gets the status of the specified legacy named permission.
* If no API on the device
* defines the specific permission requested then it must be reported as
* denied. If the status of the permission is not known because it might
* require a user interaction then it should be reported as unknown.
*
* @param permission
* to check if denied, allowed, or unknown.
* @return 0 if the permission is denied; 1 if the permission is allowed; -1
* if the status is unknown
*
* @throws IllegalStateException if the MIDlet Suite is a MIDP 3.0 MIDlet
* suite.
*
* #deprecated The permissions model in this specification does not use
* named permissions. MIDP 3.0 MIDlets needing to check permissions
* should use <code>java.security.AccessController.checkPermission</code>.
*
* @since MIDP 2.0
*/
public final int checkPermission(String permission) {
return state.checkPermission(permission);
}
/**
* <p>
* Gets the length of time that the application's splash screen has been
* shown to the user.
* </p>
*
* <p>
* An application may specify a splash screen in its manifest (see section X
* for more details). The splash screen is shown only when the application
* is started by the user and is not shown during subsequent restarts of the
* application (i.e. after being paused). The splash screen is shown on the
* primary Display.
* </p>
*
* <p>
* The implementation should show the splash screen as soon as possible
* after the MIDlet is launched, but it must guarantee that it is visible to
* the user by the time the MIDlet's startApp method is called.
* </p>
*
* <p>
* Once shown, the splash screen will remain visible until one of the
* following events occurs:
* </p>
* <ul>
* <li>The MIDlet shows a Displayable by calling setCurrent on its primary
* Display</li>
* <li>The MIDlet's startApp method returns</li>
* <li>The MIDlet is no longer in the foreground</li>
* </ul>
*
* <p>
* If the splash screen is still visible, this method returns the elapsed
* time since when it was first shown. Implementations are required to
* provide a time value that is accurate to within +/-100 milliseconds, as
* measured by viewing the physical display of the device. A value of -1 is
* returned if the splash screen has been hidden or if a valid splash screen
* image is not specified in the MIDlet's manifest.
* </p>
*
* @return the length of time (in milliseconds) that the currently visible
* splash screen has been shown, or -1 if no splash screen is
* currently visible
*
* @since MIDP 3.0
*/
public long getSplashScreenTime() {
return 0;
}
}
|