/*
* 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.midp.midlet.*;
import com.sun.midp.security.*;
import com.sun.midp.events.EventQueue;
import com.sun.midp.lcdui.*;
import com.sun.midp.configurator.Constants;
import com.sun.midp.log.*;
/**
* The class presents abstract MIDlet suite loader with routines to prepare
* runtime environment for a suite execution. The class provides generic
* scenario to load, start and terminate a MIDlet suite in the common way
* for both SVM and MVM modes. All the differences of SVM & MVM modes are
* designed as virtual or abstract methods.
*/
abstract class AbstractMIDletSuiteLoader
implements MIDletSuiteExceptionListener {
/** The ID of the MIDlte suite task Isolate */
protected int isolateId;
/** The ID of the AMS task Isolate */
protected int amsIsolateId;
/** Suite ID of the MIDlet suite */
protected int suiteId;
/** External application ID that can be provided by native AMS */
protected int externalAppId;
/** Name of the class to start MIDlet suite execution */
protected String midletClassName;
/** Display name of a MIDlet suite */
protected String midletDisplayName;
/** The arguments to start MIDlet suite with */
protected String args[];
/**
* Inner class to request security token from SecurityInitializer.
* SecurityInitializer should be able to check this inner class name.
*/
static private class SecurityTrusted implements ImplicitlyTrustedClass {}
/** This class has a different security domain than the MIDlet suite */
protected static SecurityToken internalSecurityToken =
SecurityInitializer.requestToken(new SecurityTrusted());
/** Event queue instance created for this MIDlet suite execution */
protected EventQueue eventQueue;
/**
* MIDlet suite instance created and properly initialized for
* a MIDlet suite invocation.
*/
protected MIDletSuite midletSuite;
// The MIDlet suite environment contains a set of event-related
// objects needed for each MIDlet suite execution.
/** Foreground Controller adapter. */
protected ForegroundController foregroundController;
/** Event producer for various screen change events. */
protected DisplayEventProducer displayEventProducer;
/**
* Provides interface for display preemption, creation and other
* functionality that can not be publicly added to a javax package.
*/
protected DisplayEventListener displayEventListener;
/** Event producer for all repaint events. */
protected RepaintEventProducer repaintEventProducer;
/** Stores array of active displays for a MIDlet suite isolate. */
protected DisplayContainer displayContainer;
/**
* Provides interface for display preemption, creation and other
* functionality that can not be publicly added to a javax package.
*/
protected DisplayEventHandler displayEventHandler;
/**
* Handles item events not associated directly with
* particular <code>Display</code>.
*/
protected ItemEventConsumer itemEventConsumer;
/** Starts and controls MIDlets through the lifecycle states. */
protected MIDletStateHandler midletStateHandler;
/** The event listener for LCDUI events. */
protected LCDUIEventListener lcduiEventListener;
/**
* Reports an error detected during MIDlet suite invocation.
* @param errorCode the error code to report
*/
protected abstract void reportError(int errorCode, String details);
/**
* Reports an error detected during MIDlet suite invocation.
* @param errorCode the error code to report
*/
protected void reportError(int errorCode) {
reportError(errorCode, null);
}
/**
* Allocates resources for a suite execution according to
* global resource policy.
*
* @return true in the case resources were successfully allocated,
* false otherwise
*/
protected boolean allocateReservedResources() {
return true;
}
/**
* Sets MIDlet suite arguments as temporary suite properties.
* Subclasses can override the method to export any other needed
* suite properties.
*/
protected void setSuiteProperties() {
if (args != null) {
for (int i = 0; i < args.length; i++) {
if (args[i] != null) {
midletSuite.setTempProperty(
internalSecurityToken,
"arg-" + i, args[i]);
}
}
}
}
/** Core initialization of a MIDlet suite loader */
protected void init() {
// Init security tokens for core subsystems
SecurityInitializer.initSystem();
eventQueue = EventQueue.getEventQueue(
internalSecurityToken);
}
/** Final actions to finish a MIDlet suite loader */
protected void done() {
eventQueue.shutdown();
}
/**
* Creates all needed objects of a MIDlet suite environment, but
* only initialization that is done, will be to pass other created objects,
* and the current and AMS isolate IDs. It is mostly event-related
* objects, however subclasses can extend the environment with more
* specific parts
*/
protected void createSuiteEnvironment() {
displayEventHandler =
DisplayEventHandlerFactory.getDisplayEventHandler(
internalSecurityToken);
displayEventProducer =
new DisplayEventProducer(
eventQueue);
repaintEventProducer =
new RepaintEventProducer(
eventQueue);
displayContainer = new DisplayContainer(
internalSecurityToken, isolateId);
/*
* Because the display handler is implemented in a javax
* package it cannot created outside of the package, so
* we have to get it after the static initializer of display the class
* has been run and then hook up its objects.
*/
displayEventHandler.initDisplayEventHandler(
displayEventProducer,
foregroundController,
repaintEventProducer,
displayContainer);
displayEventListener = new DisplayEventListener(
eventQueue,
displayContainer);
/* Bad style of type casting, but DisplayEventHandlerImpl
* implements both DisplayEventHandler & ItemEventConsumer IFs */
itemEventConsumer =
(ItemEventConsumer)displayEventHandler;
lcduiEventListener = new LCDUIEventListener(
internalSecurityToken,
eventQueue,
itemEventConsumer);
}
/**
* Does all initialization for already created objects of a MIDlet suite
* environment. Subclasses can also extend the initialization with
* various global system initializations needed for all suites.
* The MIDlet suite has been created at this point, so it can be
* used to initialize any per suite data.
*/
protected void initSuiteEnvironment() {
displayEventHandler.initSuiteData(
midletSuite.isTrusted());
}
/**
* Handles exception occurred during MIDlet suite execution.
* @param t exception instance
*/
public abstract void handleException(Throwable t);
/** Restricts suite access to internal API */
protected void restrictAPIAccess() {
// IMPL_NOTE: No restrictions by default
}
/**
* Start MIDlet suite in the prepared environment
* @throws Exception can be thrown during execution
*/
protected void startSuite() throws Exception {
midletStateHandler.startSuite(
this, midletSuite, externalAppId, midletClassName);
}
/** Closes suite and unlock native suite locks */
protected void closeSuite() {
if (midletSuite != null) {
/* When possible, don't wait for the finalizer
* to unlock the suite. */
midletSuite.close();
}
}
/**
* Checks whether an executed MIDlet suite has requested
* for a system shutdown. User MIDlets most probably have
* no right for it, however Java AMS MIDlet could do it.
*/
protected void checkForShutdown() {
// IMPL_NOTE: No checks for shutdown by default
}
/**
* Explicitly requests suite loader exit after MIDlet
* suite execution is finished and created environment is done.
*/
protected abstract void exitLoader();
/**
* Creates MIDlet suite instance by suite ID, the
*
* @return MIDlet suite to load
*
* @throws Exception in the case MIDlet suite can not be
* created because of a security reasons or some problems
* related to suite storage
*/
protected abstract MIDletSuite createMIDletSuite() throws Exception;
/**
* Inits MIDlet suite runtime environment and start a MIDlet
* suite with it
*/
protected void runMIDletSuite() {
// WARNING: Don't add any calls before this!
//
// The core init of a MIDlet suite task should be able
// to perform the very first initializations of the environment
init();
try {
/*
* Prepare MIDlet suite environment, classes that only need
* the isolate ID can be create here.
*/
createSuiteEnvironment();
/* Check to see that all of the core object are created. */
if (foregroundController == null ||
displayEventProducer == null ||
repaintEventProducer == null ||
displayContainer == null ||
displayEventHandler == null ||
itemEventConsumer == null ||
lcduiEventListener == null ||
midletStateHandler == null) {
throw new
RuntimeException("Suite environment not complete.");
}
// Regard resource policy for the suite task
if (!allocateReservedResources()) {
reportError(Constants.MIDLET_RESOURCE_LIMIT);
return;
}
// Create suite instance ready for start
midletSuite = createMIDletSuite();
if (midletSuite == null) {
reportError(Constants.MIDLET_SUITE_NOT_FOUND);
return;
}
if (!midletSuite.isEnabled()) {
reportError(Constants.MIDLET_SUITE_DISABLED);
return;
}
/*
* Now that we have the suite and reserved its resources
* we can initialize any classes that need MIDlet Suite
* information.
*/
initSuiteEnvironment();
// Export suite arguments as properties, so well
// set any other properties to control a suite
setSuiteProperties();
// Restrict suite access to internal API
restrictAPIAccess();
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_CORE,
"MIDlet suite task starting a suite");
}
// Blocking call to start MIDlet suite
// in the prepared environment
startSuite();
// Check for shutdown possibly requested from the suite
checkForShutdown();
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.INFORMATION, LogChannels.LC_CORE,
"MIDlet suite loader exiting");
}
} catch (Throwable t) {
handleException(t);
} finally {
closeSuite();
done();
exitLoader();
}
}
}
|