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 com.sun.midp.appmanager;
028:
029: import javax.microedition.midlet.*;
030:
031: import javax.microedition.lcdui.*;
032:
033: import com.sun.midp.i18n.Resource;
034: import com.sun.midp.i18n.ResourceConstants;
035:
036: import com.sun.cldc.isolate.*;
037:
038: import com.sun.midp.midlet.*;
039:
040: import com.sun.midp.installer.*;
041:
042: import com.sun.midp.midletsuite.*;
043:
044: import com.sun.midp.main.*;
045:
046: import com.sun.midp.io.j2me.push.*;
047:
048: import com.sun.midp.configurator.Constants;
049:
050: /**
051: * This is an implementation of the ApplicationManager interface
052: * for the MVM mode of the VM running with only one midlet at time.
053: *
054: * Application manager controls midlet life cycle:
055: * - installs, updates and removes midlets/midlet suites
056: * - launches and terminates midlets
057: * - displays info about a midlet/midlet suite
058: * - shuts down the AMS system
059: */
060: public class SMMManager extends MIDlet implements
061: MIDletProxyListListener, Runnable, ApplicationManager {
062:
063: /** Constant for the discovery application class name. */
064: private static final String DISCOVERY_APP = "com.sun.midp.installer.DiscoveryApp";
065:
066: /** Constant for the graphical installer class name. */
067: private static final String INSTALLER = "com.sun.midp.installer.GraphicalInstaller";
068:
069: /** Constant for the CA manager class name. */
070: private static final String CA_MANAGER = "com.sun.midp.appmanager.CaManager";
071:
072: /** True until constructed for the first time. */
073: private static boolean first = true;
074:
075: /** MIDlet Suite storage object. */
076: private MIDletSuiteStorage midletSuiteStorage;
077:
078: /** Screen that displays all installed midlets and installer */
079: private AppManagerUI appManagerUI;
080:
081: /** MIDlet proxy list reference. */
082: private MIDletProxyList midletProxyList;
083:
084: /** If true, MIDlet can be launched. */
085: private boolean allowMidletLaunch = true;
086:
087: /** ID of the suite to run. */
088: int suiteId;
089:
090: /** Class name of the MIDlet to run. */
091: String className;
092:
093: /** Display name of the MIDlet to run. */
094: String displayName;
095:
096: /**
097: * If not null, this string will be available to the
098: * MIDlet as application property arg-0
099: */
100: String arg0;
101:
102: /**
103: * If not null, this string will be available to the
104: * MIDlet as application property arg-1
105: */
106: String arg1;
107:
108: /**
109: * If not null, this string will be available to the
110: * MIDlet as application property arg-2
111: */
112: String arg2;
113:
114: /** UI to display error alerts. */
115: DisplayError displayError;
116:
117: /**
118: * Create and initialize a new Manager MIDlet.
119: */
120: public SMMManager() {
121: midletSuiteStorage = MIDletSuiteStorage.getMIDletSuiteStorage();
122:
123: /*
124: * Listen to the MIDlet proxy list.
125: * this allows us to notify the Application Selector
126: * of any changes whenever switch back to the AMS.
127: */
128: midletProxyList = MIDletProxyList.getMIDletProxyList();
129: midletProxyList.addListener(this );
130: midletProxyList.setDisplayController(new SMMDisplayController(
131: midletProxyList, MIDletSuite.INTERNAL_SUITE_ID, this
132: .getClass().getName()));
133:
134: PushRegistryInternal.setMvmSingleMidletMode();
135:
136: GraphicalInstaller.initSettings();
137:
138: first = (getAppProperty("logo-displayed") == null);
139:
140: Display display = Display.getDisplay(this );
141: displayError = new DisplayError(display);
142:
143: // AppSelector will be set to be current at the end of its constructor
144: appManagerUI = new AppManagerUI(this , display, displayError,
145: first, null);
146:
147: if (first) {
148: first = false;
149: }
150: }
151:
152: /**
153: * Start app; there is nothing that needs to be done at start up.
154: */
155: public void startApp() {
156: }
157:
158: /**
159: * Pause; there are no resources that need to be released.
160: */
161: public void pauseApp() {
162: }
163:
164: /**
165: * Destroy cleans up.
166: *
167: * @param unconditional is ignored; this object always
168: * destroys itself when requested.
169: */
170: public void destroyApp(boolean unconditional) {
171: // IMPL_NOTE: remove this:
172: GraphicalInstaller.saveSettings(null,
173: MIDletSuite.UNUSED_SUITE_ID);
174:
175: // Ending this MIDlet ends all others.
176: midletProxyList.shutdown();
177: }
178:
179: // ==============================================================
180: // ------ Implementation of the MIDletProxyListListener interface
181:
182: /**
183: * Called when a MIDlet is added to the list.
184: *
185: * @param midlet The proxy of the MIDlet being added
186: */
187: public void midletAdded(MIDletProxy midlet) {
188: appManagerUI.notifyMidletStarted(midlet);
189: }
190:
191: /**
192: * Called when the state of a MIDlet in the list is updated.
193: *
194: * @param midlet The proxy of the MIDlet that was updated
195: * @param fieldId code for which field of the proxy was updated
196: */
197: public void midletUpdated(MIDletProxy midlet, int fieldId) {
198: appManagerUI.notifyMidletStateChanged(midlet);
199: }
200:
201: /**
202: * Called when a MIDlet is removed from the list.
203: *
204: * @param midlet The proxy of the removed MIDlet
205: */
206: public void midletRemoved(MIDletProxy midlet) {
207: appManagerUI.notifyMidletExited(midlet);
208: }
209:
210: /**
211: * Called when error occurred while starting a MIDlet object.
212: *
213: * @param externalAppId ID assigned by the external application manager
214: * @param suiteId Suite ID of the MIDlet
215: * @param className Class name of the MIDlet
216: * @param errorCode start error code
217: * @param errorDetails start error code
218: */
219: public void midletStartError(int externalAppId, int suiteId,
220: String className, int errorCode, String errorDetails) {
221: allowMidletLaunch = true;
222: appManagerUI.notifyMidletStartError(suiteId, className,
223: errorCode, errorDetails);
224: }
225:
226: /** Launches an application Isolate and waits for it to end. */
227: public void run() {
228: try {
229: Isolate appIsolate = AmsUtil.startMidletInNewIsolate(
230: suiteId, className, displayName, arg0, arg1, arg2);
231:
232: appIsolate.waitForExit();
233: } finally {
234: suiteId = MIDletSuite.UNUSED_SUITE_ID;
235: className = null;
236: displayName = null;
237: arg0 = null;
238: arg1 = null;
239: arg2 = null;
240: allowMidletLaunch = true;
241: }
242: }
243:
244: // ===================================================================
245: // ---- Implementation of the ApplicationManager interface ------------
246:
247: /**
248: * Discover and install a suite.
249: */
250: public void installSuite() {
251: try {
252: runMidlet(
253: MIDletSuite.INTERNAL_SUITE_ID,
254: DISCOVERY_APP,
255: Resource
256: .getString(ResourceConstants.INSTALL_APPLICATION));
257:
258: } catch (Exception ex) {
259: displayError.showErrorAlert(Resource
260: .getString(ResourceConstants.INSTALL_APPLICATION),
261: ex, null, null);
262: }
263: }
264:
265: /** Launch the CA manager. */
266: public void launchCaManager() {
267: try {
268: MIDletSuiteUtils
269: .execute(
270: MIDletSuite.INTERNAL_SUITE_ID,
271: CA_MANAGER,
272: Resource
273: .getString(ResourceConstants.CA_MANAGER_APP));
274: } catch (Exception ex) {
275: displayError.showErrorAlert(Resource
276: .getString(ResourceConstants.CA_MANAGER_APP), ex,
277: null, null);
278: }
279: }
280:
281: /**
282: * Launches a suite.
283: *
284: * @param suiteInfo information for suite to launch
285: * @param midletToRun class name of the MIDlet to launch
286: */
287: public void launchSuite(RunningMIDletSuiteInfo suiteInfo,
288: String midletToRun) {
289:
290: if (Constants.MEASURE_STARTUP) {
291: System.err.println("Application Startup Time: Begin at "
292: + System.currentTimeMillis());
293: }
294:
295: try {
296: // Create an instance of the MIDlet class
297: // All other initialization happens in MIDlet constructor
298: runMidlet(suiteInfo.suiteId, midletToRun,
299: suiteInfo.displayName);
300:
301: } catch (Exception ex) {
302: displayError.showErrorAlert(suiteInfo.displayName, ex,
303: null, null);
304: }
305: }
306:
307: /**
308: * Update a suite.
309: *
310: * @param suiteInfo information for suite to update
311: */
312: public void updateSuite(RunningMIDletSuiteInfo suiteInfo) {
313: try {
314: runMidlet(MIDletSuite.INTERNAL_SUITE_ID, INSTALLER, null,
315: "U", String.valueOf(suiteInfo.suiteId), null);
316:
317: } catch (Exception ex) {
318: displayError.showErrorAlert(suiteInfo.displayName, ex,
319: null, null);
320: }
321: }
322:
323: /**
324: * Shut downt the system
325: */
326: public void shutDown() {
327: midletProxyList.shutdown();
328: }
329:
330: /**
331: * Bring the midlet with the passed in midlet suite info to the
332: * foreground.
333: *
334: * @param suiteInfo information for the midlet to be put to foreground
335: */
336: public void moveToForeground(RunningMIDletSuiteInfo suiteInfo) {
337: }
338:
339: /**
340: * Exit the midlet with the passed in midlet suite info.
341: *
342: * @param suiteInfo information for the midlet to be terminated
343: */
344: public void exitMidlet(RunningMIDletSuiteInfo suiteInfo) {
345: }
346:
347: // ==============================================================
348: // ----------------- PRIVATE methods ---------------------------
349:
350: /**
351: * Starts a MIDlet in a new Isolate.
352: *
353: * @param id ID of an installed suite
354: * @param midlet class name of MIDlet to invoke
355: * @param displayName name to display to the user
356: */
357: private void runMidlet(int id, String midlet, String displayName) {
358: runMidlet(id, midlet, displayName, null, null, null);
359: }
360:
361: /**
362: * Starts a MIDlet in a new Isolate with the given arguments.
363: *
364: * @param id ID of an installed suite
365: * @param midlet class name of MIDlet to invoke
366: * @param displayName name to display to the user
367: * @param arg0 if not null, this parameter will be available to the
368: * MIDlet as application property arg-0
369: * @param arg1 if not null, this parameter will be available to the
370: * MIDlet as application property arg-1
371: * @param arg2 if not null, this parameter will be available to the
372: * MIDlet as application property arg-2
373: */
374: private void runMidlet(int id, String midlet, String displayName,
375: String arg0, String arg1, String arg2) {
376: if (!allowMidletLaunch) {
377: return;
378: }
379:
380: this .suiteId = id;
381: this .className = midlet;
382: this .displayName = displayName;
383: this .arg0 = arg0;
384: this .arg1 = arg1;
385: this .arg2 = arg2;
386:
387: new Thread(this ).start();
388:
389: allowMidletLaunch = false;
390: }
391: }
|