javamanager/javainstaller/installer/javasrc/com/nokia/mj/impl/installer/midp2/install/steps/FinalizeInstallation.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javamanager/javainstaller/installer/javasrc/com/nokia/mj/impl/installer/midp2/install/steps/FinalizeInstallation.java Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,367 @@
+/*
+* 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.ui.ApplicationInfo;
+import com.nokia.mj.impl.installer.ui.LaunchAppInfo;
+import com.nokia.mj.impl.installer.applicationregistrator.ApplicationRegistrator;
+import com.nokia.mj.impl.installer.captainservice.CaptainService;
+import com.nokia.mj.impl.installer.exetable.ExeBall;
+import com.nokia.mj.impl.installer.exetable.ExeStep;
+import com.nokia.mj.impl.installer.Installer;
+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.utils.Uid;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.jar.JarFile;
+import java.util.jar.JarEntry;
+
+public class FinalizeInstallation extends ExeStep
+{
+ // JarFile instance, used for getting icon InputStreams.
+ private JarFile iJarFile = null;
+
+ public void execute(ExeBall aBall)
+ {
+ InstallBall ball = (InstallBall)aBall;
+ ball.log("Finalizing installation...");
+
+ // If posting OTA status notifications is still going on,
+ // stop it now and continue when next installation is made.
+ ball.getNotificationPoster().stop();
+
+ // Cleanup security components.
+ ball.cleanupSecurity();
+
+ // If -forcecancel option was specified, abort execution
+ // before committing anything.
+ if (ball.iArgs.get("forcecancel") != null)
+ {
+ InstallerException.internalError("FORCED CANCEL");
+ }
+
+ // User is not allowed to cancel installation after this step.
+ ball.setCanCancel(false);
+
+ checkWaitAttribute(ball, "before storage commit");
+
+ // StorageHandler must be committed before ApplicationRegistrator
+ // so that platform specific application registry can use the data
+ // in Java Storage (S60 AppArc application list re-scan)
+ ball.iStorageHandler.commitSession();
+
+ // StorageHandler commit is asynchronous. In case of
+ // conversion installation or preinstallation wait for
+ // a while so that the commit can be done before the
+ // application registrator commit causes accesses to
+ // Storage (S60 AppArc application list re-scan)
+ if (ball.iConversionInstallation ||
+ ball.iPreinstallation)
+ {
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException ie)
+ { }
+ }
+
+ Log.log("StorageHandler committed");
+
+ checkWaitAttribute(ball, "after storage commit");
+
+ ball.iSifRegistrator.commitSession();
+ Log.log("SifRegistrator committed");
+
+ checkWaitAttribute(ball, "after sif commit");
+
+ // ApplicationRegistrator session must be commited before
+ // IntegrityService session so that temp icon files
+ // can be removed.
+ // Make synchronous commit so that the application
+ // becomes visible to all parts of the system before
+ // installer finishes.
+ ball.iApplicationRegistrator.commitSession(true);
+
+ Log.log("ApplicationRegistrator committed");
+
+ checkWaitAttribute(ball, "after apparc commit");
+
+ boolean result = ball.iIntegrityService.commit();
+ if (!result)
+ {
+ InstallerException.internalError("IntegrityService commit failed");
+ }
+ Log.log("IntegrityService committed");
+
+ checkWaitAttribute(ball, "after integrityservice commit");
+
+ ball.iInstallationNotifier.finish(
+ ball.iSuite.getUid(), ball.iInstallationNotifier.INSTALL_OK);
+
+ // All sessions have been committed, do not throw
+ // exceptions anymore after this point!
+
+ Uid[] uids = ball.iSuite.getApplicationUids();
+
+ try
+ {
+ // Notify platform that applications have been added or updated.
+ ball.iSifRegistrator.notifyAppChange(
+ uids, (ball.iOldSuite != null?
+ ball.iSifRegistrator.APP_UPDATED:
+ ball.iSifRegistrator.APP_ADDED));
+ }
+ catch (Throwable t)
+ {
+ Log.logError("SifRegistrator.notifyAppChange failed", t);
+ }
+
+ if (ball.iCaptainMsgs)
+ {
+ // Notify JavaCaptain that application has been installed.
+ Uid[] oldUids = null;
+ if (ball.iOldSuite != null)
+ {
+ oldUids = ball.iOldSuite.getApplicationUids();
+ }
+ ball.getCaptainService().appUpdated(oldUids, uids);
+ Log.log("JavaCaptain notified");
+ }
+
+ String midletName = ball.getAttributeValue("MIDlet-Name");
+ ball.log("Application " + midletName + " successfully installed.");
+ ball.log(ball.iSuite.toShortString());
+
+ // Store the uids to Installer static variable
+ // in case CommsInstaller has to send them to
+ // TCK Runner or preinstaller
+ Installer.setInstalledUids(ball.iSuite.getUid(), uids);
+
+ if (!ball.isSilent())
+ {
+ if (ball.getInstallerUi() != null && Platform.isS60())
+ {
+ if (ball.LAUNCH_APP_QUERY)
+ {
+ // Set installation progress to 100% before
+ // displaying application launch query.
+ ball.iInstallationNotifier.set(
+ ball.iInstallationNotifier.getMax());
+ // Display launch application query to the user.
+ createLaunchAppQueryThread(ball);
+ }
+ }
+ if (Platform.isLinux() && ball.iCaptainMsgs)
+ {
+ // Launch the installed application
+ try
+ {
+ // CaptainService.launchApp() uses RLC message.
+ //ball.getCaptainService().launchApp(uids[0]);
+ // CaptainService.startApp() uses installer specific
+ // message.
+ ball.getCaptainService().startApp(new Uid[] { uids[0] });
+ }
+ catch (InstallerException ie)
+ {
+ Log.log("Launching application failed: " + ie.toString());
+ }
+ }
+ }
+ }
+
+ public void cancel(ExeBall aBall)
+ {
+ // nop
+ }
+
+ /**
+ * Constructs a new LaunchAppInfo object basing on given InstallBall.
+ */
+ private LaunchAppInfo createLaunchAppInfo(InstallBall aBall)
+ {
+ // Get suite icon InputStream.
+ InputStream suiteIconInputStream = null;
+ String suiteIconPath = aBall.iSuite.getAttributeValue("MIDlet-Icon");
+ if (suiteIconPath != null)
+ {
+ try
+ {
+ if (iJarFile == null)
+ {
+ // Temp files have already been deleted,
+ // get the icon from installed jar file.
+ iJarFile = new JarFile(aBall.iSuite.getJarPath());
+ }
+ suiteIconInputStream =
+ iJarFile.getInputStream
+ (new JarEntry(FileUtils.trimJarEntry(suiteIconPath)));
+ Log.log("LaunchAppInfo: suite icon " + suiteIconPath);
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Getting InputStream for suite icon failed", ioe);
+ }
+ }
+
+ // Get application icon InputStreams.
+ InputStream[] appIconInputStreams = null;
+ Vector appInfos = aBall.iSuite.getApplications();
+ if (appInfos != null)
+ {
+ appIconInputStreams = new InputStream[appInfos.size()];
+ try
+ {
+ if (iJarFile == null)
+ {
+ // Temp files have already been deleted,
+ // get the icon from installed jar file.
+ iJarFile = new JarFile(aBall.iSuite.getJarPath());
+ }
+ for (int i = 0; i < appIconInputStreams.length; i++)
+ {
+ String iconPath =
+ ((com.nokia.mj.impl.installer.storagehandler.ApplicationInfo)
+ appInfos.elementAt(i)).getIconPath();
+ if (iconPath != null && iconPath.length() > 0)
+ {
+ appIconInputStreams[i] =
+ iJarFile.getInputStream
+ (new JarEntry(FileUtils.trimJarEntry(iconPath)));
+ Log.log("LaunchAppInfo: app icon " + i + ": " + iconPath);
+ }
+ else
+ {
+ appIconInputStreams[i] = null;
+ Log.log("LaunchAppInfo: app icon " + i + ": null");
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Getting InputStream for application icon failed", ioe);
+ }
+ }
+
+ return new LaunchAppInfo
+ (ConfirmInstallation.getApplicationInfos(aBall),
+ appIconInputStreams, suiteIconInputStream, suiteIconPath);
+ }
+
+ /**
+ * Creates and starts a new thread for asking launch
+ * application query from the user.
+ */
+ private void createLaunchAppQueryThread(InstallBall aBall)
+ {
+ final InstallBall ball = aBall;
+ ball.iDialogOpen = true;
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ // Create and init LaunchAppinfo object.
+ LaunchAppInfo launchAppInfo = createLaunchAppInfo(ball);
+ // Display the query.
+ boolean launchApp =
+ ball.getInstallerUi().launchAppQuery(launchAppInfo);
+
+ // Close the jarFile and icon InputStreams.
+ if (iJarFile != null)
+ {
+ try
+ {
+ iJarFile.close(); // Closes also InputStreams
+ iJarFile = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing icon InputStreams failed", ioe);
+ }
+ }
+
+ //if (ball.iSifRegistrator.getSifMode() > 0 && launchApp)
+ //{
+ // ball.iSifRegistrator.launchAppView();
+ //}
+ //else
+ if (ball.iCaptainMsgs && launchApp &&
+ launchAppInfo.getApplications() != null &&
+ launchAppInfo.getApplications().length > 0)
+ {
+ int selection = launchAppInfo.getSelection();
+ Log.log("Launching application " + selection + ": " +
+ launchAppInfo.getApplications()[selection]
+ .getName());
+ ball.getCaptainService().startApp
+ (new Uid[] { launchAppInfo
+ .getApplications()[selection]
+ .getUid()
+ });
+ }
+ else
+ {
+ Log.log("No application launch");
+ }
+
+ synchronized (ball)
+ {
+ ball.iDialogOpen = false;
+ // Notify WaitForLaunchAppQuery step that
+ // we are finished with launch app query.
+ ball.notify();
+ }
+ }
+ }, "LaunchAppQueryThread").start();
+ }
+
+ /**
+ * Wait a moment if Nokia-MIDlet-Install-Commit-Wait atribute has been set.
+ */
+ private static void checkWaitAttribute(InstallBall aBall, String aWaitMsg)
+ {
+ String commitWaitEnabled = System.getProperty(
+ "com.nokia.mj.impl.installer.commitwaitenabled");
+ if (commitWaitEnabled != null &&
+ commitWaitEnabled.equalsIgnoreCase("true"))
+ {
+ Log.log("commitWaitEnabled: " + commitWaitEnabled);
+ String waitValue = aBall.getAttributeValue(
+ "Nokia-MIDlet-Install-Commit-Wait");
+ if (waitValue != null && waitValue.equalsIgnoreCase(aWaitMsg))
+ {
+ try
+ {
+ int waitTime = 30; // secs
+ Log.log("Waiting " + waitTime + " secs " + aWaitMsg);
+ Thread.sleep(waitTime * 1000);
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ }
+ }
+ }
+}