javamanager/javabackup/midp2backup_usif/src.s60/midp2backupplugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 19 Aug 2010 09:48:13 +0300
branchRCL_3
changeset 24 6c158198356e
permissions -rw-r--r--
Revision: v2.2.9 Kit: 201033

/*
* 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:  Implementation of Midp2BackupPlugin
*
*/


#include "midp2backupplugin.h"
#include "midp2backupdataids.h"
#include "apparcbackuputil.h"
#include "javastoragebackuputil.h"
#include "javaversionbackuputil.h"

#include "javastoragenames.h"
#include "javastorageentry.h"
#include "javastorage.h"

#include "javacommonutils.h"
#include "logger.h"

#include <connect/sbdefs.h>
#include <s32mem.h>
#include <s32file.h>
#include <f32file.h>
#include <apgcli.h>


using namespace std;
using namespace java::storage;
using namespace java::backup;

// ======== MEMBER FUNCTIONS ========

CMidp2BackupPlugin::CMidp2BackupPlugin()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin constructor");
}

void CMidp2BackupPlugin::ConstructL()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::ConstructL");

    iIconDescIndex = 0;
    iBufferSpaceLeft = 0;
    iFirstCallToGetBackupDataSection = ETrue;
    iStorageDataBackup = ETrue;
    iStorageDataRestore = ETrue;
    iJavaVersionInfoWritten = EFalse;
    iRestoreState = EVersion;

    User::LeaveIfError(iFs.Connect());
    // to share file handles with AppArc
    User::LeaveIfError(iFs.ShareProtected());

    iStorageBackupUtil = CStorageBackupUtil::NewL();
    iAppArcUtil = CAppArcBackupUtil::NewL(iFs);
}

CMidp2BackupPlugin* CMidp2BackupPlugin::NewL()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::NewL");

    CMidp2BackupPlugin* self = new(ELeave) CMidp2BackupPlugin();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();

    return self;
}

CMidp2BackupPlugin::~CMidp2BackupPlugin()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin destructor");

    iFs.Close();
    iIconUidArray.Close();
    delete iAppArcUtil;
    delete iIconDesc;
    delete iRestoreIconDesc;
    delete iStorageBackupUtil;
}

// from base class CBackupPlugin

void CMidp2BackupPlugin::PrepareForBURL(TInt aBackupStateValue)
{
    (void)aBackupStateValue;  // Just to suppress a warning in release builds
    LOG1(EBackup, EInfo, "CMidp2BackupPlugin::PrepareForBURL, BUR state: %d", aBackupStateValue);
}

void CMidp2BackupPlugin::ReceiveSnapshotDataL(TDriveNumber /* aDrive */, TDesC8& /* aBuffer */, TBool /* aLastSection */)
{
    JELOG2(EBackup);
    User::Leave(KErrNotSupported);
}

TUint CMidp2BackupPlugin::GetExpectedDataSize(TDriveNumber /* aDrive */)
{
    JELOG2(EBackup);
    return 0;
}

void CMidp2BackupPlugin::GetSnapshotDataL(TDriveNumber /* aDrive */, TPtr8& /* aBuffer */, TBool& /* aFinished */)
{
    JELOG2(EBackup);
    User::Leave(KErrNotSupported);
}

void CMidp2BackupPlugin::InitialiseGetBackupDataL(TDriveNumber aDrive)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::InitialiseGetBackupDataL");
    iDrive = aDrive;
}

void CMidp2BackupPlugin::GetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinished)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::GetBackupDataSectionL");

    iBufferSpaceLeft = aBuffer.MaxLength();
    RDesWriteStream stream(aBuffer);
    CleanupClosePushL(stream);

    if (!iJavaVersionInfoWritten)
    {
        JavaVersionBackupUtil::WriteJavaVersionL(stream);
        iJavaVersionInfoWritten = ETrue;
        iBufferSpaceLeft -= 8;
    }

    if (iStorageDataBackup)
    {
        iStorageBackupUtil->BackupStorageDataL(stream, iStorageDataBackup, iBufferSpaceLeft);
        aFinished = EFalse;
    }

    else
    {
        if (iFirstCallToGetBackupDataSection)
        {
            LOG(EBackup, EInfo, "First Call To GetBackupDataSection");
            // Get the uids of midlets whose icons are to be backed up
            iIconFilePointer = 0;
            ResetIconArray();
            iAppArcUtil->GetMidletsFromAppArcL(iIconUidArray, iDrive);

            /* Streaming MMC's unique Id, if current drive is MMC
               and there's at least one midlet on the drive*/
            if (iIconUidArray.Count() > 0 && iDrive >= EDriveE && iDrive <= EDriveZ)
            {
                TUint32 mmcId = MmcIdL();

                if (mmcId != 0)
                {
                    LOG1(EBackup,EInfo, "Write MMC id: %u", mmcId);
                    stream.WriteUint32L(mmcId);
                    iBufferSpaceLeft -= sizeof(mmcId);
                }
            }
            // Setting flag to EFalse
            iFirstCallToGetBackupDataSection = EFalse;
        }

        // Next icon uid and filename
        TUid currentUid;
        HBufC* fullFileName = NULL;

        // Streaming leftover part of icon file
        if (iIconDescIndex)
        {
            LOG(EBackup, EInfo, "Streaming leftover part of icon file");

            /* if the icon file is bigger than the space in the buffer, write only
             part of it and fill iLeftover with remaining part. */
            if (iIconDesc->Size() - iIconDescIndex > iBufferSpaceLeft)
            {
                stream.WriteL(iIconDesc->Mid(iIconDescIndex), iBufferSpaceLeft);
                iIconDescIndex += iBufferSpaceLeft;
            }
            else
            {
                stream.WriteL(iIconDesc->Mid(iIconDescIndex));
                iIconDescIndex = 0;
            }

            aFinished = EFalse;
        }

        // Get new icon file
        else if (NextIcon(currentUid, fullFileName))
        {
            LOG1(EBackup, EInfo, "New icon file, id: %d", currentUid.iUid);

            // Readstream for icon file
            RFileReadStream fileStream;

            User::LeaveIfError(fileStream.Open(iFs, *fullFileName, EFileRead));
            CleanupClosePushL(fileStream);

            TEntry* entry = new(ELeave) TEntry();
            CleanupStack::PushL(entry);

            iFs.Entry(*fullFileName, *entry);
            TInt32 size = entry->iSize;

            // Write icon file content into iIconDesc
            LOG(EBackup, EInfo, "Write icon file content into iIconDesc");
            delete iIconDesc;
            iIconDesc = NULL;
            iIconDesc = HBufC8::NewL(size);

            TPtr8 buf = iIconDesc->Des();
            fileStream.ReadL(buf, size);

            // get the group name of the midlet from AppArc
            TBuf< KApaMaxAppGroupName >groupName(iAppArcUtil->GetMidletGroupName(currentUid));
            TInt groupNameSize = groupName.Size();

            // Write the size of the data
            LOG(EBackup,EInfo, "Write the size of the data");

            TParsePtrC parse(*fullFileName);
            TPtrC fileName = parse.NameAndExt();
            TInt32 fileNameSize = fileName.Size();

            stream.WriteInt32L(sizeof(TUid)    // Uid
                               + sizeof(TInt32)   // fileNameSize
                               + fileNameSize // filename
                               + sizeof(TInt32)   // number of icons
                               + sizeof(TInt32)   // groupnamesize
                               + groupNameSize
                               + size // icon file
                              );
            iBufferSpaceLeft -= sizeof(TInt32);

            // Write the Uid of the midlet
            LOG(EBackup, EInfo, "Write the Uid of the midlet");
            stream.WriteInt32L(currentUid.iUid);
            iBufferSpaceLeft -= sizeof(TUid);

            // Write the size of the icon filename
            LOG(EBackup, EInfo, "Write the size of the icon filename");
            stream.WriteInt32L(fileNameSize);
            iBufferSpaceLeft -= sizeof(TInt32);

            // Write icon filename
            LOG(EBackup, EInfo, "Write icon filename");
            stream.WriteL(fileName);
            iBufferSpaceLeft -= fileNameSize;

            // Write number of icons in midlet
            LOG(EBackup, EInfo, "Write number of icons in midlet");
            TInt iconCount;
            iAppArcUtil->NumberOfOwnDefinedIcons(TUid::Uid(currentUid.iUid), iconCount);
            stream.WriteInt32L(iconCount);
            iBufferSpaceLeft -= sizeof(TInt32);

            // TPtr8 groupName(iAppArcUtil->GetMidletGroupName(currentUid));
            LOG(EBackup, EInfo, "Write the size of the Group name of the midlet");
            stream.WriteInt32L(groupNameSize);
            iBufferSpaceLeft -= sizeof(TInt32);

            if (groupNameSize != 0)
            {
                LOG(EBackup, EInfo, "Write the Group name of the midlet");
                stream.WriteL(groupName);
                iBufferSpaceLeft -= groupNameSize;
            }

            /* if the icon file is bigger than the space in the buffer,
               write only part of it and fill iLeftover with remaining part */
            LOG(EBackup, EInfo, "Write icon");
            if (size > iBufferSpaceLeft)
            {
                stream.WriteL(buf, iBufferSpaceLeft);
                iIconDescIndex = iBufferSpaceLeft;
            }
            else
            {
                stream.WriteL(buf, size);
                iIconDescIndex = 0;
            }

            aFinished = EFalse;

            CleanupStack::PopAndDestroy(&fileStream);
            CleanupStack::PopAndDestroy(entry);
        }

        else
        {
            aFinished = ETrue;
            iFirstCallToGetBackupDataSection = ETrue;
            iStorageDataBackup = ETrue;
        }

        delete fullFileName;
    }
    CleanupStack::PopAndDestroy(&stream);
}


void CMidp2BackupPlugin::InitialiseRestoreBaseDataL(TDriveNumber aDrive)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::InitialiseRestoreBaseDataL");
    iDrive = aDrive;
}

void CMidp2BackupPlugin::RestoreBaseDataSectionL(TDesC8& aBuffer, TBool aFinished)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::RestoreBaseDataSectionL");

    iBufferSpaceLeft = aBuffer.Size();
    RDesReadStream stream(aBuffer);
    CleanupClosePushL(stream);
    TBool versionCheck = ETrue;

    if (((iRestoreState == EVersion) || (iRestoreState == EInstall)) && iBufferSpaceLeft >= 8)
    {
        if (iRestoreState == EInstall)
        {
            versionCheck = EFalse;
        }
        TUint ret = JavaVersionBackupUtil::CheckJavaVersionL(stream,iDrive,versionCheck);
        if (1==ret)
        {
            // Here set the satus to restore finished, so that control goes back to SBE & SBE calls B&R for another drive
            iRestoreState = EInstall;
        }
        else
        {
            /* version information has been written to stream.
             So change restore state to restore storage data  */
            iRestoreState = EStorage;
        }
        // version information is of length 8 bytes.
        iBufferSpaceLeft -= 8;
    }

    if (iRestoreState == EStorage)
    {
        iStorageBackupUtil -> RestoreStorageDataL(stream, iRestoreState, iBufferSpaceLeft);
    }

    // Only at first call
    if ((iRestoreState != EStorage && iRestoreState != EVersion) && (iRestoreState != EInstall))
    {
        if (iRestoreState == EAppArc)
        {
            // Making AppArc deregistrations
            TRAPD(err, iAppArcUtil->DeregisterAppsL(iDrive));

            if (err)
            {
                ELOG(EBackup, "Leave in deregistering apps");
            }
        }

        // Process the data buffer for restore
        ProcessBufferL(stream);

        if (aFinished)
        {
            // Set state to EStorage
            iRestoreState = EStorage;
        }
    }

    aFinished = ETrue;
    CleanupStack::PopAndDestroy(&stream);
}

void CMidp2BackupPlugin::InitialiseRestoreIncrementDataL(TDriveNumber /* aDrive */)
{
    JELOG2(EBackup);
    User::Leave(KErrNotSupported);
}

void CMidp2BackupPlugin::RestoreIncrementDataSectionL(TDesC8& /* aBuffer */, TBool /* aFinished */)
{
    JELOG2(EBackup);
    User::Leave(KErrNotSupported);
}

void CMidp2BackupPlugin::RestoreComplete(TDriveNumber /* aDrive */)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::RestoreComplete");
}

TUint CMidp2BackupPlugin::MmcIdL()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::MmcIdL()");

    TVolumeInfo* volumeInfo = new(ELeave) TVolumeInfo();

    TInt err = iFs.Volume(*volumeInfo, iDrive);

    if (!err)
    {
        TUint mmcId = volumeInfo->iUniqueID;
        return mmcId;
    }
    else
    {
        return 0;
    }


}

void CMidp2BackupPlugin::ProcessBufferL(RDesReadStream& stream)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::ProcessBuffer()");

    // Cycle until there's data in the buffer
    while (iBufferSpaceLeft > 0)
    {
        switch (iRestoreState)
        {
        case EAppArc:
            ProcessFirstBufferL(stream, iBufferSpaceLeft);
            break;

        case EInIcon:
            ProcessInIconL(stream, iBufferSpaceLeft);
            break;

        case EInSize:
            ProcessInSizeL(stream, iBufferSpaceLeft);
            break;

        default:
            CleanupStack::PopAndDestroy(&stream);
            User::Leave(KErrNotSupported);
        }
    }
}


_LIT(KStarWildCard, "*.*");

void CMidp2BackupPlugin::RestoreMmcRegistryL()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::RestoreMmcRegistry()");

    /* If backed up MMC is not the same as the current MMC, copy the entries
       from the directory of the backed up MMC to the directory
       of the current MMC */
    TUint32 mmc = MmcIdL();

    if (iBackupMmc != mmc)
    {
        // Create path to old place
        TPath path_old;
        CreateMmcPath(path_old, iDrive, iBackupMmc);

        // Create path to new place
        TPath path_new;
        CreateMmcPath(path_new, iDrive, mmc);

        // Get old files list
        CFileMan* fileMan = CFileMan::NewL(iFs);

        CleanupStack::PushL(fileMan);

        // Copy to new place
        iFs.MkDir(path_new);
        path_old.Append(KStarWildCard);
        TInt  err = fileMan->Copy(path_old, path_new);

        ILOG1(EBackup, "File copy, status: %d", err);

        User::LeaveIfError(err);

        CleanupStack::PopAndDestroy();
    }
}

_LIT(KPrivatePath, "C:\\private\\");

void CMidp2BackupPlugin::CreateMmcPath(TDes& aPathName, TInt aDrive, TUint aUniqueId)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::CreateMmcPath()");

    aPathName.Zero();
    aPathName.Append(KPrivatePath);
    aPathName.AppendNum(KRegistryServerUid, EHex);
    aPathName.Append(KPathDelimiter);

    // append drive name
    TDriveUnit driveUnit(aDrive);
    aPathName.Append(driveUnit.Name().Left(1));
    aPathName.Append(KPathDelimiter);

    TUint64 id = aUniqueId;
    aPathName.AppendNum(id, EHex);
    aPathName.Append(KPathDelimiter);
}

TBool CMidp2BackupPlugin::NextIcon(TUid& aCurrentUid, HBufC*& aFullFileName)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::NextIcon()");

    if (iIconUidArray.Count() > iIconFilePointer)
    {
        aCurrentUid = iIconUidArray[iIconFilePointer];
        iAppArcUtil->GetIconFilename(iIconUidArray[iIconFilePointer], aFullFileName);
        iIconFilePointer++;
        return ETrue;
    }
    else
    {
        // There are no more icon files
        return EFalse;
    }
}

void CMidp2BackupPlugin::ProcessFirstBufferL(RDesReadStream& aStream, TInt& aBufferSpaceLeft)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::ProcessFirstBuffer()");

    if (iDrive >= EDriveE && iDrive <= EDriveZ)
    {
        // Read MMC id and restore MMC entries if needed
        iBackupMmc = aStream.ReadUint32L();
        aBufferSpaceLeft -= sizeof(iBackupMmc);
        LOG1(EBackup, EInfo, "Read MMC Id: %u", iBackupMmc);
        RestoreMmcRegistryL();
    }
    if (aBufferSpaceLeft >= sizeof(TInt32))
    {
        iIconFileSizeLeft = aStream.ReadInt32L();
        aBufferSpaceLeft -= sizeof(iIconFileSizeLeft);
        iRestoreIconDesc = HBufC8::NewL(iIconFileSizeLeft);
        iRestoreState = EInIcon;
    }
    else
    {
        // No more data to read
        aBufferSpaceLeft = 0;
    }
}

void CMidp2BackupPlugin::ProcessInIconL(RDesReadStream& aStream, TInt& aBufferSpaceLeft)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::ProcessInIcon()");

    TPtr8 restoreIconPtr = iRestoreIconDesc->Des();
    HBufC8* tempDesc = HBufC8::NewL(iIconFileSizeLeft);
    CleanupStack::PushL(tempDesc);
    TPtr8 tempPtr = tempDesc->Des();

    // Icon cannot be read fully
    if (iIconFileSizeLeft > aBufferSpaceLeft)
    {
        aStream.ReadL(tempPtr, aBufferSpaceLeft);
        restoreIconPtr.Append(tempPtr);
        iIconFileSizeLeft -= aBufferSpaceLeft;
        aBufferSpaceLeft = 0;
        iRestoreState = EInIcon;
    }
    // Icon can be read fully
    else
    {
        aStream.ReadL(tempPtr, iIconFileSizeLeft);
        restoreIconPtr.Append(tempPtr);
        aBufferSpaceLeft -= iIconFileSizeLeft;
        iRestoreState = EInSize;

        TRAPD(err, iAppArcUtil->RegisterAppL(restoreIconPtr, iDrive));

        if (err)
        {
            ELOG(EBackup, "Registerin application to AppArc failed.");
        }
    }

    CleanupStack::PopAndDestroy(tempDesc);
}

void CMidp2BackupPlugin::ProcessInSizeL(RDesReadStream& aStream, TInt& aBufferSpaceLeft)
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::ProcessInSize()");

    if (aBufferSpaceLeft >= sizeof(TInt32))
    {
        if (iSizeBuffer.Size() != 0)
        {
            // Read leftover part of size
            TInt readData = sizeof(TInt32) - iSizeBuffer.Size();
            aStream.ReadL(iSizeBuffer, readData);
            RMemReadStream sizeStream(iSizeBuffer.Ptr(), 4);
            CleanupClosePushL(sizeStream);
            iIconFileSizeLeft = sizeStream.ReadInt32L();
            CleanupStack::PopAndDestroy(&sizeStream);
            aBufferSpaceLeft -= sizeof(readData);
        }
        else
        {
            // Read size in full
            iIconFileSizeLeft = aStream.ReadInt32L();
            aBufferSpaceLeft -= sizeof(iIconFileSizeLeft);
        }

        delete iRestoreIconDesc;
        iRestoreIconDesc = NULL;
        iRestoreIconDesc = HBufC8::NewL(iIconFileSizeLeft);
        iRestoreState = EInIcon;
    }
    else
    {
        // Read first byte(s) of size
        aStream.ReadL(iSizeBuffer, aBufferSpaceLeft);
        aBufferSpaceLeft = 0;
    }
}

void CMidp2BackupPlugin::ResetIconArray()
{
    LOG(EBackup, EInfo, "CMidp2BackupPlugin::ResetIconArray()");

    // Remove all entries
    while (iIconUidArray.Count())
    {
        iIconUidArray.Remove(0);
    }
}