javamanager/javabackup/midp2backup_usif/src.s60/apparcbackuputil.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 19 Aug 2010 09:48:13 +0300
branchRCL_3
changeset 60 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 CAppArcBackupUtil
*
*/


#include "apparcbackuputil.h"
#include "javaapparcutil.h"

#include "javasymbianoslayer.h"
#include "javauid.h"
#include "logger.h"
#include "javacommonutils.h"
#include "s60commonutils.h"

#include <apgcli.h>
#include <wchar.h>
#include <s32mem.h>
#include <sysutil.h>
#include <f32file.h>

#include <memory>
#include <string>

#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <apgicnfl.h>
#else
#include <apgicnflpartner.h>
#endif


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

const TUid  KMidletApplicationTypeUid = { 0x10210E26 };
_LIT(KDefaultFolder, "");

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

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

void CAppArcBackupUtil::ConstructL(RFs& aFs)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::ConstructL");

    User::LeaveIfError(iApparcServer.Connect());

    iNumberOfIcons = 0;
    iFs = aFs;
}


CAppArcBackupUtil* CAppArcBackupUtil::NewL(RFs& aFs)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::NewL");

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

    return self;
}


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

    iApparcServer.Close();
}


void CAppArcBackupUtil::RegisterAppL(TPtr8& aRestoreIconPtr, TDriveNumber& aDrive)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::RegisterApp");

    RDesReadStream stream(aRestoreIconPtr);
    CleanupClosePushL(stream);

    // Read Uid
    int midletUid = stream.ReadUint32L();

    if (!CheckIfAlreadyRegisteredL(midletUid))
    {
        // Read filename
        TInt32 fileNameSize = stream.ReadInt32L();
        HBufC* fileName = HBufC::NewL(fileNameSize);
        CleanupStack::PushL(fileName);
        TPtr16 fileNamePtr = fileName->Des();
        stream.ReadL(fileNamePtr, fileNameSize / 2);   // half of size

        // Read number of icons
        TInt numberOfIcons = stream.ReadInt32L();
//        numberOfIcons = 1;
        //LOG1(EBackup, EInfo, "Number of Icons = %d", numberOfIcons);

        TInt groupNameSize = stream.ReadInt32L();
        TBuf<KApaMaxAppGroupName> groupName;

        if (groupNameSize != 0)
        {
            stream.ReadL(groupName, groupNameSize / 2);
        }

        // check disk space
        TInt index = sizeof(TUint32)    // midletUid
                     + sizeof(TInt32)                // size of fileNameSize
                     + fileNameSize                  // size of filename
                     + sizeof(TInt32)                // size of numberOfIcons
                     + sizeof(TInt32)                // group name size
                     + groupNameSize;                // groupname

        if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, aRestoreIconPtr.Size() - index, aDrive))
        {
            ELOG(EBackup, "Disk space below critical level. Leaving with KErrDiskFull.");
            User::Leave(KErrDiskFull);
        }

        // Make directory if necessary
        iFs.CreatePrivatePath(aDrive);

        // Make full path of temporary icon file
        TPath tempPath;
        TPath tempPrivatePath;
        iFs.PrivatePath(tempPrivatePath);

        TDriveUnit* driveUnit = new(ELeave) TDriveUnit(aDrive);
        CleanupStack::PushL(driveUnit);

        tempPath.Append(driveUnit->Name().Left(1));
        tempPath.Append(KDriveDelimiter);
        tempPath.Append(tempPrivatePath);
        tempPath.Append(fileNamePtr);

        // Set private session path to point same drive where restoring
        iFs.SetSessionToPrivate(aDrive);


        RFile iconFile;
        User::LeaveIfError(iconFile.Create(iFs, fileNamePtr, EFileWrite));

        CleanupStack::PopAndDestroy(fileName);
        CleanupClosePushL(iconFile);

        iconFile.Write(aRestoreIconPtr.Mid(index));

        // Register application
        LOG1(EBackup,EInfo,"Registering app %d", midletUid);
        TUid uid = TUid::Uid(midletUid);
        TBuf<128>   appName;
        CJavaApparcUtil::AppName(uid, appName);

        CApaRegistrationResourceFileWriter* writer =
            CApaRegistrationResourceFileWriter::NewL(uid,
                    appName,
                    TApaAppCapability::ENonNative);
        CleanupStack::PushL(writer);

        const TInt  KOpaqueDataLength = 4;
        TBuf8<KOpaqueDataLength>    opaqueData;
        RDesWriteStream             writeStream(opaqueData);
        CleanupClosePushL(writeStream);

        LOG(EBackup, EInfo, "Getting midlet entry");

        JavaStorageApplicationEntry_t appEntries = StorageEntryL(uid);

        if (appEntries.size() == 0)
        {
            ELOG(EBackup, "No midlet entry found in Java Storage; Mismatch between AppArc and Storage data. Abort backup");
            User::Leave(KErrNotFound);
        }

        JavaStorageEntry attribute;
        attribute.setEntry(NAME, L"");

        // Get Name attribute from read attributes.
        JavaStorageApplicationEntry_t::const_iterator findIterator = appEntries.find(attribute);
        wstring midName;

        if (findIterator != appEntries.end())
        {
            midName = (*findIterator).entryValue();

        }
        else
        {
            User::Leave(KErrBadHandle);
        }

        appEntries.clear();

        HBufC* tempstr = java::util::S60CommonUtils::wstringToDes(midName.c_str());
        TPtrC midletName = tempstr->Des();

        if (groupNameSize != 0)
        {
            writer->SetGroupNameL(groupName);
        }
        else
        {
            writer->SetGroupNameL(KDefaultFolder);
        }

        writeStream.WriteUint32L(midletUid);
        writeStream.CommitL();

        LOG(EBackup, EInfo, "Setting opaque data");
        writer->SetOpaqueDataL(opaqueData);

        CApaLocalisableResourceFileWriter*  lWriter =
            CApaLocalisableResourceFileWriter::NewL(KNullDesC,
                                                    midletName,
                                                    numberOfIcons,
                                                    KNullDesC);
        CleanupStack::PushL(lWriter);

        // Prepare AppArc for deregistration
        LOG(EBackup, EInfo, "PrepareNonNativeApplicationsUpdatesL");
        iApparcServer.PrepareNonNativeApplicationsUpdatesL();

        // Register application
        LOG(EBackup, EInfo, "RegisterNonNativeApplicationL");
        iApparcServer.RegisterNonNativeApplicationL(KMidletApplicationTypeUid,
                aDrive,
                *writer,
                lWriter,
                &iconFile);

        // Commit registration changes
        LOG(EBackup, EInfo, "CommitNonNativeApplicationsUpdatesL");
        iApparcServer.CommitNonNativeApplicationsUpdatesL();

        delete tempstr;
        CleanupStack::PopAndDestroy(lWriter);
        CleanupStack::PopAndDestroy(&writeStream);
        CleanupStack::PopAndDestroy(writer);
        iconFile.Close();
        CleanupStack::PopAndDestroy(&iconFile);

        TInt err = iFs.Delete(tempPath);
        LOG1(EBackup, EInfo, "iFs.Delete err = %d", err);
        CleanupStack::PopAndDestroy(driveUnit);
    }

    CleanupStack::PopAndDestroy(&stream);
}


void CAppArcBackupUtil::DeregisterAppsL(TDriveNumber aDrive)
{
    LOG1(EBackup, EInfo, "CAppArcBackupUtil::DeregisterApps, drive: %d", aDrive);

    // Initialise the process of getting apps
    iApparcServer.GetFilteredApps(TApaAppCapability::ENonNative,
                                  TApaAppCapability::ENonNative);

    // Getting the apps one-by-one
    TApaAppInfo* info = new(ELeave) TApaAppInfo();
    CleanupStack::PushL(info);

    TUid typeUid;

    // Prepare AppArc for deregistration
    LOG(EBackup, EInfo, "PrepareNonNativeApplicationsUpdatesL");
    iApparcServer.PrepareNonNativeApplicationsUpdatesL();

    while (!iApparcServer.GetNextApp((*info)))
    {
        LOG1(EBackup, EInfo, "Getting Next App from AppArc, UID = %d", info->iUid);

        // Getting the type of the application
        iApparcServer.GetAppType(typeUid, info->iUid);

        // If it's a MIDlet, check if it has an entry in Java Registry
        TInt drive = 0;
        GetDriveOfApp(info->iFullName, drive);

        if (typeUid == KMidletApplicationTypeUid && drive == aDrive)
        {
            LOG1(EBackup, EInfo, "Checking registry, midlet id = %d", info->iUid);
            wstring PackageID;
            // If there's no entry on the drive, deregister it from AppArc
            JavaStorageApplicationEntry_t appEntries = StorageEntryL(info->iUid);

            if (appEntries.size() != 0)
            {
                JavaStorageEntry attribute;
                attribute.setEntry(PACKAGE_ID, L"");

                JavaStorageApplicationEntry_t::const_iterator findIterator = appEntries.find(attribute);

                if (findIterator != appEntries.end())
                {
                    PackageID = (*findIterator).entryValue();
                }
                else
                {
                    User::Leave(KErrBadHandle);
                }

                if (GetDrivefromStorageL(PackageID) != aDrive)
                {
                    iApparcServer.DeregisterNonNativeApplicationL(info->iUid);
                    LOG1(EBackup, EInfo, "Deregistering midlet id = %d", info->iUid);
                }
            }
            else
            {
                LOG(EBackup, EInfo, "Midlet entry not found in Java Storage; Deregister the Application");
                iApparcServer.DeregisterNonNativeApplicationL(info->iUid);
                LOG1(EBackup, EInfo, "Deregistering midlet id = %d", info->iUid);
            }
            appEntries.clear();
        }
    }

    // Commit registration changes
    LOG(EBackup, EInfo, "CommitNonNativeApplicationsUpdatesL");
    iApparcServer.CommitNonNativeApplicationsUpdatesL();
    CleanupStack::PopAndDestroy(info);
}


void CAppArcBackupUtil::GetMidletsFromAppArcL(RArray<TUid>& aUidArray, TDriveNumber aDrive)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::GetMidletsFromAppArc");
    CleanupClosePushL(aUidArray);

    // Initialise the process of getting apps
    iApparcServer.GetFilteredApps(TApaAppCapability::ENonNative,
                                  TApaAppCapability::ENonNative);

    // Getting the apps one-by-one
    TApaAppInfo* info = new(ELeave) TApaAppInfo();
    CleanupStack::PushL(info);

    TUid typeUid;
    LOG1(EBackup, EInfo, "Drive Number aDrive = %d", aDrive);

    while (!iApparcServer.GetNextApp((*info)))
    {
        // Getting the type of the application
        iApparcServer.GetAppType(typeUid, info->iUid);

        // If it's a MIDlet, check if it's registered to this drive
        if (typeUid == KMidletApplicationTypeUid)
        {
            JavaStorageApplicationEntry_t appEntries = StorageEntryL(info->iUid);

            if (appEntries.size() != 0)
            {
                JavaStorageEntry attribute;
                attribute.setEntry(PACKAGE_ID, L"");

                JavaStorageApplicationEntry_t::const_iterator findIterator = appEntries.find(attribute);
                wstring PackageID;

                if (findIterator != appEntries.end())
                {
                    PackageID = (*findIterator).entryValue();

                }
                else
                {
                    User::Leave(KErrBadHandle);
                }
                appEntries.clear();

                if (GetDrivefromStorageL(PackageID) == aDrive)
                {
                    aUidArray.AppendL(info->iUid);
                    iNumberOfIcons++;
                }
            }
            else
            {
                ELOG(EBackup, "No entries from registry; midlet does not exist");
            }
        }
    }
    CleanupStack::PopAndDestroy(info);
    CleanupStack::Pop();

}


void CAppArcBackupUtil::GetIconFilename(TUid aUid, HBufC*& aFullFileName)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::GetIconFilename");

    iApparcServer.GetAppIcon(aUid, aFullFileName);
}

TInt CAppArcBackupUtil::NumberOfIcons()
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::NumberOfIcons");

    return iNumberOfIcons;
}

void CAppArcBackupUtil::NumberOfOwnDefinedIcons(TUid aUid, TInt& aIconCount)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::NumberOfOwnDefinedIcons");

    iApparcServer.NumberOfOwnDefinedIcons(aUid, aIconCount);
}

TBool CAppArcBackupUtil::CheckIfAlreadyRegisteredL(TInt& aUid)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::CheckIfAlreadyRegisteredL");

    TApaAppInfo* info = new(ELeave) TApaAppInfo();

    TInt err = iApparcServer.GetAppInfo(*info, TUid::Uid(aUid));
    delete info;
    if (err == KErrNone)
    {
        return ETrue;
    }
    else
    {
        return EFalse;
    }


}

void CAppArcBackupUtil::GetDriveOfApp(TFileName aPath, TInt& aDrive)
{
    LOG(EBackup, EInfo, "CAppArcBackupUtil::DriveOfApp");

    iFs.CharToDrive(aPath[0], aDrive);
}


TApaAppGroupName CAppArcBackupUtil::GetMidletGroupName(TUid aUid)
{
    TApaAppCapabilityBuf cap;

    TInt err = iApparcServer.GetAppCapability(cap, aUid);
    return cap().iGroupName;
}


JavaStorageApplicationEntry_t CAppArcBackupUtil::StorageEntryL(const TUid& aMidletUID)
{
    auto_ptr<JavaStorage> js(JavaStorage::createInstance());

    try
    {
        js->open(JAVA_DATABASE_NAME);
        LOG(EBackup, EInfo, "Java database opened");
    }
    catch (JavaStorageException jse)
    {
        ELOG(EBackup, "Opening database connection failed");
        User::Leave(KErrNotFound);
    }

    JavaStorageApplicationEntry_t entries;

    java::util::Uid appUid;
    TUidToUid(aMidletUID, appUid);

    try
    {
        js->read(APPLICATION_TABLE, appUid, entries);
    }
    catch (JavaStorageException jse)
    {
        ELOG(EBackup, "Read in Java Storage failed");
        js->close();
        User::Leave(KErrGeneral);
    }
    js->close();

    return entries;
}

TDriveNumber CAppArcBackupUtil::GetDrivefromStorageL(wstring& aPackageID)
{
    wchar_t Drive;
    auto_ptr<JavaStorage> js(JavaStorage::createInstance());

    try
    {
        js->open(JAVA_DATABASE_NAME);
    }
    catch (JavaStorageException jse)
    {
        ELOG(EBackup, "Opening database connection failed");
        User::Leave(KErrNotFound);
    }

    JavaStorageApplicationEntry_t entries;
    java::util::Uid PackageID(aPackageID);

    try
    {
        js->read(APPLICATION_PACKAGE_TABLE, PackageID, entries);
    }
    catch (JavaStorageException jse)
    {
        ELOG(EBackup, "Read in Java Storage failed");
        js->close();
        User::Leave(KErrGeneral);
    }

    js->close();

    JavaStorageEntry attribute;
    attribute.setEntry(ROOT_PATH, L"");

    JavaStorageApplicationEntry_t::const_iterator findIterator = entries.find(attribute);
    wstring RootPath;

    if (findIterator != entries.end())
    {
        RootPath = (*findIterator).entryValue();

    }
    else
    {
        User::Leave(KErrBadHandle);
    }

    Drive = (wchar_t)RootPath[0];
    LOG1(EBackup, EInfo, "Drive = %c", Drive);
    TInt i = Drive - (wchar_t)'a';
    LOG1(EBackup, EInfo, "Drive = %d", (TDriveNumber)i);
    return (TDriveNumber)i;
}