/*
*
*
* 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.installer;
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
import com.sun.midp.io.j2me.storage.*;
import com.sun.midp.i18n.Resource;
import com.sun.midp.i18n.ResourceConstants;
import com.sun.midp.configurator.Constants;
import com.sun.midp.main.TrustedMIDletIcon;
import com.sun.midp.midlet.*;
import com.sun.midp.midletsuite.*;
import com.sun.midp.security.*;
import com.sun.midp.content.CHManager;
import com.sun.midp.log.Logging;
import com.sun.midp.log.LogChannels;
import com.sun.midp.io.j2me.storage.File;
/**
* The Graphical MIDlet suite installer.
* <p>
* The graphical installer is implements the installer requirements of the
* MIDP OTA specification.</p>
* <p>
* If the Content Handler API (CHAPI) is present the GraphicalInstaller will
* dequeue a single Invocation and install from the URL contained
* in the request. If there is no Invocation present then the arguments below
* will be used.
* <p>
* The MIDlet uses certain application properties as arguments: </p>
* <ol>
* <li>arg-0: "U" for update "I" or anything else for install</li>
* <li>arg-1: Suite ID for updating, URL for installing
* <li>arg-2: For installing a name to put in the title bar when installing
* </ol>
* @see CHManagerImpl
* @see CHManager
*/
public class GraphicalInstaller extends MIDlet implements CommandListener {
/** Standard timeout for alerts. */
public static final int ALERT_TIMEOUT = 1250;
/** settings database */
public static final String SETTINGS_STORE = "settings";
/** record id of selected midlet */
public static final int URL_RECORD_ID = 1;
/** record is of the last installed midlet */
public static final int SELECTED_MIDLET_RECORD_ID = 2;
/** The installer that is being used to install or update a suite. */
private Installer installer;
/** Display for this MIDlet. */
private Display display;
/** Form obtain a password and a username. */
private Form passwordForm;
/** Contains the username for installing. */
private TextField usernameField;
/** Contains the password for installing. */
private TextField passwordField;
/** Background installer that holds state for the current install. */
private BackgroundInstaller backgroundInstaller;
/** Displays the progress of the install. */
private Form progressForm;
/** Gauge for progress form index. */
private int progressGaugeIndex;
/** URL for progress form index. */
private int progressUrlIndex;
/** Keeps track of when the display last changed, in milliseconds. */
private long lastDisplayChange;
/** What to display to the user when the current action is cancelled. */
private String cancelledMessage;
/** What to display to the user when the current action is finishing. */
private String finishingMessage;
/** ID of the storage where the new midlet suite will be installed. */
private int storageId = Constants.INTERNAL_STORAGE_ID;
/** Content handler specific install functions. */
CHManager chmanager;
/** Command object for "Stop" command for progress form. */
private Command stopCmd = new Command(Resource.getString
(ResourceConstants.STOP),
Command.STOP, 1);
/** Command object for "Cancel" command for the confirm form. */
private Command cancelCmd =
new Command(Resource.getString(ResourceConstants.CANCEL),
Command.CANCEL, 1);
/** Command object for "Install" command for the confirm download form. */
private Command continueCmd =
new Command(Resource.getString(ResourceConstants.INSTALL),
Command.OK, 1);
/** Command object for "Next" command for password form. */
private Command nextCmd =
new Command(Resource.getString(ResourceConstants.NEXT),
Command.OK, 1);
/** Command object for "continue" command for warning form. */
private Command okCmd =
new Command(Resource.getString(ResourceConstants.CONTINUE),
Command.OK, 1);
/** Command object for "OK" command for exception form. */
private Command exceptionCmd =
new Command(Resource.getString(ResourceConstants.OK),
Command.OK, 1);
/** Command object for "Yes" command for keep RMS form. */
private Command keepRMSCmd =
new Command(Resource.getString(ResourceConstants.YES),
Command.OK, 1);
/** Command object for "No" command for keep RMS form. */
private Command removeRMSCmd =
new Command(Resource.getString(ResourceConstants.NO),
Command.CANCEL, 1);
/**
* Read image data from storage file to byte array.
*
* @param imageFileName name of the file with icon data
* @return byte array with icon data, or null if file not found
*/
private static byte[] getImageFileBytes(String imageFileName) {
byte[] imageBytes;
RandomAccessStream stream;
stream = new RandomAccessStream();
try {
stream.connect(imageFileName, Connector.READ);
imageBytes = new byte[stream.getSizeOf()];
stream.readBytes(imageBytes, 0, imageBytes.length);
stream.disconnect();
return imageBytes;
} catch (java.io.IOException noIcon) {}
return null;
}
/**
* Gets an image from the internal storage.
*
* IMPL_NOTE: this method should be moved somewhere.
*
* @param imageName image file name without a path and extension
* @return Image loaded from storage, or null if not found
*/
public static Image getImageFromInternalStorage(String imageName) {
String imageFileName;
byte[] imageBytes;
MIDletStateHandler midletStateHandler =
MIDletStateHandler.getMidletStateHandler();
MIDletSuite midletSuite = midletStateHandler.getMIDletSuite();
midletSuite.checkIfPermissionAllowed(Permissions.AMS);
imageFileName = File.getStorageRoot(Constants.INTERNAL_STORAGE_ID) +
imageName;
imageBytes = getImageFileBytes(imageFileName + ".raw");
if (imageBytes == null) {
imageBytes = getImageFileBytes(imageFileName + ".png");
}
if (imageBytes != null) {
return Image.createImage(imageBytes, 0, imageBytes.length);
}
return null;
}
/**
* Translate an InvalidJadException into a message for the user.
*
* @param exception exception to translate
* @param name name of the MIDlet suite to insert into the message
* @param vendor vendor of the MIDlet suite to insert into the message,
* can be null
* @param version version of the MIDlet suite to insert into the message,
* can be null
* @param jadUrl URL of a JAD, can be null
*
* @return message to display to the user
*/
private static String translateJadException(
InvalidJadException exception, String name, String vendor,
String version, String jadUrl) {
String[] values = {name, vendor, version, jadUrl,
exception.getExtraData()};
int key;
switch (exception.getReason()) {
case InvalidJadException.OLD_VERSION:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_OLD_VERSION;
break;
case InvalidJadException.ALREADY_INSTALLED:
key =
ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_ALREADY_INSTALLED;
break;
case InvalidJadException.NEW_VERSION:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_NEW_VERSION;
break;
case InvalidJadException.JAD_SERVER_NOT_FOUND:
case InvalidJadException.JAD_NOT_FOUND:
case InvalidJadException.INVALID_JAD_URL:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INVALID_JAD_URL;
break;
case InvalidJadException.INVALID_JAD_TYPE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INVALID_JAD_TYPE;
break;
case InvalidJadException.MISSING_PROVIDER_CERT:
case InvalidJadException.MISSING_SUITE_NAME:
case InvalidJadException.MISSING_VENDOR:
case InvalidJadException.MISSING_VERSION:
case InvalidJadException.MISSING_JAR_URL:
case InvalidJadException.MISSING_JAR_SIZE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_MISSING_JAD_INFO;
break;
case InvalidJadException.MISSING_CONFIGURATION:
case InvalidJadException.MISSING_PROFILE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_MISSING_JAR_INFO;
break;
case InvalidJadException.INVALID_KEY:
case InvalidJadException.INVALID_VALUE:
case InvalidJadException.INVALID_VERSION:
case InvalidJadException.PUSH_FORMAT_FAILURE:
case InvalidJadException.PUSH_CLASS_FAILURE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INVALID_FORMAT;
break;
case InvalidJadException.DEVICE_INCOMPATIBLE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_DEVICE_INCOMPATIBLE;
break;
case InvalidJadException.JAD_MOVED:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_JAD_MOVED;
break;
case InvalidJadException.INSUFFICIENT_STORAGE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INSUFFICIENT_STORAGE;
break;
case InvalidJadException.JAR_SERVER_NOT_FOUND:
case InvalidJadException.JAR_NOT_FOUND:
case InvalidJadException.INVALID_JAR_URL:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_JAR_NOT_FOUND;
break;
case InvalidJadException.INVALID_JAR_TYPE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INVALID_JAR_TYPE;
break;
case InvalidJadException.SUITE_NAME_MISMATCH:
case InvalidJadException.VERSION_MISMATCH:
case InvalidJadException.VENDOR_MISMATCH:
case InvalidJadException.JAR_SIZE_MISMATCH:
case InvalidJadException.ATTRIBUTE_MISMATCH:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_ATTRIBUTE_MISMATCH;
break;
case InvalidJadException.CORRUPT_JAR:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_CORRUPT_JAR;
break;
case InvalidJadException.CANNOT_AUTH:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_CANNOT_AUTH;
break;
case InvalidJadException.CORRUPT_PROVIDER_CERT:
case InvalidJadException.INVALID_PROVIDER_CERT:
case InvalidJadException.CORRUPT_SIGNATURE:
case InvalidJadException.INVALID_SIGNATURE:
case InvalidJadException.UNSUPPORTED_CERT:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INVALID_SIGNATURE;
break;
case InvalidJadException.UNKNOWN_CA:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_UNKNOWN_CA;
break;
case InvalidJadException.EXPIRED_PROVIDER_CERT:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_EXPIRED_PROVIDER_CERT;
break;
case InvalidJadException.EXPIRED_CA_KEY:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_EXPIRED_CA_KEY;
break;
case InvalidJadException.AUTHORIZATION_FAILURE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_AUTHORIZATION_FAILURE;
break;
case InvalidJadException.CA_DISABLED:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_CA_DISABLED;
break;
case InvalidJadException.PUSH_DUP_FAILURE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_PUSH_DUP_FAILURE;
break;
case InvalidJadException.PUSH_PROTO_FAILURE:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_PUSH_PROTO_FAILURE;
break;
case InvalidJadException.TRUSTED_OVERWRITE_FAILURE:
if (exception.getExtraData() != null) {
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_TRUSTED_OVERWRITE_FAILURE;
} else {
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_TRUSTED_OVERWRITE_FAILURE_2;
}
break;
case InvalidJadException.TOO_MANY_PROPS:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_APP_TOO_BIG;
break;
case InvalidJadException.INVALID_CONTENT_HANDLER:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_INVALID_CONTENT_HANDLER;
break;
case InvalidJadException.CONTENT_HANDLER_CONFLICT:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_CONTENT_HANDLER_CONFLICT;
break;
case InvalidJadException.JAR_CLASSES_VERIFICATION_FAILED:
// This constant is shared between graphical installer
// and standalone class verifier MIDlet used for SVM mode
key = ResourceConstants.AMS_CLASS_VERIFIER_FAILURE;
break;
case InvalidJadException.UNSUPPORTED_CHAR_ENCODING:
key = ResourceConstants.
AMS_GRA_INTLR_INVALIDJADEXCEPTION_UNSUPPORTED_CHAR_ENCODING;
break;
default:
return exception.getMessage();
}
return Resource.getString(key, values);
}
/**
* Create and initialize a new graphical installer MIDlet.
* <p>
* If a ContentHandler request to install a suite is found,
* then that URL will be installed. In this case the command
* arguments are ignored.
* <p>
* The Display is retrieved and the list of MIDlet will be retrieved or
* update a currently installed suite.
*/
public GraphicalInstaller() {
int suiteId;
String arg0;
String label;
String url;
installer = new HttpInstaller();
display = Display.getDisplay(this);
initSettings();
// Establish Content handler installer context
chmanager = CHManager.getManager(null);
// Get the URL, if any, provided from the invocation mechanism.
url = chmanager.getInstallURL(this);
if (url != null) {
label = Resource.getString(ResourceConstants.APPLICATION);
installSuite(label, url);
return;
}
arg0 = getAppProperty("arg-0");
if (arg0 == null) {
// goto back to the discovery midlet
exit(false);
return;
}
if ("U".equals(arg0)) {
String strSuiteID = getAppProperty("arg-1");
suiteId = MIDletSuite.UNUSED_SUITE_ID;
if (strSuiteID != null) {
try {
suiteId = Integer.parseInt(strSuiteID);
} catch (NumberFormatException nfe) {
// Intentionally ignored
}
}
if (suiteId == MIDletSuite.UNUSED_SUITE_ID) {
// goto back to the discovery midlet
exit(false);
return;
}
updateSuite(suiteId);
return;
}
url = getAppProperty("arg-1");
if (url == null) {
// goto back to the discovery midlet
exit(false);
return;
}
label = getAppProperty("arg-2");
if (label == null || label.length() == 0) {
label = Resource.getString(ResourceConstants.APPLICATION);
}
installSuite(label, url);
}
/**
* Start.
*/
public void startApp() {
}
/**
* Pause; there are no resources that need to be released.
*/
public void pauseApp() {
}
/**
* Destroy cleans up.
*
* @param unconditional is ignored; this object always
* destroys itself when requested.
*/
public void destroyApp(boolean unconditional) {
if (installer != null) {
installer.stopInstalling();
}
/* The backgroundInstaller could be waiting for the user. */
cancelBackgroundInstall();
}
/**
* Exit the GraphicalInstaller with the status supplied.
* It will perform any remaining cleanup and call notifyDestroyed.
* @param success <code>true</code> if the install was a success,
* <code>false</code> otherwise.
*/
void exit(boolean success) {
chmanager.installDone(success);
notifyDestroyed();
}
/**
* Respond to a command issued on any Screen.
*
* @param c command activated by the user
* @param s the Displayable the command was on.
*/
public void commandAction(Command c, Displayable s) {
if (c == nextCmd) {
// the user has entered a username and password
resumeInstallWithPassword();
} else if (c == okCmd) {
resumeInstallAfterWarning();
} else if (c == continueCmd) {
startJarDownload();
} else if (c == keepRMSCmd) {
setKeepRMSAnswer(true);
} else if (c == removeRMSCmd) {
setKeepRMSAnswer(false);
} else if (c == stopCmd) {
if (installer != null) {
/*
* BackgroundInstaller may be displaying
* the "Finishing" message
*
* also we need to prevent the BackgroundInstaller from
* re-displaying the list before the cancelled message is
* displayed
*/
synchronized (this) {
if (installer.stopInstalling()) {
displayCancelledMessage(cancelledMessage);
}
}
} else {
// goto back to the manager midlet
exit(false);
}
} else if (c == cancelCmd) {
displayCancelledMessage(cancelledMessage);
cancelBackgroundInstall();
} else if (c == Alert.DISMISS_COMMAND) {
// goto back to the manager midlet
exit(false);
}
}
/**
* Initialize the settings database if it doesn't exist. This may create
* two entries. The first will be for the download url, the second will
* be for storing the storagename of the currently selected midlet
*/
public static void initSettings() {
MIDletStateHandler midletStateHandler =
MIDletStateHandler.getMidletStateHandler();
MIDletSuite midletSuite = midletStateHandler.getMIDletSuite();
midletSuite.checkIfPermissionAllowed(Permissions.AMS);
try {
RecordStore settings = RecordStore.
openRecordStore(SETTINGS_STORE, true);
try {
if (settings.getNumRecords() == 0) {
// space for a URL
settings.addRecord(null, 0, 0);
// space for current MIDlet Suite name
settings.addRecord(null, 0, 0);
}
} finally {
settings.closeRecordStore();
}
} catch (Exception e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"initSettings throw an Exception");
}
}
}
/**
* Save the settings the user entered.
*
* @param url the url to save
* @param curMidlet suiteId of the currently selected midlet
* @return the Exception that may have been thrown, or null
*/
public static Exception saveSettings(String url, int curMidlet) {
Exception ret = null;
MIDletStateHandler midletStateHandler =
MIDletStateHandler.getMidletStateHandler();
MIDletSuite midletSuite = midletStateHandler.getMIDletSuite();
midletSuite.checkIfPermissionAllowed(Permissions.AMS);
try {
String temp;
ByteArrayOutputStream bas;
DataOutputStream dos;
byte[] data;
RecordStore settings;
bas = new ByteArrayOutputStream();
dos = new DataOutputStream(bas);
settings = RecordStore.openRecordStore(SETTINGS_STORE, false);
if (url != null) {
dos.writeUTF(url);
data = bas.toByteArray();
settings.setRecord(URL_RECORD_ID, data, 0, data.length);
}
// Save the current midlet even if its id is
// MIDletSuite.UNUSED_SUITE_ID. Otherwise in SVM mode
// the last installed midlet will be always highlighted
// because its it is recorded in this RMS record.
bas.reset();
dos.writeInt(curMidlet);
data = bas.toByteArray();
settings.setRecord(SELECTED_MIDLET_RECORD_ID,
data, 0, data.length);
settings.closeRecordStore();
dos.close();
} catch (Exception e) {
ret = e;
}
return ret;
}
/**
* Update a suite.
*
* @param id ID of the suite to update
*/
private void updateSuite(int id) {
MIDletSuiteImpl midletSuite = null;
try {
// Any runtime error will get caught by the installer
midletSuite =
MIDletSuiteStorage.getMIDletSuiteStorage()
.getMIDletSuite(id, false);
InstallInfo installInfo = midletSuite.getInstallInfo();
MIDletInfo midletInfo;
String name;
if (midletSuite.getNumberOfMIDlets() == 1) {
midletInfo =
new MIDletInfo(midletSuite.getProperty("MIDlet-1"));
name = midletInfo.name;
} else {
name = midletSuite.getProperty(MIDletSuite.SUITE_NAME_PROP);
}
cancelledMessage =
Resource.getString(ResourceConstants.AMS_GRA_INTLR_UPD_CAN);
finishingMessage =
Resource.getString(ResourceConstants.AMS_GRA_INTLR_FIN_UPD);
installSuiteCommon(Resource.getString
(ResourceConstants.AMS_GRA_INTLR_UPDATING),
name,
installInfo.getDownloadUrl(),
name + Resource.getString
(ResourceConstants.AMS_GRA_INTLR_SUCC_UPDATED),
true);
} catch (MIDletSuiteLockedException e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"updateSuite threw MIDletSuiteLockedException");
}
} catch (MIDletSuiteCorruptedException e) {
String msg = Resource.getString
(ResourceConstants.AMS_MIDLETSUITE_ID_CORRUPT_MSG)
+ id;
Alert a = new Alert(Resource.getString(ResourceConstants.ERROR),
msg, null, AlertType.ERROR);
a.setTimeout(Alert.FOREVER);
a.setCommandListener(this);
display.setCurrent(a, new Form(""));
// this Form is never displayed
} finally {
if (midletSuite != null) {
midletSuite.close();
}
}
}
/**
* Install a suite from URL.
*
* @param label label of the URL link
* @param url HTTP/S URL of the suite to update
*/
private void installSuite(String label, String url) {
cancelledMessage =
Resource.getString(ResourceConstants.AMS_GRA_INTLR_INST_CAN);
finishingMessage =
Resource.getString(ResourceConstants.AMS_GRA_INTLR_FIN_INST);
installSuiteCommon(Resource.getString
(ResourceConstants.AMS_GRA_INTLR_INSTALLING),
label, url,
label + Resource.getString
(ResourceConstants.AMS_GRA_INTLR_SUCC_INSTALLED),
false);
}
/**
* Common helper method to install or update a suite.
*
* @param action action to put in the form's title
* @param name name to in the form's title
* @param url URL of a JAD
* @param successMessage message to display to user upon success
* @param updateFlag if true the current suite is being updated
*/
private void installSuiteCommon(String action, String name, String url,
String successMessage, boolean updateFlag) {
try {
createProgressForm(action, name, url, 0,
Resource.getString(
ResourceConstants.AMS_GRA_INTLR_CONN_GAUGE_LABEL));
backgroundInstaller = new BackgroundInstaller(this, url, name,
successMessage, updateFlag);
new Thread(backgroundInstaller).start();
} catch (Exception ex) {
StringBuffer sb = new StringBuffer();
sb.append(name);
sb.append("\n");
sb.append(Resource.getString(ResourceConstants.ERROR));
sb.append(": ");
sb.append(ex.toString());
displayException(Resource.getString
(ResourceConstants.AMS_CANT_ACCESS),
sb.toString());
}
}
/**
* Create and display the progress form to the user with the stop action.
*
* @param action action to put in the form's title
* @param name name to in the form's title
* @param url URL of a JAD
* @param size 0 if unknown, else size of object to download in K bytes
* @param gaugeLabel label for progress gauge
*/
private void createProgressForm(String action, String name,
String url, int size, String gaugeLabel) {
Form installForm;
// display the JAR progress form
installForm = displayProgressForm(action, name, url, size,
gaugeLabel);
installForm.addCommand(stopCmd);
installForm.setCommandListener(this);
}
/**
* Display the connecting form to the user, let call set actions.
*
* @param action action to put in the form's title
* @param name name to in the form's title
* @param url URL of a JAD
* @param size 0 if unknown, else size of object to download in K bytes
* @param gaugeLabel label for progress gauge
*
* @return displayed form
*/
private Form displayProgressForm(String action, String name,
String url, int size, String gaugeLabel) {
Gauge progressGauge;
StringItem urlItem;
progressForm = new Form(null);
progressForm.setTitle(action + " " + name);
if (size <= 0) {
progressGauge = new Gauge(gaugeLabel,
false, Gauge.INDEFINITE,
Gauge.CONTINUOUS_RUNNING);
} else {
progressGauge = new Gauge(gaugeLabel,
false, size, 0);
}
progressGaugeIndex = progressForm.append(progressGauge);
if (url == null) {
urlItem = new StringItem("", "");
} else {
urlItem =
new StringItem(Resource.getString
(ResourceConstants.AMS_WEBSITE) + ": ", url);
}
progressUrlIndex = progressForm.append(urlItem);
display.setCurrent(progressForm);
lastDisplayChange = System.currentTimeMillis();
return progressForm;
}
/** Cancel an install (if there is one) waiting for user input. */
private void cancelBackgroundInstall() {
if (backgroundInstaller != null) {
backgroundInstaller.continueInstall = false;
synchronized (backgroundInstaller) {
backgroundInstaller.notify();
}
}
}
/**
* Update the status form.
*
* @param status current status of the install.
* @param state current state of the install.
*/
private void updateStatus(int status, InstallState state) {
if (status == Installer.DOWNLOADING_JAD) {
updateProgressForm("", 0,
Resource.getString
(ResourceConstants.
AMS_GRA_INTLR_DOWNLOADING_JAD_GAUGE_LABEL));
return;
}
if (status == Installer.DOWNLOADING_JAR) {
updateProgressForm(state.getJarUrl(), state.getJarSize(),
Resource.getString
(ResourceConstants.
AMS_GRA_INTLR_DOWNLOADING_JAR_GAUGE_LABEL));
return;
}
if (status == Installer.DOWNLOADED_1K_OF_JAR &&
state.getJarSize() > 0) {
Gauge progressGauge = (Gauge)progressForm.get(progressGaugeIndex);
progressGauge.setValue(progressGauge.getValue() + 1);
return;
}
if (Constants.MONET_ENABLED) {
if (status == Installer.GENERATING_APP_IMAGE) {
updateProgressForm(null, 0,
Resource.getString
(ResourceConstants.
AMS_GRA_INTLR_GENERATING_APP_IMAGE_GAUGE_LABEL));
return;
}
}
if (Constants.VERIFY_ONCE) {
if (status == Installer.VERIFYING_SUITE_CLASSES) {
if (state.getLastException() != null) {
displayWarning(
Resource.getString(
ResourceConstants.AMS_GRA_INTLR_INSTALL_WARNING),
Resource.getString(
ResourceConstants.AMS_CLASS_VERIFIER_FAILURE));
} else {
updateProgressForm(null, 0,
Resource.getString(
ResourceConstants.AMS_CLASS_VERIFIER_GAUGE_LABEL));
return;
}
}
}
if (status == Installer.VERIFYING_SUITE) {
updateProgressForm(null, 0,
Resource.getString
(ResourceConstants.
AMS_GRA_INTLR_VERIFYING_SUITE_GAUGE_LABEL));
return;
}
if (status == Installer.STORING_SUITE) {
updateProgressForm(null, 0, finishingMessage);
return;
}
if (status == Installer.CORRUPTED_SUITE) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"Suite is corrupted");
}
return;
}
}
/**
* Prevent screen flash on a fast systems.
*/
void preventScreenFlash() {
long waitTime = ALERT_TIMEOUT -
(System.currentTimeMillis() - lastDisplayChange);
if (waitTime <= 0) {
return;
}
try {
Thread.sleep(waitTime);
} catch (InterruptedException ie) {
// ignore
}
}
/**
* Update URL and gauge of the progress form.
*
* @param url new URL, null to remove, "" to not change
* @param size 0 if unknown, else size of object to download in K bytes
* @param gaugeLabel label for progress gauge
*/
private void updateProgressForm(String url, int size, String gaugeLabel) {
Gauge oldProgressGauge;
Gauge progressGauge;
StringItem urlItem;
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
if (size <= 0) {
progressGauge = new Gauge(gaugeLabel,
false, Gauge.INDEFINITE,
Gauge.CONTINUOUS_RUNNING);
} else {
progressGauge = new Gauge(gaugeLabel,
false, size, 0);
}
oldProgressGauge = (Gauge)progressForm.get(progressGaugeIndex);
progressForm.set(progressGaugeIndex, progressGauge);
// this ends the background thread of gauge.
oldProgressGauge.setValue(Gauge.CONTINUOUS_IDLE);
if (url == null) {
urlItem = new StringItem("", "");
progressForm.set(progressUrlIndex, urlItem);
} else if (url.length() != 0) {
urlItem =
new StringItem(Resource.getString
(ResourceConstants.AMS_WEBSITE) + ": ", url);
progressForm.set(progressUrlIndex, urlItem);
}
lastDisplayChange = System.currentTimeMillis();
}
/**
* Give the user a chance to act on warning during an installation.
*
* @param name name of the MIDlet suite to insert into the message
* @param vendor vendor of the MIDlet suite to insert into the message,
* can be null
* @param version version of the MIDlet suite to insert into the message,
* can be null
* @param jadUrl URL of a JAD, can be null
* @param e last exception from the installer
*/
private void warnUser(String name, String vendor, String version,
String jadUrl, InvalidJadException e) {
Form warningForm;
warningForm = new Form(null);
warningForm.setTitle(Resource.getString(ResourceConstants.WARNING));
warningForm.append(translateJadException(e, name, vendor, version,
jadUrl));
warningForm.addCommand(cancelCmd);
warningForm.addCommand(okCmd);
warningForm.setCommandListener(this);
display.setCurrent(warningForm);
}
/**
* Resume the install after a the user overrides a warning.
*/
private void resumeInstallAfterWarning() {
// redisplay the progress form
display.setCurrent(progressForm);
backgroundInstaller.continueInstall = true;
synchronized (backgroundInstaller) {
backgroundInstaller.notify();
}
}
/**
* Ask for a username and password.
*/
private void getUsernameAndPassword() {
getUsernameAndPasswordCommon("");
}
/**
* Ask for proxy username and password.
*/
private void getProxyUsernameAndPassword() {
getUsernameAndPasswordCommon(
Resource.getString(
ResourceConstants.AMS_GRA_INTLR_PASSWORD_FORM_FIREWALL_TITLE));
}
/**
* Ask a username and password.
*
* @param title title of the password form
*/
private void getUsernameAndPasswordCommon(String title) {
if (passwordForm == null) {
passwordForm = new Form(null);
usernameField = new TextField(
Resource.getString(ResourceConstants.
AMS_GRA_INTLR_ENTER_ID),
null, 40,
TextField.ANY);
passwordForm.append(usernameField);
passwordField = new TextField(
Resource.getString(ResourceConstants.
AMS_GRA_INTLR_PASSWORD),
null, 40,
TextField.PASSWORD);
passwordForm.append(passwordField);
passwordForm.addCommand(cancelCmd);
passwordForm.addCommand(nextCmd);
passwordForm.setCommandListener(this);
}
passwordForm.setTitle(title);
passwordField.setString("");
display.setCurrent(passwordForm);
}
/**
* Resume the install of the suite with a password and username.
*/
private void resumeInstallWithPassword() {
String username;
String password;
username = usernameField.getString();
password = passwordField.getString();
if (username == null || username.length() == 0) {
Alert a = new Alert(Resource.getString(ResourceConstants.ERROR),
Resource.getString(ResourceConstants.
AMS_GRA_INTLR_ID_NOT_ENTERED),
null, AlertType.ERROR);
a.setTimeout(ALERT_TIMEOUT);
display.setCurrent(a, passwordForm);
return;
}
if (password == null || password.length() == 0) {
Alert a = new Alert(Resource.getString(ResourceConstants.ERROR),
Resource.getString(ResourceConstants.
AMS_GRA_INTLR_PWD_NOT_ENTERED),
null, AlertType.ERROR);
a.setTimeout(ALERT_TIMEOUT);
display.setCurrent(a, passwordForm);
return;
}
// redisplay the progress form
display.setCurrent(progressForm);
if (backgroundInstaller.proxyAuth) {
backgroundInstaller.installState.setProxyUsername(username);
backgroundInstaller.installState.setProxyPassword(password);
} else {
backgroundInstaller.installState.setUsername(username);
backgroundInstaller.installState.setPassword(password);
}
backgroundInstaller.continueInstall = true;
synchronized (backgroundInstaller) {
backgroundInstaller.notify();
}
}
/**
* Confirm the JAR download with the user.
*
* @param state current state of the install.
*/
private void displayDownloadConfirmation(InstallState state) {
Form infoForm;
StringItem item;
String name;
String desc;
StringBuffer label = new StringBuffer(40);
StringBuffer value = new StringBuffer(40);
String[] values = new String[1];
name = state.getSuiteName();
try {
infoForm = new Form(null);
infoForm.setTitle(Resource.getString
(ResourceConstants.AMS_CONFIRMATION));
values[0] = name;
item = new StringItem(null, Resource.getString
(ResourceConstants.AMS_GRA_INTLR_WANT_INSTALL,
values));
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
if (!installer.isJadSigned()) {
// The MIDlet suite is not signed, therefore will be untrusted
item = new StringItem(
Resource.getString(ResourceConstants.WARNING) + ":",
Resource.getString
(ResourceConstants.AMS_GRA_INTLR_UNTRUSTED_WARN));
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
}
// round up the size to a Kilobyte
label.append(Resource.getString(ResourceConstants.AMS_SIZE));
label.append(": ");
value.setLength(0);
value.append(state.getJarSize());
value.append(" K");
item = new StringItem(label.toString(), value.toString());
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
label.setLength(0);
label.append(Resource.getString(ResourceConstants.AMS_VERSION));
label.append(": ");
value.setLength(0);
item = new StringItem(label.toString(),
state.getAppProperty(MIDletSuite.VERSION_PROP));
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
label.setLength(0);
label.append(Resource.getString(ResourceConstants.AMS_VENDOR));
label.append(": ");
item = new StringItem(label.toString(),
state.getAppProperty(MIDletSuite.VENDOR_PROP));
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
desc = state.getAppProperty(MIDletSuite.DESC_PROP);
if (desc != null) {
label.setLength(0);
label.append(Resource.getString
(ResourceConstants.AMS_DESCRIPTION));
label.append(": ");
item = new StringItem(label.toString(), desc);
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
}
label.setLength(0);
label.append(Resource.getString(ResourceConstants.AMS_WEBSITE));
label.append(": ");
infoForm.append(new StringItem(label.toString(),
state.getJarUrl()));
infoForm.addCommand(continueCmd);
infoForm.addCommand(cancelCmd);
infoForm.setCommandListener(this);
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
display.setCurrent(infoForm);
} catch (Exception ex) {
StringBuffer sb = new StringBuffer();
sb.append(name);
sb.append("\n");
sb.append(Resource.getString(ResourceConstants.EXCEPTION));
sb.append(": ");
sb.append(ex.toString());
displayException(Resource.getString
(ResourceConstants.AMS_CANT_ACCESS),
sb.toString());
}
}
/**
* Ask the user during an update if they want to keep the old RMS data.
*
* @param state current state of the install.
*/
private void displayKeepRMSForm(InstallState state) {
Form infoForm;
String name;
String desc;
StringBuffer label = new StringBuffer(40);
StringBuffer value = new StringBuffer(40);
String[] values = new String[1];
name = state.getAppProperty(MIDletSuite.SUITE_NAME_PROP);
try {
infoForm = new Form(null);
infoForm.setTitle(Resource.getString
(ResourceConstants.AMS_CONFIRMATION));
values[0] = name;
value.append(Resource.getString
(ResourceConstants.AMS_GRA_INTLR_NEW_OLD_VERSION,
values));
infoForm.append(value.toString());
infoForm.addCommand(keepRMSCmd);
infoForm.addCommand(removeRMSCmd);
infoForm.setCommandListener(this);
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
display.setCurrent(infoForm);
} catch (Exception ex) {
StringBuffer sb = new StringBuffer();
sb.append(name);
sb.append("\n");
sb.append(Resource.getString(ResourceConstants.EXCEPTION));
sb.append(": ");
sb.append(ex.toString());
displayException(Resource.getString
(ResourceConstants.AMS_CANT_ACCESS),
sb.toString());
}
}
/**
* Confirm the authorization path with the user.
*
* @param state current state of the install.
*/
private void displayAuthPathConfirmation(InstallState state) {
Form infoForm;
String name;
String values[] = new String[1];
StringItem item;
String authPath[];
String temp;
StringBuffer label = new StringBuffer(40);
StringBuffer value = new StringBuffer(40);
name = state.getAppProperty(MIDletSuite.SUITE_NAME_PROP);
try {
infoForm = new Form(Resource.getString(
ResourceConstants.AMS_AUTHORIZATION_INFO));
infoForm.append(new ImageItem(null, TrustedMIDletIcon.getIcon(),
ImageItem.LAYOUT_NEWLINE_BEFORE |
ImageItem.LAYOUT_CENTER |
ImageItem.LAYOUT_NEWLINE_AFTER, null));
values[0] = name;
label.setLength(0);
label.append(Resource.getString(
ResourceConstants.AMS_GRA_INTLR_TRUSTED, values));
label.append(": ");
authPath = state.getAuthPath();
temp = label.toString();
for (int i = 0; i < authPath.length; i++) {
item = new StringItem(temp, authPath[i]);
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
temp = " -> ";
}
infoForm.addCommand(continueCmd);
infoForm.addCommand(cancelCmd);
infoForm.setCommandListener(this);
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
display.setCurrent(infoForm);
} catch (Exception ex) {
StringBuffer sb = new StringBuffer();
sb.append(Resource.getString(ResourceConstants.EXCEPTION));
sb.append(": ");
sb.append(ex.toString());
displayException(Resource.getString
(ResourceConstants.AMS_CANT_ACCESS),
sb.toString());
}
}
/**
* Resume the install to start the JAR download.
*/
private void startJarDownload() {
updateProgressForm(backgroundInstaller.url, 0,
Resource.getString
(ResourceConstants.
AMS_GRA_INTLR_CONN_GAUGE_LABEL));
// redisplay the progress form
display.setCurrent(progressForm);
backgroundInstaller.continueInstall = true;
synchronized (backgroundInstaller) {
backgroundInstaller.notify();
}
}
/** Confirm the JAR only download with the user. */
private void displayJarOnlyDownloadConfirmation() {
Form infoForm;
StringItem item;
StringBuffer label = new StringBuffer(40);
StringBuffer value = new StringBuffer(40);
String[] values = new String[1];
try {
infoForm = new Form(null);
infoForm.setTitle(Resource.getString
(ResourceConstants.AMS_CONFIRMATION));
values[0] = backgroundInstaller.name;
item = new StringItem(null, Resource.getString(
ResourceConstants.AMS_GRA_INTLR_WANT_INSTALL,
values));
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
label.append(Resource.getString(ResourceConstants.AMS_WEBSITE));
label.append(": ");
item = new StringItem(label.toString(), backgroundInstaller.url);
item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
infoForm.append(item);
value.append(" \n");
value.append(Resource.getString
(ResourceConstants.AMS_GRA_INTLR_NO_INFO));
infoForm.append(new StringItem(null, value.toString()));
infoForm.addCommand(continueCmd);
infoForm.addCommand(cancelCmd);
infoForm.setCommandListener(this);
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
display.setCurrent(infoForm);
} catch (Exception ex) {
StringBuffer sb = new StringBuffer();
sb.append(backgroundInstaller.name);
sb.append("\n");
sb.append(Resource.getString(ResourceConstants.EXCEPTION));
sb.append(": ");
sb.append(ex.toString());
displayException(Resource.getString
(ResourceConstants.AMS_CANT_ACCESS),
sb.toString());
}
}
/**
* Tell the background installer to keep the RMS data.
*
* @param keepRMS set to true to mean the user answered yes
*/
private void setKeepRMSAnswer(boolean keepRMS) {
// redisplay the progress form
display.setCurrent(progressForm);
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
backgroundInstaller.continueInstall = keepRMS;
synchronized (backgroundInstaller) {
backgroundInstaller.notify();
}
}
/**
* Alert the user that an action was successful.
*
* @param successMessage message to display to user
*/
private void displaySuccessMessage(String successMessage) {
Image icon;
Alert successAlert;
icon = getImageFromInternalStorage("_dukeok8");
successAlert = new Alert(null, successMessage, icon, null);
successAlert.setTimeout(Alert.FOREVER);
// Provide a listener to disable the advance-to-next-displayable
// feature of Alert.
successAlert.setCommandListener(
new CommandListener() {
public void commandAction(Command c, Displayable d) { }
}
);
// We need to prevent "flashing" on fast development platforms.
preventScreenFlash();
lastDisplayChange = System.currentTimeMillis();
display.setCurrent(successAlert, new Form(""));
// this Form is never displayed
}
/**
* Alert the user that an action was canceled. The backgroundInstaller
* will hide the message.
* @param message message to display to user
*/
private void displayCancelledMessage(String message) {
Form form;
Image icon;
form = new Form(null);
icon = getImageFromInternalStorage("_ack8");
form.append(new ImageItem(null, icon, ImageItem.LAYOUT_CENTER +
ImageItem.LAYOUT_NEWLINE_BEFORE +
ImageItem.LAYOUT_NEWLINE_AFTER, null));
form.append(message);
display.setCurrent(form);
lastDisplayChange = System.currentTimeMillis();
}
/**
* Display an alert to the user, with a done command.
*
* @param title alert's title
* @param message alert message
* @param type severity of the alert message
*/
private void displayAlert(
String title, String message, AlertType type) {
Alert a = new Alert(title, message, null, type);
a.setTimeout(Alert.FOREVER);
a.setCommandListener(this);
display.setCurrent(a, new Form(""));
// this Form is never displayed
}
/**
* Display an warning to the user, with a done command.
*
* @param title warnings form's title
* @param message warning message
*/
private void displayWarning(String title, String message) {
displayAlert(title, message, AlertType.WARNING);
}
/**
* Display an exception to the user, with a done command.
*
* @param title exception form's title
* @param message exception message
*/
private void displayException(String title, String message) {
displayAlert(title, message, AlertType.ERROR);
}
/** A class to install a suite in a background thread. */
private class BackgroundInstaller implements Runnable, InstallListener {
/** Parent installer. */
private GraphicalInstaller parent;
/** URL to install from. */
private String url;
/** Name of MIDlet suite. */
private String name;
/**
* Message for the user after the current install completes
* successfully.
*/
private String successMessage;
/** Flag to update the current suite. */
private boolean update;
/** State of the install. */
InstallState installState;
/** Signals that the user wants the install to continue. */
boolean continueInstall;
/** Signals that the suite only has JAR, no JAD. */
boolean jarOnly;
/** Signals that a proxyAuth is needed. */
boolean proxyAuth;
/**
* Construct a BackgroundInstaller.
*
* @param theParent parent installer of this object
* @param theJadUrl where to get the JAD.
* @param theName name of the MIDlet suite
* @param theSuccessMessage message to display to user upon success
* @param updateFlag if true the current suite should be
* overwritten without asking the user.
*/
private BackgroundInstaller(GraphicalInstaller theParent,
String theJadUrl, String theName, String theSuccessMessage,
boolean updateFlag) {
parent = theParent;
url = theJadUrl;
name = theName;
successMessage = theSuccessMessage;
update = updateFlag;
}
/**
* Run the installer.
*/
public void run() {
// ID of the suite that was just installed
int lastInstalledMIDletId = MIDletSuite.UNUSED_SUITE_ID;
try {
// a flag indicating that an attempt of installation must
// be repeated, but now using the jar URL instead of jad
boolean tryAgain;
// title of the window displaying an error message
String title;
// an error message to display
String msg;
// repeat while(tryAgain)
do {
tryAgain = false;
msg = null;
try {
if (jarOnly) {
lastInstalledMIDletId =
parent.installer.installJar(url, name,
storageId, false, false, this);
} else {
lastInstalledMIDletId =
parent.installer.installJad(url, storageId,
false, false, this);
}
// Let the manager know what suite was installed
GraphicalInstaller.saveSettings(null,
lastInstalledMIDletId);
parent.displaySuccessMessage(successMessage);
/*
* We need to prevent "flashing" on fast development
* platforms.
*/
parent.preventScreenFlash();
parent.exit(true);
} catch (InvalidJadException ije) {
if (ije.getReason() ==
InvalidJadException.INVALID_JAD_TYPE) {
// media type of JAD was wrong, it could be a JAR
String mediaType = (String)ije.getExtraData();
if (Installer.JAR_MT_1.equals(mediaType) ||
Installer.JAR_MT_2.equals(mediaType)) {
// re-run as a JAR only install
if (confirmJarOnlyDownload()) {
jarOnly = true;
installState = null;
tryAgain = true;
continue;
}
displayListAfterCancelMessage();
break;
}
}
msg = translateJadException(ije, name, null, null, url);
} catch (MIDletSuiteLockedException msle) {
String[] values = new String[1];
values[0] = name;
if (!update) {
msg = Resource.getString(
ResourceConstants.AMS_DISC_APP_LOCKED, values);
} else {
msg = Resource.getString(
ResourceConstants.AMS_GRA_INTLR_LOCKED, values);
}
} catch (IOException ioe) {
if (parent.installer != null &&
parent.installer.wasStopped()) {
displayListAfterCancelMessage();
break;
} else {
msg = Resource.getString(
ResourceConstants.AMS_GRA_INTLR_CONN_DROPPED);
}
} catch (Throwable ex) {
if (Logging.TRACE_ENABLED) {
Logging.trace(ex, "Exception caught " +
"while installing");
}
msg = ex.getClass().getName() + ": " + ex.getMessage();
}
} while (tryAgain);
// display an error message, if any
if (msg != null) {
title = Resource.getString(
ResourceConstants.AMS_GRA_INTLR_INSTALL_ERROR);
// go back to the app list
displayException(title, msg);
}
} finally {
if (lastInstalledMIDletId == MIDletSuite.UNUSED_SUITE_ID) {
// Reset an ID of the last successfully installed midlet
// because an error has occured.
GraphicalInstaller.saveSettings(null,
MIDletSuite.UNUSED_SUITE_ID);
}
if (parent.progressForm != null) {
// end the background thread of progress gauge.
Gauge progressGauge = (Gauge)parent.progressForm.get(
parent.progressGaugeIndex);
progressGauge.setValue(Gauge.CONTINUOUS_IDLE);
}
}
}
/**
* Called with the current state of the install so the user can be
* asked to override the warning. Calls the parent to display the
* warning to the user and then waits on the state object for
* user's response.
*
* @param state current state of the install.
*
* @return true if the user wants to continue,
* false to stop the install
*/
public boolean warnUser(InstallState state) {
installState = state;
InvalidJadException e = installState.getLastException();
switch (e.getReason()) {
case InvalidJadException.UNAUTHORIZED:
proxyAuth = false;
parent.getUsernameAndPassword();
break;
case InvalidJadException.PROXY_AUTH:
proxyAuth = true;
parent.getProxyUsernameAndPassword();
break;
case InvalidJadException.OLD_VERSION:
case InvalidJadException.ALREADY_INSTALLED:
case InvalidJadException.NEW_VERSION:
// this is now an update
update = true;
// fall through
default:
parent.warnUser(name,
state.getAppProperty(MIDletSuite.VENDOR_PROP),
state.getAppProperty(MIDletSuite.VERSION_PROP),
url, e);
}
return waitForUser();
}
/**
* Called with the current state of the install so the user can be
* asked to confirm the jar download.
* If false is returned, the an I/O exception thrown and
* {@link Installer#wasStopped()} will return true if called.
*
* @param state current state of the install.
*
* @return true if the user wants to continue, false to stop the
* install
*/
public boolean confirmJarDownload(InstallState state) {
if (update) {
// this an update, no need to confirm.
return true;
}
installState = state;
url = state.getJarUrl();
parent.displayDownloadConfirmation(state);
return waitForUser();
}
/**
* Called with the current state of the install so the user can be
* asked to confirm if the RMS data should be kept for new version of
* an updated suite.
*
* @param state current state of the install.
*
* @return true if the user wants to keep the RMS data for the next
* suite
*/
public boolean keepRMS(InstallState state) {
installState = state;
parent.displayKeepRMSForm(state);
return waitForUser();
}
/**
* Called with the current state of the install so the user can be
* asked to confirm the authentication path.
* If false is returned, the an I/O exception thrown and
* {@link Installer#wasStopped()} will return true if called.
*
* @param state current state of the install.
*
* @return true if the user wants to continue, false to stop the
* install
*/
public boolean confirmAuthPath(InstallState state) {
parent.displayAuthPathConfirmation(state);
return waitForUser();
}
/**
* Called with the current state of the install so the user can be
* asked to confirm the jar only download.
*
* @return true if the user wants to continue, false to stop the
* install
*/
private boolean confirmJarOnlyDownload() {
if (update) {
// this an update, no need to confirm.
return true;
}
parent.displayJarOnlyDownloadConfirmation();
return waitForUser();
}
/**
* Wait for the user to respond to current dialog.
*
* @return true if the user wants to continue, false to stop the
* install
*/
private boolean waitForUser() {
boolean temp;
synchronized (this) {
try {
this.wait();
} catch (InterruptedException ie) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"wait threw an InterruptedException");
}
}
}
installState = null;
temp = continueInstall;
continueInstall = false;
return temp;
}
/**
* Called with the current status of the install.
* Changes the status alert box text based on the status.
*
* @param status current status of the install.
* @param state current state of the install.
*/
public void updateStatus(int status, InstallState state) {
parent.updateStatus(status, state);
}
/**
* Wait for the cancel message to be displayed to prevent flashing
* and then display the list of suites.
*/
private void displayListAfterCancelMessage() {
// wait for the parent to display "cancelled"
synchronized (parent) {
/*
* We need to prevent "flashing" on fast
* development platforms.
*/
parent.preventScreenFlash();
// go back to app list
parent.exit(false);
}
}
}
}
|