FileDocCategorySizeDatePackage
GraphicalInstaller.javaAPI DocJ2ME MIDP 2.060981Thu Nov 07 12:02:24 GMT 2002com.sun.midp.dev

GraphicalInstaller

public class GraphicalInstaller extends MIDlet implements CommandListener
The Graphical MIDlet suite manager.

Let the user install a suite from a list of suites obtained using an HTML URL given by the user. This list is derived by extracting the links with hrefs that are in quotes and end with ".jad" from the HTML page. An href in an extracted link is assumed to be an absolute URL for a MIDP application descriptor.

Fields Summary
static final int
ALERT_TIMEOUT
Standard timeout for alerts.
static final String
SETTINGS_STORE
settings database
static final int
URL_RECORD_ID
record id of selected midlet
static final int
SELECTED_MIDLET_RECORD_ID
record is of the last installed midlet
static boolean
colorDisplay
So the static method can know if there is a color display.
private Installer
installer
The installer that is being used to install or update a suite.
private Display
display
Display for this MIDlet.
private String
defaultInstallListUrl
Contains the default URL for the install list.
private TextBox
urlTextBox
Contains the URL the user typed in.
private Form
passwordForm
Form obtain a password and a username.
private TextField
usernameField
Contains the username for installing.
private TextField
passwordField
Contains the password for installing.
private BackgroundInstaller
backgroundInstaller
Background installer that holds state for the current install.
private Form
progressForm
Displays the progress of the install.
private int
progressGaugeIndex
Gauge for progress form index.
private int
progressUrlIndex
URL for progress form index.
private long
lastDisplayChange
Keeps track of when the display last changed, in millseconds.
private String
cancelledMessage
What to display to the user when the current action is cancelled.
private String
finishingMessage
What to display to the user when the current action is finishing.
private List
installListBox
Displays a list of suites to install to the user.
private Vector
installList
Contains a list of suites to install.
private Command
endCmd
Command object for "Back" command in the URL form.
private Command
discoverCmd
Command object for URL screen to go and discover available suites.
private Command
saveCmd
Command object for URL screen to save the URL for suites.
private Command
backCmd
Command object for "Back" command in the suite list form.
private Command
installCmd
Command object for "Install" command in the suite list form .
private Command
stopCmd
Command object for "Stop" command for progress form.
private Command
cancelCmd
Command object for "Cancel" command for the confirm form.
private Command
continueCmd
Command object for "Install" command for the confirm download form.
private Command
nextCmd
Command object for "Next" command for password form.
private Command
okCmd
Command object for "continue" command for warning form.
private Command
exceptionCmd
Command object for "OK" command for exception form.
private Command
keepRMSCmd
Command object for "Yes" command for keep RMS form.
private Command
removeRMSCmd
Command object for "No" command for keep RMS form.
Constructors Summary
GraphicalInstaller()
Create and initialize a new graphical installer MIDlet. The Display is retreived and the list of MIDlet will be retrived or update a currently installed suite.

        String storageName;

        installer = Installer.getInstaller();
        display = Display.getDisplay(this);
        colorDisplay = display.isColor();

        initSettings();
        restoreSettings();
        
        storageName = getAppProperty("storageName");
        if (storageName != null) {
            updateSuite(storageName);
            return;
        }

        // get the URL of a list of suites to install
        getUrl();
    
Methods Summary
private voidcancelBackgroundInstall()
Cancel an install (if there is one) waiting for user input.

        if (backgroundInstaller != null) {
            backgroundInstaller.continueInstall = false;

            synchronized (backgroundInstaller) {
                backgroundInstaller.notify();
            }
        }
    
public voidcommandAction(Command c, Displayable s)
Respond to a command issued on any Screen.

param
c command activiated by the user
param
s the Displayable the command was on.

        if (c == discoverCmd) {
            // user wants to discover the suites that can be installed
            discoverSuitesToInstall(urlTextBox.getString());
        } else if (s == installListBox &&
                  (c == List.SELECT_COMMAND || c == installCmd)) {
            installSuite(installListBox.getSelectedIndex());
        } else if (c == backCmd) {
            display.setCurrent(urlTextBox);
        } else 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 == saveCmd) {
            saveURLSetting();
        } 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
                notifyDestroyed();
            }
        } else if (c == cancelCmd) {
            displayCancelledMessage(cancelledMessage);
            cancelBackgroundInstall();
        } else if (c == endCmd || c == Alert.DISMISS_COMMAND) {
            // goto back to the manager midlet
            notifyDestroyed();
        }
    
private voidcreateProgressForm(java.lang.String action, java.lang.String name, java.lang.String url, int size, java.lang.String gaugeLabel)
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

        Form installForm;

        // display the JAR progress form
        installForm = displayProgressForm(action, name, url, size,
                                            gaugeLabel);
        installForm.addCommand(stopCmd);
        installForm.setCommandListener(this);
    
public voiddestroyApp(boolean unconditional)
Destroy cleans up.

param
unconditional is ignored; this object always destroys itself when requested.

        if (installer != null) {
            installer.stopInstalling();
        }

        /* The backgroundInstaller could be waiting for the user. */
        cancelBackgroundInstall();
    
private voiddiscoverSuitesToInstall(java.lang.String url)
Let the user select a suite to install. The suites that are listed are the links on a web page that end with .jad.

param
url where to get the list of suites to install.

        new Thread(new BackgroundInstallListGetter(this, url)).start();
    
private voiddisplayCancelledMessage(java.lang.String message)
Alert the user that an action was canceled. The backgroundInstaller will hide the message.

param
message message to display to user

        Form form;
        Image icon;

        form = new Form(null);

        icon = getIconFromStorage(
                       (colorDisplay ? "_ack_8.png" : "_ack_2.png"));
        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();
    
private voiddisplayDownloadConfirmation(InstallState state)
Confirm the JAR download with the user.

param
state current state of the install.

        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.getAppProperty(Installer.SUITE_NAME_PROP);

        try {
            infoForm = new Form(null);

            infoForm.setTitle(Resource.getString("Confirmation"));

            values[0] = name;
            item = new StringItem(null, Resource.getString(
                "Are you sure you want to install \"%1\"?", values));
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            infoForm.append(item);

            // round up the size to a Kilobyte
            label.append(Resource.getString("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("Version"));
            label.append(": ");
            value.setLength(0);
            item = new StringItem(label.toString(),
                       state.getAppProperty(Installer.VERSION_PROP));
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            infoForm.append(item);

            label.setLength(0);
            label.append(Resource.getString("Vendor"));
            label.append(": ");
            item = new StringItem(label.toString(),
                      state.getAppProperty(Installer.VENDOR_PROP));
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            infoForm.append(item);

            desc = state.getAppProperty(Installer.DESC_PROP);
            if (desc != null) {
                label.setLength(0);
                label.append(Resource.getString("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("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.
            while (System.currentTimeMillis() - lastDisplayChange <
                   ALERT_TIMEOUT);

            display.setCurrent(infoForm);
        } catch (Exception ex) {
            StringBuffer sb = new StringBuffer();
            
            sb.append(name);
            sb.append("\n");
            sb.append(Resource.getString("Exception"));
            sb.append(": ");
            sb.append(ex.toString());
            displayException(Resource.getString("Cannot access: "), 
                                sb.toString());
        }
    
private voiddisplayException(java.lang.String title, java.lang.String message)
Display an exception to the user, with a done command.

param
title exception form's title
param
message exception message

        Alert a = new Alert(title, message, null, AlertType.ERROR);

        a.setTimeout(Alert.FOREVER);
        a.setCommandListener(this);

        display.setCurrent(a);
    
private voiddisplayJarOnlyDownloadConfirmation()
Confirm the JAR only download with the user.

        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("Confirmation"));

            values[0] = backgroundInstaller.name;
            item = new StringItem(null, Resource.getString(
                       "Are you sure you want to install \"%1\"?", values));
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            infoForm.append(item);

            label.append(Resource.getString("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("There is no further " +
                "information available for the application."));
            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.
            while (System.currentTimeMillis() - lastDisplayChange <
                   ALERT_TIMEOUT);

            display.setCurrent(infoForm);
        } catch (Exception ex) {
            StringBuffer sb = new StringBuffer();
            
            sb.append(backgroundInstaller.name);
            sb.append("\n");
            sb.append(Resource.getString("Exception"));
            sb.append(": ");
            sb.append(ex.toString());
            displayException(Resource.getString("Cannot access: "), 
                             sb.toString());
        }
    
private voiddisplayKeepRMSForm(InstallState state)
Ask the user during an update if they want to keep the old RMS data.

param
state current state of the install.

        Form infoForm;
        String name;
        String desc;
        StringBuffer label = new StringBuffer(40);
        StringBuffer value = new StringBuffer(40);
        String[] values = new String[1];

        name = state.getAppProperty(Installer.SUITE_NAME_PROP);

        try {
            infoForm = new Form(null);

            infoForm.setTitle(Resource.getString("Confirmation"));

            values[0] = name;
            value.append(Resource.getString("Do you want the new version " +
                "of %1 to be able to use the information stored by the " +
                "old version of %1?", values));
            infoForm.append(value.toString());

            infoForm.addCommand(keepRMSCmd);
            infoForm.addCommand(removeRMSCmd);
            infoForm.setCommandListener(this);

            // We need to prevent "flashing" on fast development platforms.
            while (System.currentTimeMillis() - lastDisplayChange <
                   ALERT_TIMEOUT);

            display.setCurrent(infoForm);
        } catch (Exception ex) {
            StringBuffer sb = new StringBuffer();
            
            sb.append(name);
            sb.append("\n");
            sb.append(Resource.getString("Exception"));
            sb.append(": ");
            sb.append(ex.toString());
            displayException(Resource.getString("Cannot access: "), 
                                sb.toString());
        }
    
private FormdisplayProgressForm(java.lang.String action, java.lang.String name, java.lang.String url, int size, java.lang.String gaugeLabel)
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

        Gauge progressGauge;
        StringItem urlItem;

        progressForm = new Form(null);

        progressForm.setTitle(Resource.getString(action) + " " + name);

        if (size <= 0) {
            progressGauge = new Gauge(Resource.getString(gaugeLabel), 
				      false, Gauge.INDEFINITE,
				      Gauge.CONTINUOUS_RUNNING);
        } else {
            progressGauge = new Gauge(Resource.getString(gaugeLabel), 
				      false, size, 0);
        }

        progressGaugeIndex = progressForm.append(progressGauge);

        if (url == null) {
            urlItem = new StringItem("", "");
        } else {
            urlItem =
                new StringItem(Resource.getString("Website") + ": ", url);
        }

        progressUrlIndex = progressForm.append(urlItem);

        display.setCurrent(progressForm);
        lastDisplayChange = System.currentTimeMillis();

        return progressForm;
    
private voiddisplaySuccessMessage(java.lang.String successMessage)
Alert the user that an action was successful.

param
successMessage message to display to user

        Image icon;
        Alert successAlert;

        icon = getIconFromStorage(
                       (colorDisplay ? "_dukeok8.png" : "_dukeok2.png"));

        successAlert = new Alert(null, successMessage, icon, null);

        successAlert.setTimeout(ALERT_TIMEOUT);

        // We need to prevent "flashing" on fast development platforms.
        while (System.currentTimeMillis() - lastDisplayChange <
               ALERT_TIMEOUT);

        lastDisplayChange = System.currentTimeMillis();
        display.setCurrent(successAlert);
    
static ImagegetIconFromStorage(java.lang.String iconName)
Gets an icon from storage.

param
iconName name without a path
return
icon image


                       
        
        String iconFilename;
        RandomAccessStream stream;
        byte[] rawPng;

        iconFilename = File.getStorageRoot() + iconName;
        stream = new RandomAccessStream();
        try { 
            stream.connect(iconFilename, Connector.READ);
            rawPng = new byte[stream.getSizeOf()];
            stream.readBytes(rawPng, 0, rawPng.length);
            stream.disconnect();
            return Image.createImage(rawPng, 0, rawPng.length);
        } catch (java.io.IOException noImage) {
        }

        return null;
    
private voidgetProxyUsernameAndPassword()
Ask for proxy username and password.

        getUsernameAndPasswordCommon("Firewall Authentication");
    
private voidgetUrl()
Ask the user for the URL.

        try {
            if (urlTextBox == null) {
                urlTextBox = new TextBox(Resource.getString(
                                         "Enter a website to Install From:"),
                                         defaultInstallListUrl, 1024,
                                         TextField.ANY);
                urlTextBox.addCommand(endCmd);
                urlTextBox.addCommand(saveCmd);
                urlTextBox.addCommand(discoverCmd);
                urlTextBox.setCommandListener(this);
            }

            display.setCurrent(urlTextBox);
        } catch (Exception ex) {
            displayException(Resource.getString("Exception"), 
                             ex.toString());
        }
    
private voidgetUsernameAndPassword()
Ask for a username and password.

        getUsernameAndPasswordCommon("");
    
private voidgetUsernameAndPasswordCommon(java.lang.String title)
Ask a username and password.

param
title title of the password form

        if (passwordForm == null) {
            passwordForm = new Form(null);

            usernameField = new TextField(
                            Resource.getString("Please Enter ID"), null, 40,
                            TextField.ANY);
            passwordForm.append(usernameField);

            passwordField = new TextField(
                            Resource.getString("Password"), null, 40,
                            TextField.PASSWORD);
            passwordForm.append(passwordField);
            passwordForm.addCommand(cancelCmd);
            passwordForm.addCommand(nextCmd);
            passwordForm.setCommandListener(this);
        }

        passwordForm.setTitle(Resource.getString(title));
        passwordField.setString("");
        display.setCurrent(passwordForm);
    
static voidinitSettings()
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

        try {
            RecordStore settings = RecordStore.
                                   openRecordStore(SETTINGS_STORE, true);

            if (settings.getNumRecords() == 0) {
                // space for a URL
                settings.addRecord(null, 0, 0);

                // space for current MIDlet Suite name
                settings.addRecord(null, 0, 0);
            }

            settings.closeRecordStore();

        } catch (Exception e) {}
    
private voidinstallSuite(int selectedSuite)
Install a suite.

param
selectedSuite index into the installList

        SuiteDownloadInfo suite;

        suite = (SuiteDownloadInfo)installList.elementAt(selectedSuite);
        cancelledMessage = Resource.getString("Installation cancelled.");
        finishingMessage = Resource.getString("Finishing installation.");
        installSuiteCommon("Installing", suite.label, suite.url,
            suite.label + Resource.getString(" was successfully installed"),
            false);
    
private voidinstallSuiteCommon(java.lang.String action, java.lang.String name, java.lang.String url, java.lang.String successMessage, boolean updateFlag)
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

        try {
            createProgressForm(action, name, url, 0, "Connecting...");
            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("Error"));
            sb.append(": ");
            sb.append(ex.toString());
            displayException(Resource.getString("Cannot access: "), 
                            sb.toString());
        }
    
public voidpauseApp()
Pause; there are no resources that need to be released.

    
private voidrestoreSettings()
Get the settings the Manager saved for the user.

        ByteArrayInputStream bas;
        DataInputStream dis;
        byte[] data;
        RecordStore settings = null;
        
        try {
            settings = RecordStore.openRecordStore(SETTINGS_STORE, false);

            data = settings.getRecord(1);
            if (data != null) {
                bas = new ByteArrayInputStream(data);
                dis = new DataInputStream(bas);
                defaultInstallListUrl = dis.readUTF();
            }

        } catch (RecordStoreException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        } finally {
            if (settings != null) {
                try {
                    settings.closeRecordStore();
                } catch (RecordStoreException e) {
                    // ignore
                }
            }
        }
    
private voidresumeInstallAfterWarning()
Resume the install after a the user overrides a warning.

        // redisplay the progress form
        display.setCurrent(progressForm);

        backgroundInstaller.continueInstall = true;
        synchronized (backgroundInstaller) {
            backgroundInstaller.notify();
        }
    
private voidresumeInstallWithPassword()
Resume the install of the suite with a password and username.

        String username;
        String password;


        username = usernameField.getString();
        password = passwordField.getString();
        if (username == null || username.length() == 0) {
            Alert a = new Alert(Resource.getString("Error"), 
                             Resource.getString(
                             "The ID has not been 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("Error"), 
                                Resource.getString(
                                "The password has not been 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();
        }
    
static java.lang.ExceptionsaveSettings(java.lang.String url, java.lang.String curMidlet)
Save the settings the user entered.

param
url the url to save
param
curMidlet the storagename of the currently selected midlet
return
the Exception that may have been thrown, or null


        Exception ret = null;

        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);
            }

            if (curMidlet != null) {
                bas.reset();

                dos.writeUTF(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;
    
private voidsaveURLSetting()
Save the URL setting the user entered in to the urlTextBox.

        String temp;
        Exception ex;

        temp = urlTextBox.getString();

        ex = saveSettings(temp, null);
        if (ex != null) {
            displayException(Resource.getString("Exception"), ex.toString());
            return;
        }

        defaultInstallListUrl = temp;

        displaySuccessMessage(Resource.getString("Saved!"));
    
private voidsetKeepRMSAnswer(boolean keepRMS)
Tell the background installer to keep the RMS data.

param
keepRMS set to true to mean the user answered yes

        // redisplay the progress form
        display.setCurrent(progressForm);

        // We need to prevent "flashing" on fast development platforms.
        while (System.currentTimeMillis() - lastDisplayChange <
               ALERT_TIMEOUT);

        backgroundInstaller.continueInstall = keepRMS;
        synchronized (backgroundInstaller) {
            backgroundInstaller.notify();
        }
    
public voidstartApp()
Start.

    
private voidstartJarDownload()
Resume the install to start the JAR download.

        updateProgressForm(backgroundInstaller.url, 0, "Connecting...");

        // redisplay the progress form
        display.setCurrent(progressForm);

        backgroundInstaller.continueInstall = true;
        synchronized (backgroundInstaller) {
            backgroundInstaller.notify();
        }
    
private static java.lang.StringtranslateJadException(InvalidJadException exception, java.lang.String name, java.lang.String vendor, java.lang.String version, java.lang.String jadUrl)
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

        String[] values = {name, vendor, version, jadUrl,
                           exception.getExtraData()};
        String key;

        switch (exception.getReason()) {
        case InvalidJadException.OLD_VERSION:
            key = "An OLDER version of %1 has been found. " +
                  "Continuing will replace the version installed on your " +
                  "phone.\n\n" +
                  "Currently installed: %5\n" +
                  "Version found: %3\n" +
                  "Vendor: %2\n" +
                  "Website: %4\n\n" +
                  "Would you like to continue?";
            break;

        case InvalidJadException.ALREADY_INSTALLED:
            key = "This version of %1 is already installed on your phone. " +
                  "Continuing will replace the version installed on your " +
                  "phone.\n\n" +
                  "Currently installed: %5\n" +
                  "Version found: %3\n" +
                  "Vendor: %2\n" +
                  "Website: %4\n\n" +
                  "Would you like to continue?";
            break;

        case InvalidJadException.NEW_VERSION:
            key = "A NEWER version of %1 is has been found. " +
                  "Continuing will replace the version installed on your " +
                  "phone.\n\n" +
                  "Currently installed: %5\n" +
                  "Latest available: %3\n" +
                  "Vendor: %2\n" +
                  "Website: %4\n\n" +
                  "Would you like to continue?";
            break;

        case InvalidJadException.JAD_SERVER_NOT_FOUND:
        case InvalidJadException.JAD_NOT_FOUND:
        case InvalidJadException.INVALID_JAD_URL:
            key = "%1 cannot be found at this URL. " +
                  "Contact the application provider for more information.";
            break;

        case InvalidJadException.INVALID_JAD_TYPE:
            key = "The application file (.jad) for %1 does not appear to " +
                  "be the correct type. Contact the application provider " +
                  "for more information.";
            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 = "%1 cannot be installed because critical information is " +
                  "missing from the application file (.jad).";
            break;

        case InvalidJadException.MISSING_CONFIGURATION:
        case InvalidJadException.MISSING_PROFILE:
            key = "%1 cannot be installed because critical information is " +
                  "missing from the application file (.jar).";
            break;

        case InvalidJadException.INVALID_KEY:
        case InvalidJadException.INVALID_VALUE:
        case InvalidJadException.INVALID_VERSION:
        case InvalidJadException.PUSH_FORMAT_FAILURE:
        case InvalidJadException.PUSH_CLASS_FAILURE:
            key = "%1 cannot be installed because critical " + 
                  "information is not formatted correctly or is invalid. " +
                  "Contact your application provider to correct this " +
                  "situation.";
            break;

        case InvalidJadException.DEVICE_INCOMPATIBLE:
            key = "%1 is not designed to work with this device and cannot " +
                  "be installed.";
            break;

        case InvalidJadException.JAD_MOVED:
            key = "The new version of %1 is not from the same provider " +
                  "as the old version. The download URLs do not match. " +
                  "Do you want to install the new version?" +
                  "\n\nOld URL: %5\nNew URL: %4";
            break;

        case InvalidJadException.INSUFFICIENT_STORAGE:
            key = "There is not enough room to install %1 (%5K is needed " +
                  "for installation.). Try removing other items to free " +
                  "up space.";
            break;

        case InvalidJadException.JAR_SERVER_NOT_FOUND:
        case InvalidJadException.JAR_NOT_FOUND:
        case InvalidJadException.INVALID_JAR_URL:
            key = "The application file (.jar) for %1 cannot be found at " +
                  "its URL. Contact the application provider for more " +
                  "information.";
            break;

        case InvalidJadException.INVALID_JAR_TYPE:
            key = "The application file (.jar) for %1 does not appear to " +
                  "be the correct type. Contact the application provider " +
                  "for more information.";
            break;

        case InvalidJadException.SUITE_NAME_MISMATCH:
        case InvalidJadException.VERSION_MISMATCH:
        case InvalidJadException.VENDOR_MISMATCH:
        case InvalidJadException.JAR_SIZE_MISMATCH:
        case InvalidJadException.ATTRIBUTE_MISMATCH:
            key = "%1 cannot be installed because critical information " +
                  "between the website and the application file does not " +
                  "match.";
            break;

        case InvalidJadException.CORRUPT_JAR:
            key = "The application file (.jar) for %1 appears to be " +
                  "corrupt. Contact the application provider " +
                  "for more information.";
            break;

        case InvalidJadException.CANNOT_AUTH:
            key = "The website has requested to authenticate the user " +
                  "in way that this device does not support.";
            break;

        case InvalidJadException.CORRUPT_PROVIDER_CERT:
        case InvalidJadException.INVALID_PROVIDER_CERT:
        case InvalidJadException.CORRUPT_SIGNATURE:
        case InvalidJadException.INVALID_SIGNATURE:
        case InvalidJadException.UNSUPPORTED_CERT:
            key = "%1 cannnot be installed because the application files " +
                  "cannot verified. Contact your application " +
                  "provider to correct this situation.";
            break;

        case InvalidJadException.UNKNOWN_CA:
            key = "%1 cannot be installed. The system does recognize who " +
                  "is trying to authorize the application. Contact your " +
                  "service provider to correct this situation. \n\n%5";
            break;

        case InvalidJadException.EXPIRED_PROVIDER_CERT:
            key = "%1 cannot be installed. The trusted certificate used to " +
                  "authorize the application has expired. Contact your " +
                  "application provider to correct this situation.";
            break;

        case InvalidJadException.EXPIRED_CA_KEY:
            key = "%1 cannot be installed. The public key used for " +
                  "authorization has expired. Contact your service " +
                  "provider to correct this situation.";
            break;

        case InvalidJadException.AUTHORIZATION_FAILURE:
            key = "%1 cannot be installed because it does not have " +
                  "permission to the operation it requires.";
            break;

        case InvalidJadException.PUSH_DUP_FAILURE:
            key = "%1 cannot be installed. %1 is requires the use of a " +
                  "particular network resource to listen for network " +
                  "information. This resource is in use by another " + 
                  "application. Try removing the other application and " +
                  "re-installing.";
            break;

        case InvalidJadException.PUSH_PROTO_FAILURE:
            key = "%1 cannot be installed. %1 is requires the use of a " +
                  "particular network resource to listen for network " +
                  "information. This network resource is not supported on " +
                  "this device.";
            break;

        case InvalidJadException.TRUSTED_OVERWRITE_FAILURE:
            key = "The new version of %1, cannot be installed. " +
                  "The old version of %1 is authorized by %5. " +
                  "The new version is not authorized. " +
                  "Authorized applications cannot be replaced by " +
                  "unauthorized applications.";
            break;

        default:
            return exception.getMessage();
        }

        return Resource.getString(key, values);
    
private voidupdateProgressForm(java.lang.String url, int size, java.lang.String gaugeLabel)
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

        Gauge oldProgressGauge;
        Gauge progressGauge;
        StringItem urlItem;

        // We need to prevent "flashing" on fast development platforms.
        while (System.currentTimeMillis() - lastDisplayChange < ALERT_TIMEOUT);

        if (size <= 0) {
            progressGauge = new Gauge(Resource.getString(gaugeLabel), 
				      false, Gauge.INDEFINITE, 
				      Gauge.CONTINUOUS_RUNNING);
        } else {
            progressGauge = new Gauge(Resource.getString(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("Website") + ": ", url);
            progressForm.set(progressUrlIndex, urlItem);
        }

        lastDisplayChange = System.currentTimeMillis();
    
private voidupdateStatus(int status, InstallState state)
Update the status form.

param
status current status of the install.
param
state current state of the install.

        if (status == Installer.DOWNLOADING_JAD) {
            updateProgressForm("", 0,
               "Downloading the application description file...");
            return;
        }

        if (status == Installer.DOWNLOADING_JAR) {
            updateProgressForm(state.getJarUrl(), state.getJarSize(),
                               "Downloading the application file...");
            return;
        }

        if (status == Installer.DOWNLOADED_1K_OF_JAR &&
                state.getJarSize() > 0) {
            Gauge progressGauge = (Gauge)progressForm.get(progressGaugeIndex);
            progressGauge.setValue(progressGauge.getValue() + 1);
            return;
        }

        if (status == Installer.VERIFYING_SUITE) {
            updateProgressForm(null, 0, "Verifying the application...");
            return;
        }

        if (status == Installer.STORING_SUITE) {
            displaySuccessMessage(finishingMessage);
            return;
        }
    
private voidupdateSuite(java.lang.String storageName)
Update a suite.

param
storageName storage name of the suite to update

        MIDletSuite midletSuite = installer.getMIDletSuite(storageName);
        MIDletInfo midletInfo;
        String name;

        if (midletSuite.getNumberOfMIDlets() == 1) {
            midletInfo = new MIDletInfo(midletSuite.getProperty("MIDlet-1"));
            name = midletInfo.name;
        } else {
            name = midletSuite.getProperty(Installer.SUITE_NAME_PROP);
        }

        cancelledMessage = Resource.getString("Update cancelled.");
        finishingMessage = Resource.getString("Finishing update.");
        installSuiteCommon("Updating", name,
            midletSuite.getDownloadUrl(),
            name + Resource.getString(" was successfully updated"),
            true);
    
private voidwarnUser(java.lang.String name, java.lang.String vendor, java.lang.String version, java.lang.String jadUrl, InvalidJadException e)
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

        Form warningForm;

        warningForm = new Form(null);
        warningForm.setTitle(Resource.getString("Warning"));
        warningForm.append(translateJadException(e, name, vendor, version,
                                                 jadUrl)); 
        warningForm.addCommand(cancelCmd);
        warningForm.addCommand(okCmd);
        warningForm.setCommandListener(this);
        display.setCurrent(warningForm);