--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javamanager/javainstaller/installer/javasrc/com/nokia/mj/impl/installer/midp2/install/steps/PrepareSplashScreen.java Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,440 @@
+/*
+* 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.exetable.ExeBall;
+import com.nokia.mj.impl.installer.exetable.ExeStep;
+import com.nokia.mj.impl.installer.integrityservice.IntegrityService;
+import com.nokia.mj.impl.installer.utils.FileUtils;
+import com.nokia.mj.impl.installer.utils.Log;
+import com.nokia.mj.impl.installer.utils.SysUtil;
+import com.nokia.mj.impl.utils.Tokenizer;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.jar.JarFile;
+import java.util.jar.JarEntry;
+
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Installation step PrepareSplashScreen prepares splash
+ * screen images from MIDlet-Splash-Screen-Image attribute.
+ */
+public class PrepareSplashScreen extends ExeStep
+{
+ public void execute(ExeBall aBall)
+ {
+ InstallBall ball = (InstallBall)aBall;
+
+ String userImageRoot = ball.iSuite.getRootDir() +
+ "startupimages" + FileUtils.pathSeparator();
+ if (!deleteSplashScreenDir(ball, userImageRoot))
+ {
+ // Deleting splash screen directory failed,
+ // do not process splash screen images.
+ return;
+ }
+
+ String autoImageRoot = ball.iSuite.getRootDir() +
+ "autostartupimages" + FileUtils.pathSeparator();
+ if (!deleteSplashScreenDir(ball, autoImageRoot))
+ {
+ // Deleting screenshots directory failed,
+ // do not process splash screen images.
+ return;
+ }
+
+ if (ball.iJarFilename == null)
+ {
+ // No jar file available, do not proceed further.
+ return;
+ }
+
+ String attrName = "MIDlet-Splash-Screen-Image";
+ String attrValue = ball.getAttributeValue(attrName);
+ if (attrValue != null && attrValue.length() > 0)
+ {
+ if (attrValue.equalsIgnoreCase("suppress"))
+ {
+ // Splash screen is suppressed, do not
+ // process splash screen images.
+ Log.log("Splash screen suppressed");
+ // Create splash screen directory to indicate
+ // that splash screen has been suppressed.
+ createSplashScreenDir(ball, userImageRoot);
+ return;
+ }
+
+ // Get the screen size for portrait and landscape.
+ int screenWidth = SysUtil.getScreenWidth();
+ int screenHeight = SysUtil.getScreenHeight();
+ Point portraitScreenSize = new Point(screenWidth, screenHeight);
+ Point landscapeScreenSize = new Point(screenHeight, screenWidth);
+ if (screenWidth > screenHeight)
+ {
+ portraitScreenSize.x = screenHeight;
+ portraitScreenSize.y = screenWidth;
+ landscapeScreenSize.x = screenWidth;
+ landscapeScreenSize.y = screenHeight;
+ }
+ Log.log("Portrait screen size: " + portraitScreenSize);
+ Log.log("Landscape screen size: " + landscapeScreenSize);
+ // Get the sizes of all images specified in the attribute value.
+ ImageData[] currentImage = null;
+ String[] tokens = Tokenizer.split(attrValue, ",");
+ Point[] imageSizes = new Point[tokens.length];
+ for (int i = 0; i < tokens.length; i++)
+ {
+ tokens[i] = tokens[i].trim();
+ currentImage = loadImage(tokens[i], ball.iJarFilename);
+ if (currentImage == null)
+ {
+ // Image loading failed, proceed to the next image.
+ imageSizes[i] = new Point(0, 0);
+ continue;
+ }
+ imageSizes[i] = new Point(
+ currentImage[0].width, currentImage[0].height);
+ }
+ // Choose the images which best fill the portrait and
+ // landscape screens.
+ String portraitImageName = null;
+ String landscapeImageName = null;
+ int imageIndex = selectImage(portraitScreenSize, imageSizes);
+ if (imageIndex != -1)
+ {
+ portraitImageName = tokens[imageIndex];
+ Log.log("Selected portrait image " + imageIndex +
+ ": " + portraitImageName);
+ }
+ imageIndex = selectImage(landscapeScreenSize, imageSizes);
+ if (imageIndex != -1)
+ {
+ landscapeImageName = tokens[imageIndex];
+ Log.log("Selected landscape image " + imageIndex +
+ ": " + landscapeImageName);
+ }
+
+ // Save splash screen image to the disk.
+ if (portraitImageName != null &&
+ landscapeImageName != null &&
+ !portraitImageName.equals(landscapeImageName))
+ {
+ // Save portrait and landscape splash screen images.
+ createSplashScreenDir(ball, userImageRoot);
+ saveImage(portraitImageName, ball.iJarFilename,
+ userImageRoot + "startupscreen_portrait",
+ ball.iIntegrityService);
+ saveImage(landscapeImageName, ball.iJarFilename,
+ userImageRoot + "startupscreen_landscape",
+ ball.iIntegrityService);
+ }
+ else if (portraitImageName != null)
+ {
+ // Save one splash screen image.
+ createSplashScreenDir(ball, userImageRoot);
+ saveImage(portraitImageName, ball.iJarFilename,
+ userImageRoot + "startupscreen",
+ ball.iIntegrityService);
+ }
+ else if (landscapeImageName != null)
+ {
+ // Save one splash screen image.
+ createSplashScreenDir(ball, userImageRoot);
+ saveImage(landscapeImageName, ball.iJarFilename,
+ userImageRoot + "startupscreen",
+ ball.iIntegrityService);
+ }
+ else
+ {
+ Log.logWarning("No splash screen image selected.");
+ }
+ }
+ else
+ {
+ createSplashScreenDir(ball, autoImageRoot);
+ }
+ }
+
+ public void cancel(ExeBall aBall)
+ {
+ // nop
+ }
+
+ /**
+ * Deletes splash screen image directory if it exists.
+ *
+ * @return true if directory does not exist after this method returns,
+ * false if deleting existing directory fails
+ */
+ private static boolean deleteSplashScreenDir(
+ InstallBall aBall, String aImageRoot)
+ {
+ boolean result = true;
+ if (aBall.iOldSuite != null)
+ {
+ // Note that PrepareSplashScreen step is executed after
+ // CopyAppFiles step, which means that old image root has
+ // already been moved under new application suite root.
+ if (FileUtils.exists(aImageRoot))
+ {
+ // In case of update, remove old splash screen images.
+ result = aBall.iIntegrityService.delete(aImageRoot);
+ if (!result)
+ {
+ Log.logWarning("Removing " + aImageRoot +
+ " failed, aborting splash screen" +
+ " image preparation.");
+ return result;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates splash screen image directory.
+ *
+ * @return true if directory exists after this method returns,
+ * false if creating directory fails
+ */
+ private static boolean createSplashScreenDir(
+ InstallBall aBall, String aImageRoot)
+ {
+ boolean result = true;
+ if (!FileUtils.exists(aImageRoot))
+ {
+ result = aBall.iIntegrityService.createDir(aImageRoot);
+ if (!result)
+ {
+ Log.logWarning("Creating " + aImageRoot +
+ " failed, aborting splash screen" +
+ " image preparation.");
+ return result;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Loads image from specified resource from given jar file.
+ *
+ * @param aResource resource file name
+ * @param aJar jar file name
+ * @return loaded image, or null if image loading fails
+ */
+ private static ImageData[] loadImage(String aResource, String aJar)
+ {
+ ImageData[] result = null;
+ JarFile jarFile = null;
+ InputStream is = null;
+ try
+ {
+ // Open jar file and input stream.
+ jarFile = new JarFile(aJar);
+ is = jarFile.getInputStream
+ (new JarEntry(FileUtils.trimJarEntry(aResource)));
+ if (is != null)
+ {
+ result = (new ImageLoader()).load(is);
+ Log.log("Loaded image " + aResource + " from " + aJar);
+ }
+ else
+ {
+ Log.logWarning("Image " + aResource + " not found from " + aJar);
+ }
+ }
+ catch (Throwable t)
+ {
+ Log.logWarning("Loading image " + aResource + " from " +
+ aJar + " failed", t);
+ }
+ finally
+ {
+ // Close streams and jar file.
+ if (is != null)
+ {
+ try
+ {
+ is.close();
+ is = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing InputStream failed", ioe);
+ }
+ }
+ if (jarFile != null)
+ {
+ try
+ {
+ jarFile.close();
+ jarFile = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing " + aJar + " failed", ioe);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Save image from specified resource from given jar file to disk.
+ *
+ * @param aResource resource file name
+ * @param aJar jar file name
+ * @param aFilename filename for the image (without extension)
+ * @param aIs IntegrityService instance to be used in file creation
+ */
+ private static void saveImage(
+ String aResource, String aJar, String aFilename, IntegrityService aIs)
+ {
+ JarFile jarFile = null;
+ InputStream is = null;
+ OutputStream os = null;
+ String imageFilename = aFilename + ".img";
+ try
+ {
+ // Open jar file and input and output streams.
+ jarFile = new JarFile(aJar);
+ is = jarFile.getInputStream
+ (new JarEntry(FileUtils.trimJarEntry(aResource)));
+ os = FileUtils.getOutputStream(imageFilename);
+ // Copy the image data from InputStream to OutputStream.
+ byte[] buf = new byte[16384];
+ int i = 0;
+ while ((i = is.read(buf)) != -1)
+ {
+ os.write(buf, 0, i);
+ }
+ // Record file creation to integrityService.
+ aIs.create(imageFilename);
+ Log.log("Saved image to " + imageFilename);
+ }
+ catch (Throwable t)
+ {
+ Log.logWarning("Saving image " + aResource + " from " +
+ aJar + " to " + imageFilename + " failed", t);
+ }
+ finally
+ {
+ // Close streams and jar file.
+ if (os != null)
+ {
+ try
+ {
+ os.close();
+ os = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing OutputStream failed", ioe);
+ }
+ }
+ if (is != null)
+ {
+ try
+ {
+ is.close();
+ is = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing InputStream failed", ioe);
+ }
+ }
+ if (jarFile != null)
+ {
+ try
+ {
+ jarFile.close();
+ jarFile = null;
+ }
+ catch (IOException ioe)
+ {
+ Log.logWarning("Closing " + aJar + " failed", ioe);
+ }
+ }
+ }
+ }
+
+ /**
+ * Selects image which best fills the given screen when image
+ * is scaled down so that it fits to the screen.
+ *
+ * @param aScreenSize screen size
+ * @param aImageSizes array of image sizes
+ * @return index to aImageSizes array for the selected image, or -1
+ * if selection could not be made
+ */
+ private static int selectImage(Point aScreenSize, Point[] aImageSizes)
+ {
+ // Amount of fill for the image which best fills
+ // the screen when scaled down to fit the screen.
+ int biggestFill = 0;
+ // Index of the image which best fills the screen.
+ int biggestFillIndex = -1;
+ for (int i = 0; i < aImageSizes.length; i++)
+ {
+ Point imageSize = aImageSizes[i];
+ if (imageSize.x > aScreenSize.x ||
+ imageSize.y > aScreenSize.y)
+ {
+ imageSize = downscaleImageSize(aScreenSize, imageSize);
+ }
+ int imageFill = imageSize.x * imageSize.y;
+ if (imageFill > biggestFill)
+ {
+ biggestFill = imageFill;
+ biggestFillIndex = i;
+ }
+ Log.log("Image " + i + " fill amount " + imageFill);
+ }
+ return biggestFillIndex;
+ }
+
+ /**
+ * Downscales the given aImageSize so that it fits to aScreenSize.
+ */
+ private static Point downscaleImageSize(Point aScreenSize, Point aImageSize)
+ {
+ Point result = new Point(aImageSize.x, aImageSize.y);
+ if (result.x > aScreenSize.x)
+ {
+ // Downscale the image width.
+ result.y = result.y * aScreenSize.x / result.x;
+ result.x = aScreenSize.x;
+ }
+ if (result.y > aScreenSize.y)
+ {
+ // Downscale the image height.
+ result.x = result.x * aScreenSize.y / result.y;
+ result.y = aScreenSize.y;
+ }
+ Log.log("Image size " + aImageSize + " scaled down to " +
+ result + " for screen size " + aScreenSize);
+ return result;
+ }
+}