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