|
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.applicationregistrator; |
|
20 |
|
21 import com.nokia.mj.impl.installer.storagehandler.ApplicationInfo; |
|
22 import com.nokia.mj.impl.installer.storagehandler.SuiteInfo; |
|
23 import com.nokia.mj.impl.installer.utils.ComponentId; |
|
24 import com.nokia.mj.impl.installer.utils.InstallerException; |
|
25 import com.nokia.mj.impl.installer.utils.FileUtils; |
|
26 import com.nokia.mj.impl.installer.utils.Log; |
|
27 import com.nokia.mj.impl.installer.utils.PlatformUid; |
|
28 import com.nokia.mj.impl.rt.installer.ApplicationInfoImpl; |
|
29 import com.nokia.mj.impl.utils.Attribute; |
|
30 import com.nokia.mj.impl.utils.Uid; |
|
31 |
|
32 import java.util.Enumeration; |
|
33 import java.util.Hashtable; |
|
34 import java.util.Vector; |
|
35 |
|
36 /** |
|
37 * Registers (and unregisters) Java application to S60 platform's |
|
38 * software installation framework (USIF). |
|
39 */ |
|
40 public final class SifRegistrator |
|
41 { |
|
42 /** Added application. Used with notifyAppChange() method. */ |
|
43 public static final int APP_ADDED = 0; |
|
44 /** Removed application. Used with notifyAppChange() method. */ |
|
45 public static final int APP_REMOVED = 1; |
|
46 /** Updated application. Used with notifyAppChange() method. */ |
|
47 public static final int APP_UPDATED = 2; |
|
48 |
|
49 /** Native session handle. */ |
|
50 private int iSessionHandle = 0; |
|
51 |
|
52 /*** ----------------------------- PUBLIC ------------------------------ */ |
|
53 |
|
54 /** |
|
55 * Returns greater than zero if application registration to |
|
56 * software installation framework is enabled. |
|
57 */ |
|
58 public static int getSifMode() |
|
59 { |
|
60 return _getUsifMode(); |
|
61 } |
|
62 |
|
63 /** |
|
64 * Launches the application view. If launching application view |
|
65 * fails this method does not throw exception but produces an |
|
66 * error log entry. |
|
67 */ |
|
68 public static void launchAppView() |
|
69 { |
|
70 int err = _launchAppView(); |
|
71 if (err < 0) |
|
72 { |
|
73 Log.logError("Launching AppLib failed with code " + err); |
|
74 } |
|
75 } |
|
76 |
|
77 /** |
|
78 * Notifies system about added/updated/removed applications. |
|
79 * This method should be called only after the changes have been |
|
80 * committed. |
|
81 * |
|
82 * @param aAppUids application uids |
|
83 * @param aAppChange change type: APP_ADDED, APP_UPDATED, or APP_REMOVED |
|
84 * @throws InstallerException if notification fails |
|
85 */ |
|
86 public static void notifyAppChange(Uid[] aAppUids, int aAppChange) |
|
87 { |
|
88 if (aAppUids == null || aAppUids.length == 0) |
|
89 { |
|
90 return; |
|
91 } |
|
92 int[] appUids = new int[aAppUids.length]; |
|
93 for (int i = 0; i < appUids.length; i++) |
|
94 { |
|
95 appUids[i] = ((PlatformUid)aAppUids[i]).getIntValue(); |
|
96 } |
|
97 int err = _notifyAppChange(appUids, aAppChange); |
|
98 if (err < 0) |
|
99 { |
|
100 InstallerException.internalError( |
|
101 "Notifying app changes failed with code " + err); |
|
102 } |
|
103 } |
|
104 |
|
105 /** |
|
106 * Get component uid basing on component id. |
|
107 * This method can be called before session is created. |
|
108 * |
|
109 * @param aCid component id |
|
110 * @return uid for the component, or null if component is not found |
|
111 * @throws InstallerException if an error occurs |
|
112 */ |
|
113 public static Uid getUid(int aCid) |
|
114 { |
|
115 // Use ComponentId to return int type value from native to java. |
|
116 ComponentId id = new ComponentId(); |
|
117 int err = _getUid(aCid, id); |
|
118 if (err < 0) |
|
119 { |
|
120 InstallerException.internalError( |
|
121 "Getting uid for cid " + aCid + " failed with code " + err); |
|
122 } |
|
123 Uid uid = null; |
|
124 if (id.getId() != 0) |
|
125 { |
|
126 uid = PlatformUid.createUid(id.getId()); |
|
127 } |
|
128 return uid; |
|
129 } |
|
130 |
|
131 /** |
|
132 * Registers or unregisters Java software type to software |
|
133 * installation framework. |
|
134 * |
|
135 * @param aRegister true for registration, false for unregistration |
|
136 */ |
|
137 public static void registerJavaSoftwareType(boolean aRegister) |
|
138 { |
|
139 String op = (aRegister? "Register": "Unregister"); |
|
140 int err = _registerJavaSoftwareType(aRegister); |
|
141 if (err < 0) |
|
142 { |
|
143 InstallerException.internalError( |
|
144 op + " Java software type failed with code " + err); |
|
145 } |
|
146 else |
|
147 { |
|
148 Log.log("SifRegistrator " + op + "ed Java software type"); |
|
149 } |
|
150 } |
|
151 |
|
152 /** |
|
153 * Starts application registration session. |
|
154 * The registrations and unregistrations are done only |
|
155 * when commitSession is called. |
|
156 * If you want to discard the registrations and unregistrations |
|
157 * call rollbackSession. |
|
158 * Does nothing if session has already been successfully started |
|
159 * from this SifRegistrator instance. |
|
160 * |
|
161 * @param aTransaction true if also transaction for this session should |
|
162 * be opened, false otherwise |
|
163 * @throws InstallerException if the session cannot created |
|
164 * @see commitSession |
|
165 * @see rollbackSession |
|
166 */ |
|
167 public void startSession(boolean aTransaction) |
|
168 { |
|
169 if (0 != iSessionHandle) |
|
170 { |
|
171 // Session has already been created, do nothing. |
|
172 Log.logWarning("SifRegistrator.startSession called although session is already open."); |
|
173 return; |
|
174 } |
|
175 |
|
176 // Native method writes error log and returns |
|
177 // negative Symbian error code if it fails. |
|
178 int ret = _startSession(aTransaction); |
|
179 if (ret < 0) |
|
180 { |
|
181 InstallerException.internalError( |
|
182 "Creating session failed with code " + ret); |
|
183 } |
|
184 //Log.log("SifRegistrator session started"); |
|
185 iSessionHandle = ret; |
|
186 } |
|
187 |
|
188 /** |
|
189 * Registers Java application suite to S60 USIF. |
|
190 * |
|
191 * @param aSuiteInfo Information needed to register the application |
|
192 * @param aIsUpdate true in case of an update, false in case of a new |
|
193 * installation |
|
194 * @throws InstallerException if registration cannot done or |
|
195 * startSession has not been called successfully |
|
196 * @see startSession |
|
197 * @see SuiteInfo |
|
198 */ |
|
199 public void registerSuite(SuiteInfo aSuiteInfo, boolean aIsUpdate) |
|
200 { |
|
201 if (0 == iSessionHandle) |
|
202 { |
|
203 InstallerException.internalError("No valid SIF session."); |
|
204 } |
|
205 Log.log("SifRegistrator registering application suite " + |
|
206 aSuiteInfo.getGlobalId()); |
|
207 |
|
208 if (_getUsifMode() > 0) |
|
209 { |
|
210 // USIF Phase 2 registration. |
|
211 // Register suite as a component. |
|
212 registerComponent(aSuiteInfo, aIsUpdate); |
|
213 registerLocalizedComponentName(aSuiteInfo, -1); |
|
214 // Register applications within the component. |
|
215 Vector apps = aSuiteInfo.getApplications(); |
|
216 for (int i = 0; i < apps.size(); i++) |
|
217 { |
|
218 registerApplication(aSuiteInfo, i); |
|
219 } |
|
220 } |
|
221 else |
|
222 { |
|
223 // USIF Phase 1 registration. |
|
224 // Register each application in the suite. |
|
225 Vector apps = aSuiteInfo.getApplications(); |
|
226 for (int i = 0; i < apps.size(); i++) |
|
227 { |
|
228 registerComponent(aSuiteInfo, i, aIsUpdate); |
|
229 registerLocalizedComponentName(aSuiteInfo, i); |
|
230 } |
|
231 } |
|
232 registerLocalizedProperties(aSuiteInfo); |
|
233 } |
|
234 |
|
235 /** |
|
236 * Unregisters Java application suite from S60 USIF. |
|
237 * |
|
238 * @param aSuiteInfo Information needed to unregister the application, |
|
239 * @throws InstallerException if unregistration cannot done or |
|
240 * startSession has not been called successfully |
|
241 * @see startSession |
|
242 * @see SuiteInfo |
|
243 */ |
|
244 public void unregisterSuite(SuiteInfo aSuiteInfo) |
|
245 { |
|
246 if (0 == iSessionHandle) |
|
247 { |
|
248 InstallerException.internalError("No valid SIF session."); |
|
249 } |
|
250 Log.log("SifRegistrator unregistering application suite " + |
|
251 aSuiteInfo.getGlobalId()); |
|
252 |
|
253 if (_getUsifMode() > 0) |
|
254 { |
|
255 // USIF Phase 2 unregistration. |
|
256 // Unregister suite as a component. |
|
257 unregisterComponent(aSuiteInfo); |
|
258 } |
|
259 else |
|
260 { |
|
261 // USIF Phase 1 unregistration. |
|
262 // Unregister each application in the suite. |
|
263 Vector apps = aSuiteInfo.getApplications(); |
|
264 for (int i = 0; i < apps.size(); i++) |
|
265 { |
|
266 unregisterComponent(aSuiteInfo, i); |
|
267 } |
|
268 } |
|
269 } |
|
270 |
|
271 /** |
|
272 * Commits the registrations and unregistrations. |
|
273 * Ends the current session if commit is successfull. |
|
274 * If commit fails the session is kept open so that |
|
275 * rollbackSession can be called. |
|
276 * |
|
277 * @throws InstallerException if session cannot be committed |
|
278 */ |
|
279 public void commitSession() |
|
280 { |
|
281 if (0 == iSessionHandle) |
|
282 { |
|
283 InstallerException.internalError("No valid SIF session."); |
|
284 } |
|
285 |
|
286 int err = _commitSession(iSessionHandle); |
|
287 if (err < 0) |
|
288 { |
|
289 InstallerException.internalError("Commiting session failed with code " + err); |
|
290 } |
|
291 // Current session has been closed |
|
292 iSessionHandle = 0; |
|
293 //Log.log("SifRegistrator session committed"); |
|
294 } |
|
295 |
|
296 /** |
|
297 * Rolls back the registrations and unregistrations. |
|
298 * Ends the current session. |
|
299 * |
|
300 * @throws InstallerException if session cannot be rolled back. |
|
301 */ |
|
302 public void rollbackSession() |
|
303 { |
|
304 if (0 == iSessionHandle) |
|
305 { |
|
306 InstallerException.internalError("No valid SIF session."); |
|
307 } |
|
308 |
|
309 int err = _rollbackSession(iSessionHandle); |
|
310 // Session is closed always when rollback is called |
|
311 iSessionHandle = 0; |
|
312 if (err < 0) |
|
313 { |
|
314 InstallerException.internalError("Rolling back the session failed with code " + err); |
|
315 } |
|
316 //Log.log("SifRegistrator session rolled back"); |
|
317 } |
|
318 |
|
319 /** |
|
320 * Closes the current session if it still open. |
|
321 * If registerComponent or unregisterComponent has been called, |
|
322 * commitSession or rollbackSession must be called instead of this method. |
|
323 */ |
|
324 public void closeSession() |
|
325 { |
|
326 if (0 == iSessionHandle) |
|
327 { |
|
328 return; |
|
329 } |
|
330 |
|
331 _closeSession(iSessionHandle); |
|
332 // Current session has been closed |
|
333 iSessionHandle = 0; |
|
334 //Log.log("SifRegistrator session closed"); |
|
335 } |
|
336 |
|
337 /** |
|
338 * Returns the component id of the application. |
|
339 * |
|
340 * @param aGlobalId the global id for the application. |
|
341 * @return the component id for the application, or null if the |
|
342 * application with given global id cannot be found. |
|
343 * @throws InstallerException if an error occurs |
|
344 */ |
|
345 public ComponentId getComponentId(String aGlobalId) |
|
346 { |
|
347 if (0 == iSessionHandle) |
|
348 { |
|
349 InstallerException.internalError("No valid SIF session."); |
|
350 } |
|
351 |
|
352 ComponentId result = new ComponentId(); |
|
353 int ret = _getComponentId(iSessionHandle, aGlobalId, result); |
|
354 if (-1 == ret) |
|
355 { |
|
356 // Symbian error code KErrNotFound means that the |
|
357 // application with given global id does not exist. |
|
358 result = null; |
|
359 } |
|
360 else if (ret < -1) |
|
361 { |
|
362 InstallerException.internalError( |
|
363 "Getting component id for global id " + aGlobalId + |
|
364 " failed with code " + ret); |
|
365 } |
|
366 return result; |
|
367 } |
|
368 |
|
369 /** |
|
370 * Returns the component id of the application. |
|
371 * |
|
372 * @param aAppUid the uid for the application. |
|
373 * @return the component id for the application, or null if the |
|
374 * application with given uid cannot be found. |
|
375 * @throws InstallerException if an error occurs |
|
376 */ |
|
377 public ComponentId getComponentId(Uid aAppUid) |
|
378 { |
|
379 if (0 == iSessionHandle) |
|
380 { |
|
381 InstallerException.internalError("No valid SIF session."); |
|
382 } |
|
383 |
|
384 ComponentId result = new ComponentId(); |
|
385 int ret = _getComponentIdForApp( |
|
386 iSessionHandle, ((PlatformUid)aAppUid).getIntValue(), result); |
|
387 if (-1 == ret) |
|
388 { |
|
389 // Symbian error code KErrNotFound means that the |
|
390 // application with given uid does not exist. |
|
391 result = null; |
|
392 } |
|
393 else if (ret < -1) |
|
394 { |
|
395 InstallerException.internalError( |
|
396 "Getting component id for uid " + aAppUid + |
|
397 " failed with code " + ret); |
|
398 } |
|
399 return result; |
|
400 } |
|
401 |
|
402 /** |
|
403 * Writes information of the given application to JavaInstaller log. |
|
404 * |
|
405 * @param aGlobalId the global id for the application. |
|
406 */ |
|
407 public void logComponent(String aGlobalId) |
|
408 { |
|
409 if (0 == iSessionHandle) |
|
410 { |
|
411 InstallerException.internalError("No valid SIF session."); |
|
412 } |
|
413 |
|
414 int ret = _logComponent(iSessionHandle, aGlobalId); |
|
415 if (ret < -1) |
|
416 { |
|
417 Log.logError("SifRegistrator logComponent failed with code " + ret); |
|
418 } |
|
419 } |
|
420 |
|
421 /*** ----------------------------- PACKAGE ---------------------------- */ |
|
422 /*** ----------------------------- PRIVATE ---------------------------- */ |
|
423 |
|
424 /** |
|
425 * Registers one Java application to S60 USIF as a component. |
|
426 * Used with USIF Phase 1. |
|
427 * |
|
428 * @param aSuiteInfo Information needed to register the application |
|
429 * @param aIndex index of the application in the suite |
|
430 * @param aIsUpdate true in case of an update, false in case of a new |
|
431 * installation |
|
432 * @throws InstallerException if registration cannot done or |
|
433 * startSession has not been called successfully |
|
434 * @see startSession |
|
435 * @see SuiteInfo |
|
436 */ |
|
437 private void registerComponent( |
|
438 SuiteInfo aSuiteInfo, int aIndex, boolean aIsUpdate) |
|
439 { |
|
440 String globalId = aSuiteInfo.getGlobalId(aIndex); |
|
441 if (globalId == null) |
|
442 { |
|
443 Log.logWarning("SifRegistrator: Application with index " + aIndex + |
|
444 " not found from " + aSuiteInfo.getGlobalId()); |
|
445 return; |
|
446 } |
|
447 ApplicationInfo appInfo = |
|
448 (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex); |
|
449 String suiteName = aSuiteInfo.getName(); |
|
450 String vendor = aSuiteInfo.getVendor(); |
|
451 String version = aSuiteInfo.getVersion().toString(); |
|
452 String name = appInfo.getName(); |
|
453 int uid = ((PlatformUid)appInfo.getUid()).getIntValue(); |
|
454 String[] componentFiles = getComponentFiles(aSuiteInfo); |
|
455 long componentSize = aSuiteInfo.getInitialSize(); |
|
456 String attrValue = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Block-Uninstall"); |
|
457 boolean isRemovable = !(attrValue != null && attrValue.equalsIgnoreCase("true")); |
|
458 boolean isDrmProtected = (aSuiteInfo.getContentInfo() == aSuiteInfo.CONTENT_INFO_DRM); |
|
459 boolean isOriginVerified = aSuiteInfo.isTrusted(); |
|
460 String midletInfoUrl = aSuiteInfo.getAttributeValue("MIDlet-Info-URL"); |
|
461 String midletDescription = aSuiteInfo.getAttributeValue("MIDlet-Description"); |
|
462 String downloadUrl = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Download-URL"); |
|
463 ComponentId componentId = new ComponentId(); |
|
464 int err = _registerComponent( |
|
465 iSessionHandle, uid, |
|
466 getScrString(suiteName), getScrString(vendor), |
|
467 getScrString(version), getScrString(name), |
|
468 getScrString(globalId), componentFiles, |
|
469 componentSize, isRemovable, isDrmProtected, |
|
470 isOriginVerified, aIsUpdate, aSuiteInfo.getMediaId(), |
|
471 getScrString(midletInfoUrl), |
|
472 getScrString(midletDescription), |
|
473 getScrString(downloadUrl), |
|
474 componentId); |
|
475 if (err < 0) |
|
476 { |
|
477 InstallerException.internalError( |
|
478 "Registering component " + globalId + |
|
479 " failed with code " + err); |
|
480 } |
|
481 else |
|
482 { |
|
483 appInfo.setComponentId(componentId); |
|
484 Log.log("SifRegistrator registered component " + globalId + |
|
485 " with id " + componentId.getId()); |
|
486 } |
|
487 } |
|
488 |
|
489 /** |
|
490 * Unregisters one Java application from being S60 USIF component. |
|
491 * Used with USIF Phase 1. |
|
492 * |
|
493 * @param aSuiteInfo Information needed to unregister the application, |
|
494 * @param aIndex index of the application in the suite |
|
495 * @throws InstallerException if unregistration cannot done or |
|
496 * startSession has not been called successfully |
|
497 * @see startSession |
|
498 * @see SuiteInfo |
|
499 */ |
|
500 private void unregisterComponent(SuiteInfo aSuiteInfo, int aIndex) |
|
501 { |
|
502 String globalId = aSuiteInfo.getGlobalId(aIndex); |
|
503 if (globalId == null) |
|
504 { |
|
505 Log.logWarning("SifRegistrator: Application with index " + aIndex + |
|
506 " not found from " + aSuiteInfo.getGlobalId()); |
|
507 return; |
|
508 } |
|
509 ComponentId componentId = getComponentId(globalId); |
|
510 if (componentId == null) |
|
511 { |
|
512 Log.logWarning( |
|
513 "SifRegistrator unregistration failed, application " + |
|
514 globalId + " does not exist"); |
|
515 return; |
|
516 } |
|
517 // Save component id to ApplicationInfo. |
|
518 ApplicationInfo appInfo = |
|
519 (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex); |
|
520 appInfo.setComponentId(componentId); |
|
521 // Unregister application. |
|
522 int err = _unregisterComponent(iSessionHandle, componentId.getId()); |
|
523 if (err < 0) |
|
524 { |
|
525 InstallerException.internalError( |
|
526 "Unregistering component " + globalId + |
|
527 " failed with code " + err); |
|
528 } |
|
529 else |
|
530 { |
|
531 Log.log("SifRegistrator unregistered component " + globalId + |
|
532 " with id " + componentId.getId()); |
|
533 } |
|
534 } |
|
535 |
|
536 /** |
|
537 * Registers Java application suite to S60 USIF as a component. |
|
538 * Used with USIF Phase 2. |
|
539 * |
|
540 * @param aSuiteInfo Suite information |
|
541 * @param aIsUpdate true in case of an update, false in case of a new |
|
542 * installation |
|
543 * @throws InstallerException if registration cannot done or |
|
544 * startSession has not been called successfully |
|
545 * @see startSession |
|
546 * @see SuiteInfo |
|
547 */ |
|
548 private void registerComponent(SuiteInfo aSuiteInfo, boolean aIsUpdate) |
|
549 { |
|
550 String globalId = aSuiteInfo.getGlobalId(); |
|
551 String suiteName = aSuiteInfo.getName(); |
|
552 String vendor = aSuiteInfo.getVendor(); |
|
553 String version = aSuiteInfo.getVersion().toString(); |
|
554 String name = null; // Set name to null so that suite name will be used. |
|
555 int uid = ((PlatformUid)aSuiteInfo.getUid()).getIntValue(); |
|
556 String[] componentFiles = getComponentFiles(aSuiteInfo); |
|
557 long componentSize = aSuiteInfo.getInitialSize(); |
|
558 String attrValue = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Block-Uninstall"); |
|
559 boolean isRemovable = !(attrValue != null && attrValue.equalsIgnoreCase("true")); |
|
560 boolean isDrmProtected = (aSuiteInfo.getContentInfo() == aSuiteInfo.CONTENT_INFO_DRM); |
|
561 boolean isOriginVerified = aSuiteInfo.isTrusted(); |
|
562 String midletInfoUrl = aSuiteInfo.getAttributeValue("MIDlet-Info-URL"); |
|
563 String midletDescription = aSuiteInfo.getAttributeValue("MIDlet-Description"); |
|
564 String downloadUrl = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Download-URL"); |
|
565 ComponentId componentId = new ComponentId(); |
|
566 int err = _registerComponent( |
|
567 iSessionHandle, uid, |
|
568 getScrString(suiteName), getScrString(vendor), |
|
569 getScrString(version), getScrString(name), |
|
570 getScrString(globalId), componentFiles, |
|
571 componentSize, isRemovable, isDrmProtected, |
|
572 isOriginVerified, aIsUpdate, aSuiteInfo.getMediaId(), |
|
573 getScrString(midletInfoUrl), |
|
574 getScrString(midletDescription), |
|
575 getScrString(downloadUrl), |
|
576 componentId); |
|
577 if (err < 0) |
|
578 { |
|
579 InstallerException.internalError( |
|
580 "Registering component " + globalId + |
|
581 " failed with code " + err); |
|
582 } |
|
583 else |
|
584 { |
|
585 aSuiteInfo.setComponentId(componentId); |
|
586 Log.log("SifRegistrator registered component " + globalId + |
|
587 " with id " + componentId.getId()); |
|
588 } |
|
589 } |
|
590 |
|
591 /** |
|
592 * Unregisters Java application suite from being S60 USIF component. |
|
593 * Used with USIF Phase 2. |
|
594 * |
|
595 * @param aSuiteInfo suite information |
|
596 * @throws InstallerException if unregistration cannot done or |
|
597 * startSession has not been called successfully |
|
598 * @see startSession |
|
599 * @see SuiteInfo |
|
600 */ |
|
601 private void unregisterComponent(SuiteInfo aSuiteInfo) |
|
602 { |
|
603 String globalId = aSuiteInfo.getGlobalId(); |
|
604 ComponentId componentId = getComponentId(globalId); |
|
605 if (componentId == null) |
|
606 { |
|
607 Log.logWarning( |
|
608 "SifRegistrator unregistration failed, application " + |
|
609 globalId + " does not exist"); |
|
610 return; |
|
611 } |
|
612 // Save component id to SuiteInfo. |
|
613 aSuiteInfo.setComponentId(componentId); |
|
614 // Unregister application. |
|
615 int err = _unregisterComponent(iSessionHandle, componentId.getId()); |
|
616 if (err < 0) |
|
617 { |
|
618 InstallerException.internalError( |
|
619 "Unregistering component " + globalId + |
|
620 " failed with code " + err); |
|
621 } |
|
622 else |
|
623 { |
|
624 Log.log("SifRegistrator unregistered component " + globalId + |
|
625 " with id " + componentId.getId()); |
|
626 } |
|
627 } |
|
628 |
|
629 /** |
|
630 * Registers one Java application to S60 USIF as an S60 application. |
|
631 * The application is registered to component whose id is taken |
|
632 * from given SuiteInfo object. The SuiteInfo must already have |
|
633 * been registered to USIF as a component with registerComponent() |
|
634 * method before this method is called. |
|
635 * Used with USIF Phase 2. |
|
636 * |
|
637 * @param aSuiteInfo information needed to register the application |
|
638 * @param aIndex index of the application in the suite |
|
639 * @throws InstallerException if registration cannot done or |
|
640 * startSession has not been called successfully |
|
641 * @see startSession |
|
642 * @see SuiteInfo |
|
643 */ |
|
644 private void registerApplication(SuiteInfo aSuiteInfo, int aIndex) |
|
645 { |
|
646 int cid = aSuiteInfo.getComponentId().getId(); |
|
647 ApplicationInfo appInfo = |
|
648 (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex); |
|
649 int appUid = ((PlatformUid)appInfo.getUid()).getIntValue(); |
|
650 String appName = appInfo.getName(); |
|
651 String appFilename = aSuiteInfo.getJarPath(); |
|
652 String groupName = aSuiteInfo.getInstallationGroup(); |
|
653 if (groupName == null) |
|
654 { |
|
655 groupName = ""; // default installation group |
|
656 } |
|
657 String iconFilename = aSuiteInfo.getRegisteredIconPath(aIndex); |
|
658 Log.log("SifRegistrator iconFilename " + aIndex + ": " + iconFilename); |
|
659 int numberOfIcons = 1; |
|
660 // Initalize localized names for the application. |
|
661 LocalizedName[] localizedNames = getLocalizedNames( |
|
662 aSuiteInfo, "Nokia-MIDlet-" + (aIndex+1) + "-"); |
|
663 int[] languages = new int[localizedNames.length]; |
|
664 String[] appNames = new String[localizedNames.length]; |
|
665 for (int i = 0; i < localizedNames.length; i++) |
|
666 { |
|
667 languages[i] = localizedNames[i].getLanguage(); |
|
668 appNames[i] = localizedNames[i].getName(); |
|
669 } |
|
670 int err = _registerApplication( |
|
671 iSessionHandle, cid, appUid, appName, appFilename, groupName, |
|
672 iconFilename, numberOfIcons, languages, appNames); |
|
673 if (err < 0) |
|
674 { |
|
675 InstallerException.internalError( |
|
676 "Registering application " + appUid + " to component " + cid + |
|
677 " failed with code " + err); |
|
678 } |
|
679 else |
|
680 { |
|
681 Log.log("SifRegistrator registered application " + appUid + |
|
682 " to component " + cid); |
|
683 } |
|
684 } |
|
685 |
|
686 private static String[] getComponentFiles(SuiteInfo aSuite) |
|
687 { |
|
688 Vector componentFiles = new Vector(); |
|
689 String path = aSuite.getJadPath(); |
|
690 if (path != null) |
|
691 { |
|
692 componentFiles.addElement(getScrString(path)); |
|
693 } |
|
694 path = aSuite.getJarPath(); |
|
695 if (path != null) |
|
696 { |
|
697 componentFiles.addElement(getScrString(path)); |
|
698 } |
|
699 boolean addRootPath = true; |
|
700 int rootDrive = FileUtils.getDrive(aSuite.getRootDir()); |
|
701 for (int i = 0; i < componentFiles.size(); i++) |
|
702 { |
|
703 if (FileUtils.getDrive((String)componentFiles.elementAt(i)) == |
|
704 rootDrive) |
|
705 { |
|
706 // File from the root path drive already exists in |
|
707 // component files vector, no need to add root path |
|
708 // separately. |
|
709 addRootPath = false; |
|
710 break; |
|
711 } |
|
712 } |
|
713 if (addRootPath) |
|
714 { |
|
715 componentFiles.addElement(getScrString(aSuite.getRootDir())); |
|
716 } |
|
717 String[] result = new String[componentFiles.size()]; |
|
718 componentFiles.copyInto(result); |
|
719 return result; |
|
720 } |
|
721 |
|
722 /** |
|
723 * Registers localized names for given application from given suite. |
|
724 * This method can be called only after registerComponent method has |
|
725 * been called. |
|
726 * |
|
727 * @param aSuite suite info |
|
728 * @param aIndex index of the application within the suite, if -1 then |
|
729 * localized names for the suite itself is registered |
|
730 */ |
|
731 private void registerLocalizedComponentName(SuiteInfo aSuite, int aIndex) |
|
732 { |
|
733 LocalizedName[] localizedNames = null; |
|
734 int cid = 0; |
|
735 if (aIndex == -1) |
|
736 { |
|
737 if (aSuite.getComponentId() == null) |
|
738 { |
|
739 Log.logWarning( |
|
740 "SifRegistrator.registerLocalizedComponentName: cid not present in suite"); |
|
741 return; |
|
742 } |
|
743 cid = aSuite.getComponentId().getId(); |
|
744 localizedNames = getLocalizedNames(aSuite, "Nokia-MIDlet-Name-"); |
|
745 } |
|
746 else |
|
747 { |
|
748 ApplicationInfo app = |
|
749 (ApplicationInfo)aSuite.getApplications().elementAt(aIndex); |
|
750 if (app.getComponentId() == null) |
|
751 { |
|
752 Log.logWarning( |
|
753 "SifRegistrator.registerLocalizedComponentName: cid not present in app"); |
|
754 return; |
|
755 } |
|
756 cid = app.getComponentId().getId(); |
|
757 localizedNames = getLocalizedNames( |
|
758 aSuite, "Nokia-MIDlet-" + (aIndex+1) + "-"); |
|
759 } |
|
760 for (int i = 0; i < localizedNames.length; i++) |
|
761 { |
|
762 int err = _registerLocalizedComponentName( |
|
763 iSessionHandle, cid, |
|
764 getScrString(localizedNames[i].getName()), |
|
765 getScrString(aSuite.getVendor()), |
|
766 localizedNames[i].getLanguage()); |
|
767 if (err < 0) |
|
768 { |
|
769 InstallerException.internalError( |
|
770 "Adding localized name for component " + cid + |
|
771 " failed with code " + err + |
|
772 " (" + localizedNames[i] + ")"); |
|
773 } |
|
774 } |
|
775 } |
|
776 |
|
777 /** |
|
778 * Registers localized property values for given suite. |
|
779 * This method can be called only after registerComponent |
|
780 * method has been called. |
|
781 * |
|
782 * @param aSuite suite info |
|
783 */ |
|
784 private void registerLocalizedProperties(SuiteInfo aSuite) |
|
785 { |
|
786 if (aSuite.getComponentId() == null) |
|
787 { |
|
788 Log.logWarning( |
|
789 "SifRegistrator.registerLocalizedProperties: cid not present in suite"); |
|
790 return; |
|
791 } |
|
792 int cid = aSuite.getComponentId().getId(); |
|
793 final int UNSPECIFIED_LOCALE = -1; // KUnspecifiedLocale |
|
794 |
|
795 // Register MIDlet-Delete-Confirm attribute values. |
|
796 final String attrName = "MIDlet-Delete-Confirm"; |
|
797 String nonlocalizedAttrValue = aSuite.getAttributeValue(attrName); |
|
798 int err = _setLocalizedComponentProperty( |
|
799 iSessionHandle, cid, getScrString(attrName), |
|
800 getScrString(nonlocalizedAttrValue), UNSPECIFIED_LOCALE); |
|
801 if (err < 0) |
|
802 { |
|
803 InstallerException.internalError( |
|
804 "Adding property " + attrName + " for component " + cid + |
|
805 " failed with code " + err + " (" + nonlocalizedAttrValue + ")"); |
|
806 } |
|
807 LocalizedName[] localizedAttrValues = |
|
808 getLocalizedNames(aSuite, attrName + "-"); |
|
809 for (int i = 0; i < localizedAttrValues.length; i++) |
|
810 { |
|
811 err = _setLocalizedComponentProperty( |
|
812 iSessionHandle, cid, getScrString(attrName), |
|
813 getScrString(localizedAttrValues[i].getName()), |
|
814 localizedAttrValues[i].getLanguage()); |
|
815 if (err < 0) |
|
816 { |
|
817 InstallerException.internalError( |
|
818 "Adding localized property " + attrName + |
|
819 " for component " + cid + " failed with code " + err + |
|
820 " (" + localizedAttrValues[i] + ")"); |
|
821 } |
|
822 } |
|
823 |
|
824 // Register Domain-Category property. |
|
825 ApplicationInfoImpl appInfoImpl = (ApplicationInfoImpl) |
|
826 com.nokia.mj.impl.rt.support.ApplicationInfo.getInstance(); |
|
827 String domainCategory = appInfoImpl.getProtectionDomain(); |
|
828 err = _setLocalizedComponentProperty( |
|
829 iSessionHandle, cid, "Domain-Category", |
|
830 domainCategory, UNSPECIFIED_LOCALE); |
|
831 if (err < 0) |
|
832 { |
|
833 InstallerException.internalError( |
|
834 "Adding property Domain-Category value " + domainCategory + |
|
835 " for component " + cid + " failed with code " + err); |
|
836 } |
|
837 } |
|
838 |
|
839 /** |
|
840 * Returns array of localized names from the specified |
|
841 * attributes of given suite. Assumes that aAttrPrefix |
|
842 * is an attribute name prefix that is followed by locale. |
|
843 * If the same locale is found more than once, localized |
|
844 * name for only the last occurrence is returned. |
|
845 */ |
|
846 private LocalizedName[] getLocalizedNames( |
|
847 SuiteInfo aSuite, String aAttrPrefix) |
|
848 { |
|
849 Hashtable localizedNames = new Hashtable(); |
|
850 Enumeration e = aSuite.getAttributes().elements(); |
|
851 while (e.hasMoreElements()) |
|
852 { |
|
853 Attribute attr = (Attribute)e.nextElement(); |
|
854 String name = attr.getName(); |
|
855 if (name.startsWith(aAttrPrefix)) |
|
856 { |
|
857 String locale = name.substring(aAttrPrefix.length()); |
|
858 if (isValidLocale(locale)) |
|
859 { |
|
860 LocalizedName localizedName = |
|
861 new LocalizedName(attr.getValue(), locale); |
|
862 if (localizedName.getLanguage() == -1) |
|
863 { |
|
864 Log.logWarning( |
|
865 "SifRegistrator ignored unknown locale: " + |
|
866 name + ": " + localizedName); |
|
867 } |
|
868 else |
|
869 { |
|
870 Log.log("SifRegistrator found localized text " + |
|
871 name + ": " + localizedName); |
|
872 localizedNames.put( |
|
873 new Integer(localizedName.getLanguage()), |
|
874 localizedName); |
|
875 } |
|
876 } |
|
877 } |
|
878 } |
|
879 LocalizedName[] result = new LocalizedName[localizedNames.size()]; |
|
880 e = localizedNames.elements(); |
|
881 for (int i = 0; e.hasMoreElements(); i++) |
|
882 { |
|
883 result[i] = (LocalizedName)e.nextElement(); |
|
884 } |
|
885 return result; |
|
886 } |
|
887 |
|
888 /** |
|
889 * Returns true if given locale is a valid one. Valid locales |
|
890 * use two letter ISO language and optionally country codes. |
|
891 */ |
|
892 private boolean isValidLocale(String aLocale) |
|
893 { |
|
894 boolean result = false; |
|
895 if (aLocale.length() == 2) |
|
896 { |
|
897 // Assume that locale has only language code. |
|
898 result = true; |
|
899 } |
|
900 if (aLocale.length() == 5) |
|
901 { |
|
902 // Assume that locale has language and country codes. |
|
903 char separator = aLocale.charAt(2); |
|
904 if (separator == '-' || separator == '_') |
|
905 { |
|
906 result = true; |
|
907 } |
|
908 } |
|
909 return result; |
|
910 } |
|
911 |
|
912 /** |
|
913 * Returns a string which can be stored to S60 SCR. This method ensures |
|
914 * that the length of the returned string does not exceed the maximum |
|
915 * length limit set by SCR (512 characters). |
|
916 */ |
|
917 private static String getScrString(String aStr) |
|
918 { |
|
919 final int maxLen = 512; |
|
920 if (aStr != null && aStr.length() > maxLen) |
|
921 { |
|
922 return aStr.substring(0, maxLen); |
|
923 } |
|
924 return aStr; |
|
925 } |
|
926 |
|
927 /*** ----------------------------- NATIVE ----------------------------- */ |
|
928 |
|
929 /** |
|
930 * Notifies system about added/updated/removed applications. |
|
931 * This method should be called only after the changes have been |
|
932 * committed. |
|
933 * |
|
934 * @param aAppUids application uids |
|
935 * @param aAppChange change type: APP_ADDED, APP_UPDATED, or APP_REMOVED |
|
936 * @return 0 or Symbian error code (negative number) |
|
937 */ |
|
938 private static native int _notifyAppChange(int[] aAppUids, int aAppChange); |
|
939 |
|
940 /** |
|
941 * Launches the applications view. |
|
942 * |
|
943 * @return 0 or Symbian error code (negative number) |
|
944 */ |
|
945 private static native int _launchAppView(); |
|
946 |
|
947 /** |
|
948 * Registers Java software type to software installation framework. |
|
949 * |
|
950 * @param aRegister true for registration, false for unregistration |
|
951 * @return 0 or Symbian error code (negative number) |
|
952 */ |
|
953 private static native int _registerJavaSoftwareType(boolean aRegister); |
|
954 |
|
955 /** |
|
956 * Starts native application registration session. |
|
957 * |
|
958 * @param aTransaction true if also transaction for this session should |
|
959 * be opened, false otherwise |
|
960 * @return native session handle or Symbian error code (negative number) |
|
961 */ |
|
962 private static native int _startSession(boolean aTransaction); |
|
963 |
|
964 /** |
|
965 * Commits native application registration session. |
|
966 * If commit succeeds the native session is closed. |
|
967 * |
|
968 * @param aSessionHandle |
|
969 * @param aSynchronous if true, makes synchronous commit |
|
970 * @return 0 or Symbian error code (negative number) |
|
971 */ |
|
972 private static native int _commitSession(int aSessionHandle); |
|
973 |
|
974 /** |
|
975 * Rolls back and closes native application registration session. |
|
976 * |
|
977 * @param aSessionHandle |
|
978 * @return 0 or Symbian error code (negative number) |
|
979 */ |
|
980 private static native int _rollbackSession(int aSessionHandle); |
|
981 |
|
982 /** |
|
983 * Closes native application registration session. |
|
984 * |
|
985 * @param aSessionHandle the session to be closed |
|
986 */ |
|
987 private static native void _closeSession(int aSessionHandle); |
|
988 |
|
989 /** |
|
990 * Registers Java application to S60 USIF as a component. |
|
991 * |
|
992 * @param aSessionHandle |
|
993 * @param aUid |
|
994 * @param aSuiteName |
|
995 * @param aVendor |
|
996 * @param aVersion |
|
997 * @param aName |
|
998 * @param aGlobalId |
|
999 * @param aComponentFiles |
|
1000 * @param aComponentSize |
|
1001 * @param aIsRemovable |
|
1002 * @param aIsDrmProtected |
|
1003 * @param aIsOriginVerified |
|
1004 * @param aIsUpdate |
|
1005 * @param aMediaId |
|
1006 * @param aMidletInfoUrl |
|
1007 * @param aMidletDescription |
|
1008 * @param aDownloadUrl |
|
1009 * @param aComponentId upon successful execution contains the |
|
1010 * component id for the registered component |
|
1011 * @return 0 if registration succeeded or Symbian error code |
|
1012 */ |
|
1013 private static native int _registerComponent( |
|
1014 int aSessionHandle, int aUid, String aSuiteName, String aVendor, |
|
1015 String aVersion, String aName, String aGlobalId, |
|
1016 String[] aComponentFiles, long aComponentSize, |
|
1017 boolean aIsRemovable, boolean aIsDrmProtected, |
|
1018 boolean aIsOriginVerified, boolean aIsUpdate, int aMediaId, |
|
1019 String aMidletInfoUrl, String aMidletDescription, String aDownloadUrl, |
|
1020 ComponentId aComponentId); |
|
1021 |
|
1022 /** |
|
1023 * Unregisters Java application from S60 USIF. |
|
1024 * |
|
1025 * @param aSessionHandle |
|
1026 * @param aComponentId The component id of the application |
|
1027 * @return 0 if unregistration succeeded or Symbian error code |
|
1028 */ |
|
1029 private static native int _unregisterComponent( |
|
1030 int aSessionHandle, int aComponentId); |
|
1031 |
|
1032 /** |
|
1033 * Registers Java application to S60 USIF as an application |
|
1034 * inside specified component. |
|
1035 * |
|
1036 * @param aSessionHandle |
|
1037 * @param aCid |
|
1038 * @param aAppUid |
|
1039 * @param aAppName |
|
1040 * @param aAppFilename |
|
1041 * @param aGroupName |
|
1042 * @param aIconFilename |
|
1043 * @param aNumberOfIcons |
|
1044 * @param aLanguages |
|
1045 * @param aAppNames |
|
1046 * @return 0 if registration succeeded or Symbian error code |
|
1047 */ |
|
1048 private static native int _registerApplication( |
|
1049 int aSessionHandle, int aCid, int aAppUid, String aAppName, |
|
1050 String aAppFilename, String aGroupName, String aIconFilename, |
|
1051 int aNumberOfIcons, int[] aLanguages, String[] aAppNames); |
|
1052 |
|
1053 /** |
|
1054 * Registers localized name and vendor for specified component. |
|
1055 * |
|
1056 * @param aSessionHandle |
|
1057 * @param aCid component id |
|
1058 * @param aName localized component name |
|
1059 * @param aVendor localized component vendor (can be null) |
|
1060 * @param aLanguage S60 language code |
|
1061 * @return 0 if unregistration succeeded or Symbian error code |
|
1062 */ |
|
1063 private static native int _registerLocalizedComponentName( |
|
1064 int aSessionHandle, int aCid, String aName, String aVendor, int aLanguage); |
|
1065 |
|
1066 /** |
|
1067 * Sets localized property value for specified component. |
|
1068 * |
|
1069 * @param aSessionHandle |
|
1070 * @param aCid component id |
|
1071 * @param aName property name |
|
1072 * @param aValue localized property value |
|
1073 * @param aLanguage S60 language code |
|
1074 * @return 0 if unregistration succeeded or Symbian error code |
|
1075 */ |
|
1076 private static native int _setLocalizedComponentProperty( |
|
1077 int aSessionHandle, int aCid, String aName, String aValue, int aLanguage); |
|
1078 |
|
1079 /** |
|
1080 * Returns the component id of the application. |
|
1081 * |
|
1082 * @param aSessionHandle |
|
1083 * @param aGlobalId |
|
1084 * @param aComponentId contains component id after successful function call |
|
1085 * @return Symbian error code (negative number) if fails, otherwise 0 |
|
1086 */ |
|
1087 private static native int _getComponentId( |
|
1088 int aSessionHandle, String aGlobalId, ComponentId aComponentId); |
|
1089 |
|
1090 /** |
|
1091 * Returns the component id of the application. |
|
1092 * |
|
1093 * @param aSessionHandle |
|
1094 * @param aAppUid |
|
1095 * @param aComponentId contains component id after successful function call |
|
1096 * @return Symbian error code (negative number) if fails, otherwise 0 |
|
1097 */ |
|
1098 private static native int _getComponentIdForApp( |
|
1099 int aSessionHandle, int aAppUid, ComponentId aComponentId); |
|
1100 |
|
1101 /** |
|
1102 * Returns the uid of the component. |
|
1103 * |
|
1104 * @param aSessionHandle |
|
1105 * @param aCid component id |
|
1106 * @param aUid contains uid after successful function call |
|
1107 * @return Symbian error code (negative number) if fails, otherwise 0 |
|
1108 */ |
|
1109 private static native int _getUid(int aCid, ComponentId aUid); |
|
1110 |
|
1111 /** |
|
1112 * Writes information of the given application to JavaInstaller log. |
|
1113 * |
|
1114 * @param aSessionHandle |
|
1115 * @param aGlobalId the global id for the application |
|
1116 * @return Symbian error code (negative number) if fails, otherwise 0 |
|
1117 */ |
|
1118 private static native int _logComponent( |
|
1119 int aSessionHandle, String aGlobalId); |
|
1120 |
|
1121 /** |
|
1122 * Checks if USIF is enabled. |
|
1123 * |
|
1124 * @return 1 if application data should be registered to USIF, 0 otherwise |
|
1125 */ |
|
1126 private static native int _getUsifMode(); |
|
1127 } |