javamanager/javainstaller/installer/javasrc.s60/com/nokia/mj/impl/installer/applicationregistrator/SifRegistrator.java
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javamanager/javainstaller/installer/javasrc.s60/com/nokia/mj/impl/installer/applicationregistrator/SifRegistrator.java	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1127 @@
+/*
+* 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.applicationregistrator;
+
+import com.nokia.mj.impl.installer.storagehandler.ApplicationInfo;
+import com.nokia.mj.impl.installer.storagehandler.SuiteInfo;
+import com.nokia.mj.impl.installer.utils.ComponentId;
+import com.nokia.mj.impl.installer.utils.InstallerException;
+import com.nokia.mj.impl.installer.utils.FileUtils;
+import com.nokia.mj.impl.installer.utils.Log;
+import com.nokia.mj.impl.installer.utils.PlatformUid;
+import com.nokia.mj.impl.rt.installer.ApplicationInfoImpl;
+import com.nokia.mj.impl.utils.Attribute;
+import com.nokia.mj.impl.utils.Uid;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * Registers (and unregisters) Java application to S60 platform's
+ * software installation framework (USIF).
+ */
+public final class SifRegistrator
+{
+    /** Added application. Used with notifyAppChange() method. */
+    public static final int APP_ADDED = 0;
+    /** Removed application. Used with notifyAppChange() method. */
+    public static final int APP_REMOVED = 1;
+    /** Updated application. Used with notifyAppChange() method. */
+    public static final int APP_UPDATED = 2;
+
+    /** Native session handle. */
+    private int iSessionHandle = 0;
+
+    /*** ----------------------------- PUBLIC ------------------------------ */
+
+    /**
+     * Returns greater than zero if application registration to
+     * software installation framework is enabled.
+     */
+    public static int getSifMode()
+    {
+        return _getUsifMode();
+    }
+
+    /**
+     * Launches the application view. If launching application view
+     * fails this method does not throw exception but produces an
+     * error log entry.
+     */
+    public static void launchAppView()
+    {
+        int err = _launchAppView();
+        if (err < 0)
+        {
+            Log.logError("Launching AppLib failed with code " + err);
+        }
+    }
+
+    /**
+     * Notifies system about added/updated/removed applications.
+     * This method should be called only after the changes have been
+     * committed.
+     *
+     * @param aAppUids application uids
+     * @param aAppChange change type: APP_ADDED, APP_UPDATED, or APP_REMOVED
+     * @throws InstallerException if notification fails
+     */
+    public static void notifyAppChange(Uid[] aAppUids, int aAppChange)
+    {
+        if (aAppUids == null || aAppUids.length == 0)
+        {
+            return;
+        }
+        int[] appUids = new int[aAppUids.length];
+        for (int i = 0; i < appUids.length; i++)
+        {
+            appUids[i] = ((PlatformUid)aAppUids[i]).getIntValue();
+        }
+        int err = _notifyAppChange(appUids, aAppChange);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Notifying app changes failed with code " + err);
+        }
+    }
+
+    /**
+     * Get component uid basing on component id.
+     * This method can be called before session is created.
+     *
+     * @param aCid component id
+     * @return uid for the component, or null if component is not found
+     * @throws InstallerException if an error occurs
+     */
+    public static Uid getUid(int aCid)
+    {
+        // Use ComponentId to return int type value from native to java.
+        ComponentId id = new ComponentId();
+        int err = _getUid(aCid, id);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Getting uid for cid " + aCid + " failed with code " + err);
+        }
+        Uid uid = null;
+        if (id.getId() != 0)
+        {
+            uid = PlatformUid.createUid(id.getId());
+        }
+        return uid;
+    }
+
+    /**
+     * Registers or unregisters Java software type to software
+     * installation framework.
+     *
+     * @param aRegister true for registration, false for unregistration
+     */
+    public static void registerJavaSoftwareType(boolean aRegister)
+    {
+        String op = (aRegister? "Register": "Unregister");
+        int err = _registerJavaSoftwareType(aRegister);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                op + " Java software type failed with code " + err);
+        }
+        else
+        {
+            Log.log("SifRegistrator " + op + "ed Java software type");
+        }
+    }
+
+    /**
+     * Starts application registration session.
+     * The registrations and unregistrations are done only
+     * when commitSession is called.
+     * If you want to discard the registrations and unregistrations
+     * call rollbackSession.
+     * Does nothing if session has already been successfully started
+     * from this SifRegistrator instance.
+     *
+     * @param aTransaction true if also transaction for this session should
+     * be opened, false otherwise
+     * @throws InstallerException if the session cannot created
+     * @see commitSession
+     * @see rollbackSession
+     */
+    public void startSession(boolean aTransaction)
+    {
+        if (0 != iSessionHandle)
+        {
+            // Session has already been created, do nothing.
+            Log.logWarning("SifRegistrator.startSession called although session is already open.");
+            return;
+        }
+
+        // Native method writes error log and returns
+        // negative Symbian error code if it fails.
+        int ret = _startSession(aTransaction);
+        if (ret < 0)
+        {
+            InstallerException.internalError(
+                "Creating session failed with code " + ret);
+        }
+        //Log.log("SifRegistrator session started");
+        iSessionHandle = ret;
+    }
+
+    /**
+     * Registers Java application suite to S60 USIF.
+     *
+     * @param aSuiteInfo Information needed to register the application
+     * @param aIsUpdate true in case of an update, false in case of a new
+     * installation
+     * @throws InstallerException if registration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    public void registerSuite(SuiteInfo aSuiteInfo, boolean aIsUpdate)
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+        Log.log("SifRegistrator registering application suite " +
+                aSuiteInfo.getGlobalId());
+
+        if (_getUsifMode() > 0)
+        {
+            // USIF Phase 2 registration.
+            // Register suite as a component.
+            registerComponent(aSuiteInfo, aIsUpdate);
+            registerLocalizedComponentName(aSuiteInfo, -1);
+            // Register applications within the component.
+            Vector apps = aSuiteInfo.getApplications();
+            for (int i = 0; i < apps.size(); i++)
+            {
+                registerApplication(aSuiteInfo, i);
+            }
+        }
+        else
+        {
+            // USIF Phase 1 registration.
+            // Register each application in the suite.
+            Vector apps = aSuiteInfo.getApplications();
+            for (int i = 0; i < apps.size(); i++)
+            {
+                registerComponent(aSuiteInfo, i, aIsUpdate);
+                registerLocalizedComponentName(aSuiteInfo, i);
+            }
+        }
+        registerLocalizedProperties(aSuiteInfo);
+    }
+
+    /**
+     * Unregisters Java application suite from S60 USIF.
+     *
+     * @param aSuiteInfo Information needed to unregister the application,
+     * @throws InstallerException if unregistration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    public void unregisterSuite(SuiteInfo aSuiteInfo)
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+        Log.log("SifRegistrator unregistering application suite " +
+                aSuiteInfo.getGlobalId());
+
+        if (_getUsifMode() > 0)
+        {
+            // USIF Phase 2 unregistration.
+            // Unregister suite as a component.
+            unregisterComponent(aSuiteInfo);
+        }
+        else
+        {
+            // USIF Phase 1 unregistration.
+            // Unregister each application in the suite.
+            Vector apps = aSuiteInfo.getApplications();
+            for (int i = 0; i < apps.size(); i++)
+            {
+                unregisterComponent(aSuiteInfo, i);
+            }
+        }
+    }
+
+    /**
+     * Commits the registrations and unregistrations.
+     * Ends the current session if commit is successfull.
+     * If commit fails the session is kept open so that
+     * rollbackSession can be called.
+     *
+     * @throws InstallerException if session cannot be committed
+     */
+    public void commitSession()
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+
+        int err = _commitSession(iSessionHandle);
+        if (err < 0)
+        {
+            InstallerException.internalError("Commiting session failed with code " + err);
+        }
+        // Current session has been closed
+        iSessionHandle = 0;
+        //Log.log("SifRegistrator session committed");
+    }
+
+    /**
+     * Rolls back the registrations and unregistrations.
+     * Ends the current session.
+     *
+     * @throws InstallerException if session cannot be rolled back.
+     */
+    public void rollbackSession()
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+
+        int err = _rollbackSession(iSessionHandle);
+        // Session is closed always when rollback is called
+        iSessionHandle = 0;
+        if (err < 0)
+        {
+            InstallerException.internalError("Rolling back the session failed with code " + err);
+        }
+        //Log.log("SifRegistrator session rolled back");
+    }
+
+    /**
+     * Closes the current session if it still open.
+     * If registerComponent or unregisterComponent has been called,
+     * commitSession or rollbackSession must be called instead of this method.
+     */
+    public void closeSession()
+    {
+        if (0 == iSessionHandle)
+        {
+            return;
+        }
+
+        _closeSession(iSessionHandle);
+        // Current session has been closed
+        iSessionHandle = 0;
+        //Log.log("SifRegistrator session closed");
+    }
+
+    /**
+     * Returns the component id of the application.
+     *
+     * @param aGlobalId the global id for the application.
+     * @return the component id for the application, or null if the
+     * application with given global id cannot be found.
+     * @throws InstallerException if an error occurs
+     */
+    public ComponentId getComponentId(String aGlobalId)
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+
+        ComponentId result = new ComponentId();
+        int ret = _getComponentId(iSessionHandle, aGlobalId, result);
+        if (-1 == ret)
+        {
+            // Symbian error code KErrNotFound means that the
+            // application with given global id does not exist.
+            result = null;
+        }
+        else if (ret < -1)
+        {
+            InstallerException.internalError(
+                "Getting component id for global id " + aGlobalId +
+                " failed with code " + ret);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the component id of the application.
+     *
+     * @param aAppUid the uid for the application.
+     * @return the component id for the application, or null if the
+     * application with given uid cannot be found.
+     * @throws InstallerException if an error occurs
+     */
+    public ComponentId getComponentId(Uid aAppUid)
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+
+        ComponentId result = new ComponentId();
+        int ret = _getComponentIdForApp(
+                      iSessionHandle, ((PlatformUid)aAppUid).getIntValue(), result);
+        if (-1 == ret)
+        {
+            // Symbian error code KErrNotFound means that the
+            // application with given uid does not exist.
+            result = null;
+        }
+        else if (ret < -1)
+        {
+            InstallerException.internalError(
+                "Getting component id for uid " + aAppUid +
+                " failed with code " + ret);
+        }
+        return result;
+    }
+
+    /**
+     * Writes information of the given application to JavaInstaller log.
+     *
+     * @param aGlobalId the global id for the application.
+     */
+    public void logComponent(String aGlobalId)
+    {
+        if (0 == iSessionHandle)
+        {
+            InstallerException.internalError("No valid SIF session.");
+        }
+
+        int ret = _logComponent(iSessionHandle, aGlobalId);
+        if (ret < -1)
+        {
+            Log.logError("SifRegistrator logComponent failed with code " + ret);
+        }
+    }
+
+    /*** ----------------------------- PACKAGE ---------------------------- */
+    /*** ----------------------------- PRIVATE ---------------------------- */
+
+    /**
+     * Registers one Java application to S60 USIF as a component.
+     * Used with USIF Phase 1.
+     *
+     * @param aSuiteInfo Information needed to register the application
+     * @param aIndex index of the application in the suite
+     * @param aIsUpdate true in case of an update, false in case of a new
+     * installation
+     * @throws InstallerException if registration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    private void registerComponent(
+        SuiteInfo aSuiteInfo, int aIndex, boolean aIsUpdate)
+    {
+        String globalId = aSuiteInfo.getGlobalId(aIndex);
+        if (globalId == null)
+        {
+            Log.logWarning("SifRegistrator: Application with index " + aIndex +
+                           " not found from " + aSuiteInfo.getGlobalId());
+            return;
+        }
+        ApplicationInfo appInfo =
+            (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex);
+        String suiteName = aSuiteInfo.getName();
+        String vendor = aSuiteInfo.getVendor();
+        String version = aSuiteInfo.getVersion().toString();
+        String name = appInfo.getName();
+        int uid = ((PlatformUid)appInfo.getUid()).getIntValue();
+        String[] componentFiles = getComponentFiles(aSuiteInfo);
+        long componentSize = aSuiteInfo.getInitialSize();
+        String attrValue = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Block-Uninstall");
+        boolean isRemovable = !(attrValue != null && attrValue.equalsIgnoreCase("true"));
+        boolean isDrmProtected = (aSuiteInfo.getContentInfo() == aSuiteInfo.CONTENT_INFO_DRM);
+        boolean isOriginVerified = aSuiteInfo.isTrusted();
+        String midletInfoUrl = aSuiteInfo.getAttributeValue("MIDlet-Info-URL");
+        String midletDescription = aSuiteInfo.getAttributeValue("MIDlet-Description");
+        String downloadUrl = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Download-URL");
+        ComponentId componentId = new ComponentId();
+        int err = _registerComponent(
+                      iSessionHandle, uid,
+                      getScrString(suiteName), getScrString(vendor),
+                      getScrString(version), getScrString(name),
+                      getScrString(globalId), componentFiles,
+                      componentSize, isRemovable, isDrmProtected,
+                      isOriginVerified, aIsUpdate, aSuiteInfo.getMediaId(),
+                      getScrString(midletInfoUrl),
+                      getScrString(midletDescription),
+                      getScrString(downloadUrl),
+                      componentId);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Registering component " + globalId +
+                " failed with code " + err);
+        }
+        else
+        {
+            appInfo.setComponentId(componentId);
+            Log.log("SifRegistrator registered component " + globalId +
+                    " with id " + componentId.getId());
+        }
+    }
+
+    /**
+     * Unregisters one Java application from being S60 USIF component.
+     * Used with USIF Phase 1.
+     *
+     * @param aSuiteInfo Information needed to unregister the application,
+     * @param aIndex index of the application in the suite
+     * @throws InstallerException if unregistration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    private void unregisterComponent(SuiteInfo aSuiteInfo, int aIndex)
+    {
+        String globalId = aSuiteInfo.getGlobalId(aIndex);
+        if (globalId == null)
+        {
+            Log.logWarning("SifRegistrator: Application with index " + aIndex +
+                           " not found from " + aSuiteInfo.getGlobalId());
+            return;
+        }
+        ComponentId componentId = getComponentId(globalId);
+        if (componentId == null)
+        {
+            Log.logWarning(
+                "SifRegistrator unregistration failed, application " +
+                globalId + " does not exist");
+            return;
+        }
+        // Save component id to ApplicationInfo.
+        ApplicationInfo appInfo =
+            (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex);
+        appInfo.setComponentId(componentId);
+        // Unregister application.
+        int err = _unregisterComponent(iSessionHandle, componentId.getId());
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Unregistering component " + globalId +
+                " failed with code " + err);
+        }
+        else
+        {
+            Log.log("SifRegistrator unregistered component " + globalId +
+                    " with id " + componentId.getId());
+        }
+    }
+
+    /**
+     * Registers Java application suite to S60 USIF as a component.
+     * Used with USIF Phase 2.
+     *
+     * @param aSuiteInfo Suite information
+     * @param aIsUpdate true in case of an update, false in case of a new
+     * installation
+     * @throws InstallerException if registration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    private void registerComponent(SuiteInfo aSuiteInfo, boolean aIsUpdate)
+    {
+        String globalId = aSuiteInfo.getGlobalId();
+        String suiteName = aSuiteInfo.getName();
+        String vendor = aSuiteInfo.getVendor();
+        String version = aSuiteInfo.getVersion().toString();
+        String name = null; // Set name to null so that suite name will be used.
+        int uid = ((PlatformUid)aSuiteInfo.getUid()).getIntValue();
+        String[] componentFiles = getComponentFiles(aSuiteInfo);
+        long componentSize = aSuiteInfo.getInitialSize();
+        String attrValue = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Block-Uninstall");
+        boolean isRemovable = !(attrValue != null && attrValue.equalsIgnoreCase("true"));
+        boolean isDrmProtected = (aSuiteInfo.getContentInfo() == aSuiteInfo.CONTENT_INFO_DRM);
+        boolean isOriginVerified = aSuiteInfo.isTrusted();
+        String midletInfoUrl = aSuiteInfo.getAttributeValue("MIDlet-Info-URL");
+        String midletDescription = aSuiteInfo.getAttributeValue("MIDlet-Description");
+        String downloadUrl = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Download-URL");
+        ComponentId componentId = new ComponentId();
+        int err = _registerComponent(
+                      iSessionHandle, uid,
+                      getScrString(suiteName), getScrString(vendor),
+                      getScrString(version), getScrString(name),
+                      getScrString(globalId), componentFiles,
+                      componentSize, isRemovable, isDrmProtected,
+                      isOriginVerified, aIsUpdate, aSuiteInfo.getMediaId(),
+                      getScrString(midletInfoUrl),
+                      getScrString(midletDescription),
+                      getScrString(downloadUrl),
+                      componentId);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Registering component " + globalId +
+                " failed with code " + err);
+        }
+        else
+        {
+            aSuiteInfo.setComponentId(componentId);
+            Log.log("SifRegistrator registered component " + globalId +
+                    " with id " + componentId.getId());
+        }
+    }
+
+    /**
+     * Unregisters Java application suite from being S60 USIF component.
+     * Used with USIF Phase 2.
+     *
+     * @param aSuiteInfo suite information
+     * @throws InstallerException if unregistration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    private void unregisterComponent(SuiteInfo aSuiteInfo)
+    {
+        String globalId = aSuiteInfo.getGlobalId();
+        ComponentId componentId = getComponentId(globalId);
+        if (componentId == null)
+        {
+            Log.logWarning(
+                "SifRegistrator unregistration failed, application " +
+                globalId + " does not exist");
+            return;
+        }
+        // Save component id to SuiteInfo.
+        aSuiteInfo.setComponentId(componentId);
+        // Unregister application.
+        int err = _unregisterComponent(iSessionHandle, componentId.getId());
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Unregistering component " + globalId +
+                " failed with code " + err);
+        }
+        else
+        {
+            Log.log("SifRegistrator unregistered component " + globalId +
+                    " with id " + componentId.getId());
+        }
+    }
+
+    /**
+     * Registers one Java application to S60 USIF as an S60 application.
+     * The application is registered to component whose id is taken
+     * from given SuiteInfo object. The SuiteInfo must already have
+     * been registered to USIF as a component with registerComponent()
+     * method before this method is called.
+     * Used with USIF Phase 2.
+     *
+     * @param aSuiteInfo information needed to register the application
+     * @param aIndex index of the application in the suite
+     * @throws InstallerException if registration cannot done or
+     *  startSession has not been called successfully
+     * @see startSession
+     * @see SuiteInfo
+     */
+    private void registerApplication(SuiteInfo aSuiteInfo, int aIndex)
+    {
+        int cid = aSuiteInfo.getComponentId().getId();
+        ApplicationInfo appInfo =
+            (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex);
+        int appUid = ((PlatformUid)appInfo.getUid()).getIntValue();
+        String appName = appInfo.getName();
+        String appFilename = aSuiteInfo.getJarPath();
+        String groupName = aSuiteInfo.getInstallationGroup();
+        if (groupName == null)
+        {
+            groupName = ""; // default installation group
+        }
+        String iconFilename = aSuiteInfo.getRegisteredIconPath(aIndex);
+        Log.log("SifRegistrator iconFilename " + aIndex + ": " + iconFilename);
+        int numberOfIcons = 1;
+        // Initalize localized names for the application.
+        LocalizedName[] localizedNames = getLocalizedNames(
+                                             aSuiteInfo, "Nokia-MIDlet-" + (aIndex+1) + "-");
+        int[] languages = new int[localizedNames.length];
+        String[] appNames = new String[localizedNames.length];
+        for (int i = 0; i < localizedNames.length; i++)
+        {
+            languages[i] = localizedNames[i].getLanguage();
+            appNames[i] = localizedNames[i].getName();
+        }
+        int err = _registerApplication(
+                      iSessionHandle, cid, appUid, appName, appFilename, groupName,
+                      iconFilename, numberOfIcons, languages, appNames);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Registering application " + appUid + " to component " + cid +
+                " failed with code " + err);
+        }
+        else
+        {
+            Log.log("SifRegistrator registered application " + appUid +
+                    " to component " + cid);
+        }
+    }
+
+    private static String[] getComponentFiles(SuiteInfo aSuite)
+    {
+        Vector componentFiles = new Vector();
+        String path = aSuite.getJadPath();
+        if (path != null)
+        {
+            componentFiles.addElement(getScrString(path));
+        }
+        path = aSuite.getJarPath();
+        if (path != null)
+        {
+            componentFiles.addElement(getScrString(path));
+        }
+        boolean addRootPath = true;
+        int rootDrive = FileUtils.getDrive(aSuite.getRootDir());
+        for (int i = 0; i < componentFiles.size(); i++)
+        {
+            if (FileUtils.getDrive((String)componentFiles.elementAt(i)) ==
+                    rootDrive)
+            {
+                // File from the root path drive already exists in
+                // component files vector, no need to add root path
+                // separately.
+                addRootPath = false;
+                break;
+            }
+        }
+        if (addRootPath)
+        {
+            componentFiles.addElement(getScrString(aSuite.getRootDir()));
+        }
+        String[] result = new String[componentFiles.size()];
+        componentFiles.copyInto(result);
+        return result;
+    }
+
+    /**
+     * Registers localized names for given application from given suite.
+     * This method can be called only after registerComponent method has
+     * been called.
+     *
+     * @param aSuite suite info
+     * @param aIndex index of the application within the suite, if -1 then
+     * localized names for the suite itself is registered
+     */
+    private void registerLocalizedComponentName(SuiteInfo aSuite, int aIndex)
+    {
+        LocalizedName[] localizedNames = null;
+        int cid = 0;
+        if (aIndex == -1)
+        {
+            if (aSuite.getComponentId() == null)
+            {
+                Log.logWarning(
+                    "SifRegistrator.registerLocalizedComponentName: cid not present in suite");
+                return;
+            }
+            cid = aSuite.getComponentId().getId();
+            localizedNames = getLocalizedNames(aSuite, "Nokia-MIDlet-Name-");
+        }
+        else
+        {
+            ApplicationInfo app =
+                (ApplicationInfo)aSuite.getApplications().elementAt(aIndex);
+            if (app.getComponentId() == null)
+            {
+                Log.logWarning(
+                    "SifRegistrator.registerLocalizedComponentName: cid not present in app");
+                return;
+            }
+            cid = app.getComponentId().getId();
+            localizedNames = getLocalizedNames(
+                                 aSuite, "Nokia-MIDlet-" + (aIndex+1) + "-");
+        }
+        for (int i = 0; i < localizedNames.length; i++)
+        {
+            int err = _registerLocalizedComponentName(
+                          iSessionHandle, cid,
+                          getScrString(localizedNames[i].getName()),
+                          getScrString(aSuite.getVendor()),
+                          localizedNames[i].getLanguage());
+            if (err < 0)
+            {
+                InstallerException.internalError(
+                    "Adding localized name for component " + cid +
+                    " failed with code " + err +
+                    " (" + localizedNames[i] + ")");
+            }
+        }
+    }
+
+    /**
+     * Registers localized property values for given suite.
+     * This method can be called only after registerComponent
+     * method has been called.
+     *
+     * @param aSuite suite info
+     */
+    private void registerLocalizedProperties(SuiteInfo aSuite)
+    {
+        if (aSuite.getComponentId() == null)
+        {
+            Log.logWarning(
+                "SifRegistrator.registerLocalizedProperties: cid not present in suite");
+            return;
+        }
+        int cid = aSuite.getComponentId().getId();
+        final int UNSPECIFIED_LOCALE = -1; // KUnspecifiedLocale
+
+        // Register MIDlet-Delete-Confirm attribute values.
+        final String attrName = "MIDlet-Delete-Confirm";
+        String nonlocalizedAttrValue = aSuite.getAttributeValue(attrName);
+        int err = _setLocalizedComponentProperty(
+                      iSessionHandle, cid, getScrString(attrName),
+                      getScrString(nonlocalizedAttrValue), UNSPECIFIED_LOCALE);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Adding property " + attrName + " for component " + cid +
+                " failed with code " + err + " (" + nonlocalizedAttrValue + ")");
+        }
+        LocalizedName[] localizedAttrValues =
+            getLocalizedNames(aSuite, attrName + "-");
+        for (int i = 0; i < localizedAttrValues.length; i++)
+        {
+            err = _setLocalizedComponentProperty(
+                      iSessionHandle, cid, getScrString(attrName),
+                      getScrString(localizedAttrValues[i].getName()),
+                      localizedAttrValues[i].getLanguage());
+            if (err < 0)
+            {
+                InstallerException.internalError(
+                    "Adding localized property " + attrName +
+                    " for component " + cid + " failed with code " + err +
+                    " (" + localizedAttrValues[i] + ")");
+            }
+        }
+
+        // Register Domain-Category property.
+        ApplicationInfoImpl appInfoImpl = (ApplicationInfoImpl)
+                                          com.nokia.mj.impl.rt.support.ApplicationInfo.getInstance();
+        String domainCategory = appInfoImpl.getProtectionDomain();
+        err = _setLocalizedComponentProperty(
+                  iSessionHandle, cid, "Domain-Category",
+                  domainCategory, UNSPECIFIED_LOCALE);
+        if (err < 0)
+        {
+            InstallerException.internalError(
+                "Adding property Domain-Category value " + domainCategory +
+                " for component " + cid + " failed with code " + err);
+        }
+    }
+
+    /**
+     * Returns array of localized names from the specified
+     * attributes of given suite. Assumes that aAttrPrefix
+     * is an attribute name prefix that is followed by locale.
+     * If the same locale is found more than once, localized
+     * name for only the last occurrence is returned.
+     */
+    private LocalizedName[] getLocalizedNames(
+        SuiteInfo aSuite, String aAttrPrefix)
+    {
+        Hashtable localizedNames = new Hashtable();
+        Enumeration e = aSuite.getAttributes().elements();
+        while (e.hasMoreElements())
+        {
+            Attribute attr = (Attribute)e.nextElement();
+            String name = attr.getName();
+            if (name.startsWith(aAttrPrefix))
+            {
+                String locale = name.substring(aAttrPrefix.length());
+                if (isValidLocale(locale))
+                {
+                    LocalizedName localizedName =
+                        new LocalizedName(attr.getValue(), locale);
+                    if (localizedName.getLanguage() == -1)
+                    {
+                        Log.logWarning(
+                            "SifRegistrator ignored unknown locale: " +
+                            name + ": " + localizedName);
+                    }
+                    else
+                    {
+                        Log.log("SifRegistrator found localized text " +
+                                name + ": " + localizedName);
+                        localizedNames.put(
+                            new Integer(localizedName.getLanguage()),
+                            localizedName);
+                    }
+                }
+            }
+        }
+        LocalizedName[] result = new LocalizedName[localizedNames.size()];
+        e = localizedNames.elements();
+        for (int i = 0; e.hasMoreElements(); i++)
+        {
+            result[i] = (LocalizedName)e.nextElement();
+        }
+        return result;
+    }
+
+    /**
+     * Returns true if given locale is a valid one. Valid locales
+     * use two letter ISO language and optionally country codes.
+     */
+    private boolean isValidLocale(String aLocale)
+    {
+        boolean result = false;
+        if (aLocale.length() == 2)
+        {
+            // Assume that locale has only language code.
+            result = true;
+        }
+        if (aLocale.length() == 5)
+        {
+            // Assume that locale has language and country codes.
+            char separator = aLocale.charAt(2);
+            if (separator == '-' || separator == '_')
+            {
+                result = true;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns a string which can be stored to S60 SCR. This method ensures
+     * that the length of the returned string does not exceed the maximum
+     * length limit set by SCR (512 characters).
+     */
+    private static String getScrString(String aStr)
+    {
+        final int maxLen = 512;
+        if (aStr != null && aStr.length() > maxLen)
+        {
+            return aStr.substring(0, maxLen);
+        }
+        return aStr;
+    }
+
+    /*** ----------------------------- NATIVE ----------------------------- */
+
+    /**
+     * Notifies system about added/updated/removed applications.
+     * This method should be called only after the changes have been
+     * committed.
+     *
+     * @param aAppUids application uids
+     * @param aAppChange change type: APP_ADDED, APP_UPDATED, or APP_REMOVED
+     * @return 0 or Symbian error code (negative number)
+     */
+    private static native int _notifyAppChange(int[] aAppUids, int aAppChange);
+
+    /**
+     * Launches the applications view.
+     *
+     * @return 0 or Symbian error code (negative number)
+     */
+    private static native int _launchAppView();
+
+    /**
+     * Registers Java software type to software installation framework.
+     *
+     * @param aRegister true for registration, false for unregistration
+     * @return 0 or Symbian error code (negative number)
+     */
+    private static native int _registerJavaSoftwareType(boolean aRegister);
+
+    /**
+     * Starts native application registration session.
+     *
+     * @param aTransaction true if also transaction for this session should
+     * be opened, false otherwise
+     * @return native session handle or Symbian error code (negative number)
+     */
+    private static native int _startSession(boolean aTransaction);
+
+    /**
+     * Commits native application registration session.
+     * If commit succeeds the native session is closed.
+     *
+     * @param aSessionHandle
+     * @param aSynchronous if true, makes synchronous commit
+     * @return 0 or Symbian error code (negative number)
+     */
+    private static native int _commitSession(int aSessionHandle);
+
+    /**
+     * Rolls back and closes native application registration session.
+     *
+     * @param aSessionHandle
+     * @return 0 or Symbian error code (negative number)
+     */
+    private static native int _rollbackSession(int aSessionHandle);
+
+    /**
+     * Closes native application registration session.
+     *
+     * @param aSessionHandle the session to be closed
+     */
+    private static native void _closeSession(int aSessionHandle);
+
+    /**
+     * Registers Java application to S60 USIF as a component.
+     *
+     * @param aSessionHandle
+     * @param aUid
+     * @param aSuiteName
+     * @param aVendor
+     * @param aVersion
+     * @param aName
+     * @param aGlobalId
+     * @param aComponentFiles
+     * @param aComponentSize
+     * @param aIsRemovable
+     * @param aIsDrmProtected
+     * @param aIsOriginVerified
+     * @param aIsUpdate
+     * @param aMediaId
+     * @param aMidletInfoUrl
+     * @param aMidletDescription
+     * @param aDownloadUrl
+     * @param aComponentId upon successful execution contains the
+     * component id for the registered component
+     * @return 0 if registration succeeded or Symbian error code
+     */
+    private static native int _registerComponent(
+        int aSessionHandle, int aUid, String aSuiteName, String aVendor,
+        String aVersion, String aName, String aGlobalId,
+        String[] aComponentFiles, long aComponentSize,
+        boolean aIsRemovable, boolean aIsDrmProtected,
+        boolean aIsOriginVerified, boolean aIsUpdate, int aMediaId,
+        String aMidletInfoUrl, String aMidletDescription, String aDownloadUrl,
+        ComponentId aComponentId);
+
+    /**
+     * Unregisters Java application from S60 USIF.
+     *
+     * @param aSessionHandle
+     * @param aComponentId The component id of the application
+     * @return 0 if unregistration succeeded or Symbian error code
+     */
+    private static native int _unregisterComponent(
+        int aSessionHandle, int aComponentId);
+
+    /**
+     * Registers Java application to S60 USIF as an application
+     * inside specified component.
+     *
+     * @param aSessionHandle
+     * @param aCid
+     * @param aAppUid
+     * @param aAppName
+     * @param aAppFilename
+     * @param aGroupName
+     * @param aIconFilename
+     * @param aNumberOfIcons
+     * @param aLanguages
+     * @param aAppNames
+     * @return 0 if registration succeeded or Symbian error code
+     */
+    private static native int _registerApplication(
+        int aSessionHandle, int aCid, int aAppUid, String aAppName,
+        String aAppFilename, String aGroupName, String aIconFilename,
+        int aNumberOfIcons, int[] aLanguages, String[] aAppNames);
+
+    /**
+     * Registers localized name and vendor for specified component.
+     *
+     * @param aSessionHandle
+     * @param aCid component id
+     * @param aName localized component name
+     * @param aVendor localized component vendor (can be null)
+     * @param aLanguage S60 language code
+     * @return 0 if unregistration succeeded or Symbian error code
+     */
+    private static native int _registerLocalizedComponentName(
+        int aSessionHandle, int aCid, String aName, String aVendor, int aLanguage);
+
+    /**
+     * Sets localized property value for specified component.
+     *
+     * @param aSessionHandle
+     * @param aCid component id
+     * @param aName property name
+     * @param aValue localized property value
+     * @param aLanguage S60 language code
+     * @return 0 if unregistration succeeded or Symbian error code
+     */
+    private static native int _setLocalizedComponentProperty(
+        int aSessionHandle, int aCid, String aName, String aValue, int aLanguage);
+
+    /**
+     * Returns the component id of the application.
+     *
+     * @param aSessionHandle
+     * @param aGlobalId
+     * @param aComponentId contains component id after successful function call
+     * @return Symbian error code (negative number) if fails, otherwise 0
+     */
+    private static native int _getComponentId(
+        int aSessionHandle, String aGlobalId, ComponentId aComponentId);
+
+    /**
+     * Returns the component id of the application.
+     *
+     * @param aSessionHandle
+     * @param aAppUid
+     * @param aComponentId contains component id after successful function call
+     * @return Symbian error code (negative number) if fails, otherwise 0
+     */
+    private static native int _getComponentIdForApp(
+        int aSessionHandle, int aAppUid, ComponentId aComponentId);
+
+    /**
+     * Returns the uid of the component.
+     *
+     * @param aSessionHandle
+     * @param aCid component id
+     * @param aUid contains uid after successful function call
+     * @return Symbian error code (negative number) if fails, otherwise 0
+     */
+    private static native int _getUid(int aCid, ComponentId aUid);
+
+    /**
+     * Writes information of the given application to JavaInstaller log.
+     *
+     * @param aSessionHandle
+     * @param aGlobalId the global id for the application
+     * @return Symbian error code (negative number) if fails, otherwise 0
+     */
+    private static native int _logComponent(
+        int aSessionHandle, String aGlobalId);
+
+    /**
+     * Checks if USIF is enabled.
+     *
+     * @return 1 if application data should be registered to USIF, 0 otherwise
+     */
+    private static native int _getUsifMode();
+}