/*
*
*
* Copyright 1990-2007 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 com.sun.midp.main;
import com.sun.cldc.isolate.*;
import com.sun.midp.midlet.MIDletSuite;
import com.sun.midp.midletsuite.MIDletSuiteStorage;
import com.sun.midp.configurator.Constants;
import com.sun.midp.log.Logging;
/**
* Implements utilities that are different for SVM and MVM modes.
* Utilities to start a MIDlet in a suite. If not the called from the
* AMS Isolate the request is forwarded to the AMS Isolate.
* See {@link #executeWithArgs}.
* <p>
* In the AMS Isolate, a check is make that the MIDlet is
* not already running and is not in the process of starting.
* If the MIDlet is already running or is starting the request
* returns immediately. See {@link #startMidletCommon}
* <p>
*/
public class AmsUtil {
/** Cached reference to the MIDletExecuteEventProducer. */
private static MIDletExecuteEventProducer midletExecuteEventProducer;
/** Cached reference to the MIDletControllerEventProducer. */
private static MIDletControllerEventProducer midletControllerEventProducer;
/** Cached reference to the MIDletProxyList. */
private static MIDletProxyList midletProxyList;
/**
* Initializes AmsUtil class. shall only be called from
* MIDletSuiteLoader's main() in MVM AMS isolate
* or in SVM main isolate.
* No need in security checks since it is package private method.
*
* @param theMIDletProxyList MIDletController's container
* @param theMidletControllerEventProducer utility to send events
*/
static void initClass(MIDletProxyList theMIDletProxyList,
MIDletControllerEventProducer theMidletControllerEventProducer) {
midletProxyList = theMIDletProxyList;
midletControllerEventProducer = theMidletControllerEventProducer;
IsolateMonitor.initClass(theMIDletProxyList);
StartMIDletMonitor.initClass(theMIDletProxyList);
}
/**
* Initializes AmsUtil class. shall only be called from
* AppIsolateMIDletSuiteLoader's main() in
* non-AMS isolates.
* No need in security checks since it is package private method.
*
* @param theMIDletExecuteEventProducer event producer
* to be used by this class to send events
*/
static void initClassInAppIsolate(
MIDletExecuteEventProducer theMIDletExecuteEventProducer) {
midletExecuteEventProducer = theMIDletExecuteEventProducer;
}
/**
* Starts a MIDlet in a new Isolate.
*
* @param midletSuiteStorage reference to a MIDletStorage object
* @param externalAppId ID of MIDlet to invoke, given by an external
* application manager
* @param id ID of an installed suite
* @param midlet class name of MIDlet to invoke
* @param displayName name to display to the user
* @param arg0 if not null, this parameter will be available to the
* MIDlet as application property arg-0
* @param arg1 if not null, this parameter will be available to the
* MIDlet as application property arg-1
* @param arg2 if not null, this parameter will be available to the
* MIDlet as application property arg-2
* @param memoryReserved the minimum amount of memory guaranteed to be
* available to the isolate at any time; < 0 if not used
* @param memoryTotal the total amount of memory that the isolate can
reserve; < 0 if not used
* @param priority priority to set for the new isolate;
* <= 0 if not used
* @param profileName name of the profile to set for the new isolate;
* null if not used
*
* @return false to signal that the MIDlet suite does not have to exit
* before the MIDlet is run
*/
static boolean executeWithArgs(MIDletSuiteStorage midletSuiteStorage,
int externalAppId, int id, String midlet,
String displayName, String arg0, String arg1, String arg2,
int memoryReserved, int memoryTotal, int priority,
String profileName) {
if (id == MIDletSuite.UNUSED_SUITE_ID) {
// this was just a cancel request meant for SVM mode
return false;
}
if (midlet == null) {
throw new IllegalArgumentException("MIDlet class cannot be null");
}
if (!MIDletSuiteUtils.isAmsIsolate()) {
/*
* This is not the AMS isolate so send the request to the
* AMS isolate.
*/
midletExecuteEventProducer.sendMIDletExecuteEvent(
externalAppId, id,
midlet, displayName,
arg0, arg1, arg2,
memoryReserved, memoryTotal, priority,
profileName
);
return false;
}
// Don't start the MIDlet if it is already running.
if (midletProxyList.isMidletInList(id, midlet)) {
return false;
}
try {
startMidletCommon(midletSuiteStorage, externalAppId, id, midlet,
displayName, arg0, arg1, arg2,
memoryReserved, memoryTotal, priority,
profileName);
} catch (Throwable t) {
/*
* This method does not throw exceptions for start errors,
* (just like the SVM case), for errors, MVM callers rely on
* start error events.
*/
}
return false;
}
/**
* Starts a MIDlet in a new Isolate. Called from the AMS MIDlet suite.
*
* @param id ID of an installed suite
* @param midlet class name of MIDlet to invoke
* @param displayName name to display to the user
* @param arg0 if not null, this parameter will be available to the
* MIDlet as application property arg-0
* @param arg1 if not null, this parameter will be available to the
* MIDlet as application property arg-1
* @param arg2 if not null, this parameter will be available to the
* MIDlet as application property arg-2
*
* @return Isolate that the MIDlet suite was started in
*/
public static Isolate startMidletInNewIsolate(int id, String midlet,
String displayName, String arg0, String arg1, String arg2) {
// Note: getMIDletSuiteStorage performs an AMS permission check
return startMidletCommon(MIDletSuiteStorage.getMIDletSuiteStorage(),
0, id, midlet, displayName, arg0, arg1, arg2,
-1, -1, Isolate.MIN_PRIORITY - 1, null);
}
/**
* Starts a MIDlet in a new Isolate.
* Check that the MIDlet is is not realy running and is not already
* being started. If so, return immediately.
*
* @param midletSuiteStorage midletSuiteStorage for obtaining a
* classpath
* @param externalAppId ID of MIDlet to invoke, given by an external
* application manager
* @param id ID of an installed suite
* @param midlet class name of MIDlet to invoke
* @param displayName name to display to the user
* @param arg0 if not null, this parameter will be available to the
* MIDlet as application property arg-0
* @param arg1 if not null, this parameter will be available to the
* MIDlet as application property arg-1
* @param arg2 if not null, this parameter will be available to the
* MIDlet as application property arg-2
* @param memoryReserved the minimum amount of memory guaranteed to be
* available to the isolate at any time; < 0 if not used
* @param memoryTotal the total amount of memory that the isolate can
reserve; < 0 if not used
* @param priority priority to set for the new isolate;
* <= 0 if not used
* @param profileName name of the profile to set for the new isolate;
* null if not used
*
* @return Isolate that the MIDlet suite was started in;
* <code>null</code> if the MIDlet is already running
*/
private static Isolate startMidletCommon(MIDletSuiteStorage
midletSuiteStorage, int externalAppId, int id, String midlet,
String displayName, String arg0, String arg1, String arg2,
int memoryReserved, int memoryTotal,
int priority, String profileName) {
Isolate isolate;
String[] args = {Integer.toString(id), midlet, displayName, arg0,
arg1, arg2, Integer.toString(externalAppId)};
String[] classpath = midletSuiteStorage.getMidletSuiteClassPath(id);
if (classpath[0] == null) {
/*
* Avoid a null pointer exception, rommized midlets don't need
* a classpath.
*/
classpath[0] = "";
}
String isolateClassPath = System.getProperty("classpathext");
String[] classpathext = null;
if (isolateClassPath != null) {
classpathext = new String[] {isolateClassPath};
}
try {
StartMIDletMonitor app = StartMIDletMonitor.okToStart(id, midlet);
if (app == null) {
// Isolate is already running; don't start it again
return null;
}
isolate =
new Isolate("com.sun.midp.main.AppIsolateMIDletSuiteLoader",
args, classpath, classpathext);
app.setIsolate(isolate);
} catch (Throwable t) {
t.printStackTrace();
throw new RuntimeException("Can't create Isolate****");
}
try {
int reserved, limit;
if (memoryReserved >= 0) {
reserved = memoryReserved;
} else {
reserved = Constants.SUITE_MEMORY_RESERVED * 1024;
}
if (memoryTotal > 0) {
limit = memoryTotal;
} else {
limit = Constants.SUITE_MEMORY_LIMIT;
if (limit < 0) {
limit = isolate.totalMemory();
} else {
limit = limit * 1024;
}
}
isolate.setMemoryQuota(reserved, limit);
if (priority >= Isolate.MIN_PRIORITY) {
isolate.setPriority(priority);
}
if (profileName != null) {
IsolateUtil.setProfile(isolate, profileName);
}
isolate.setAPIAccess(true);
isolate.start();
} catch (Throwable t) {
int errorCode;
String msg;
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
t.printStackTrace();
}
if (t instanceof IsolateStartupException) {
/*
* An error occured in the
* initialization or configuration of the new isolate
* before any application code is invoked, or if this
* Isolate was already started or is terminated.
*/
errorCode = Constants.MIDLET_ISOLATE_CONSTRUCTOR_FAILED;
msg = "Can't start Application.";
} else if (t instanceof IsolateResourceError) {
/* The system has exceeded the maximum Isolate count. */
errorCode = Constants.MIDLET_ISOLATE_RESOURCE_LIMIT;
msg = "No more concurrent applications allowed.";
} else if (t instanceof IllegalArgumentException) {
/* Requested profile doesn't exist. */
errorCode = Constants.MIDLET_ISOLATE_CONSTRUCTOR_FAILED;
msg = "Invalid profile name: " + profileName;
} else if (t instanceof OutOfMemoryError) {
/* The reserved memory cannot be allocated */
errorCode = Constants.MIDLET_OUT_OF_MEM_ERROR;
msg = "Not enough memory to run the application.";
} else {
errorCode = Constants.MIDLET_ISOLATE_CONSTRUCTOR_FAILED;
msg = t.toString();
}
midletControllerEventProducer.sendMIDletStartErrorEvent(
id,
midlet,
externalAppId,
errorCode,
msg);
throw new RuntimeException(msg);
}
return isolate;
}
/**
* Terminates an isolate.
*
* @param id Isolate Id
*/
static void terminateIsolate(int id) {
Isolate isolate = MIDletProxyUtils.getIsolateFromId(id);
if (isolate != null) {
isolate.exit(0);
}
}
}
|