javatools/javaapppreconverter/src.s60/preconverter.cpp
changeset 21 2a9601315dfc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javatools/javaapppreconverter/src.s60/preconverter.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,931 @@
+/*
+* Copyright (c) 2008 - 2009 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: Java platform 2.0 javaapppreconverter process.
+*              This process needs AllFiles capability to be able to read
+*              the icon files of all midlets and to store midlet data
+*              to the data cage of the javaappbackconverter process.
+*
+*/
+
+
+#include <e32base.h>
+#include <pathinfo.h>
+#include <driveinfo.h>
+#include <apgcli.h>
+#include <d32dbms.h>
+
+#include <mdatabasev2.h>
+#include <mmidlettablev2.h>
+#include <mmidlettableiterator.h>
+
+#include "javacommonutils.h"
+#include "javauids.h"
+#include "preconverter.h"
+#include "noarmlogs.h"
+
+const TInt    KDelayWhenWaitingAppArc = 500000;
+const TUint32 KDBVersion = 0x0200;
+
+// Name for the system AMS DB policy
+_LIT(KUidSSystemAMSDbPolicy, "secure[102045FE]");
+
+// Constant needed to access SystemAMS static database
+_LIT(KStaticDbFileName, "C:\\private\\100012A5\\DBS_102045FE_MIDP2SystemAMSStaticV2");
+
+// This is in the private data cage of javaappbackconverter.
+// javaappbackconverter will destroy the files created to this directory
+// after it has done the back conversion.
+_LIT(KMidletExportDirectory, "C:\\private\\20022D90\\data\\");
+
+// This is in the private data cage of usersettingsconfigurator.
+_LIT(KMidletExportDirectoryForUserSettings, "C:\\private\\20022E7A\\data\\");
+
+// This is in the private data cage of javappconverter
+// javaappconverter will destroy the 'uids' file created to this directory
+// after it has made the conversion.
+_LIT(KUidsExportDirectory, "C:\\private\\2002121C\\data\\");
+_LIT(KUidsExportDataFileName, "uids");
+
+// These literals are used for logging midlet information found from db.
+_LIT8(KMLName, "\nname: ");
+_LIT8(KMLClassName, "\nclassName: ");
+_LIT8(KMLIdString, "\nidString: ");
+
+
+/**
+ * To create new instance of this class.
+ *
+ * @param aFs - A reference to the file server.
+ * @return Reference to the object of this class.
+ * @exception If construction fails.
+ */
+CPreConverter* CPreConverter::NewLC(RFs& aFs)
+{
+    CPreConverter* self = new(ELeave) CPreConverter(aFs);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+}
+
+/**
+ * To do 1st phase construction for this object.
+ *
+ * Adds this active object to the scheduler.
+ */
+CPreConverter::CPreConverter(RFs& aFs) :
+        CActive(EPriorityStandard), iFs(aFs)
+{
+    CActiveScheduler::Add(this);
+}
+
+/**
+ * To do 2nd phase construction for this object.
+ *
+ * @exception If the method is not able to allocate necessary buffers.
+ */
+void CPreConverter::ConstructL()
+{
+    JELOG2(EJavaConverters);
+
+    iMidlets = new(ELeave) CMidletList();
+    iState = EConversionDataAlreadyGathered;
+}
+
+/**
+ * Deletes this object.
+ * All allocated resources are released.
+ */
+CPreConverter::~CPreConverter()
+{
+    JELOG2(EJavaConverters);
+    Cancel();
+    if (iMidlets)
+    {
+        iMidlets->ResetAndDestroy();
+        delete iMidlets;
+        iMidlets = NULL;
+    }
+}
+
+/**
+ * To start preconversion
+ */
+void CPreConverter::Start()
+{
+    JELOG2(EJavaConverters);
+    iState = EConversionDataAlreadyGathered;
+    CompleteRequest();
+}
+
+/**
+ * To stop whole preconversion.
+ * Stops the active scheduler.
+ */
+void CPreConverter::Exit()
+{
+    Deque();
+    CActiveScheduler::Stop();
+}
+
+/**
+ * To complete the request for this object.
+ *
+ * @Postconditions The following conditions are true immediately after
+ * returning from this method.
+ * - iStatus == KErrNone
+ * - IsActive() == ETrue
+ */
+void CPreConverter::CompleteRequest()
+{
+    JELOG2(EJavaConverters);
+
+    TRequestStatus *status = &iStatus;
+    User::RequestComplete(status, KErrNone);
+    if (!IsActive())
+    {
+        SetActive();
+    }
+}
+
+/**
+ * To run this active object.
+ *
+ * The state logic is:
+ *
+ * EConversionDataAlreadyGathered:
+ *    if midlet export data file already exists,
+ *       active object exits from this state
+ *
+ * EFindOutInstalledMidlets:
+ *    iterate through all apps in AppArc,
+ *      if java app,
+ *        store all info available from AppArc to iMidlets
+ *
+ * EFillDataFromSystemAmsDb:
+ *    add info from SystemAMS DB to iMidlets
+ *
+ * EStoreData:
+ *    store data in iMidlets to a file
+ *
+ * EStopMidlets:
+ *    stop all running midlets
+ *
+ * EUnregisterMidlets
+ *    unregister all midlets in iMidlets from AppArc
+ *
+ * EExit:
+ *    free resources and exit
+ *
+ */
+void CPreConverter::RunL()
+{
+    JELOG2(EJavaConverters);
+
+    switch (iState)
+    {
+
+    case EConversionDataAlreadyGathered:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CPreConverter::RunL EConversionDataAlreadyGathered");
+
+        TFileName exportDataFile(KMidletExportDirectory);
+        exportDataFile.Append(KMidletExportDataFileName);
+        TUint attributes;
+        TInt  err = iFs.Att(exportDataFile, attributes);
+        if (KErrNone == err)
+        {
+            LOG(EJavaConverters, EInfo,
+                "CPreConverter::RunL EConversionDataAlreadyGathered "
+                "data file already exists. Can exit.");
+            iState = EExit;
+        }
+        else
+        {
+            if ((KErrNotFound == err) || (KErrPathNotFound == err))
+            {
+                // We come here only when OMJ is not currently installed
+                // to the device. However, the device may still have
+                // old OMJ database files. Clean them now to make sure
+                // that e.g. old db schemas do not cause problems.
+                LOG(EJavaConverters, EInfo,
+                    "CPreConverter::RunL EConversionDataAlreadyGathered "
+                    "Trying to destroy OMJ database files");
+
+                _LIT(KJavaOtaStorageDbPath, "C:\\private\\10281E17\\[200211dc]JavaOtaStorage.db");
+                err = iFs.Delete(KJavaOtaStorageDbPath);
+                LOG1(EJavaConverters, EInfo,
+                     "CPreConverter::RunL EConversionDataAlreadyGathered "
+                     "Destroy C:\\private\\10281E17\\[200211dc]JavaOtaStorage.db, err %d", err);
+
+                _LIT(KJavaOtaStorageJournalPath, "C:\\private\\10281E17\\[200211dc]JavaOtaStorage.db-journal");
+                err = iFs.Delete(KJavaOtaStorageJournalPath);
+                LOG1(EJavaConverters, EInfo,
+                     "CPreConverter::RunL EConversionDataAlreadyGathered "
+                     "Destroy C:\\private\\10281E17\\[200211dc]JavaOtaStorage.db-journal, err %d", err);
+
+                _LIT(KJavaStorageDbPath, "C:\\private\\10281E17\\[200211dc]JavaStorage.db");
+                err = iFs.Delete(KJavaStorageDbPath);
+                LOG1(EJavaConverters, EInfo,
+                     "CPreConverter::RunL EConversionDataAlreadyGathered "
+                     "Destroy C:\\private\\10281E17\\[200211dc]JavaStorage.db, err %d", err);
+
+                _LIT(KJavaStorageJournalPath, "C:\\private\\10281E17\\[200211dc]JavaStorage.db-journal");
+                err = iFs.Delete(KJavaStorageJournalPath);
+                LOG1(EJavaConverters, EInfo,
+                     "CPreConverter::RunL EConversionDataAlreadyGathered "
+                     "Destroy C:\\private\\10281E17\\[200211dc]JavaStorage.db-journal, err %d", err);
+
+                LOG(EJavaConverters, EInfo,
+                    "CPreConverter::RunL EConversionDataAlreadyGathered "
+                    "Data file does not exist yet. OK");
+            }
+            else
+            {
+                LOG1(EJavaConverters, EInfo,
+                     "CPreConverter::RunL EConversionDataAlreadyGathered "
+                     "Checking data file attributes caused error %d", err);
+            }
+            iState = EFindOutInstalledMidlets;
+        }
+        CompleteRequest();
+    }
+    break;
+
+    case EFindOutInstalledMidlets:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CPreConverter::RunL EFindOutInstalledMidlets");
+
+        // Read all installed midlets from AppArc,
+        // store info to iMidlets
+        ReadMidletsFromAppArcL();
+
+        iState = EFillDataFromSystemAmsDb;
+        CompleteRequest();
+    }
+    break;
+
+    case EFillDataFromSystemAmsDb:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CPreConverter::RunL EFillDataFromSystemAmsDb");
+
+        // Some of the necessary information is in SystemAMS DB,
+        // read it now for each midlet in iMidlets
+        AddDataFromSystemAmsDbL();
+
+        // Especially in R&D environment it is possible to that
+        // AppArc contains some midlets that have not really
+        // been installed to old S60 java environment.
+        // SystemAMS DB does not contain any information of
+        // these midlets. They must be removed now.
+        RemoveInvalidMidlets();
+
+        iState = EStoreData;
+        CompleteRequest();
+    }
+    break;
+
+    case EStoreData:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CPreConverter::RunL EStoreData");
+
+        if (iMidlets->Count() == 0)
+        {
+            // No midlets to convert
+            WLOG(EJavaConverters, "CPreConverter::RunL EStoreData No midlets to convert.");
+        }
+        else
+        {
+            // Store the data directly to the data cage of
+            // javaappbackconverter.exe
+            TFileName exportDirectory(KMidletExportDirectory);
+            iMidlets->ExportListL(iFs, exportDirectory);
+
+            // Store the data also to the data cage of
+            // usersettingsconfigurator.exe
+            TFileName exportDirectoryForUserSettings(KMidletExportDirectoryForUserSettings);
+            iMidlets->ExportListL(iFs, exportDirectoryForUserSettings);
+
+            // Store the uids of the midlets to be converted
+            // to the data cage of javaappconverter.exe
+            StoreUidsL();
+        }
+
+        iState = EStopMidlets;
+        CompleteRequest();
+    }
+    break;
+
+    case EStopMidlets:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CPreConverter::RunL EStopMidlets");
+
+        CMidletInfo* pMidlet = iMidlets->GetFirst();
+
+        TFullName foundName;
+        TFullName searchName;
+
+        while (pMidlet != NULL)
+        {
+            searchName = pMidlet->GetMidletName();
+            _LIT(KMidletProcessIdString, "[102033e6]*");
+            searchName.Append(KMidletProcessIdString);
+
+            LOG1WSTR(EJavaConverters, EInfo, "Searching midlet process named %s",
+                     (wchar_t *)(searchName.PtrZ()));
+
+            TFindProcess find(searchName);
+            TInt err = find.Next(foundName);
+            if (KErrNone == err)
+            {
+                LOG1WSTR(EJavaConverters, EInfo, "The midlet process %s was found",
+                         (wchar_t *)(foundName.PtrZ()));
+                RProcess process;
+                err = process.Open(find);
+                if (KErrNone == err)
+                {
+                    LOG(EJavaConverters, EInfo, "Killing the midlet process");
+                    process.Kill(KErrNone);
+                    process.Close();
+                }
+            }
+
+            pMidlet = iMidlets->GetNext();
+        }
+
+        iState = EUnregisterMidlets;
+        CompleteRequest();
+    }
+    break;
+
+    case EUnregisterMidlets:
+    {
+        LOG(EJavaConverters, EInfo, "CPreConverter::RunL EUnregisterMidlets");
+
+        // Unregister all midlets in iMidlets from AppArc
+        UnregisterOldJavaAppsL();
+
+        iState = EExit;
+        CompleteRequest();
+    }
+    break;
+
+    case EExit:
+    {
+        LOG(EJavaConverters, EInfo, "CPreConverter::RunL EExit");
+
+        FullCleanup();
+
+        // The whole javaapppreconverter process is stopped.
+        Exit();
+    }
+    break;
+
+    }
+}
+
+/**
+ * To handle leave from RunL.
+ * This method exits this active object using normal state machine
+ * After calling this method this active object will exit.
+ *
+ * @param aError - A reason of error.
+ * @return KErrNone.
+ */
+TInt CPreConverter::RunError(TInt aError)
+{
+    ELOG2(EJavaConverters,
+          "CPreConverter::RunError(%d) from state %d", aError, iState);
+
+    Cancel();
+
+    iState = EExit;
+    CompleteRequest();
+
+    return KErrNone;
+}
+
+/**
+ * To do cancelling for this object.
+ *
+ */
+void CPreConverter::DoCancel()
+{
+    ELOG1(EJavaConverters,
+          "CPreConverter::DoCancel from state %d", iState);
+
+}
+
+/**
+ * To cleanup member variables.
+ *
+ */
+void CPreConverter::FullCleanup()
+{
+    JELOG2(EJavaPreinstaller);
+
+    if (iMidlets)
+    {
+        iMidlets->ResetAndDestroy();
+        delete iMidlets;
+        iMidlets = NULL;
+    }
+}
+
+/**
+ * Read all midlets from AppArc.
+ * Store midlet Uid, Midlet name, installation drive,
+ * group name and icon file path name to iMidlets.
+ */
+void CPreConverter::ReadMidletsFromAppArcL()
+{
+    JELOG2(EJavaConverters);
+
+    TInt   retryCounter = 10;
+    TUid   appTypeUid;
+    HBufC *pIconFilePathName = NULL;
+    TApaAppInfo   info;
+    RApaLsSession apaSession;
+    TApaAppCapabilityBuf cbuf;
+    TApaAppCapability    capability;
+
+    TBuf8<512> midletDesc;
+
+
+    TInt err = apaSession.Connect();
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "CPreConverter::ReadMidletsFromAppArcL RApaLsSession Connect error %d", err);
+        User::Leave(err);
+    }
+    CleanupClosePushL(apaSession);
+
+    // Get the process of getting the list of all non native applications
+    // (mostly java applications)
+    err =
+        apaSession.GetFilteredApps(
+            TApaAppCapability::ENonNative, TApaAppCapability::ENonNative);
+
+    do
+    {
+        err = apaSession.GetNextApp(info);
+        if (RApaLsSession::EAppListInvalid == err)
+        {
+            // Application list has not yet been populated,
+            // try again after a short delay
+            retryCounter--;
+            if (retryCounter > 0)
+            {
+                User::After(KDelayWhenWaitingAppArc);
+                continue;
+            }
+            else
+            {
+                ELOG(EJavaConverters,
+                     "CPreConverter::ReadMidletsFromAppArcL RApaLsSession "
+                     "GetNext returned EAppListInvalid for 10 times, error");
+                User::Leave(err);
+            }
+        }
+        else if (KErrNone == err)
+        {
+            // Info contains valid app info. Now check whether it is java app
+            err = apaSession.GetAppType(appTypeUid, info.iUid);
+            if (KErrNone != err)
+            {
+                ELOG1(EJavaConverters,
+                      "CPreConverter::ReadMidletsFromAppArcL RApaLsSession "
+                      "GetAppType returned error %d", err);
+                User::Leave(err);
+            }
+            if (appTypeUid.iUid == KMidletApplicationTypeUid)
+            {
+                // This is java application. Store info to list.
+                CMidletInfo *midletInfo = new(ELeave) CMidletInfo();
+                midletInfo->SetMidletUid(info.iUid);
+                midletInfo->SetMidletName(info.iCaption);
+                midletInfo->SetDrive(ExtractDriveNumberFromPathL(info.iFullName));
+
+                // Get group name
+                err = apaSession.GetAppCapability(cbuf, info.iUid);
+                if (KErrNone != err)
+                {
+                    ELOG1(EJavaConverters,
+                          "CPreConverter::ReadMidletsFromAppArcL RApaLsSession "
+                          "GetAppCapability returned error %d", err);
+                    User::Leave(err);
+                }
+                capability = cbuf();
+                midletInfo->SetGroupName(capability.iGroupName);
+
+                // Get icon file path name
+                err = apaSession.GetAppIcon(info.iUid, pIconFilePathName);
+                if ((KErrNone != err) || (NULL == pIconFilePathName))
+                {
+                    ELOG1(EJavaConverters,
+                          "CPreConverter::ReadMidletsFromAppArcL RApaLsSession "
+                          "GetAppIcon returned error %d", err);
+                    User::Leave(err);
+                }
+                midletInfo->SetIconFileName(pIconFilePathName);
+                delete pIconFilePathName;
+                pIconFilePathName = NULL;
+
+                err = iMidlets->Append(midletInfo);
+                if (KErrNone != err)
+                {
+                    ELOG1(EJavaConverters,
+                          "CPreConverter::ReadMidletsFromAppArcL CMidletList "
+                          "Append returned error %d", err);
+                    User::Leave(err);
+                }
+                else
+                {
+                    midletInfo->ToString8(midletDesc);
+                    LOG(EJavaConverters, EInfo,
+                        "CPreConverter::ReadMidletsFromAppArcL Added this midlet:");
+                    midletDesc.ZeroTerminate();
+                    LOG(EJavaPreinstaller, EInfo, (const char *)(midletDesc.Ptr()));
+                    midletDesc.Zero();
+                }
+            }
+        }
+
+    }
+    while (KErrNone == err);
+
+    if (RApaLsSession::ENoMoreAppsInList != err)
+    {
+        ELOG1(EJavaConverters,
+              "CPreConverter::ReadMidletsFromAppArcL RApaLsSession GetNext returned error %d", err);
+        User::Leave(err);
+    }
+
+    CleanupStack::PopAndDestroy(); // apaSession
+}
+
+/**
+ * Parse the drive letter from path and return it as TDriveNumber.
+ *
+ * @param aPathName full path name. Contains always the drive.
+ * @return the drive number
+ * @exception if the drive cannot parsed from path
+ */
+TDriveNumber CPreConverter::ExtractDriveNumberFromPathL(TFileName &aPathName)
+{
+    TDriveNumber drive = EDriveE;
+    TUint driveLetter = aPathName[0];
+
+    if ((driveLetter >= 'a') && (driveLetter <= 'z'))
+    {
+        drive = (TDriveNumber)(driveLetter - 'a');
+    }
+    else if ((driveLetter >= 'A') && (driveLetter <= 'Z'))
+    {
+        drive = (TDriveNumber)(driveLetter - 'A');
+    }
+    else
+    {
+        ELOG1(EJavaConverters,
+              "CPreConverter::ExtractDriveNumberFromPathL path starts "
+              "with illegal char, value %d", drive);
+        User::Leave(KErrArgument);
+    }
+
+    return drive;
+}
+
+/**
+ * Read the midlet id and suite id for each midlet in iMidlets from
+ * SystemAMS DB and store them to iMidlets
+ */
+void CPreConverter::AddDataFromSystemAmsDbL()
+{
+    MIDP::DBv2::MDatabase* database = NULL;
+    MIDP::DBv2::MMIDletTable* midletTable = NULL;
+    RDbNamedDatabase dbNamed;
+    RDbs dbs;
+
+    // Connect to db
+    TInt err = dbs.Connect();
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot connect to RDbs, "
+              "error %d", err);
+        User::Leave(err);
+    }
+
+    // Open db
+    err = dbs.ShareAuto();
+    if (KErrNone != err)
+    {
+        dbs.Close();
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot share RDbs session, "
+              "error %d", err);
+        User::Leave(err);
+    }
+    err = dbNamed.Open(
+              iFs, KStaticDbFileName(), KUidSSystemAMSDbPolicy, RDbNamedDatabase::EReadOnly);
+    if (KErrNone != err)
+    {
+        dbs.Close();
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot open named db, "
+              "error %d", err);
+        User::Leave(err);
+    }
+
+    // Get db
+    TRAP(err, database = MIDP::DBv2::GetDatabaseL(KDBVersion));
+    if (KErrNone != err)
+    {
+        dbNamed.Close();
+        dbs.Close();
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot get database, "
+              "error %d", err);
+        User::Leave(err);
+    }
+
+    // Get midlet table
+    TRAP(err, midletTable = database->MIDletTableL());
+    if (KErrNone != err)
+    {
+        delete database;
+        dbNamed.Close();
+        dbs.Close();
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot get midlet table from db, "
+              "error %d", err);
+        User::Leave(err);
+    }
+
+    // Open midlet table
+    TRAP(err, midletTable->OpenL(dbNamed));
+    if (KErrNone != err)
+    {
+        delete database;
+        dbNamed.Close();
+        dbs.Close();
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot open midlet table in db, "
+              "error %d", err);
+        User::Leave(err);
+    }
+
+    // get iterator to access the data in midlet table
+    MIDP::DBv2::MMIDletTableIterator* tableIterator = NULL;
+    // No items must be left in cleanup stack when exiting TRAP macro
+    TRAP(err,
+         tableIterator = midletTable->IteratorLC();
+         if (KErrNone == err) CleanupStack::Pop();
+        );
+    if (KErrNone != err)
+    {
+        midletTable->Close();
+        delete database;
+        dbNamed.Close();
+        dbs.Close();
+        ELOG1(EJavaConverters,
+              "CPreConverter::AddDataFromSystemAmsDbL Cannot get iterator for midlet table in db, "
+              "error %d", err);
+        User::Leave(err);
+    }
+
+
+    TBuf8<512> midletDesc;
+    TInt32  count = 0;
+    TUint32 msId;
+    TUint32 id;
+    TUint32 uid;
+    TPtrC   name;
+    TPtrC   className;
+    TPtrC   idString;
+    while (tableIterator->HasNext())
+    {
+        TRAP(err, tableIterator->NextL(msId, id, uid, name, className, idString));
+        if (KErrNone != err)
+        {
+            delete tableIterator;
+            midletTable->Close();
+            delete database;
+            dbNamed.Close();
+            dbs.Close();
+            ELOG1(EJavaConverters,
+                  "CPreConverter::AddDataFromSystemAmsDbL Midlet table iterator NextL failed, "
+                  "error %d", err);
+            User::Leave(err);
+        }
+        LOG3(EJavaConverters, EInfo,
+             "CPreConverter::AddDataFromSystemAmsDbL Found midlet uid %x, suite id %d, midlet id %d",
+             uid, msId, id);
+
+        midletDesc.Append(KMLName);
+        midletDesc.Append(name);
+        midletDesc.Append(KMLClassName);
+        midletDesc.Append(className);
+        midletDesc.Append(KMLIdString);
+        midletDesc.Append(idString);
+        LOG(EJavaPreinstaller, EInfo, (const char *)midletDesc.PtrZ());
+        midletDesc.Zero();
+
+        iMidlets->SetIds(name, msId, id);
+        count++;
+    }
+
+    LOG1(EJavaConverters, EInfo,
+         "CPreConverter::AddDataFromSystemAmsDbL midlet table had %d midlets.", count);
+
+    // close and free everything
+    delete tableIterator;
+    midletTable->Close();
+    delete database;
+    dbNamed.Close();
+    dbs.Close();
+}
+
+/**
+ * Check all midlets in iMidlets and remove those midlets that do not
+ * have midlet id and suite id.
+ */
+void CPreConverter::RemoveInvalidMidlets()
+{
+    // If midlet id or suite id is KMaxTUint32, it has not been set ->
+    // remove the midlet
+
+    CMidletInfo *midlet = iMidlets->GetFirst();
+    TBuf8<512> midletDesc;
+
+    while (NULL != midlet)
+    {
+        if ((midlet->GetMidletId() == KMaxTUint32) ||
+                (midlet->GetSuiteId() == KMaxTUint32))
+        {
+            midlet->ToString8(midletDesc);
+            WLOG(EJavaConverters,
+                 "CPreConverter::RemoveInvalidMidlets Not going to convert this midlet:");
+            midletDesc.ZeroTerminate();
+            WLOG(EJavaPreinstaller, (const char *)(midletDesc.Ptr()));
+            midletDesc.Zero();
+            iMidlets->Remove(midlet);
+        }
+
+        midlet = iMidlets->GetNext();
+    }
+}
+
+/**
+ * Store the uids of the midlets to be converted
+ * to file 'uids' in the data cage of javaappconverter.exe
+ */
+void CPreConverter::StoreUidsL()
+{
+    TFileName exportUidsPath(KUidsExportDirectory);
+
+    // Create directory if it does not exist
+    TInt err= iFs.MkDirAll(exportUidsPath);
+    if ((KErrNone != err) && (KErrAlreadyExists != err))
+    {
+        User::Leave(err);
+    }
+
+    // Store all uids to file 'uids' in the directory
+    exportUidsPath.Append(KUidsExportDataFileName);
+
+    // Construct write stream so that possibly existing old data file is replaced.
+    RFileWriteStream writeStream;
+    User::LeaveIfError(writeStream.Replace(iFs, exportUidsPath, EFileWrite));
+    CleanupClosePushL(writeStream);
+
+    // Write the number of midlets
+    TUint32 nMidlets = iMidlets->Count();
+    writeStream.WriteUint32L(nMidlets);
+
+    // Write Uids of the midlets one by one
+    CMidletInfo *midlet = iMidlets->GetFirst();
+
+    while (NULL != midlet)
+    {
+        writeStream.WriteUint32L(midlet->GetMidletUid().iUid);
+        midlet = iMidlets->GetNext();
+    }
+
+    // Closes writeStream
+    CleanupStack::PopAndDestroy();
+}
+
+/**
+ * Unregisters the applications to be converted from AppArc
+ * so that Java Installer can make conversion installation
+ * using the same Uids as the applications now have.
+ *
+ * Leaves with error code if AppArc cannot be connected or if
+ * unregistrations cannot be committed.
+ */
+void CPreConverter::UnregisterOldJavaAppsL()
+{
+    // connect to AppArc
+    RApaLsSession apaSession;
+
+    TInt err = apaSession.Connect();
+    if (KErrNone != err)
+    {
+        // Fatal error, try to connect again. The midlets cannot be converted
+        // using the same uids as earlier if the unregistration cannot be done.
+        TInt retryCount = 0;
+        do
+        {
+            ELOG1(EJavaConverters,
+                  "CPreConverter::UnregisterOldJavaAppsL Cannot connect to "
+                  "AppArc server, err %d", err);
+
+            // wait
+            User::After(KDelayWhenWaitingAppArc);
+
+            err = apaSession.Connect();
+            if (KErrNone == err)
+            {
+                break;
+            }
+
+            retryCount++;
+        }
+        while (retryCount < 10);
+
+        if (KErrNone != err)
+        {
+            User::Leave(err);
+        }
+    }
+    CleanupClosePushL(apaSession);
+
+    // Delete any pending (un)registrations (possible if
+    // e.g. device rebooted before commit).
+    // This call does nothing if there is no pending registrations.
+    // Ignore errors.
+    (void)apaSession.RollbackNonNativeApplicationsUpdates();
+
+    // Prepare for Java application unregistrations
+    TRAP(err, apaSession.PrepareNonNativeApplicationsUpdatesL());
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "CPreConverter::UnregisterOldJavaAppsL: "
+              "PrepareNonNativeApplicationsUpdatesL leaved with err %d",
+              err);
+        User::Leave(err);
+    }
+
+    // Unregister all apps
+    CMidletInfo *midlet = iMidlets->GetFirst();
+
+    while (NULL != midlet)
+    {
+        TRAP(err, apaSession.DeregisterNonNativeApplicationL(midlet->GetMidletUid()));
+        if (KErrNone != err)
+        {
+            WLOG2(EJavaConverters,
+                  "CPreConverter::UnregisterOldJavaAppsL: "
+                  "DeregisterNonNativeApplicationL leaved with err %d for uid %d",
+                  err, midlet->GetMidletUid().iUid);
+            // Ignore error, this particular application cannot be converted.
+        }
+
+        midlet = iMidlets->GetNext();
+    }
+
+    // Commit unregistrations
+    TRAP(err, apaSession.CommitNonNativeApplicationsUpdatesL())
+    {
+        if (KErrNone != err)
+        {
+            ELOG1(EJavaConverters,
+                  "CPreConverter::UnregisterOldJavaAppsL: "
+                  "CommitNonNativeApplicationsUpdatesL leaved with err %d",
+                  err);
+            User::Leave(err);
+        }
+    }
+
+    // Closes apaSession
+    CleanupStack::PopAndDestroy();
+}
+