javamanager/javainstaller/installer/javasrc/com/nokia/mj/impl/installer/midp2/install/steps/ConfirmInstallation.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javamanager/javainstaller/installer/javasrc/com/nokia/mj/impl/installer/midp2/install/steps/ConfirmInstallation.java Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,391 @@
+/*
+* Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+package com.nokia.mj.impl.installer.midp2.install.steps;
+
+import com.nokia.mj.impl.installer.customisationproperties.CustomisationProperties;
+import com.nokia.mj.impl.installer.exetable.ExeBall;
+import com.nokia.mj.impl.installer.exetable.ExeStep;
+import com.nokia.mj.impl.installer.ui.ApplicationInfo;
+import com.nokia.mj.impl.installer.ui.InstallInfo;
+import com.nokia.mj.impl.installer.utils.DriveInfo;
+import com.nokia.mj.impl.installer.utils.FileUtils;
+import com.nokia.mj.impl.installer.utils.InstallerException;
+import com.nokia.mj.impl.installer.utils.Log;
+import com.nokia.mj.impl.installer.utils.Platform;
+import com.nokia.mj.impl.installer.utils.SysUtil;
+import com.nokia.mj.impl.security.midp.common.SigningCertificate;
+import com.nokia.mj.impl.security.midp.authentication.AuthenticationModule;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.jar.JarFile;
+import java.util.jar.JarEntry;
+
+/**
+ * ConfirmInstallation shows installation confirmation dialog to user.
+ *
+ * @author Nokia Corporation
+ * @version $Rev: $ $Date: $
+ */
+public class ConfirmInstallation extends ExeStep
+{
+ public void execute(ExeBall aBall)
+ {
+ InstallBall ball = (InstallBall)aBall;
+
+ // Get possible certificates for the application.
+ SigningCertificate[] certs = AuthenticationModule.getInstance()
+ .getCertificatesDetails(ball.iStorageHandler.getSession(),
+ ball.iSuite.getUid());
+ if (certs != null)
+ {
+ Log.log("Possible certificates for this application:");
+ for (int i = 0; i < certs.length; i++)
+ {
+ Log.log("Certificate[" + i + "]:\n" + certs[i]);
+ }
+ }
+ // Check if RMS data should be retained in case of an
+ // upgrade as specified in MIDP 2.1 spec chapter
+ // 2.1.5 "MIDlet Suite Update".
+ if (ball.iOldSuite != null)
+ {
+ // Check from signer if private data should
+ // be retained in application upgrade.
+ checkSameSignerForUpgradeData(ball, ball.iOldCertificates, certs);
+ // Check from jad and jar urls if private data should
+ // be retained in application upgrade.
+ checkUrlsForUpgradeData(ball);
+ }
+
+ if (ball.isSilent() || Platform.isLinux())
+ {
+ // Silent installation, assume positive answer from user.
+ // Linux does not have UI, assume positive answer from user.
+ ball.iUserConfirmation = new Boolean(true);
+ return;
+ }
+
+ // Collect all the info needed in confirmation dialog,
+ // display it to user and based on user response
+ // initialise ball.iUserConfirmation and other data.
+ // Use localized suite name if it exists
+ String suiteName = ball.getAttributeValue("Nokia-MIDlet-Localized-Name");
+ if (suiteName == null)
+ {
+ suiteName = ball.iSuite.getName();
+ }
+ InstallInfo installInfo = new InstallInfo(ball.iSuite.getUid(),
+ suiteName, ball.iSuite.getVendor(),
+ ball.iSuite.getVersion().toString());
+
+ // In case of an update, set old suite version.
+ if (ball.iOldSuite != null)
+ {
+ installInfo.setOldVersion(ball.iOldSuite.getVersion().toString());
+ }
+
+ // Set Jar size and data size from Jad/Manifest attributes.
+ installInfo.setJarSize(getAttributeLongValue(ball, "MIDlet-Jar-Size"));
+ installInfo.setDataSize(getAttributeLongValue(ball, "MIDlet-Data-Size"));
+ if (installInfo.getJarSize() <= 0 &&
+ ball.iJarFilename != null && ball.iDownloader == null)
+ {
+ // Get jar file size.
+ installInfo.setJarSize(FileUtils.getSize(ball.iJarFilename));
+ }
+
+ // Set certificates.
+ installInfo.setCertificates(certs);
+
+ // Set ApplicationInfos.
+ installInfo.setApplications(getApplicationInfos(ball));
+
+ // Set RetainData flag if this is an application update and
+ // retain user data decision has not been made yet.
+ if (ball.iOldSuite != null && ball.iUpgradeData == null)
+ {
+ installInfo.setRetainData(true);
+ }
+
+ // Set installation drive.
+ installInfo.setDriveId(ball.iInstallationDrive);
+ Vector drives = new Vector();
+ SysUtil.getUserVisibleDrives(drives);
+ int[] driveIds = new int[drives.size()];
+ int[] driveTypes = new int[drives.size()];
+ long[] driveFreeSpaces = new long[drives.size()];
+ for (int i = 0; i < drives.size(); i++)
+ {
+ DriveInfo driveInfo = (DriveInfo)drives.elementAt(i);
+ // Note that this trusts that DriveInfo constant values
+ // are identical to drive type constants in InstallInfo.
+ driveIds[i] = driveInfo.getNumber();
+ driveTypes[i] = driveInfo.getDriveType();
+ driveFreeSpaces[i] = driveInfo.getFreeSpace();
+ }
+ installInfo.setDriveIdsTypes(driveIds, driveTypes);
+ installInfo.setDriveFreeSpaces(driveFreeSpaces);
+
+ // Set icon paths.
+ JarFile jarFile = null;
+ InputStream iconInputStream = null;
+ if (ball.iJarFilename != null && ball.iDownloader == null)
+ {
+ // We have jar filename and are not downloading it,
+ // so jar file must be available.
+ // Get icon InputStream for correct icon in jar file.
+ String suiteIconPath = ball.iSuite.getAttributeValue("MIDlet-Icon");
+ if (suiteIconPath == null)
+ {
+ suiteIconPath = ball.iSuite.getFirstIconPath();
+ }
+ Log.log("SuiteIconPath for the UI resource: " + suiteIconPath);
+ if (suiteIconPath != null)
+ {
+ try
+ {
+ jarFile = new JarFile(ball.iJarFilename);
+ iconInputStream = jarFile.getInputStream
+ (new JarEntry(FileUtils.trimJarEntry(suiteIconPath)));
+ installInfo.setIconInputStream(iconInputStream);
+ installInfo.setIconPath(suiteIconPath);
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Getting InputStream for icon failed", ioe);
+ }
+ }
+ }
+
+ // Ask user confirmation.
+ boolean userConfirmation = true;
+ try
+ {
+ if (ball.getInstallerUi() != null)
+ {
+ userConfirmation = ball.getInstallerUi().confirm(installInfo);
+ }
+ }
+ catch (Throwable t)
+ {
+ InstallerException.internalError(
+ "Exception from InstallerUi.confirm: " + t, t);
+ userConfirmation = false;
+ }
+
+ if (!userConfirmation)
+ {
+ ball.cancel();
+ }
+ ball.iUserConfirmation = new Boolean(userConfirmation);
+
+ // Close the jarFile and iconInputStream.
+ if (jarFile != null)
+ {
+ try
+ {
+ jarFile.close(); // Closes also input stream
+ jarFile = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing icon InputStream failed", ioe);
+ }
+ }
+
+ // Now that user has answered to confirmation dialog, take into
+ // use user selections: driveId and retainData.
+ int oldInstallationDrive = ball.iInstallationDrive;
+ ball.iInstallationDrive = installInfo.getDriveId();
+ if (ball.iUpgradeData == null)
+ {
+ // Get RetainData flag.
+ ball.iUpgradeData = installInfo.getRetainData();
+ }
+ Log.log("UserConfirmation: " + ball.iUserConfirmation);
+ Log.log("InstallationDrive: " + ball.iInstallationDrive);
+ Log.log("UpgradeData: " + ball.iUpgradeData);
+ if (oldInstallationDrive != ball.iInstallationDrive)
+ {
+ try
+ {
+ // Save user selection.
+ SysUtil.setRepositoryStringValue(
+ SysUtil.REPO_ID_JAVA_INST_VARIATION,
+ SysUtil.REPO_KEY_JAVA_INST_DEF_INST_DRIVE,
+ FileUtils.getDriveName(ball.iInstallationDrive));
+ Log.log("Updated user chosen drive to repository: " +
+ ball.iInstallationDrive);
+ }
+ catch (Throwable t)
+ {
+ Log.log("Updating user chosen drive to repository failed", t);
+ }
+ }
+
+ // Log all suite info.
+ //ball.log(ball.iSuite.toString());
+ }
+
+ public void cancel(ExeBall aBall)
+ {
+ // nop
+ }
+
+ /**
+ * Get ApplicationInfos to be passed to InstallerUi.
+ */
+ protected static ApplicationInfo[] getApplicationInfos(InstallBall aBall)
+ {
+ Vector appInfos = aBall.iSuite.getApplications();
+ ApplicationInfo[] result = null;
+ if (appInfos != null)
+ {
+ result = new ApplicationInfo[appInfos.size()];
+ for (int i = 0; i < result.length; i++)
+ {
+ com.nokia.mj.impl.installer.storagehandler.ApplicationInfo
+ appInfo =
+ (com.nokia.mj.impl.installer.storagehandler.ApplicationInfo)
+ appInfos.elementAt(i);
+ // Use localized application names if defined
+ String attrName = "Nokia-MIDlet-Localized-" + (i + 1);
+ String midletName = aBall.getAttributeValue(attrName);
+ if (midletName == null)
+ {
+ midletName = appInfo.getName();
+ }
+ result[i] = new ApplicationInfo(appInfo.getUid(),
+ midletName,
+ appInfo.getIconPath());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks from certificate signers if the application private data
+ * needs to be retained during application upgrade.
+ */
+ private void checkSameSignerForUpgradeData(InstallBall aBall,
+ SigningCertificate[] aOldCerts,
+ SigningCertificate[] aNewCerts)
+ {
+ if (aBall.iUpgradeData != null)
+ {
+ // iUpgradeData flag has already been set.
+ return;
+ }
+ if (aOldCerts == null && aNewCerts != null)
+ {
+ // Old and new suites have different signers, do not set
+ // iUpgradeData flag.
+ return;
+ }
+ if (aOldCerts != null && aNewCerts != null)
+ {
+ for (int i = 0;
+ i < aOldCerts.length && aBall.iUpgradeData == null;
+ i++)
+ {
+ for (int j = 0;
+ j < aNewCerts.length && aBall.iUpgradeData == null;
+ j++)
+ {
+ if (aOldCerts[i].isSameSigner(aNewCerts[j]))
+ {
+ // Old and new suites have the same signer
+ // so data must be retained.
+ Log.log("Retain user data, same signer for old and new suite: " +
+ aNewCerts[j].getOrganization());
+ aBall.iUpgradeData = new Boolean(true);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks from jad and jar urls if the application private data
+ * needs to be retained during application upgrade.
+ */
+ private void checkUrlsForUpgradeData(InstallBall aBall)
+ {
+ if (aBall.iUpgradeData != null)
+ {
+ // iUpgradeData flag has already been set.
+ return;
+ }
+ if (aBall.iOldSuite != null)
+ {
+ checkUrlsForUpgradeData(aBall,
+ aBall.iOldSuite.getJadUrl(),
+ aBall.iJadUrl);
+ checkUrlsForUpgradeData(aBall,
+ aBall.iOldSuite.getJarUrl(),
+ aBall.iJarUrl);
+ }
+ }
+
+ /**
+ * Checks from given urls if the application private data
+ * needs to be retained during application upgrade.
+ */
+ private void checkUrlsForUpgradeData
+ (InstallBall aBall, String aOldUrl, String aNewUrl)
+ {
+ if (aBall.iUpgradeData == null)
+ {
+ // Upgrade data selection has not been made yet,
+ // check from given urls.
+ if (aOldUrl != null && aNewUrl != null && aOldUrl.equals(aNewUrl))
+ {
+ // Old and new urls are identical so data must be retained.
+ Log.log("Retain user data, same url for old and new suite: " +
+ aNewUrl);
+ aBall.iUpgradeData = new Boolean(true);
+ }
+ }
+ }
+
+ /**
+ * Get long type Jad/Manifest attribute value, or -1 if attribute
+ * is not found.
+ */
+ private long getAttributeLongValue(InstallBall aBall, String aAttrName)
+ {
+ String attrValue = aBall.getAttributeValue(aAttrName);
+ long size = -1;
+ if (attrValue != null)
+ {
+ try
+ {
+ size = Long.parseLong(attrValue);
+ }
+ catch (NumberFormatException nfe)
+ {
+ Log.logWarning("Parsing " + aAttrName + " value " +
+ attrValue + " failed", nfe);
+ }
+ }
+ return size;
+ }
+}