javatools/javaappconverter/src.s60/silentmidletconvert.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javatools/javaappconverter/src.s60/silentmidletconvert.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,953 @@
+/*
+* 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 javaappconverter process
+*
+*/
+
+
+#include <e32base.h>
+#include <apgcli.h>
+#include <pathinfo.h>
+#include <driveinfo.h>
+
+#include "silentmidletconvert.h"
+#include "javauids.h"
+#include "javacommonutils.h"
+#include "logger.h"
+#include "javaprocessconstants.h"
+#include "javasymbianoslayer.h"
+
+
+using namespace java::util;
+
+_LIT(KJarFileNameSuffix, ".jar");
+_LIT(KJadFileNameSuffix, ".jad");
+_LIT(KFLJarFileNameSuffix, ".dm");
+_LIT(KSDJarFileNameSuffix, ".dcf");
+_LIT(KSMCBackSplash, "\\");
+
+// The directory where the java applications to be converted are searched from
+_LIT(KMidletSuiteInstallBasePath, ":\\Private\\102033E6\\MIDlets\\");
+
+
+/**
+ * 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.
+ *
+ */
+CSilentMIDletConvert* CSilentMIDletConvert::NewLC(RFs& aFs)
+{
+    CSilentMIDletConvert* self = new(ELeave) CSilentMIDletConvert(aFs);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+}
+
+/**
+ * To do 1st phase construction for this object.
+ *
+ * Adds this active object to the scheduler.
+ *
+ * @param aFs - A reference to the file server.
+ */
+CSilentMIDletConvert::CSilentMIDletConvert(RFs& aFs) :
+        CActive(EPriorityStandard), iFs(aFs), iNumberOfAppsToInstall(0),
+        iDefaultTargetInstallationDrive(-1)
+{
+    CActiveScheduler::Add(this);
+}
+
+/**
+ * To do 2nd phase construction for this object.
+ *
+ * @exception If the method is not able to allocate necessary buffers.
+ */
+void CSilentMIDletConvert::ConstructL()
+{
+    JELOG2(EJavaConverters);
+
+    iConvertServer = new(ELeave) ConvertServer();
+}
+
+/**
+ * Deletes this object.
+ * All allocated resources are released.
+ */
+CSilentMIDletConvert::~CSilentMIDletConvert()
+{
+    JELOG2(EJavaConverters);
+    Cancel();
+    iInstallFiles.ResetAndDestroy();
+    iInstallFiles.Close();
+
+    iDirs.ResetAndDestroy();
+    iDirs.Close();
+
+    delete iConvertServer;
+    iConvertServer = NULL;
+}
+
+/**
+ * To start silent installation.
+ */
+void CSilentMIDletConvert::Start()
+{
+    JELOG2(EJavaConverters);
+    iState = EFindOutDeviceDrives;
+    CompleteRequest();
+}
+
+/**
+ * To stop whole preinstaller.
+ * Stops the active scheduler.
+ */
+void CSilentMIDletConvert::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 CSilentMIDletConvert::CompleteRequest()
+{
+    JELOG2(EJavaConverters);
+
+    TRequestStatus *status = &iStatus;
+    User::RequestComplete(status, KErrNone);
+    if (!IsActive())
+    {
+        SetActive();
+    }
+}
+
+/**
+ * To run this active object.
+ *
+ * The state logic is:
+ *
+ * EFindOutDeviceDrives: find out all non-remote drives in the device
+ *    - mark externally mountable drives (removable drives)
+ *    - mark read only drives (ROM)
+ *
+ * EFindOutDrivesToBeScannedNow: make list of drives to be scanned
+ *    - start with all mounted drives
+ *
+ * EAppsInInstalledDirectories: go through all directories in iDirs one by one
+ *  and find all java applications in the subdirectories of the directory
+ *    - if only .jar/.dcf/.dm file is found it is added to iInstallFiles
+ *    - if .jad file is found, it is added to iInstallFiles
+ *
+ * ECheckWhichAppsShouldBeConverted: for each java application check from
+ *  AppArc whether it should be converted
+ *    - if the application has been installed, convert it
+ *
+ * EExecuteConvertServer: give list of install files to preinstall server,
+ *  start Java Installer in poll mode, start convert server in another thread,
+ *  convert server will give the names of the .jad or .jar/.dcf/.dm files to Java Installer
+ *  when it polls them,  convert server will log whether each installation
+ *  succeeded. After all install files have been polled, convert server will ask
+ *  Java Installer to exit. After that this active object moves to next state.
+ *
+ * EMarkConversionDone: remove 'uids' data file created by javaapppreconverter
+ *
+ * EExit: free resources and exit
+ *
+ */
+void CSilentMIDletConvert::RunL()
+{
+    JELOG2(EJavaConverters);
+
+    switch (iState)
+    {
+    case EFindOutDeviceDrives:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CSilentMIDletConvert::RunL EFindOutDeviceDrives");
+        GetAllDeviceDrivesL();
+        iState = EFindOutDrivesToBeScannedNow;
+        CompleteRequest();
+    }
+    break;
+
+    case EFindOutDrivesToBeScannedNow:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CSilentMIDletConvert::RunL EFindOutDrivesToBeScannedNow");
+
+        TChar driveChar = 'C';
+
+        // forget old search directories
+        iDirs.ResetAndDestroy();
+
+        for (TInt drive = 0; drive < KMaxDrives; drive++)
+        {
+            // All present drives will be scanned for
+            // java applications to be converted
+            if (iDriveStatuses[drive] & DriveInfo::EDrivePresent)
+            {
+                (void)iFs.DriveToChar(drive, driveChar);
+
+                // The base Java application install directory in this
+                // drive must be scanned.
+                // Reserve memory also for drive letter and terminating zero
+                // for logging.
+                HBufC *baseInstallDir = HBufC::NewLC(KMidletSuiteInstallBasePath().Length() + 2);
+
+                TPtr dirPtr(baseInstallDir->Des());
+                dirPtr.Append(driveChar);
+                dirPtr.Append(KMidletSuiteInstallBasePath());
+
+                // Add new search directory
+                iDirs.AppendL(baseInstallDir);
+                CleanupStack::Pop(baseInstallDir);
+            }
+        }
+
+        iState = EAppsInInstalledDirectories;
+        CompleteRequest();
+    }
+    break;
+
+    case EAppsInInstalledDirectories:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CSilentMIDletConvert::RunL EAppsInInstalledDirectories");
+
+        GetInstallFilesL(iDirs);
+
+        iState = ECheckWhichAppsShouldBeConverted;
+        CompleteRequest();
+    }
+    break;
+
+    case ECheckWhichAppsShouldBeConverted:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CSilentMIDletConvert::RunL ECheckWhichAppsShouldBeConverted");
+
+        // Check all Jad / Jar files in iInstallFiles and remove those
+        // that need not be converted (those that cannot be found from
+        // AppArc). Updates also iNumberOfAppsToInstall
+        CheckNeedToInstall();
+
+        iState = EExecuteConvertServer;
+        CompleteRequest();
+    }
+    break;
+
+    case EExecuteConvertServer:
+    {
+        LOG(EJavaConverters, EInfo,
+            "CSilentMIDletConvert::RunL EExecuteConvertServer");
+
+        if (iNumberOfAppsToInstall > 0)
+        {
+            // Install all MIDlet Suites still in iInstallFiles.
+
+            // Pass iInstallFiles to ConvertServer
+            iConvertServer->setInstallFiles(iInstallFiles);
+
+            // Start the server
+            int err = iConvertServer->start();
+            if (0 != err)
+            {
+                // server cannot be started
+                ELOG1(EJavaConverters,
+                      "Cannot start convert server, err %d", err);
+            }
+
+            // Starts Java Installer, waits until Java Installer exits
+            RunJavaInstallerL();
+
+            iState = EMarkConversionDone;
+        }
+        else
+        {
+            iState = EMarkConversionDone;
+            CompleteRequest();
+        }
+    }
+    break;
+
+    case EMarkConversionDone:
+    {
+        // If this line is executed, converting old midlets succeeded.
+        // Remove the 'uids' data file so that conversion will not be
+        // done again if OMJ sis package is installed again to the same device.
+        RemoveDataFile();
+
+        iState = EExit;
+        CompleteRequest();
+    }
+    break;
+
+    case EExit:
+    {
+        LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunL EExit");
+
+        // Stops the server if it is running
+        iConvertServer->stop();
+
+        FullCleanup();
+
+        // The whole javaappconverter 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 CSilentMIDletConvert::RunError(TInt aError)
+{
+    ELOG2(EJavaConverters,
+          "CSilentMIDletConvert::RunError(%d) from state %d", aError, iState);
+
+    Cancel();
+
+    iState = EExit;
+    CompleteRequest();
+
+    return KErrNone;
+}
+
+/**
+ * To do cancelling for this object.
+ *
+ */
+void CSilentMIDletConvert::DoCancel()
+{
+    ELOG1(EJavaConverters,
+          "CSilentMIDletConvert::DoCancel from state %d", iState);
+
+    // Check whether convert server must be stopped
+    if (iState == EExecuteConvertServer)
+    {
+        // Stops the server if it is running
+        iConvertServer->stop();
+    }
+}
+
+/**
+ * Add .jad files in the directories specified in aDirs to iInstallFiles.
+ * If a directory does not contain a .jad file but it contains a .jar/.dcf/.dm file,
+ * add that file to iInstallFiles
+ *
+ * @param aDirs - An array of directories to be scanned.
+ * @exception Unable to alloc memory for the internal buffers.
+ * @exception Unable to get directory's contents.
+ */
+void CSilentMIDletConvert::GetInstallFilesL(RPointerArray<HBufC>& aDirs)
+{
+    JELOG2(EJavaConverters);
+
+    // Number of MIDlet installation base directories to scan,
+    // one directory per local drive
+    const TInt nBaseDirs = aDirs.Count();
+
+    for (TInt i = 0; i < nBaseDirs; i++)
+    {
+        TFileName suitePath;
+
+        // Form base directory path, MIDlets have been installed
+        // to subdirectories of this directory
+        const TPtrC& dir = ((HBufC *)(aDirs[i]))->Des();
+        TFileName baseSuitePath = dir;
+
+        CDir *entryList;
+        CDir *dirList;
+        TInt err = iFs.GetDir(baseSuitePath, KEntryAttMatchMask, ESortNone, entryList, dirList);
+        if (KErrNone != err)
+        {
+            WLOG1WSTR(EJavaConverters,
+                      "CSilentMIDletConvert::GetInstallFilesL Cannot list directory %s",
+                      (wchar_t *)(baseSuitePath.PtrZ()));
+
+            // If no S60 Java application has been installed to the drive,
+            // the directory does not exist but it is OK
+            if (KErrPathNotFound != err)
+            {
+                User::Leave(err);
+            }
+            continue;
+        }
+
+        // Only midlet installation directory entries are meaningfull,
+        // discard other possible entries
+        delete entryList;
+
+        TInt   nCount = dirList->Count();
+        TEntry dirEntry;
+
+        for (TInt nInd = 0; nInd < nCount; nInd++)
+        {
+            dirEntry = (*dirList)[nInd];
+            // Just to make sure this really is subdirectory
+            if (dirEntry.IsDir())
+            {
+                // Is this midlet suite subdir?
+                // Midlet suite subdirs look like this "[102b567B]"
+                // Must parse the value of the Uid as unsigned int to avoid
+                // overflow
+                TUint32 nUid;
+                TLex   lexer(dirEntry.iName);
+                lexer.Inc();
+                err = lexer.Val(nUid, EHex);
+                if (KErrNone != err)
+                {
+                    // Not midlet suite subdir, skip it
+                    continue;
+                }
+
+                // Does the subdirectory contain any Jar files?
+                suitePath = baseSuitePath;
+                suitePath.Append(dirEntry.iName);
+                suitePath.Append(KSMCBackSplash);
+
+                CDir *suiteDirEntryList;
+                err = iFs.GetDir(suitePath, KEntryAttMatchMask, ESortNone, suiteDirEntryList);
+                if (KErrNone != err)
+                {
+                    ELOG1WSTR(EJavaConverters,
+                              "CSilentMIDletConvert::GetInstallFilesL Cannot list content of suite dir %s",
+                              (wchar_t *)(suitePath.PtrZ()));
+                    User::Leave(err);
+                    return;
+                }
+                // If there is .jad or Jar file in suiteDirEntryList, adds
+                // it to iInstallFiles.
+                // Recognizes also DRM protected Jar files (.dm, .dcf)
+                AddJadJarToInstallFilesL(suitePath, suiteDirEntryList);
+                delete suiteDirEntryList;
+            }
+        } // for - loop all directory entries in a base installation directories
+        delete dirList;
+
+    } // for - loop all base installation directories
+
+    if (iInstallFiles.Count() == 0)
+    {
+        WLOG(EJavaConverters,
+             "CSilentMIDletConvert::GetInstallFilesL No MIDlets to convert");
+    }
+}
+
+/**
+ * Check all Jad / Jar files in iInstallFiles and remove those
+ * that need not be converted. Updates also iNumberOfAppsToInstall.
+ */
+void CSilentMIDletConvert::CheckNeedToInstall()
+{
+    // It is too late to check from AppArc whether the application is a
+    // valid java application or no. The Java registry dll:s have been eclipsed and
+    // old apps are now invalid.
+    // javaapppreconverter has stored the Uids of the valid midlets to 'uids' file
+    // in to the data subdirectory of this process.
+    // ReadMidletUids() can be used to read the uids of the valid midlets to array.
+    // If uid is in the array, it is valid.
+    TFileName uidsDataFilePathName(KUidsImportDataFilePathName);
+    RArray<TUid> validUids = ReadMidletUids(uidsDataFilePathName);
+
+    // loop through iInstallFiles one be one
+    TInt   nNumberOfAppsToInstall = 0;
+    TInt   err;
+    TInt   nFiles = iInstallFiles.Count();
+    TParse fp;
+    for (TInt nInd = 0; nInd < nFiles; nInd++)
+    {
+        // get the directory path of the current iInstallFiles[nInd]
+        err = fp.Set(*(iInstallFiles[nInd]), NULL, NULL);
+        if (KErrNone != err)
+        {
+            WLOG1(EJavaConverters,
+                  "CSilentMIDletConvert::CheckNeedToInstall Cannot parse install file name %s",
+                  iInstallFiles[nInd]);
+            continue;
+        }
+
+        TPtrC installDir = fp.DriveAndPath();
+
+        // read Java applications uid(s) from 'uids' file in the directory
+        RArray<TUid> appUids = ReadMidletUids(installDir);
+
+        // For each app uid, check whether it is uid of an valid java  application.
+        // If yes, make conversion installation for the .jad/Jar file
+        // in this directory.
+        TInt nIndUids;
+        TInt nCountUids = appUids.Count();
+        for (nIndUids = 0; nIndUids < nCountUids; nIndUids++)
+        {
+            err = validUids.Find(appUids[nIndUids]);
+            if (KErrNotFound == err)
+            {
+                LOG1(EJavaConverters, EInfo,
+                     "CSilentMIDletConvert::CheckNeedToInstall Midlet with Uid %x "
+                     "was not registered to AppArc",
+                     appUids[nIndUids].iUid);
+
+                // Do not convert any app in this Midlet suite
+                delete iInstallFiles[nInd];
+                iInstallFiles[nInd] = NULL;
+                break;
+            }
+            else
+            {
+                // The application is valid, so it should be converted
+                nNumberOfAppsToInstall++;
+            }
+        }
+        appUids.Close();
+    }
+    validUids.Close();
+
+    // how many applications to convert
+    iNumberOfAppsToInstall = nNumberOfAppsToInstall;
+}
+
+/**
+ * Read the midlet uids from file 'uids' in the directory
+ * given in parameter aDir and return them in RArray
+ *
+ * @param aDir -  directory that contains 'uids' file
+ * @return the midlet uids in RArray. Caller must destroy the RArray
+ */
+RArray<TUid> CSilentMIDletConvert::ReadMidletUids(const TPtrC& aDir)
+{
+    RArray<TUid> midletUids;
+    RFile fileUids;
+    TFileName nameUids = aDir;
+    nameUids.Append(_L("uids"));
+
+    TInt err = fileUids.Open(iFs, nameUids, EFileRead);
+    if (KErrNone != err)
+    {
+        // cannot open "uids" file
+        nameUids.Append(0);
+        WLOG1WSTR(EJavaConverters,
+                  "CSilentMIDletConvert::ReadMidletUids cannot open uids file in dir %s",
+                  (wchar_t *)(&(nameUids[0])));
+        WLOG1(EJavaConverters, "Error is %d", err);
+        return midletUids;
+    }
+
+    TInt fileSize(0);
+    err = fileUids.Size(fileSize);
+    if (fileSize < 8)
+    {
+        // valid "uids" file contains at least the uid of the suite and
+        // uid of at least one midlet
+        fileUids.Close();
+        // invalid "uids" file
+        nameUids.Append(0);
+        WLOG1WSTR(EJavaConverters,
+                  "CSilentMIDletConvert::ReadMidletUids invalid uids file in dir %s",
+                  (wchar_t *)(&(nameUids[0])));
+        return midletUids;
+    }
+
+    // reserve buffer for one uid
+    TBuf8<4> readBuf;
+    TDes8 readBufDes(readBuf);
+
+    // The first uid is suite uid but we are not interested in it. Skip it.
+    err = fileUids.Read(readBufDes);
+    if (KErrNone != err)
+    {
+        fileUids.Close();
+        // cannot read "uids" file
+        nameUids.Append(0);
+        WLOG1WSTR(EJavaConverters,
+                  "CSilentMIDletConvert::ReadMidletUids cannot read uids file in dir %s",
+                  (wchar_t *)(&(nameUids[0])));
+        WLOG1(EJavaConverters, "Error is %d", err);
+        return midletUids;
+    }
+
+    // Now read rest of the file one uid at a time
+    TInt  nReadBytes = readBufDes.Length();
+    TUint midletUidValue;
+    TUint temp;
+
+    while (nReadBytes == 4)
+    {
+        err = fileUids.Read(readBufDes);
+        if (KErrNone != err)
+        {
+            fileUids.Close();
+            // cannot read "uids" file
+            nameUids.Append(0);
+            WLOG1WSTR(EJavaConverters,
+                      "CSilentMIDletConvert::ReadMidletUids(2) cannot from uids file in dir %s",
+                      (wchar_t *)(&(nameUids[0])));
+            WLOG1(EJavaConverters, "Error is %d", err);
+            return midletUids;
+        }
+
+        nReadBytes = readBufDes.Length();
+        if (nReadBytes == 4)
+        {
+            // One whole midlet id was read to buffer.
+            // 4 bytes per midlet, least significant byte first
+            TUid  midletUid;
+
+            midletUidValue = readBufDes[0];
+            temp = readBufDes[1];
+            midletUidValue += temp<<8;
+            temp = readBufDes[2];
+            midletUidValue += temp<<16;
+            temp = readBufDes[3];
+            midletUidValue += temp<<24;
+
+            midletUid.iUid = midletUidValue;
+            midletUids.Append(midletUid);
+        }
+    }
+
+    fileUids.Close();
+
+    return midletUids;
+}
+
+/**
+ * Scan the content of one directory entry and add the name of
+ * .jad / .jar /.dcf/.dm file to iInstallFiles if
+ * the directory contains a valid, installed Java application.
+ * Recognizes also DRM protected jar files (.dm, .dcf)
+ *
+ * @param aSuitePathName -  directory to be scanned.
+ * @param aSuiteDirEntryList - contents of the directory
+ * @exception Unable to alloc memory for the internal buffers.
+ */
+void CSilentMIDletConvert::AddJadJarToInstallFilesL(
+    const TFileName &aSuitePathName,
+    const CDir *aSuiteDirEntryList)
+{
+    JELOG2(EJavaConverters);
+
+    if (NULL == aSuiteDirEntryList)
+    {
+        return;
+    }
+
+    TInt nCount = aSuiteDirEntryList->Count();
+    if (0 == nCount)
+    {
+        return;
+    }
+
+    TInt        suffixPos;
+    TEntry      dirEntry;
+    TBool       jarFileInSuiteDir = EFalse;
+    TBool       jadFileInSuiteDir = EFalse;
+    TFileName   jadFullPathName;
+    TFileName   jarFullPathName;
+
+    for (TInt nInd = 0; nInd < nCount; nInd++)
+    {
+        dirEntry = (*aSuiteDirEntryList)[nInd];
+        // Directory cannot be Jar file.
+        // Empty file cannot valid Jar file
+        if (dirEntry.IsDir() || (dirEntry.iSize == 0))
+        {
+            continue;
+        }
+        // get the suffix of the name
+        suffixPos = dirEntry.iName.LocateReverse('.');
+        if (suffixPos == KErrNotFound)
+        {
+            // File name does not contain '.' char
+            continue;
+        }
+        TPtrC suffix(dirEntry.iName.Mid(suffixPos));
+
+        // if the name ends with ".jar" the name is current candidate
+        // for the name to be added to iInstallFiles list
+        if (suffix.CompareF(KJarFileNameSuffix) == 0)
+        {
+            jarFullPathName = aSuitePathName;
+            jarFullPathName.Append(dirEntry.iName);
+            jarFileInSuiteDir = ETrue;
+        }
+        else if (suffix.CompareF(KJadFileNameSuffix) == 0)
+        {
+            // If .jad file is found, then it will be added
+            // to iInstallFiles list
+            jadFullPathName = aSuitePathName;
+            jadFullPathName.Append(dirEntry.iName);
+            jadFileInSuiteDir = ETrue;
+        }
+        else if (suffix.CompareF(KFLJarFileNameSuffix) == 0)
+        {
+            // forward locked and combined delivery DRM protected
+            // .jar files have suffix ".dm"
+            jarFullPathName = aSuitePathName;
+            jarFullPathName.Append(dirEntry.iName);
+            jarFileInSuiteDir = ETrue;
+        }
+        else if (suffix.CompareF(KSDJarFileNameSuffix) == 0)
+        {
+            // separate delivery DRM protected .jar files have suffix ".dcf"
+            jarFullPathName = aSuitePathName;
+            jarFullPathName.Append(dirEntry.iName);
+            jarFileInSuiteDir = ETrue;
+        }
+    }
+
+    // If directory contains a Jar file, then add something to iInstallFiles
+    if (jarFileInSuiteDir)
+    {
+        // If directory contains also .jad file, add .jad file name to iInstallFiles
+        if (jadFileInSuiteDir)
+        {
+            // Reserve one char for null terminator
+            HBufC* path = HBufC::NewLC(jadFullPathName.Length() + 1);
+            TPtr pathPtr(path->Des());
+            pathPtr.Append(jadFullPathName);
+
+            LOG1WSTR(EJavaConverters, EInfo,
+                     "CSilentMIDletConvert::AddJadJarToInstallFilesL Adding jad file %s",
+                     (wchar_t *)(pathPtr.PtrZ()));
+            iInstallFiles.Append(path);
+            CleanupStack::Pop(path);
+        }
+        else
+        {
+            // Reserve one char for null terminator
+            HBufC* path = HBufC::NewLC(jarFullPathName.Length() + 1);
+            TPtr pathPtr(path->Des());
+            pathPtr.Append(jarFullPathName);
+
+            LOG1WSTR(EJavaConverters, EInfo,
+                     "CSilentMIDletConvert::AddJadJarToInstallFilesL Adding jar file %s",
+                     (wchar_t *)(pathPtr.PtrZ()));
+            iInstallFiles.Append(path);
+            CleanupStack::Pop(path);
+        }
+    }
+}
+
+/**
+ * Start Java Installer in poll mode and then wait until it exits.
+ */
+void CSilentMIDletConvert::RunJavaInstallerL()
+{
+    LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller");
+
+    RProcess rJavaInstaller;
+    TFileName fileName;
+    TInt err;
+    // Max one path name, user name and password and some options ->
+    // 1536 is enough
+    TBuf<1536> commandLine;
+
+    // Build command line used to pass all necessary info to Java Installer
+    std::auto_ptr<HBufC> installerStarterDll(
+        stringToDes(java::runtime::JAVA_INSTALLER_STARTER_DLL));
+    commandLine = installerStarterDll->Des();
+    commandLine.Append(_L(" poll -address=convert"));
+
+    // Run installer silently
+    commandLine.Append(_L(" -silent"));
+
+    // Convert old S60 applications so that applications uids,
+    // private data and RMS data are all preserved
+    commandLine.Append(_L(" -convert=yes"));
+
+    // Upgrading MIDlets is allowed
+    commandLine.Append(_L(" -upgrade=yes"));
+
+    // No OCSP checks for converted MIDlets
+    commandLine.Append(_L(" -ocsp=no"));
+
+    // Allow upgrade even if version number has not increased
+    commandLine.Append(_L(" -overwrite=yes"));
+
+    // Downloading .jar is not allowed.
+    commandLine.Append(_L(" -download=no"));
+
+    // If upgrade install, automatically upgrade also the data
+    commandLine.Append(_L(" -upgrade_data=yes"));
+
+    // If the device has an internal drive with much free disk space,
+    // install all converted applications to that drive
+    if (iDefaultTargetInstallationDrive > -1)
+    {
+        TChar targetDrive;
+        err = RFs::DriveToChar(iDefaultTargetInstallationDrive, targetDrive);
+        if (KErrNone == err)
+        {
+            commandLine.Append(_L(" -drive="));
+            commandLine.Append(targetDrive);
+        }
+    }
+
+    // start JavaInstaller
+    std::auto_ptr<HBufC> installerProcess(
+        stringToDes(java::runtime::JAVA_PROCESS));
+    err = rJavaInstaller.Create(installerProcess->Des(), commandLine);
+    if (KErrNone == err)
+    {
+        LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller calling Rendezvous");
+        // This call will wait until Java Installer exits (or panics)
+        rJavaInstaller.Logon(iStatus);
+
+        LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller calling Resume");
+        rJavaInstaller.Resume();
+    }
+    else
+    {
+        ELOG1(EJavaConverters,
+              "CSilentMIDletConvert::RunJavaInstaller Cannot start Installer, error %d", err);
+        // CActive will trap the following leave, execution will go to RunError
+        User::Leave(err);
+    }
+
+    LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller calling RProcess::Close");
+    // free resources before returning
+    rJavaInstaller.Close();
+
+    // now wait until Java Installer exits
+    SetActive();
+}
+
+/**
+ * To cleanup member variables.
+ */
+void CSilentMIDletConvert::FullCleanup()
+{
+    JELOG2(EJavaConverters);
+
+    iDirs.ResetAndDestroy();
+    iInstallFiles.ResetAndDestroy();
+}
+
+
+/**
+ * Checks all local drives in the device and stores the DriveInfo API drive
+ * status information for each drive to iDriveStatuses
+ * @exception Cannot get drive list.
+ */
+void CSilentMIDletConvert::GetAllDeviceDrivesL()
+{
+    JELOG2(EJavaConverters);
+
+    TDriveList driveList;
+    // get all drives
+    TInt err = iFs.DriveList(driveList);
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "CSilentMIDletConvert::GetAllDeviceDrives cannot get drive list, err %d", err);
+        User::Leave(err);
+    }
+
+    // store status of the non-remote, non-substed drives
+    TInt64 requiredFreeDiskSpace = KMinimumFreeDiskSpace;
+    TUint  status = 0;
+    for (TInt drive = 0; drive < KMaxDrives; drive++)
+    {
+        iDriveStatuses[drive] = 0;
+
+        if (driveList[drive] == 0)
+        {
+            // no such drive in this device
+            continue;
+        }
+
+        err = DriveInfo::GetDriveStatus(iFs, drive, status);
+        if (KErrNone != err)
+        {
+            ELOG2(EJavaConverters,
+                  "CSilentMIDletConvert::GetAllDeviceDrivesL cannot get drive %d status, err %d",
+                  drive, err);
+            User::Leave(err);
+        }
+        // D drive is temporary RAM drive, skip it
+        // Drives J to Y are substed or remote drives, skip them
+        if ((drive == EDriveD) || ((drive >= EDriveJ) && (drive <= EDriveY)))
+        {
+            continue;
+        }
+
+        iDriveStatuses[drive] = status;
+
+        // If the device has an internal (non-removable) drive with much
+        // free disk space, use that drive as the target installation drive
+        // when making the conversion installations.
+        // Skip drives A: to D:, C: drive is not valid target drive because
+        // we do not want to fill C: drive unnecessarily
+        if (drive < EDriveE)
+        {
+            continue;
+        }
+        // drive must be internal and visible to the user but
+        // it must NOT be corrupted or in exclusive use or read only
+        if ((status & DriveInfo::EDriveInternal) &&
+                (!(status & DriveInfo::EDriveCorrupt)) &&
+                (!(status & DriveInfo::EDriveInUse)) &&
+                (!(status & DriveInfo::EDriveReadOnly)) &&
+                (status & DriveInfo::EDriveUserVisible))
+        {
+            // Is there 'enough' free disk space for conversion
+            TVolumeInfo volumeInfo;
+            err = iFs.Volume(volumeInfo, drive);
+            if (KErrNone == err)
+            {
+                if (volumeInfo.iFree > requiredFreeDiskSpace)
+                {
+                    iDefaultTargetInstallationDrive = drive;
+
+                    // If some other internal drive has even more free
+                    // disk space, it will be used as the target drive
+                    requiredFreeDiskSpace = volumeInfo.iFree;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Remove the data file that contain information about the midlets to be converted.
+ */
+void CSilentMIDletConvert::RemoveDataFile()
+{
+    TFileName dataFile(KUidsImportDataFilePathName);
+    dataFile.Append(KUidsImportDataFileName);
+
+    TInt err = iFs.Delete(dataFile);
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "CSilentMIDletConvert::RemoveDataFile: Cannot delete data file, err %d ",
+              err);
+    }
+}