javamanager/javainstaller/installer/javasrc/com/nokia/mj/impl/installer/midp2/install/steps/ConfirmInstallation.java
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package com.nokia.mj.impl.installer.midp2.install.steps;
       
    20 
       
    21 import com.nokia.mj.impl.installer.customisationproperties.CustomisationProperties;
       
    22 import com.nokia.mj.impl.installer.exetable.ExeBall;
       
    23 import com.nokia.mj.impl.installer.exetable.ExeStep;
       
    24 import com.nokia.mj.impl.installer.ui.ApplicationInfo;
       
    25 import com.nokia.mj.impl.installer.ui.InstallInfo;
       
    26 import com.nokia.mj.impl.installer.utils.DriveInfo;
       
    27 import com.nokia.mj.impl.installer.utils.FileUtils;
       
    28 import com.nokia.mj.impl.installer.utils.InstallerException;
       
    29 import com.nokia.mj.impl.installer.utils.Log;
       
    30 import com.nokia.mj.impl.installer.utils.Platform;
       
    31 import com.nokia.mj.impl.installer.utils.SysUtil;
       
    32 import com.nokia.mj.impl.security.midp.common.SigningCertificate;
       
    33 import com.nokia.mj.impl.security.midp.authentication.AuthenticationModule;
       
    34 
       
    35 import java.io.InputStream;
       
    36 import java.io.IOException;
       
    37 import java.util.Vector;
       
    38 import java.util.jar.JarFile;
       
    39 import java.util.jar.JarEntry;
       
    40 
       
    41 /**
       
    42  * ConfirmInstallation shows installation confirmation dialog to user.
       
    43  *
       
    44  * @author Nokia Corporation
       
    45  * @version $Rev:  $ $Date:  $
       
    46  */
       
    47 public class ConfirmInstallation extends ExeStep
       
    48 {
       
    49     public void execute(ExeBall aBall)
       
    50     {
       
    51         InstallBall ball = (InstallBall)aBall;
       
    52 
       
    53         // Get possible certificates for the application.
       
    54         SigningCertificate[] certs = AuthenticationModule.getInstance()
       
    55                                      .getCertificatesDetails(ball.iStorageHandler.getSession(),
       
    56                                                              ball.iSuite.getUid());
       
    57         if (certs != null)
       
    58         {
       
    59             Log.log("Possible certificates for this application:");
       
    60             for (int i = 0; i < certs.length; i++)
       
    61             {
       
    62                 Log.log("Certificate[" + i + "]:\n" + certs[i]);
       
    63             }
       
    64         }
       
    65         // Check if RMS data should be retained in case of an
       
    66         // upgrade as specified in MIDP 2.1 spec chapter
       
    67         // 2.1.5 "MIDlet Suite Update".
       
    68         if (ball.iOldSuite != null)
       
    69         {
       
    70             // Check from signer if private data should
       
    71             // be retained in application upgrade.
       
    72             checkSameSignerForUpgradeData(ball, ball.iOldCertificates, certs);
       
    73             // Check from jad and jar urls if private data should
       
    74             // be retained in application upgrade.
       
    75             checkUrlsForUpgradeData(ball);
       
    76         }
       
    77 
       
    78         if (ball.isSilent() || Platform.isLinux())
       
    79         {
       
    80             // Silent installation, assume positive answer from user.
       
    81             // Linux does not have UI, assume positive answer from user.
       
    82             ball.iUserConfirmation = new Boolean(true);
       
    83             return;
       
    84         }
       
    85 
       
    86         // Collect all the info needed in confirmation dialog,
       
    87         // display it to user and based on user response
       
    88         // initialise ball.iUserConfirmation and other data.
       
    89         // Use localized suite name if it exists
       
    90         String suiteName = ball.getAttributeValue("Nokia-MIDlet-Localized-Name");
       
    91         if (suiteName == null)
       
    92         {
       
    93             suiteName = ball.iSuite.getName();
       
    94         }
       
    95         InstallInfo installInfo = new InstallInfo(ball.iSuite.getUid(),
       
    96                 suiteName, ball.iSuite.getVendor(),
       
    97                 ball.iSuite.getVersion().toString());
       
    98 
       
    99         // In case of an update, set old suite version.
       
   100         if (ball.iOldSuite != null)
       
   101         {
       
   102             installInfo.setOldVersion(ball.iOldSuite.getVersion().toString());
       
   103         }
       
   104 
       
   105         // Set Jar size and data size from Jad/Manifest attributes.
       
   106         installInfo.setJarSize(getAttributeLongValue(ball, "MIDlet-Jar-Size"));
       
   107         installInfo.setDataSize(getAttributeLongValue(ball, "MIDlet-Data-Size"));
       
   108         if (installInfo.getJarSize() <= 0 &&
       
   109                 ball.iJarFilename != null && ball.iDownloader == null)
       
   110         {
       
   111             // Get jar file size.
       
   112             installInfo.setJarSize(FileUtils.getSize(ball.iJarFilename));
       
   113         }
       
   114 
       
   115         // Set certificates.
       
   116         installInfo.setCertificates(certs);
       
   117 
       
   118         // Set ApplicationInfos.
       
   119         installInfo.setApplications(getApplicationInfos(ball));
       
   120 
       
   121         // Set RetainData flag if this is an application update and
       
   122         // retain user data decision has not been made yet.
       
   123         if (ball.iOldSuite != null && ball.iUpgradeData == null)
       
   124         {
       
   125             installInfo.setRetainData(true);
       
   126         }
       
   127 
       
   128         // Set installation drive.
       
   129         installInfo.setDriveId(ball.iInstallationDrive);
       
   130         Vector drives = new Vector();
       
   131         SysUtil.getUserVisibleDrives(drives);
       
   132         int[] driveIds = new int[drives.size()];
       
   133         int[] driveTypes = new int[drives.size()];
       
   134         long[] driveFreeSpaces = new long[drives.size()];
       
   135         for (int i = 0; i < drives.size(); i++)
       
   136         {
       
   137             DriveInfo driveInfo = (DriveInfo)drives.elementAt(i);
       
   138             // Note that this trusts that DriveInfo constant values
       
   139             // are identical to drive type constants in InstallInfo.
       
   140             driveIds[i] = driveInfo.getNumber();
       
   141             driveTypes[i] = driveInfo.getDriveType();
       
   142             driveFreeSpaces[i] = driveInfo.getFreeSpace();
       
   143         }
       
   144         installInfo.setDriveIdsTypes(driveIds, driveTypes);
       
   145         installInfo.setDriveFreeSpaces(driveFreeSpaces);
       
   146 
       
   147         // Set icon paths.
       
   148         JarFile jarFile = null;
       
   149         InputStream iconInputStream = null;
       
   150         if (ball.iJarFilename != null && ball.iDownloader == null)
       
   151         {
       
   152             // We have jar filename and are not downloading it,
       
   153             // so jar file must be available.
       
   154             // Get icon InputStream for correct icon in jar file.
       
   155             String suiteIconPath = ball.iSuite.getAttributeValue("MIDlet-Icon");
       
   156             if (suiteIconPath == null)
       
   157             {
       
   158                 suiteIconPath = ball.iSuite.getFirstIconPath();
       
   159             }
       
   160             Log.log("SuiteIconPath for the UI resource: " + suiteIconPath);
       
   161             if (suiteIconPath != null)
       
   162             {
       
   163                 try
       
   164                 {
       
   165                     jarFile = new JarFile(ball.iJarFilename);
       
   166                     iconInputStream = jarFile.getInputStream
       
   167                                       (new JarEntry(FileUtils.trimJarEntry(suiteIconPath)));
       
   168                     installInfo.setIconInputStream(iconInputStream);
       
   169                     installInfo.setIconPath(suiteIconPath);
       
   170                 }
       
   171                 catch (IOException ioe)
       
   172                 {
       
   173                     Log.logWarning("Getting InputStream for icon failed", ioe);
       
   174                 }
       
   175             }
       
   176         }
       
   177 
       
   178         // Ask user confirmation.
       
   179         boolean userConfirmation = true;
       
   180         try
       
   181         {
       
   182             if (ball.getInstallerUi() != null)
       
   183             {
       
   184                 userConfirmation = ball.getInstallerUi().confirm(installInfo);
       
   185             }
       
   186         }
       
   187         catch (Throwable t)
       
   188         {
       
   189             InstallerException.internalError(
       
   190                 "Exception from InstallerUi.confirm: " + t, t);
       
   191             userConfirmation = false;
       
   192         }
       
   193 
       
   194         if (!userConfirmation)
       
   195         {
       
   196             ball.cancel();
       
   197         }
       
   198         ball.iUserConfirmation = new Boolean(userConfirmation);
       
   199 
       
   200         // Close the jarFile and iconInputStream.
       
   201         if (jarFile != null)
       
   202         {
       
   203             try
       
   204             {
       
   205                 jarFile.close(); // Closes also input stream
       
   206                 jarFile = null;
       
   207             }
       
   208             catch (IOException ioe)
       
   209             {
       
   210                 Log.logWarning("Closing icon InputStream failed", ioe);
       
   211             }
       
   212         }
       
   213 
       
   214         // Now that user has answered to confirmation dialog, take into
       
   215         // use user selections: driveId and retainData.
       
   216         int oldInstallationDrive = ball.iInstallationDrive;
       
   217         ball.iInstallationDrive = installInfo.getDriveId();
       
   218         if (ball.iUpgradeData == null)
       
   219         {
       
   220             // Get RetainData flag.
       
   221             ball.iUpgradeData = installInfo.getRetainData();
       
   222         }
       
   223         Log.log("UserConfirmation: " + ball.iUserConfirmation);
       
   224         Log.log("InstallationDrive: " + ball.iInstallationDrive);
       
   225         Log.log("UpgradeData: " + ball.iUpgradeData);
       
   226         if (oldInstallationDrive != ball.iInstallationDrive)
       
   227         {
       
   228             try
       
   229             {
       
   230                 // Save user selection.
       
   231                 SysUtil.setRepositoryStringValue(
       
   232                     SysUtil.REPO_ID_JAVA_INST_VARIATION,
       
   233                     SysUtil.REPO_KEY_JAVA_INST_DEF_INST_DRIVE,
       
   234                     FileUtils.getDriveName(ball.iInstallationDrive));
       
   235                 Log.log("Updated user chosen drive to repository: " +
       
   236                         ball.iInstallationDrive);
       
   237             }
       
   238             catch (Throwable t)
       
   239             {
       
   240                 Log.log("Updating user chosen drive to repository failed", t);
       
   241             }
       
   242         }
       
   243 
       
   244         // Log all suite info.
       
   245         //ball.log(ball.iSuite.toString());
       
   246     }
       
   247 
       
   248     public void cancel(ExeBall aBall)
       
   249     {
       
   250         // nop
       
   251     }
       
   252 
       
   253     /**
       
   254      * Get ApplicationInfos to be passed to InstallerUi.
       
   255      */
       
   256     protected static ApplicationInfo[] getApplicationInfos(InstallBall aBall)
       
   257     {
       
   258         Vector appInfos = aBall.iSuite.getApplications();
       
   259         ApplicationInfo[] result = null;
       
   260         if (appInfos != null)
       
   261         {
       
   262             result = new ApplicationInfo[appInfos.size()];
       
   263             for (int i = 0; i < result.length; i++)
       
   264             {
       
   265                 com.nokia.mj.impl.installer.storagehandler.ApplicationInfo
       
   266                 appInfo =
       
   267                     (com.nokia.mj.impl.installer.storagehandler.ApplicationInfo)
       
   268                     appInfos.elementAt(i);
       
   269                 // Use localized application names if defined
       
   270                 String attrName = "Nokia-MIDlet-Localized-" + (i + 1);
       
   271                 String midletName = aBall.getAttributeValue(attrName);
       
   272                 if (midletName == null)
       
   273                 {
       
   274                     midletName = appInfo.getName();
       
   275                 }
       
   276                 result[i] = new ApplicationInfo(appInfo.getUid(),
       
   277                                                 midletName,
       
   278                                                 appInfo.getIconPath());
       
   279             }
       
   280         }
       
   281         return result;
       
   282     }
       
   283 
       
   284     /**
       
   285      * Checks from certificate signers if the application private data
       
   286      * needs to be retained during application upgrade.
       
   287      */
       
   288     private void checkSameSignerForUpgradeData(InstallBall aBall,
       
   289             SigningCertificate[] aOldCerts,
       
   290             SigningCertificate[] aNewCerts)
       
   291     {
       
   292         if (aBall.iUpgradeData != null)
       
   293         {
       
   294             // iUpgradeData flag has already been set.
       
   295             return;
       
   296         }
       
   297         if (aOldCerts == null && aNewCerts != null)
       
   298         {
       
   299             // Old and new suites have different signers, do not set
       
   300             // iUpgradeData flag.
       
   301             return;
       
   302         }
       
   303         if (aOldCerts != null && aNewCerts != null)
       
   304         {
       
   305             for (int i = 0;
       
   306                     i < aOldCerts.length && aBall.iUpgradeData == null;
       
   307                     i++)
       
   308             {
       
   309                 for (int j = 0;
       
   310                         j < aNewCerts.length && aBall.iUpgradeData == null;
       
   311                         j++)
       
   312                 {
       
   313                     if (aOldCerts[i].isSameSigner(aNewCerts[j]))
       
   314                     {
       
   315                         // Old and new suites have the same signer
       
   316                         // so data must be retained.
       
   317                         Log.log("Retain user data, same signer for old and new suite: " +
       
   318                                 aNewCerts[j].getOrganization());
       
   319                         aBall.iUpgradeData = new Boolean(true);
       
   320                     }
       
   321                 }
       
   322             }
       
   323         }
       
   324     }
       
   325 
       
   326     /**
       
   327      * Checks from jad and jar urls if the application private data
       
   328      * needs to be retained during application upgrade.
       
   329      */
       
   330     private void checkUrlsForUpgradeData(InstallBall aBall)
       
   331     {
       
   332         if (aBall.iUpgradeData != null)
       
   333         {
       
   334             // iUpgradeData flag has already been set.
       
   335             return;
       
   336         }
       
   337         if (aBall.iOldSuite != null)
       
   338         {
       
   339             checkUrlsForUpgradeData(aBall,
       
   340                                     aBall.iOldSuite.getJadUrl(),
       
   341                                     aBall.iJadUrl);
       
   342             checkUrlsForUpgradeData(aBall,
       
   343                                     aBall.iOldSuite.getJarUrl(),
       
   344                                     aBall.iJarUrl);
       
   345         }
       
   346     }
       
   347 
       
   348     /**
       
   349      * Checks from given urls if the application private data
       
   350      * needs to be retained during application upgrade.
       
   351      */
       
   352     private void checkUrlsForUpgradeData
       
   353     (InstallBall aBall, String aOldUrl, String aNewUrl)
       
   354     {
       
   355         if (aBall.iUpgradeData == null)
       
   356         {
       
   357             // Upgrade data selection has not been made yet,
       
   358             // check from given urls.
       
   359             if (aOldUrl != null && aNewUrl != null && aOldUrl.equals(aNewUrl))
       
   360             {
       
   361                 // Old and new urls are identical so data must be retained.
       
   362                 Log.log("Retain user data, same url for old and new suite: " +
       
   363                         aNewUrl);
       
   364                 aBall.iUpgradeData = new Boolean(true);
       
   365             }
       
   366         }
       
   367     }
       
   368 
       
   369     /**
       
   370      * Get long type Jad/Manifest attribute value, or -1 if attribute
       
   371      * is not found.
       
   372      */
       
   373     private long getAttributeLongValue(InstallBall aBall, String aAttrName)
       
   374     {
       
   375         String attrValue = aBall.getAttributeValue(aAttrName);
       
   376         long size = -1;
       
   377         if (attrValue != null)
       
   378         {
       
   379             try
       
   380             {
       
   381                 size = Long.parseLong(attrValue);
       
   382             }
       
   383             catch (NumberFormatException nfe)
       
   384             {
       
   385                 Log.logWarning("Parsing " + aAttrName + " value " +
       
   386                                attrValue + " failed", nfe);
       
   387             }
       
   388         }
       
   389         return size;
       
   390     }
       
   391 }