001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package javax.microedition.midlet;
028:
029: import com.sun.midp.midlet.MIDletPeer;
030: import com.sun.midp.midlet.MIDletStateHandler;
031:
032: import com.sun.midp.security.SecurityToken;
033: import com.sun.midp.security.SecurityInitializer;
034: import com.sun.midp.security.ImplicitlyTrustedClass;
035:
036: import javax.microedition.lcdui.Display;
037:
038: /**
039: * A <code>MIDlet</code> is a MID Profile application.
040: * The application must extend this class to allow the
041: * application management software to control the MIDlet and to be
042: * able to retrieve properties from the application descriptor
043: * and notify and request state changes.
044: * The methods of this class allow the application management software
045: * to create, start, pause, and destroy a MIDlet.
046: * A <code>MIDlet</code> is a set of classes designed to be run and
047: * controlled by the application management software via this interface.
048: * The states allow the application management software to manage
049: * the activities of multiple <CODE>MIDlets</CODE> within
050: * a runtime environment.
051: * It can select which <code>MIDlet</code>s are active at a given time
052: * by starting and pausing them individually.
053: * The application management software maintains the state of the
054: * <code>MIDlet</code> and
055: * invokes methods on the <code>MIDlet</code> to notify the MIDlet of
056: * change states.
057: * The <code>MIDlet</code>
058: * implements these methods to update its internal activities and
059: * resource usage as directed by the application management software.
060: * The <code>MIDlet</code> can initiate some state changes itself and
061: * notifies the application management software of those state changes
062: * by invoking the appropriate methods.<p>
063: *
064: * <strong>Note:</strong> The methods on this interface signal state
065: * changes. The state change is not considered complete until the state
066: * change method has returned. It is intended that these methods return
067: * quickly.<p>
068: */
069:
070: public abstract class MIDlet {
071:
072: /**
073: * Inner class to request security token from SecurityInitializer.
074: * SecurityInitializer should be able to check this inner class name.
075: */
076: static private class SecurityTrusted implements
077: ImplicitlyTrustedClass {
078: }
079:
080: /** Security token to allow access to implementation APIs */
081: private static SecurityToken classSecurityToken = SecurityInitializer
082: .requestToken(new SecurityTrusted());
083:
084: /** Internal peer of this MIDlet */
085: private MIDletPeer peer;
086:
087: /**
088: * Static initializer to set MIDletTunnel implementation
089: * in MIDletPeer class.
090: */
091: static {
092: MIDletPeer.setMIDletTunnel(classSecurityToken,
093: new MIDletTunnelImpl());
094: }
095:
096: /**
097: * Gets the MIDletPeer instance for this MIDlet.
098: *
099: * @return MIDletPeer instance for this midlet.
100: */
101: MIDletPeer getMIDletPeer() {
102: return peer;
103: }
104:
105: /**
106: * Protected constructor for subclasses.
107: * The application management software is responsible
108: * for creating MIDlets and creation of MIDlets is restricted.
109: * MIDlets should not attempt to create other MIDlets.
110: *
111: * @exception java.lang.SecurityException unless the application
112: * management software is creating the MIDlet.
113: */
114: protected MIDlet() {
115: peer = MIDletStateHandler.newMIDletPeer(classSecurityToken,
116: this );
117:
118: // Ensure that a display for this midlet is created
119: Display d = Display.getDisplay(this );
120: }
121:
122: /**
123: * Signals the <code>MIDlet</code> that it has entered the
124: * <em>Active</em> state.
125: * In the <em>Active</EM> state the <code>MIDlet</code> may
126: * hold resources.
127: * The method will only be called when
128: * the <code>MIDlet</code> is in the <em>Paused</em> state.
129: * <p>
130: * Two kinds of failures can prevent the service from starting,
131: * transient and non-transient. For transient failures the
132: * <code>MIDletStateChangeException</code> exception should be thrown.
133: * For non-transient failures the <code>notifyDestroyed</code>
134: * method should be called.
135: * <p>
136: * If a Runtime exception occurs during <code>startApp</code> the
137: * MIDlet will be
138: * destroyed immediately. Its <code>destroyApp</code> will be
139: * called allowing
140: * the MIDlet to cleanup.
141: *
142: * @exception MIDletStateChangeException is thrown
143: * if the <code>MIDlet</code>
144: * cannot start now but might be able to start at a
145: * later time.
146: */
147: protected abstract void startApp()
148: throws MIDletStateChangeException;
149:
150: /**
151: *
152: * Signals the <code>MIDlet</code> to enter
153: * the <em>Paused</em> state.
154: * In the <em>Paused</em> state the <code>MIDlet</code> must
155: * release shared resources
156: * and become quiescent. This method will only be called
157: * called when the <code>MIDlet</code> is in the <em>Active</em> state. <p>
158: * <p>
159: * If a Runtime exception occurs during <code>pauseApp</code> the
160: * MIDlet will be destroyed immediately. Its
161: * <code>destroyApp</code> will be called allowing
162: * the MIDlet to cleanup.
163: */
164: protected abstract void pauseApp();
165:
166: /**
167: * Signals the <code>MIDlet</code> to terminate and enter the
168: * <em>Destroyed</em> state.
169: * In the destroyed state the <code>MIDlet</code> must release
170: * all resources and save any persistent state. This method may
171: * be called from the <em>Paused</em> or
172: * <em>Active</em> states. <p>
173: * <code>MIDlet</code>s should
174: * perform any operations required before being terminated, such as
175: * releasing resources or saving preferences or
176: * state. <p>
177: *
178: * <strong>Note:</strong> The <code>MIDlet</code> can request that
179: * it not enter the <em>Destroyed</em>
180: * state by throwing an <code>MIDletStateChangeException</code>. This
181: * is only a valid response if the <code>unconditional</code>
182: * flag is set to <code>false</code>. If it is <code>true</code>
183: * the <code>MIDlet</code> is assumed to be in the <em>Destroyed</em> state
184: * regardless of how this method terminates. If it is not an
185: * unconditional request, the <code>MIDlet</code> can signify that it
186: * wishes to stay in its current state by throwing the
187: * <code>MIDletStateChangeException</code>.
188: * This request may be honored and the <code>destroy()</code>
189: * method called again at a later time.
190: *
191: * <p>If a Runtime exception occurs during <code>destroyApp</code> then
192: * they are ignored and the MIDlet is put into the <em>Destroyed</em>
193: * state.
194: *
195: * @param unconditional If true when this method is called, the
196: * <code>MIDlet</code> must cleanup and release all resources. If
197: * false the <code>MIDlet</code> may throw
198: * <CODE>MIDletStateChangeException</CODE> to indicate it does not
199: * want to be destroyed at this time.
200: *
201: * @exception MIDletStateChangeException is thrown
202: * if the <code>MIDlet</code> wishes to continue to
203: * execute (Not enter the <em>Destroyed</em> state).
204: * This exception is ignored if <code>unconditional</code>
205: * is equal to <code>true</code>.
206: */
207: protected abstract void destroyApp(boolean unconditional)
208: throws MIDletStateChangeException;
209:
210: /**
211: *
212: * Used by an <code>MIDlet</code> to notify the application
213: * management software that it has entered into the
214: * <em>Destroyed</em> state. The application management software
215: * will not call the MIDlet's <code>destroyApp</code> method,
216: * and all resources
217: * held by the <code>MIDlet</code> will be considered eligible for
218: * reclamation.
219: * The <code>MIDlet</code> must have performed the same operations
220: * (clean up, releasing of resources etc.) it would have if the
221: * <code>MIDlet.destroyApp()</code> had been called.
222: *
223: */
224: public final void notifyDestroyed() {
225: peer.notifyDestroyed();
226: }
227:
228: /**
229: * Notifies the application management software that the MIDlet
230: * does not want to be active and has
231: * entered the <em>Paused</em> state. Invoking this method will
232: * have no effect if the <code>MIDlet</code> is destroyed, or if
233: * it has not yet been started. <p>
234: * It may be invoked by the <code>MIDlet</code> when it is
235: * in the <em>Active</em> state. <p>
236: *
237: * If a <code>MIDlet</code> calls <code>notifyPaused()</code>, in the
238: * future its <code>startApp()</code> method may be called make
239: * it active again, or its <code>destroyApp()</code> method may be
240: * called to request it to destroy itself. <p>
241: *
242: * If the application pauses itself it will need to call
243: * <code>resumeRequest</code> to request to reenter the
244: * <code>active</code> state.
245: */
246: public final void notifyPaused() {
247: peer.notifyPaused();
248: }
249:
250: /**
251: * Provides a <code>MIDlet</code> with a mechanism to retrieve named
252: * properties from the application management software.
253: * The properties are retrieved from the combination of
254: * the application descriptor file and the manifest.
255: * For trusted applications the values in the manifest MUST NOT
256: * be overridden by those in the application descriptor. If they
257: * differ, the MIDlet will not be installed on the device.
258: * For untrusted applications, if an attribute
259: * in the descriptor has the same name as an attribute in the
260: * manifest the value from the descriptor is used and the value
261: * from the manifest is ignored.
262: *
263: * @param key the name of the property
264: * @return A string with the value of the property.
265: * <code>null</code> is returned if no value is available for the
266: * key.
267: * @exception NullPointerException is thrown
268: * if key is <code>null</code>.
269: */
270: public final String getAppProperty(String key) {
271: return peer.getMIDletSuite().getProperty(key);
272: }
273:
274: /**
275: * Provides a <code>MIDlet</code> with a mechanism to indicate
276: * that it is interested in entering the <em>Active</em>
277: * state. Calls to this method can be used by the application
278: * management software to determine which applications to move to
279: * the <em>Active</em> state. <p> When the application management
280: * software decides to activate this application it will call the
281: * <code>startApp</code> method. <p> The application is generally
282: * in the <em>Paused</em> state when this is called. Even in the
283: * paused state the application may handle asynchronous events
284: * such as timers or callbacks.
285: */
286: public final void resumeRequest() {
287: peer.resumeRequest();
288: }
289:
290: /**
291: * <p>Requests that the device handle (for example, display or
292: * install) the indicated URL.</p>
293: *
294: * <p>If the platform has the appropriate capabilities and
295: * resources available, it SHOULD bring the appropriate
296: * application to the foreground and let the user interact with
297: * the content, while keeping the MIDlet suite running in the
298: * background. If the platform does not have appropriate
299: * capabilities or resources available, it MAY wait to handle the
300: * URL request until after the MIDlet suite exits. In this case,
301: * when the requesting MIDlet suite exits, the platform MUST then
302: * bring the appropriate application (if one exists) to the
303: * foreground to let the user interact with the content.</p>
304: *
305: * <p>This is a non-blocking method. In addition, this method does
306: * NOT queue multiple requests. On platforms where the MIDlet
307: * suite must exit before the request is handled, the platform
308: * MUST handle only the last request made. On platforms where the
309: * MIDlet suite and the request can be handled concurrently, each
310: * request that the MIDlet suite makes MUST be passed to the
311: * platform software for handling in a timely fashion.</p>
312: *
313: * <p>If the URL specified refers to a MIDlet suite (either an
314: * Application Descriptor or a JAR file), the application handling
315: * the request MUST interpret it as a request to install the named
316: * package. In this case, the platform's normal MIDlet suite
317: * installation process SHOULD be used, and the user MUST be
318: * allowed to control the process (including cancelling the
319: * download and/or installation). If the MIDlet suite being
320: * installed is an <em>update</em> of the currently running MIDlet
321: * suite, the platform MUST first stop the currently running
322: * MIDlet suite before performing the update. On some platforms,
323: * the currently running MIDlet suite MAY need to be stopped
324: * before any installations can occur.</p>
325: *
326: * <p>If the URL specified is of the form
327: * <code>tel:<number></code>, as specified in <a
328: * href="http://www.ietf.org/rfc/rfc2806.txt">RFC2806</a>, then the
329: * platform MUST interpret this as a request to initiate a voice
330: * call. The request MUST be passed to the "phone"
331: * application to handle if one is present in the platform. The
332: * "phone" application, if present, MUST be able to set
333: * up local and global phone calls and also perform DTMF post
334: * dialing. Not all elements of RFC2806 need be implemented,
335: * especially the area-specifier or any other requirement on the
336: * terminal to know its context. The isdn-subaddress,
337: * service-provider and future-extension may also be
338: * ignored. Pauses during dialing are not relevant in some
339: * telephony services.</p>
340: *
341: * <p>Devices MAY choose to support additional URL schemes beyond
342: * the requirements listed above.</p>
343: *
344: * <p>Many of the ways this method will be used could have a
345: * financial impact to the user (e.g. transferring data through a
346: * wireless network, or initiating a voice call). Therefore the
347: * platform MUST ask the user to explicitly acknowledge each
348: * request before the action is taken. Implementation freedoms are
349: * possible so that a pleasant user experience is retained. For
350: * example, some platforms may put up a dialog for each request
351: * asking the user for permission, while other platforms may
352: * launch the appropriate application and populate the URL or
353: * phone number fields, but not take the action until the user
354: * explicitly clicks the load or dial buttons.</p>
355: *
356: * @return true if the MIDlet suite MUST first exit before the
357: * content can be fetched.
358: *
359: * @param URL The URL for the platform to load. An empty string
360: * (not null) cancels any pending requests.
361: *
362: * @exception javax.microedition.io.ConnectionNotFoundException if
363: * the platform cannot handle the URL requested.
364: *
365: */
366: public final boolean platformRequest(String URL)
367: throws javax.microedition.io.ConnectionNotFoundException {
368: return peer.platformRequest(URL);
369: }
370:
371: /**
372: * Get the status of the specified permission.
373: * If no API on the device defines the specific permission
374: * requested then it must be reported as denied.
375: * If the status of the permission is not known because it might
376: * require a user interaction then it should be reported as unknown.
377: *
378: * @param permission to check if denied, allowed, or unknown.
379: * @return 0 if the permission is denied; 1 if the permission is allowed;
380: * -1 if the status is unknown
381: *
382: */
383: public final int checkPermission(String permission) {
384: return peer.checkPermission(permission);
385: }
386: }
|