|
1 /* |
|
2 * Copyright (c) 2008-2009 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.exetable.ExeBall; |
|
22 import com.nokia.mj.impl.installer.exetable.ExeStep; |
|
23 import com.nokia.mj.impl.installer.utils.DriveInfo; |
|
24 import com.nokia.mj.impl.installer.utils.FileUtils; |
|
25 import com.nokia.mj.impl.installer.utils.InstallerException; |
|
26 import com.nokia.mj.impl.installer.utils.Log; |
|
27 import com.nokia.mj.impl.installer.utils.Platform; |
|
28 import com.nokia.mj.impl.installer.utils.SysUtil; |
|
29 import com.nokia.mj.impl.utils.InstallerDetailedErrorMessage; |
|
30 import com.nokia.mj.impl.utils.InstallerErrorMessage; |
|
31 import com.nokia.mj.impl.utils.OtaStatusCode; |
|
32 |
|
33 import java.util.Vector; |
|
34 |
|
35 /** |
|
36 * Checks available disk space and chooses the default installation drive. |
|
37 * This step is called twice: before installation confirmation dialog is |
|
38 * displayed to user and after the user has answered to the dialog. |
|
39 */ |
|
40 public class CheckDiskSpace extends ExeStep |
|
41 { |
|
42 public void execute(ExeBall aBall) |
|
43 { |
|
44 InstallBall ball = (InstallBall)aBall; |
|
45 |
|
46 int initialSize = ball.iSuite.calculateInitialSize(); |
|
47 if (initialSize == 0 && ball.iJarFilename != null) |
|
48 { |
|
49 // Get initialSize from jar file size. |
|
50 initialSize = (int)FileUtils.getSize(ball.iJarFilename); |
|
51 |
|
52 } |
|
53 int requiredSize = initialSize + (100 * 1024); // +100kB |
|
54 |
|
55 if (ball.iUserConfirmation == null) |
|
56 { |
|
57 // Before installation confirmation dialog is displayed, |
|
58 // choose the default installation drive. |
|
59 // Do not change the already selected installation drive |
|
60 // in case of preinstallation or if the -drive option |
|
61 // has been specified from command line. |
|
62 if (!ball.iPreinstallation && |
|
63 ball.iArgs.get("drive") == null && |
|
64 !Platform.isLinux()) |
|
65 { |
|
66 Log.log("Choosing default installation drive"); |
|
67 Vector drives = new Vector(); |
|
68 SysUtil.getUserVisibleDrives(drives); |
|
69 if (ball.iOldSuite == null || |
|
70 !SysUtil.isDrivePresent(ball.iInstallationDrive)) |
|
71 { |
|
72 // Either this is a new installation, or this is an |
|
73 // update but the old installation drive is not present, |
|
74 // so choose the default installation drive. |
|
75 ball.iInstallationDrive = getDefaultInstallationDrive( |
|
76 drives, requiredSize); |
|
77 } |
|
78 } |
|
79 } |
|
80 else |
|
81 { |
|
82 Log.log("Checking available disk space from drive " + |
|
83 ball.iInstallationDrive); |
|
84 // After user has selected installation drive, check |
|
85 // free space from user selected drive. |
|
86 checkFreeSpace(requiredSize, ball.iInstallationDrive); |
|
87 // Update paths in the suite info to point to |
|
88 // user selected installation drive. |
|
89 FileUtils.setAppsRoot(ball.iInstallationDrive); |
|
90 updateSuitePaths(ball); |
|
91 ball.iSuite.setMediaId(SysUtil.getDriveUniqId |
|
92 (ball.iInstallationDrive)); |
|
93 } |
|
94 |
|
95 // Add initial size to suite. |
|
96 ball.iSuite.setInitialSize(initialSize); |
|
97 } |
|
98 |
|
99 public void cancel(ExeBall aBall) |
|
100 { |
|
101 // nop |
|
102 } |
|
103 |
|
104 /** |
|
105 * Checks if given drive has enough free disk space. Throws |
|
106 * InstallerException if there is not enough free disk space. |
|
107 */ |
|
108 private static void checkFreeSpace(int aSizeInBytes, int aDrive) |
|
109 { |
|
110 if (SysUtil.isDiskSpaceBelowCriticalLevel(aSizeInBytes, aDrive)) |
|
111 { |
|
112 Log.logError("Disk space below critical level, required space " + |
|
113 aSizeInBytes + " bytes, drive " + aDrive); |
|
114 throw InstallerException.getOutOfDiskSpaceException( |
|
115 aSizeInBytes, null); |
|
116 } |
|
117 } |
|
118 |
|
119 /** |
|
120 * Chooses the default installation drive from given DriveInfo vector. |
|
121 * Default installation drive is the first INTERNAL_MASS_STORAGE, |
|
122 * PHONE_MEMORY or MEMORY_CARD drive that has enough free space for |
|
123 * the application. |
|
124 * @param aDrives DriveInfo objects. |
|
125 * @param aSizeInBytes application size. |
|
126 * @return Default installation drive id. |
|
127 * @throws InstallerException if none of the drives has enough free |
|
128 * space for the application. |
|
129 */ |
|
130 private static int getDefaultInstallationDrive( |
|
131 Vector aDrives, int aSizeInBytes) |
|
132 { |
|
133 sortDrives(aDrives); |
|
134 for (int i = 0; i < aDrives.size(); i++) |
|
135 { |
|
136 DriveInfo drive = (DriveInfo)aDrives.elementAt(i); |
|
137 int driveId = drive.getNumber(); |
|
138 if (SysUtil.isDiskSpaceBelowCriticalLevel(aSizeInBytes, driveId)) |
|
139 { |
|
140 Log.logWarning("Drive " + driveId + |
|
141 " space below critical level, required space " + |
|
142 aSizeInBytes + " bytes"); |
|
143 } |
|
144 else |
|
145 { |
|
146 Log.log("Drive " + driveId + |
|
147 " has enough free space, required space " + |
|
148 aSizeInBytes + " bytes"); |
|
149 return driveId; |
|
150 } |
|
151 } |
|
152 // None of the available drives has enough space, throw an exception. |
|
153 throw InstallerException.getOutOfDiskSpaceException( |
|
154 aSizeInBytes, null); |
|
155 } |
|
156 |
|
157 /** |
|
158 * Sorts DriveInfos in given vector to drive priority order. |
|
159 * Priority order for the drives is USER_CHOSEN, INTERNAL_MASS_STORAGE, |
|
160 * PHONE_MEMORY, MEMORY_CARD. If there is more than one drive |
|
161 * of the same type, the ones which have more free space have |
|
162 * higher priority. |
|
163 */ |
|
164 private static void sortDrives(Vector aDrives) |
|
165 { |
|
166 for (int i = 1; i < aDrives.size(); i++) |
|
167 { |
|
168 for (int j = 0; j < i; j++) |
|
169 { |
|
170 DriveInfo d1 = (DriveInfo)aDrives.elementAt(j); |
|
171 DriveInfo d2 = (DriveInfo)aDrives.elementAt(i); |
|
172 if (hasHigherPriority(d1, d2)) |
|
173 { |
|
174 aDrives.removeElementAt(j); |
|
175 aDrives.insertElementAt(d2, i); |
|
176 } |
|
177 } |
|
178 } |
|
179 // Move user chosen drive to be the first. |
|
180 int userChosen = getUserChosenDrive(); |
|
181 if (userChosen != -1) |
|
182 { |
|
183 for (int i = 0; i < aDrives.size(); i++) |
|
184 { |
|
185 DriveInfo d = (DriveInfo)aDrives.elementAt(i); |
|
186 if (d.getNumber() == userChosen) |
|
187 { |
|
188 aDrives.removeElementAt(i); |
|
189 aDrives.insertElementAt(d, 0); |
|
190 } |
|
191 } |
|
192 } |
|
193 } |
|
194 |
|
195 /** |
|
196 * Returns the installation drive the user has chosen last. |
|
197 * If user selection is not available, returns -1. |
|
198 */ |
|
199 private static int getUserChosenDrive() |
|
200 { |
|
201 int result = -1; |
|
202 try |
|
203 { |
|
204 String driveName = SysUtil.getRepositoryStringValue( |
|
205 SysUtil.REPO_ID_JAVA_INST_VARIATION, |
|
206 SysUtil.REPO_KEY_JAVA_INST_DEF_INST_DRIVE); |
|
207 if (driveName != null && driveName.length() > 0) |
|
208 { |
|
209 result = driveName.toLowerCase().charAt(0) - 'a'; |
|
210 } |
|
211 } |
|
212 catch (Throwable t) |
|
213 { |
|
214 Log.log("Getting user chosen drive from repository failed", t); |
|
215 } |
|
216 Log.log("Last user chosen drive from repository: " + result); |
|
217 return result; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Returns true if aD2 has higher priority than aD1. |
|
222 */ |
|
223 private static boolean hasHigherPriority( |
|
224 DriveInfo aD1, DriveInfo aD2) |
|
225 { |
|
226 boolean result = false; |
|
227 int type1 = aD1.getDriveType(); |
|
228 int type2 = aD2.getDriveType(); |
|
229 if (type1 == type2) |
|
230 { |
|
231 // Check which drive has more free space. |
|
232 if (aD2.getFreeSpace() > aD1.getFreeSpace()) |
|
233 { |
|
234 result = true; |
|
235 } |
|
236 } |
|
237 // Check priority basing on drive type. |
|
238 if (!result && |
|
239 type1 != DriveInfo.INTERNAL_MASS_STORAGE && |
|
240 type2 == DriveInfo.INTERNAL_MASS_STORAGE) |
|
241 { |
|
242 result = true; |
|
243 } |
|
244 if (!result && |
|
245 type1 != DriveInfo.INTERNAL_MASS_STORAGE && |
|
246 type1 != DriveInfo.PHONE_MEMORY && |
|
247 type2 == DriveInfo.PHONE_MEMORY) |
|
248 { |
|
249 result = true; |
|
250 } |
|
251 if (!result && |
|
252 type1 != DriveInfo.INTERNAL_MASS_STORAGE && |
|
253 type1 != DriveInfo.PHONE_MEMORY && |
|
254 type1 != DriveInfo.MEMORY_CARD && |
|
255 type2 == DriveInfo.MEMORY_CARD) |
|
256 { |
|
257 result = true; |
|
258 } |
|
259 return result; |
|
260 } |
|
261 |
|
262 /** |
|
263 * Updates installation drive into root, jad and jar |
|
264 * paths in suite info object. |
|
265 */ |
|
266 private static void updateSuitePaths(InstallBall aBall) |
|
267 { |
|
268 aBall.iSuite.setRootDir |
|
269 (FileUtils.setDrive |
|
270 (aBall.iSuite.getRootDir(), aBall.iInstallationDrive)); |
|
271 if (aBall.iSuite.getJadPath() != null) |
|
272 { |
|
273 if (!aBall.iPreinstallation) |
|
274 { |
|
275 aBall.iSuite.setJadPath |
|
276 (FileUtils.setDrive |
|
277 (aBall.iSuite.getJadPath(), aBall.iInstallationDrive)); |
|
278 } |
|
279 } |
|
280 if (aBall.iSuite.getJarPath() != null) |
|
281 { |
|
282 if (!aBall.iPreinstallation) |
|
283 { |
|
284 aBall.iSuite.setJarPath |
|
285 (FileUtils.setDrive |
|
286 (aBall.iSuite.getJarPath(), aBall.iInstallationDrive)); |
|
287 } |
|
288 } |
|
289 } |
|
290 } |