|
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.storagehandler; |
|
20 |
|
21 import com.nokia.mj.impl.installer.utils.InstallerException; |
|
22 import com.nokia.mj.impl.installer.utils.Log; |
|
23 import com.nokia.mj.impl.installer.utils.PlatformUid; |
|
24 import com.nokia.mj.impl.storage.StorageAttribute; |
|
25 import com.nokia.mj.impl.storage.StorageEntry; |
|
26 import com.nokia.mj.impl.storage.StorageFactory; |
|
27 import com.nokia.mj.impl.storage.StorageNames; |
|
28 import com.nokia.mj.impl.storage.StorageSession; |
|
29 import com.nokia.mj.impl.utils.Attribute; |
|
30 import com.nokia.mj.impl.utils.Tokenizer; |
|
31 import com.nokia.mj.impl.utils.Uid; |
|
32 import com.nokia.mj.impl.utils.Version; |
|
33 |
|
34 import java.util.Enumeration; |
|
35 import java.util.Hashtable; |
|
36 import java.util.Vector; |
|
37 |
|
38 /** |
|
39 * StorageHandler offers JavaStorage services for JavaInstaller. |
|
40 */ |
|
41 public class StorageHandler |
|
42 { |
|
43 |
|
44 /** StorageSession instance. */ |
|
45 private StorageSession iSession = null; |
|
46 private boolean iTransactionExists = false; |
|
47 |
|
48 /** |
|
49 * Default constructor. |
|
50 */ |
|
51 public StorageHandler() |
|
52 { |
|
53 try |
|
54 { |
|
55 iSession = StorageFactory.createSession(); |
|
56 iSession.open(); |
|
57 } |
|
58 catch (Throwable t) |
|
59 { |
|
60 InstallerException.internalError |
|
61 ("Error while constructing StorageHandler", t); |
|
62 } |
|
63 } |
|
64 |
|
65 /** |
|
66 * Closes this object. |
|
67 */ |
|
68 public void close() |
|
69 { |
|
70 if (iSession != null) |
|
71 { |
|
72 try |
|
73 { |
|
74 iSession.close(); |
|
75 iSession.destroySession(); |
|
76 iSession = null; |
|
77 } |
|
78 catch (Throwable t) |
|
79 { |
|
80 InstallerException.internalError |
|
81 ("Error while closing StorageHandler", t); |
|
82 } |
|
83 } |
|
84 } |
|
85 |
|
86 /** |
|
87 * Start a new Storage session for storage update. |
|
88 * This method creates a new JavaStorage transaction. |
|
89 * @throws InstallerException if session opening fails. |
|
90 */ |
|
91 public void startSession() |
|
92 { |
|
93 try |
|
94 { |
|
95 checkSession(); |
|
96 iSession.startTransaction(); |
|
97 iTransactionExists = true; |
|
98 } |
|
99 catch (Throwable t) |
|
100 { |
|
101 InstallerException.internalError |
|
102 ("Error while starting Storage session", t); |
|
103 } |
|
104 } |
|
105 |
|
106 /** |
|
107 * Commit a successful session. |
|
108 * @throws InstallerException if committing session fails. |
|
109 */ |
|
110 public void commitSession() |
|
111 { |
|
112 try |
|
113 { |
|
114 checkSession(); |
|
115 checkTransaction(); |
|
116 iSession.commitTransaction(); |
|
117 iTransactionExists = false; |
|
118 close(); |
|
119 } |
|
120 catch (Throwable t) |
|
121 { |
|
122 InstallerException.internalError |
|
123 ("Error while committing Storage session", t); |
|
124 } |
|
125 } |
|
126 |
|
127 /** |
|
128 * Rollback a session. |
|
129 * @throws InstallerException if session rollback fails. |
|
130 */ |
|
131 public void rollbackSession() |
|
132 { |
|
133 try |
|
134 { |
|
135 checkSession(); |
|
136 checkTransaction(); |
|
137 iSession.rollbackTransaction(); |
|
138 iTransactionExists = false; |
|
139 close(); |
|
140 } |
|
141 catch (Throwable t) |
|
142 { |
|
143 InstallerException.internalError |
|
144 ("Error while rolling back Storage session", t); |
|
145 } |
|
146 } |
|
147 |
|
148 /** |
|
149 * Returns instance of StorageSession, or null if session |
|
150 * does not exist. |
|
151 */ |
|
152 public StorageSession getSession() |
|
153 { |
|
154 return iSession; |
|
155 } |
|
156 |
|
157 /** |
|
158 * Get string which contains listing of all entries |
|
159 * from given storage table. |
|
160 */ |
|
161 public String getStorageEntriesString(String aTableName) |
|
162 { |
|
163 StringBuffer result = new StringBuffer(); |
|
164 try |
|
165 { |
|
166 result.append("Table ").append(aTableName).append("\n"); |
|
167 StorageEntry query = new StorageEntry(); |
|
168 StorageEntry[] entries = iSession.search(aTableName, query); |
|
169 if (entries == null) |
|
170 { |
|
171 return null; |
|
172 } |
|
173 for (int i = 0; i < entries.length; i++) |
|
174 { |
|
175 StorageEntry entry = entries[i]; |
|
176 result.append(entry.toString()).append("\n"); |
|
177 } |
|
178 } |
|
179 catch (Throwable t) |
|
180 { |
|
181 InstallerException.internalError |
|
182 ("Error while getting storage table " + aTableName, t); |
|
183 } |
|
184 return result.toString(); |
|
185 } |
|
186 |
|
187 /** |
|
188 * Get uids for all existing suites. |
|
189 */ |
|
190 public Uid[] getSuiteUids() |
|
191 { |
|
192 try |
|
193 { |
|
194 checkSession(); |
|
195 StorageEntry query = new StorageEntry(); |
|
196 query.addAttribute(new StorageAttribute(StorageNames.ID, "")); |
|
197 StorageEntry[] entries = iSession.search( |
|
198 StorageNames.APPLICATION_PACKAGE_TABLE, query); |
|
199 if (entries == null) |
|
200 { |
|
201 return null; |
|
202 } |
|
203 Uid[] uids = new Uid[entries.length]; |
|
204 for (int i = 0; i < entries.length; i++) |
|
205 { |
|
206 StorageEntry entry = entries[i]; |
|
207 uids[i] = PlatformUid.createUid |
|
208 (entry.getAttribute(StorageNames.ID).getValue()); |
|
209 } |
|
210 return uids; |
|
211 } |
|
212 catch (Throwable t) |
|
213 { |
|
214 InstallerException.internalError |
|
215 ("Error while getting suite uids", t); |
|
216 } |
|
217 return null; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Get suite uid. Given uid parameter can either be an |
|
222 * application uid or suite uid. If it is a suite uid, |
|
223 * itself is returned. If no matching suite is found, |
|
224 * returns null. |
|
225 */ |
|
226 public Uid getSuiteUid(Uid aUid) |
|
227 { |
|
228 try |
|
229 { |
|
230 checkSession(); |
|
231 // Check if aUid is an application uid. |
|
232 StorageEntry query = new StorageEntry(); |
|
233 query.addAttribute(new StorageAttribute |
|
234 (StorageNames.ID, aUid.getStringValue())); |
|
235 query.addAttribute(new StorageAttribute( |
|
236 StorageNames.PACKAGE_ID, "")); |
|
237 StorageEntry[] entries = iSession.search( |
|
238 StorageNames.APPLICATION_TABLE, query); |
|
239 if (entries != null && entries.length > 0) |
|
240 { |
|
241 // Uid is an application uid, return suite uid column. |
|
242 return PlatformUid.createUid |
|
243 (entries[0].getAttribute(StorageNames.PACKAGE_ID).getValue()); |
|
244 } |
|
245 // Check if aUid is a suite uid. |
|
246 query = new StorageEntry(); |
|
247 query.addAttribute(new StorageAttribute |
|
248 (StorageNames.ID, aUid.getStringValue())); |
|
249 entries = iSession.search( |
|
250 StorageNames.APPLICATION_PACKAGE_TABLE, query); |
|
251 if (entries != null && entries.length > 0) |
|
252 { |
|
253 // Uid is a suite uid, return itself. |
|
254 return aUid; |
|
255 } |
|
256 } |
|
257 catch (Throwable t) |
|
258 { |
|
259 InstallerException.internalError |
|
260 ("Error while getting suite uid", t); |
|
261 } |
|
262 return null; |
|
263 } |
|
264 |
|
265 /** |
|
266 * Get application uids that belong to given suite. |
|
267 * Note that this method does not guarantee the order in which |
|
268 * application uids are returned. |
|
269 * If no matching suite is found, returns null. |
|
270 */ |
|
271 public Uid[] getAppUids(Uid aUid) |
|
272 { |
|
273 try |
|
274 { |
|
275 checkSession(); |
|
276 Uid[] uids = null; |
|
277 StorageEntry query = new StorageEntry(); |
|
278 query.addAttribute(new StorageAttribute |
|
279 (StorageNames.PACKAGE_ID, aUid.getStringValue())); |
|
280 query.addAttribute(new StorageAttribute(StorageNames.ID, "")); |
|
281 StorageEntry[] entries = iSession.search( |
|
282 StorageNames.APPLICATION_TABLE, query); |
|
283 if (entries != null && entries.length > 0) |
|
284 { |
|
285 uids = new Uid[entries.length]; |
|
286 for (int i = 0; i < entries.length; i++) |
|
287 { |
|
288 uids[i] = PlatformUid.createUid |
|
289 (entries[i].getAttribute(StorageNames.ID).getValue()); |
|
290 } |
|
291 } |
|
292 return uids; |
|
293 } |
|
294 catch (Throwable t) |
|
295 { |
|
296 InstallerException.internalError |
|
297 ("Error while getting application uids", t); |
|
298 } |
|
299 return null; |
|
300 } |
|
301 |
|
302 /** |
|
303 * Reads suite info from JavaStorage. Retrieves info basing |
|
304 * on uid field in the given SuiteInfo. If uid field is not present, |
|
305 * then info is fetched using Name and Vendor fields. |
|
306 * If matching suite is not found from storage, returns false. |
|
307 */ |
|
308 public boolean readSuiteInfo(SuiteInfo aSuiteInfo) |
|
309 { |
|
310 try |
|
311 { |
|
312 checkSession(); |
|
313 if (aSuiteInfo == null) |
|
314 { |
|
315 return false; |
|
316 } |
|
317 boolean result = false; |
|
318 if (aSuiteInfo.getUid() == null) |
|
319 { |
|
320 // Fetch suite info basing on name and vendor. |
|
321 if (aSuiteInfo.getName() == null || |
|
322 aSuiteInfo.getVendor() == null) |
|
323 { |
|
324 Log.logError |
|
325 ("StorageHandler.readSuiteInfo: uid or name " + |
|
326 "and vendor not found from SuiteInfo"); |
|
327 return result; |
|
328 } |
|
329 StorageEntry query = new StorageEntry(); |
|
330 query.addAttribute(new StorageAttribute |
|
331 (StorageNames.PACKAGE_NAME, |
|
332 aSuiteInfo.getName())); |
|
333 query.addAttribute(new StorageAttribute |
|
334 (StorageNames.VENDOR, |
|
335 aSuiteInfo.getVendor())); |
|
336 query.addAttribute(new StorageAttribute(StorageNames.ID, "")); |
|
337 StorageEntry[] entries = iSession.search( |
|
338 StorageNames.APPLICATION_PACKAGE_TABLE, query); |
|
339 if (entries != null && entries.length > 0) |
|
340 { |
|
341 // Found matching suite. |
|
342 aSuiteInfo.setUid(PlatformUid.createUid |
|
343 (entries[0].getAttribute( |
|
344 StorageNames.ID).getValue())); |
|
345 } |
|
346 } |
|
347 if (aSuiteInfo.getUid() != null) |
|
348 { |
|
349 // Fetch suite info basing on uid. |
|
350 result = readSuiteInfoByUid(aSuiteInfo); |
|
351 } |
|
352 return result; |
|
353 } |
|
354 catch (Throwable t) |
|
355 { |
|
356 InstallerException.internalError |
|
357 ("Error while reading suite info", t); |
|
358 } |
|
359 return false; |
|
360 } |
|
361 |
|
362 /** |
|
363 * Writes suite info to JavaStorage. |
|
364 */ |
|
365 public void writeSuiteInfo(SuiteInfo aSuiteInfo) |
|
366 { |
|
367 try |
|
368 { |
|
369 checkSession(); |
|
370 checkTransaction(); |
|
371 // Write StorageNames.APPLICATION_PACKAGE_TABLE table. |
|
372 StorageEntry entry = new StorageEntry(); |
|
373 entry.addAttribute |
|
374 (new StorageAttribute |
|
375 (StorageNames.ID, aSuiteInfo.getUid().getStringValue())); |
|
376 entry.addAttribute |
|
377 (new StorageAttribute |
|
378 (StorageNames.PACKAGE_NAME, aSuiteInfo.getName())); |
|
379 entry.addAttribute |
|
380 (new StorageAttribute |
|
381 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
382 entry.addAttribute |
|
383 (new StorageAttribute |
|
384 (StorageNames.VERSION, aSuiteInfo.getVersion().toString())); |
|
385 entry.addAttribute |
|
386 (new StorageAttribute |
|
387 (StorageNames.ROOT_PATH, aSuiteInfo.getRootDir())); |
|
388 entry.addAttribute |
|
389 (new StorageAttribute |
|
390 (StorageNames.MEDIA_ID, Integer.toString(aSuiteInfo.getMediaId()), |
|
391 StorageAttribute.INT_TYPE)); |
|
392 entry.addAttribute |
|
393 (new StorageAttribute |
|
394 (StorageNames.INITIAL_SIZE, Integer.toString(aSuiteInfo.getInitialSize()), |
|
395 StorageAttribute.INT_TYPE)); |
|
396 entry.addAttribute |
|
397 (new StorageAttribute |
|
398 (StorageNames.JAD_PATH, aSuiteInfo.getJadPath())); |
|
399 entry.addAttribute |
|
400 (new StorageAttribute |
|
401 (StorageNames.JAR_PATH, aSuiteInfo.getJarPath())); |
|
402 entry.addAttribute |
|
403 (new StorageAttribute |
|
404 (StorageNames.JAD_URL, aSuiteInfo.getJadUrl())); |
|
405 entry.addAttribute |
|
406 (new StorageAttribute |
|
407 (StorageNames.JAR_URL, aSuiteInfo.getJarUrl())); |
|
408 entry.addAttribute |
|
409 (new StorageAttribute |
|
410 (StorageNames.ACCESS_POINT, aSuiteInfo.getAccessPoint())); |
|
411 entry.addAttribute |
|
412 (new StorageAttribute |
|
413 (StorageNames.CONTENT_INFO, Integer.toString(aSuiteInfo.getContentInfo()), |
|
414 StorageAttribute.INT_TYPE)); |
|
415 entry.addAttribute |
|
416 (new StorageAttribute |
|
417 (StorageNames.CONTENT_ID, aSuiteInfo.getContentId())); |
|
418 iSession.write(StorageNames.APPLICATION_PACKAGE_TABLE, entry); |
|
419 // Write StorageNames.APPLICATION_PACKAGE_ATTRIBUTES_TABLE table. |
|
420 writeAttributes(aSuiteInfo.getUid(), aSuiteInfo.getAttributes()); |
|
421 // Write StorageNames.APPLICATION_TABLE table. |
|
422 Vector apps = aSuiteInfo.getApplications(); |
|
423 if (apps != null) |
|
424 { |
|
425 for (int i = 0; i < apps.size(); i++) |
|
426 { |
|
427 writeAppInfo(aSuiteInfo.getUid(), |
|
428 (ApplicationInfo)apps.elementAt(i)); |
|
429 } |
|
430 } |
|
431 // Update StorageNames.MIDP_PACKAGE_TABLE table. |
|
432 // This table is shared with security framework |
|
433 // so we must have a special handling for it. |
|
434 // Create a new entry to be inserted or updated. |
|
435 entry = new StorageEntry(); |
|
436 entry.addAttribute |
|
437 (new StorageAttribute |
|
438 (StorageNames.ID, aSuiteInfo.getUid().getStringValue())); |
|
439 entry.addAttribute |
|
440 (new StorageAttribute |
|
441 (StorageNames.ON_SCREEN_KEYPAD, |
|
442 Integer.toString(aSuiteInfo.getOnScreenKeypad()), |
|
443 StorageAttribute.INT_TYPE)); |
|
444 // Check if an entry already exists. |
|
445 StorageEntry matchEntry = new StorageEntry(); |
|
446 matchEntry.addAttribute(new StorageAttribute(StorageNames.ID, |
|
447 aSuiteInfo.getUid().getStringValue())); |
|
448 StorageEntry[] entries = iSession.search( |
|
449 StorageNames.MIDP_PACKAGE_TABLE, matchEntry); |
|
450 if (entries != null && entries.length > 0) |
|
451 { |
|
452 // Entry exists, update it. |
|
453 iSession.update(StorageNames.MIDP_PACKAGE_TABLE, entry, matchEntry); |
|
454 } |
|
455 else |
|
456 { |
|
457 // Entry does not exist, create it. |
|
458 iSession.write(StorageNames.MIDP_PACKAGE_TABLE, entry); |
|
459 } |
|
460 // Update StorageNames.PREINSTALL_TABLE table. |
|
461 writePreinstallState(aSuiteInfo); |
|
462 } |
|
463 catch (Throwable t) |
|
464 { |
|
465 InstallerException.internalError |
|
466 ("Error while writing suite info", t); |
|
467 } |
|
468 } |
|
469 |
|
470 /** |
|
471 * Updates changed parts of suite info to JavaStorage. |
|
472 */ |
|
473 public void updateSuiteInfo(SuiteInfo aOldSuiteInfo, SuiteInfo aNewSuiteInfo) |
|
474 { |
|
475 try |
|
476 { |
|
477 checkSession(); |
|
478 checkTransaction(); |
|
479 removeSuiteInfo(aOldSuiteInfo, true); |
|
480 writeSuiteInfo(aNewSuiteInfo); |
|
481 } |
|
482 catch (Throwable t) |
|
483 { |
|
484 InstallerException.internalError |
|
485 ("Error while updating suite info", t); |
|
486 } |
|
487 } |
|
488 |
|
489 /** |
|
490 * Removes info from JavaStorage for given suite uid. |
|
491 */ |
|
492 public void removeSuiteInfo(SuiteInfo aSuiteInfo) |
|
493 { |
|
494 try |
|
495 { |
|
496 removeSuiteInfo(aSuiteInfo, false); |
|
497 } |
|
498 catch (Throwable t) |
|
499 { |
|
500 InstallerException.internalError |
|
501 ("Error while removing suite info", t); |
|
502 } |
|
503 } |
|
504 |
|
505 /** |
|
506 * Allocates a free uid which is not in use in storage. |
|
507 * |
|
508 * @param aPreviousUid if null allocates a random uid, |
|
509 * if not null allocates next free uid |
|
510 * @return a free uid, or null if uid cannot be allocated |
|
511 */ |
|
512 public Uid allocateUid(Uid aPreviousUid) |
|
513 { |
|
514 try |
|
515 { |
|
516 checkSession(); |
|
517 Uid uid = PlatformUid.generateUid(aPreviousUid, null); |
|
518 if (uidInUse(uid)) |
|
519 { |
|
520 Uid startUid = uid; |
|
521 do |
|
522 { |
|
523 uid = PlatformUid.generateUid(uid, null); |
|
524 if (uid.equals(startUid)) |
|
525 { |
|
526 InstallerException.internalError |
|
527 ("No more free uids."); |
|
528 } |
|
529 } |
|
530 while (uidInUse(uid)); |
|
531 } |
|
532 return uid; |
|
533 } |
|
534 catch (Throwable t) |
|
535 { |
|
536 InstallerException.internalError |
|
537 ("Error while allocating uid", t); |
|
538 } |
|
539 return null; |
|
540 } |
|
541 |
|
542 /** |
|
543 * Allocates a free uid which is not in use in storage. |
|
544 * |
|
545 * @param aUidSeed seed used for allocating uid |
|
546 * @return a free uid, or null if uid cannot be allocated |
|
547 */ |
|
548 public Uid allocateUid(String aUidSeed) |
|
549 { |
|
550 Uid uid = PlatformUid.generateUid(null, aUidSeed); |
|
551 if (uidInUse(uid)) |
|
552 { |
|
553 uid = allocateUid(uid); |
|
554 } |
|
555 return uid; |
|
556 } |
|
557 |
|
558 /** |
|
559 * Removes all data from all JavaStorage tables. |
|
560 * @return true if removal was successful, false if removal failed. |
|
561 * @throws StorageException if JavaStorage throws it. |
|
562 */ |
|
563 public static boolean removeAllData() |
|
564 { |
|
565 boolean result = true; |
|
566 // Remove all data from JavaStorage tables. |
|
567 String[] tableNames = |
|
568 { |
|
569 StorageNames.APPLICATION_PACKAGE_TABLE, |
|
570 StorageNames.APPLICATION_TABLE, |
|
571 StorageNames.APPLICATION_PACKAGE_ATTRIBUTES_TABLE, |
|
572 StorageNames.MIDP_PACKAGE_TABLE, |
|
573 StorageNames.MIDP_PERMISSIONS_TABLE, |
|
574 StorageNames.MIDP_FUNC_GRP_SETTINGS_TABLE, |
|
575 StorageNames.PUSH_REGISTRATIONS_TABLE, |
|
576 StorageNames.ALARM_REGISTRATIONS_TABLE, |
|
577 StorageNames.RUNTIME_SETTINGS_TABLE, |
|
578 StorageNames.PREINSTALL_TABLE, |
|
579 }; |
|
580 StorageSession session = StorageFactory.createSession(); |
|
581 session.open(); |
|
582 session.startTransaction(); |
|
583 for (int i = 0; i < tableNames.length; i++) |
|
584 { |
|
585 if (session.remove(tableNames[i], new StorageEntry()) == -1) |
|
586 { |
|
587 Log.logError("Removing data from JavaStorage table " + |
|
588 tableNames[i] + " failed"); |
|
589 result = false; |
|
590 } |
|
591 else |
|
592 { |
|
593 Log.log("Removed data from JavaStorage table " + tableNames[i]); |
|
594 } |
|
595 } |
|
596 session.commitTransaction(); |
|
597 session.close(); |
|
598 session.destroySession(); |
|
599 // Remove all data from JavaOtaStorage tables. |
|
600 String tableName = StorageNames.OTA_STATUS_TABLE; |
|
601 session = StorageFactory.createSession(); |
|
602 session.open(StorageNames.JAVA_OTA_DATABASE_NAME); |
|
603 if (session.remove(tableName, new StorageEntry()) == -1) |
|
604 { |
|
605 Log.logError("Removing data from JavaOtaStorage table " + |
|
606 tableName + " failed"); |
|
607 result = false; |
|
608 } |
|
609 else |
|
610 { |
|
611 Log.log("Removed data from JavaOtaStorage table " + tableName); |
|
612 } |
|
613 session.close(); |
|
614 session.destroySession(); |
|
615 return result; |
|
616 } |
|
617 |
|
618 /** |
|
619 * Returns storage attribute value from given entry, or null |
|
620 * if attribute does not exist. |
|
621 */ |
|
622 static String getAttributeValue(StorageEntry aEntry, String aName) |
|
623 { |
|
624 if (aEntry == null) |
|
625 { |
|
626 return null; |
|
627 } |
|
628 StorageAttribute attr = aEntry.getAttribute(aName); |
|
629 if (attr != null) |
|
630 { |
|
631 return attr.getValue(); |
|
632 } |
|
633 return null; |
|
634 } |
|
635 |
|
636 /** |
|
637 * Returns true if given uid is already in use in storage. |
|
638 */ |
|
639 private boolean uidInUse(Uid aUid) |
|
640 { |
|
641 checkSession(); |
|
642 StorageEntry query = new StorageEntry(); |
|
643 query.addAttribute(new StorageAttribute( |
|
644 StorageNames.ID, aUid.getStringValue())); |
|
645 // Check if aUid is a suite uid. |
|
646 StorageEntry[] entries = iSession.search( |
|
647 StorageNames.APPLICATION_PACKAGE_TABLE, query); |
|
648 if (entries != null && entries.length > 0) |
|
649 { |
|
650 return true; |
|
651 } |
|
652 // Check if aUid is an application uid. |
|
653 entries = iSession.search(StorageNames.APPLICATION_TABLE, query); |
|
654 if (entries != null && entries.length > 0) |
|
655 { |
|
656 return true; |
|
657 } |
|
658 return false; |
|
659 } |
|
660 |
|
661 /** |
|
662 * Reads suite info from JavaStorage. Retrieves info basing |
|
663 * on uid field in the given SuiteInfo. |
|
664 * If matching suite is not found from storage, returns false. |
|
665 */ |
|
666 private boolean readSuiteInfoByUid(SuiteInfo aSuiteInfo) |
|
667 { |
|
668 if (aSuiteInfo == null) |
|
669 { |
|
670 return false; |
|
671 } |
|
672 boolean result = false; |
|
673 // Read StorageNames.APPLICATION_PACKAGE_TABLE table. |
|
674 StorageEntry query = new StorageEntry(); |
|
675 query.addAttribute(new StorageAttribute(StorageNames.ID, |
|
676 aSuiteInfo.getUid().getStringValue())); |
|
677 StorageEntry[] entries = iSession.search( |
|
678 StorageNames.APPLICATION_PACKAGE_TABLE, query); |
|
679 if (entries != null && entries.length > 0) |
|
680 { |
|
681 result = true; |
|
682 // Fill suite info. |
|
683 StorageEntry entry = entries[0]; |
|
684 aSuiteInfo.setName(getAttributeValue(entry, StorageNames.PACKAGE_NAME)); |
|
685 aSuiteInfo.setVendor(getAttributeValue(entry, StorageNames.VENDOR)); |
|
686 aSuiteInfo.setVersion(Version.getVersion( |
|
687 getAttributeValue(entry, StorageNames.VERSION))); |
|
688 aSuiteInfo.setRootDir(getAttributeValue(entry, StorageNames.ROOT_PATH)); |
|
689 aSuiteInfo.setMediaId(Integer.parseInt( |
|
690 getAttributeValue(entry, StorageNames.MEDIA_ID))); |
|
691 aSuiteInfo.setInitialSize(Integer.parseInt( |
|
692 getAttributeValue(entry, StorageNames.INITIAL_SIZE))); |
|
693 aSuiteInfo.setJadPath(getAttributeValue(entry, StorageNames.JAD_PATH)); |
|
694 aSuiteInfo.setJarPath(getAttributeValue(entry, StorageNames.JAR_PATH)); |
|
695 aSuiteInfo.setJadUrl(getAttributeValue(entry, StorageNames.JAD_URL)); |
|
696 aSuiteInfo.setJarUrl(getAttributeValue(entry, StorageNames.JAR_URL)); |
|
697 aSuiteInfo.setAccessPoint(getAttributeValue(entry, StorageNames.ACCESS_POINT)); |
|
698 aSuiteInfo.setContentInfo(Integer.parseInt( |
|
699 getAttributeValue(entry, StorageNames.CONTENT_INFO))); |
|
700 aSuiteInfo.setContentId(getAttributeValue(entry, StorageNames.CONTENT_ID)); |
|
701 // Read attributes. |
|
702 aSuiteInfo.setAttributes(readAttributes(aSuiteInfo.getUid())); |
|
703 // Check from attributes if suite is trusted. |
|
704 // This check does not work if the MIDlet-Jar-RSA-SHA1 |
|
705 // attribute is specified in Manifest for untrusted |
|
706 // application: in upgrade the existing application |
|
707 // is assumed to be trusted! Trust info must be initialized |
|
708 // from Security framework after SuiteInfo has been read. |
|
709 if (aSuiteInfo.getAttribute("MIDlet-Jar-RSA-SHA1") != null) |
|
710 { |
|
711 aSuiteInfo.setTrusted(true); |
|
712 } |
|
713 // Read application uids. |
|
714 Uid[] appUids = getAppUids(aSuiteInfo.getUid()); |
|
715 if (appUids != null) |
|
716 { |
|
717 for (int i = 0; i < appUids.length; i++) |
|
718 { |
|
719 ApplicationInfo appInfo = readAppInfo(appUids[i]); |
|
720 aSuiteInfo.addApplication(appInfo); |
|
721 } |
|
722 } |
|
723 sortApps(aSuiteInfo); |
|
724 } |
|
725 |
|
726 if (result) |
|
727 { |
|
728 // Read StorageNames.MIDP_PACKAGE_TABLE table. |
|
729 result = false; |
|
730 query = new StorageEntry(); |
|
731 query.addAttribute(new StorageAttribute(StorageNames.ID, |
|
732 aSuiteInfo.getUid().getStringValue())); |
|
733 query.addAttribute(new StorageAttribute( |
|
734 StorageNames.ON_SCREEN_KEYPAD, "")); |
|
735 entries = iSession.search(StorageNames.MIDP_PACKAGE_TABLE, query); |
|
736 if (entries != null && entries.length > 0) |
|
737 { |
|
738 result = true; |
|
739 // Fill suite info. |
|
740 StorageEntry entry = entries[0]; |
|
741 aSuiteInfo.setOnScreenKeypad(Integer.parseInt( |
|
742 getAttributeValue(entry, StorageNames.ON_SCREEN_KEYPAD))); |
|
743 } |
|
744 else |
|
745 { |
|
746 Log.logError("Reading " + StorageNames.MIDP_PACKAGE_TABLE + |
|
747 " table failed, no entries found"); |
|
748 } |
|
749 } |
|
750 |
|
751 if (result) |
|
752 { |
|
753 // Read StorageNames.PREINSTALL_TABLE table. |
|
754 //result = false; |
|
755 aSuiteInfo.iPreinstallState = readPreinstallState(aSuiteInfo); |
|
756 if (aSuiteInfo.iPreinstallState >= 0) |
|
757 { |
|
758 result = true; |
|
759 } |
|
760 else |
|
761 { |
|
762 Log.logWarning("Reading " + StorageNames.PREINSTALL_TABLE + |
|
763 " table failed, no entries found"); |
|
764 } |
|
765 } |
|
766 |
|
767 return result; |
|
768 } |
|
769 |
|
770 /** |
|
771 * Reads suite attributes from JavaStorage. Retrieves info basing |
|
772 * on given suite uid. |
|
773 * If matching suite is not found from storage, returns null. |
|
774 */ |
|
775 private Hashtable readAttributes(Uid aUid) |
|
776 { |
|
777 if (aUid == null) |
|
778 { |
|
779 return null; |
|
780 } |
|
781 Hashtable attrs = null; |
|
782 StorageEntry query = new StorageEntry(); |
|
783 query.addAttribute(new StorageAttribute( |
|
784 StorageNames.ID, aUid.getStringValue())); |
|
785 StorageEntry[] entries = iSession.search( |
|
786 StorageNames.APPLICATION_PACKAGE_ATTRIBUTES_TABLE, query); |
|
787 if (entries != null) |
|
788 { |
|
789 attrs = new Hashtable(); |
|
790 for (int i = 0; i < entries.length; i++) |
|
791 { |
|
792 StorageEntry entry = entries[i]; |
|
793 String name = getAttributeValue(entry, StorageNames.NAME); |
|
794 String value = getAttributeValue(entry, StorageNames.VALUE); |
|
795 String trustedStr = getAttributeValue(entry, StorageNames.TRUSTED); |
|
796 boolean trusted = Integer.parseInt(trustedStr) > 0; |
|
797 if (value == null) |
|
798 { |
|
799 Log.logWarning("Attribute " + name + " has empty value"); |
|
800 value = ""; |
|
801 } |
|
802 attrs.put(name, new Attribute(name, value, trusted)); |
|
803 } |
|
804 } |
|
805 return attrs; |
|
806 } |
|
807 |
|
808 /** |
|
809 * Writes suite attributes to JavaStorage. |
|
810 */ |
|
811 private void writeAttributes(Uid aUid, Hashtable aAttrs) |
|
812 { |
|
813 if (aUid == null || aAttrs == null) |
|
814 { |
|
815 return; |
|
816 } |
|
817 StorageEntry entry = null; |
|
818 Enumeration e = aAttrs.elements(); |
|
819 while (e.hasMoreElements()) |
|
820 { |
|
821 Attribute attr = (Attribute)e.nextElement(); |
|
822 entry = new StorageEntry(); |
|
823 entry.addAttribute(new StorageAttribute( |
|
824 StorageNames.ID, aUid.getStringValue())); |
|
825 entry.addAttribute(new StorageAttribute( |
|
826 StorageNames.NAME, attr.getName())); |
|
827 entry.addAttribute(new StorageAttribute( |
|
828 StorageNames.VALUE, attr.getValue())); |
|
829 entry.addAttribute(new StorageAttribute( |
|
830 StorageNames.TRUSTED, (attr.isTrusted()? "1": "0"), |
|
831 StorageAttribute.INT_TYPE)); |
|
832 iSession.write(StorageNames.APPLICATION_PACKAGE_ATTRIBUTES_TABLE, entry); |
|
833 } |
|
834 } |
|
835 |
|
836 /** |
|
837 * Reads application info from JavaStorage. Retrieves info basing |
|
838 * on given application uid. |
|
839 * If matching application is not found from storage, returns null. |
|
840 */ |
|
841 private ApplicationInfo readAppInfo(Uid aUid) |
|
842 { |
|
843 if (aUid == null) |
|
844 { |
|
845 return null; |
|
846 } |
|
847 ApplicationInfo appInfo = null; |
|
848 StorageEntry query = new StorageEntry(); |
|
849 query.addAttribute(new StorageAttribute( |
|
850 StorageNames.ID, aUid.getStringValue())); |
|
851 StorageEntry[] entries = iSession.search( |
|
852 StorageNames.APPLICATION_TABLE, query); |
|
853 if (entries != null) |
|
854 { |
|
855 for (int i = 0; i < entries.length; i++) |
|
856 { |
|
857 StorageEntry entry = entries[i]; |
|
858 String autoStartStr = getAttributeValue( |
|
859 entry, StorageNames.AUTORUN); |
|
860 int autoStart = Integer.parseInt(autoStartStr); |
|
861 appInfo = new ApplicationInfo(aUid, |
|
862 getAttributeValue(entry, StorageNames.NAME), |
|
863 getAttributeValue(entry, StorageNames.MAIN_CLASS), |
|
864 autoStart); |
|
865 } |
|
866 } |
|
867 return appInfo; |
|
868 } |
|
869 |
|
870 /** |
|
871 * Writes application info to JavaStorage. |
|
872 */ |
|
873 private void writeAppInfo(Uid aUid, ApplicationInfo aAppInfo) |
|
874 { |
|
875 if (aUid == null || aAppInfo == null) |
|
876 { |
|
877 return; |
|
878 } |
|
879 StorageEntry entry = new StorageEntry(); |
|
880 entry.addAttribute(new StorageAttribute( |
|
881 StorageNames.ID, aAppInfo.getUid().getStringValue())); |
|
882 entry.addAttribute(new StorageAttribute( |
|
883 StorageNames.PACKAGE_ID, aUid.getStringValue())); |
|
884 entry.addAttribute(new StorageAttribute( |
|
885 StorageNames.NAME, aAppInfo.getName())); |
|
886 entry.addAttribute(new StorageAttribute( |
|
887 StorageNames.MAIN_CLASS, aAppInfo.getMainClass())); |
|
888 entry.addAttribute(new StorageAttribute( |
|
889 StorageNames.AUTORUN, Integer.toString(aAppInfo.getAutoStart()), |
|
890 StorageAttribute.INT_TYPE)); |
|
891 iSession.write(StorageNames.APPLICATION_TABLE, entry); |
|
892 } |
|
893 |
|
894 /** |
|
895 * Removes info from JavaStorage for given suite uid. |
|
896 */ |
|
897 private void removeSuiteInfo(SuiteInfo aSuiteInfo, boolean aUpdate) |
|
898 { |
|
899 Uid uid = aSuiteInfo.getUid(); |
|
900 checkSession(); |
|
901 checkTransaction(); |
|
902 iSession.remove(StorageNames.APPLICATION_PACKAGE_TABLE, uid); |
|
903 iSession.remove(StorageNames.APPLICATION_PACKAGE_ATTRIBUTES_TABLE, uid); |
|
904 |
|
905 // StorageNames.MIDP_PACKAGE_TABLE table is removed when |
|
906 // AuthenticationModule.removeSecurityData() |
|
907 // is called in RemoveSecurityData step, |
|
908 // so do not remove it here. |
|
909 // If StorageNames.MIDP_PACKAGE_TABLE was removed here, |
|
910 // it would cause security error in update. |
|
911 |
|
912 // Remove data from StorageNames.APPLICATION_TABLE table. |
|
913 Uid[] appUids = getAppUids(uid); |
|
914 if (appUids != null) |
|
915 { |
|
916 for (int i = 0; i < appUids.length; i++) |
|
917 { |
|
918 iSession.remove(StorageNames.APPLICATION_TABLE, appUids[i]); |
|
919 } |
|
920 } |
|
921 if (aUpdate) |
|
922 { |
|
923 // User or Preinstaller is making an update, |
|
924 // do not change preinstall state. |
|
925 } |
|
926 else |
|
927 { |
|
928 // Not an update ==> user is making uninstallation. |
|
929 int oldPreinstallState = readPreinstallState(aSuiteInfo); |
|
930 if (oldPreinstallState == aSuiteInfo.STATE_PREINSTALLED) |
|
931 { |
|
932 // User is uninstalling a preinstalled application, |
|
933 // set preinstall state to STATE_NO_PREINSTALL. |
|
934 setNoPreinstallState(aSuiteInfo); |
|
935 } |
|
936 else if (oldPreinstallState == aSuiteInfo.STATE_INSTALLED) |
|
937 { |
|
938 // Remove existing data from StorageNames.PREINSTALL_TABLE table. |
|
939 removePreinstallState(aSuiteInfo); |
|
940 } |
|
941 } |
|
942 } |
|
943 |
|
944 /** |
|
945 * Reads preinstall state from INSTALL_STATE column |
|
946 * value from StorageNames.PREINSTALL_TABLE table. |
|
947 * If INSTALL_STATE value is not found, returns -1. |
|
948 */ |
|
949 private int readPreinstallState(SuiteInfo aSuiteInfo) |
|
950 { |
|
951 int result = -1; |
|
952 // Match preinstall state using name and vendor. |
|
953 StorageEntry query = new StorageEntry(); |
|
954 query.addAttribute |
|
955 (new StorageAttribute |
|
956 (StorageNames.NAME, aSuiteInfo.getName())); |
|
957 query.addAttribute |
|
958 (new StorageAttribute |
|
959 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
960 query.addAttribute(new StorageAttribute( |
|
961 StorageNames.INSTALL_STATE, "")); |
|
962 StorageEntry[] entries = iSession.search( |
|
963 StorageNames.PREINSTALL_TABLE, query); |
|
964 if (entries != null && entries.length > 0) |
|
965 { |
|
966 // Fill suite info. |
|
967 StorageEntry entry = entries[0]; |
|
968 result = Integer.parseInt |
|
969 (getAttributeValue(entry, StorageNames.INSTALL_STATE)); |
|
970 } |
|
971 return result; |
|
972 } |
|
973 |
|
974 /** |
|
975 * Writes preinstall state to StorageNames.PREINSTALL_TABLE table. |
|
976 */ |
|
977 private void writePreinstallState(SuiteInfo aSuiteInfo) |
|
978 { |
|
979 if (aSuiteInfo == null) |
|
980 { |
|
981 return; |
|
982 } |
|
983 |
|
984 // Before writing new preinstall state we must fetch the old state. |
|
985 int oldPreinstallState = readPreinstallState(aSuiteInfo); |
|
986 |
|
987 // Match preinstall state using name and vendor. |
|
988 StorageEntry matchEntry = new StorageEntry(); |
|
989 matchEntry.addAttribute |
|
990 (new StorageAttribute |
|
991 (StorageNames.NAME, aSuiteInfo.getName())); |
|
992 matchEntry.addAttribute |
|
993 (new StorageAttribute |
|
994 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
995 |
|
996 // Create a new entry with name, vendor and version. |
|
997 StorageEntry entry = new StorageEntry(); |
|
998 entry.addAttribute |
|
999 (new StorageAttribute |
|
1000 (StorageNames.NAME, aSuiteInfo.getName())); |
|
1001 entry.addAttribute |
|
1002 (new StorageAttribute |
|
1003 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
1004 entry.addAttribute |
|
1005 (new StorageAttribute |
|
1006 (StorageNames.VERSION, aSuiteInfo.getVersion().toString())); |
|
1007 |
|
1008 if (oldPreinstallState >= 0) |
|
1009 { |
|
1010 // Entry exists, update version into it. |
|
1011 if (aSuiteInfo.iPreinstallState == aSuiteInfo.STATE_PREINSTALLED) |
|
1012 { |
|
1013 // Update preinstall state only if the new state |
|
1014 // indicates preinstallation. |
|
1015 entry.addAttribute |
|
1016 (new StorageAttribute |
|
1017 (StorageNames.INSTALL_STATE, |
|
1018 Integer.toString(aSuiteInfo.iPreinstallState), |
|
1019 StorageAttribute.INT_TYPE)); |
|
1020 Log.log("Setting preinstall state to " + |
|
1021 aSuiteInfo.iPreinstallState); |
|
1022 } |
|
1023 iSession.update(StorageNames.PREINSTALL_TABLE, entry, matchEntry); |
|
1024 } |
|
1025 else |
|
1026 { |
|
1027 // Entry does not exist, create it with name, vendor, |
|
1028 // version and state. |
|
1029 entry.addAttribute |
|
1030 (new StorageAttribute |
|
1031 (StorageNames.INSTALL_STATE, |
|
1032 Integer.toString(aSuiteInfo.iPreinstallState), |
|
1033 StorageAttribute.INT_TYPE)); |
|
1034 Log.log("Setting preinstall state to " + |
|
1035 aSuiteInfo.iPreinstallState); |
|
1036 iSession.write(StorageNames.PREINSTALL_TABLE, entry); |
|
1037 } |
|
1038 } |
|
1039 |
|
1040 /** |
|
1041 * Updates preinstall state to STATE_NO_PREINSTALL in |
|
1042 * StorageNames.PREINSTALL_TABLE table. |
|
1043 */ |
|
1044 private void setNoPreinstallState(SuiteInfo aSuiteInfo) |
|
1045 { |
|
1046 if (aSuiteInfo == null) |
|
1047 { |
|
1048 return; |
|
1049 } |
|
1050 |
|
1051 // Match preinstall state using name and vendor. |
|
1052 StorageEntry matchEntry = new StorageEntry(); |
|
1053 matchEntry.addAttribute |
|
1054 (new StorageAttribute |
|
1055 (StorageNames.NAME, aSuiteInfo.getName())); |
|
1056 matchEntry.addAttribute |
|
1057 (new StorageAttribute |
|
1058 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
1059 |
|
1060 // Create a new entry with name, vendor, version and state. |
|
1061 StorageEntry entry = new StorageEntry(); |
|
1062 entry.addAttribute |
|
1063 (new StorageAttribute |
|
1064 (StorageNames.NAME, aSuiteInfo.getName())); |
|
1065 entry.addAttribute |
|
1066 (new StorageAttribute |
|
1067 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
1068 entry.addAttribute |
|
1069 (new StorageAttribute |
|
1070 (StorageNames.VERSION, aSuiteInfo.getVersion().toString())); |
|
1071 entry.addAttribute |
|
1072 (new StorageAttribute |
|
1073 (StorageNames.INSTALL_STATE, |
|
1074 Integer.toString(aSuiteInfo.STATE_NO_PREINSTALL), |
|
1075 StorageAttribute.INT_TYPE)); |
|
1076 |
|
1077 Log.log("Setting preinstall state to " + |
|
1078 aSuiteInfo.STATE_NO_PREINSTALL); |
|
1079 iSession.update(StorageNames.PREINSTALL_TABLE, entry, matchEntry); |
|
1080 } |
|
1081 |
|
1082 /** |
|
1083 * Removes preinstall state for given suite from |
|
1084 * preinstall table but only if preinstall state |
|
1085 * in given SuiteInfo is SuiteInfo.STATE_INSTALLED. |
|
1086 */ |
|
1087 private void removePreinstallState(SuiteInfo aSuiteInfo) |
|
1088 { |
|
1089 if (aSuiteInfo == null || |
|
1090 aSuiteInfo.iPreinstallState != aSuiteInfo.STATE_INSTALLED) |
|
1091 { |
|
1092 return; |
|
1093 } |
|
1094 // Match preinstall state using name and vendor. |
|
1095 StorageEntry matchEntry = new StorageEntry(); |
|
1096 matchEntry.addAttribute |
|
1097 (new StorageAttribute |
|
1098 (StorageNames.NAME, aSuiteInfo.getName())); |
|
1099 matchEntry.addAttribute |
|
1100 (new StorageAttribute |
|
1101 (StorageNames.VENDOR, aSuiteInfo.getVendor())); |
|
1102 |
|
1103 Log.log("Removing preinstall state"); |
|
1104 iSession.remove(StorageNames.PREINSTALL_TABLE, matchEntry); |
|
1105 } |
|
1106 |
|
1107 /** |
|
1108 * Checks that JavaStorage session exists. |
|
1109 * @throws InstallerException if session does not exist. |
|
1110 */ |
|
1111 private void checkSession() |
|
1112 { |
|
1113 if (iSession == null) |
|
1114 { |
|
1115 InstallerException.internalError("Session does not exist."); |
|
1116 } |
|
1117 } |
|
1118 |
|
1119 /** |
|
1120 * Checks that JavaStorage transaction exists. |
|
1121 * @throws InstallerException if transaction does not exist. |
|
1122 */ |
|
1123 private void checkTransaction() |
|
1124 { |
|
1125 if (!iTransactionExists) |
|
1126 { |
|
1127 InstallerException.internalError("Transaction does not exist."); |
|
1128 } |
|
1129 } |
|
1130 |
|
1131 /** |
|
1132 * Sort the suite applications by matching application mainclass |
|
1133 * names and classnames in MIDlet-n attributes. |
|
1134 */ |
|
1135 private void sortApps(SuiteInfo aSuiteInfo) |
|
1136 { |
|
1137 Vector apps = aSuiteInfo.getApplications(); |
|
1138 ApplicationInfo[] sortedApps = new ApplicationInfo[apps.size()]; |
|
1139 for (int i = 0; i < apps.size(); i++) |
|
1140 { |
|
1141 ApplicationInfo app = (ApplicationInfo)apps.elementAt(i); |
|
1142 String appMainClass = app.getMainClass(); |
|
1143 for (int j = 1; true; j++) |
|
1144 { |
|
1145 String attrValue = aSuiteInfo.getAttributeValue("MIDlet-" + j); |
|
1146 if (attrValue == null) |
|
1147 { |
|
1148 break; |
|
1149 } |
|
1150 String[] tokens = Tokenizer.split(attrValue, ","); |
|
1151 if (tokens[2].trim().equals(appMainClass)) |
|
1152 { |
|
1153 while (j < sortedApps.length && sortedApps[j - 1] != null) |
|
1154 { |
|
1155 // Increase j in case the same class name is already |
|
1156 // used by some other application in the same suite. |
|
1157 j++; |
|
1158 } |
|
1159 sortedApps[j-1] = (ApplicationInfo)apps.elementAt(i); |
|
1160 break; |
|
1161 } |
|
1162 } |
|
1163 } |
|
1164 aSuiteInfo.setApplications(new Vector()); |
|
1165 for (int i = 0; i < sortedApps.length; i++) |
|
1166 { |
|
1167 aSuiteInfo.addApplication(sortedApps[i]); |
|
1168 } |
|
1169 } |
|
1170 } |