// Copyright (c) 2005-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:
//
/**
@file
@internalComponent
@released
*/
#include "CIniFileManager.h"
#include "CCntDbManagerController.h"
#include "CCntBackupRestoreAgent.h"
#include "CntCurrentItemMap.h"
#include "CntSpeedDials.h"
// uncomment this for debug logging
//#define INIFILE_DEBUG_LOG
const TUid KContactsIniUid = { 0x10009099 };
const TUid KContactsCurrentDatabaseUid = { 0x1000909A };
const TUid KUidContactsDefaultDatabaseLocation = { 0x1020380A };
const TInt KIniFileSaveDelay = 100000;
/**
First phase constructor.
*/
CIniFileManager::CIniFileManager(RFs& aFs, CCntDbManagerController& aDbMgrCtrlr)
: CTimer(CActive::EPriorityStandard), iFs(aFs), iDbMgrCtrlr(aDbMgrCtrlr), iBackupFlag(ENoSaveRestore)
{
CActiveScheduler::Add(this);
}
/**
Object factory method.
*/
CIniFileManager* CIniFileManager::NewL(RFs& aFs, CCntDbManagerController& aDbMgrCtrlr)
{
CIniFileManager* IniFileManager = new (ELeave) CIniFileManager(aFs, aDbMgrCtrlr);
CleanupStack::PushL(IniFileManager);
IniFileManager->ConstructL();
CleanupStack::Pop(IniFileManager);
return IniFileManager;
}
/**
Second phase constructor.
*/
void CIniFileManager::ConstructL()
{
CTimer::ConstructL();
iSpeedDialManager = new(ELeave) CCntServerSpeedDialManager();
iCurrentItemMap = new(ELeave) CCntServerCurrentItemMap();
iCurrentDb = KNullDesC;
// Restore the current database if possible. If this fails, the
// current database is set to KNullDesC (i.e. zero'd)
RequestRestoreIniFileSettingsL();
}
CIniFileManager::~CIniFileManager()
{
if (iFs.Handle()!=0)
{
TRAP_IGNORE(SaveIniFileSettingsL(ESaveAll,EFalse));
}
delete iSpeedDialManager;
delete iCurrentItemMap;
}
/**
Update/create a map entry for the current item associated with a database file.
*/
void CIniFileManager::SetCurrentItemForDatabaseL(const TDesC& aDatabase, TContactItemId aContactId)
{
// Does the specified database contain a current item already?
TInt index = KErrNotFound;
if (iCurrentItemMap->EntryAvailable(aDatabase, index))
{
// Yes, already exists, so update it....
iCurrentItemMap->UpdateEntryL(index, aContactId);
}
else
{
// No, so create a new entry to represent this database
iCurrentItemMap->AddEntryL(aDatabase, aContactId);
}
}
void CIniFileManager::RemoveCurrentItemL(const TDesC& aDatabase)
{
SetCurrentItemForDatabaseL(aDatabase, KNullContactId);
}
void CIniFileManager::SetCurrentItemL(const TDesC& aDatabase, TContactItemId aNewCurrentItem)
{
SetCurrentItemForDatabaseL(aDatabase, aNewCurrentItem);
}
/**
Returns the current item associated with the specified database.
*/
TContactItemId CIniFileManager::CurrentItem(const TDesC& aDatabase) const
{
return iCurrentItemMap->CurrentItem(aDatabase);
}
const TDesC& CIniFileManager::CurrentDb() const
{
return iCurrentDb;
}
void CIniFileManager::SetCurrentDb(const TDesC& aDb)
{
iCurrentDb = aDb;
}
CCntServerSpeedDialManager& CIniFileManager::SpeedDialManager()
{
return *iSpeedDialManager;
}
void CIniFileManager::ScheduleSaveIniFileSettings(TInt aSaveFlags, TBool aReplace)
{
// make sure all requested writes are saved
iSaveType |= aSaveFlags;
iReplace = aReplace;
// make sure change isn't due to Internalize
if (iBackupFlag != EIsRestoring)
{
iBackupFlag = ERequestSave;
//iNumberOfAttemptedRetries = 0;
// set the time to RunL if not already set to run
// check that no Backup or Restore is in progress,
// For Backup And Restore
if (!(iDbMgrCtrlr.BackupRestoreAgent().BackupInProgress()) &&
!(iDbMgrCtrlr.BackupRestoreAgent().RestoreInProgress()))
{
if (!IsActive())
{
#ifdef INIFILE_DEBUG_LOG
RDebug::Print(_L("\n[CNTMODEL] CIniFileManager::ScheduleSaveIniFileSettings(aSaveFlags = %i, aReplace %i)\r\n"),aSaveFlags, aReplace);
#endif
After(KIniFileSaveDelay);
}
}
}
}
void CIniFileManager::SaveIniFileSettingsIfRequestedL()
{
if (iBackupFlag == ERequestSave)
{
// Don't RunL
Cancel();
SaveIniFileSettingsL(iSaveType, iReplace);
iBackupFlag = ENoSaveRestore;
}
}
void CIniFileManager::RequestRestoreIniFileSettingsL()
{
if (!(iDbMgrCtrlr.BackupRestoreAgent().RestoreInProgress()))
{
TInt ret = StartRestoreIniFileSettings();
switch (ret)
{
case KErrNone:
break;
// If file does not exist create ini file immediately.
case KErrPathNotFound:
SaveIniFileSettingsL(ESaveAll, EFalse);
break;
// If file is damaged replace ini file.
case KErrEof:
SaveIniFileSettingsL(ESaveAll, ETrue);
break;
default:
#if defined(_DEBUG)
User::Leave(KErrNotSupported);
#endif
break; //Would not build in UREL without it
}
}
}
TInt CIniFileManager::StartRestoreIniFileSettings()
{
iBackupFlag = EIsRestoring;
TInt err;
TRAP(err,RestoreIniFileSettingsL());
iBackupFlag = ENoSaveRestore;
return err ;
}
void CIniFileManager::GetIniFileNameL(TDes& aFileName, TBool aIncPrivatePath)
{
if (aIncPrivatePath)
{
User::LeaveIfError(iFs.PrivatePath(aFileName));
}
// Drive name goes before the path.
aFileName.Insert(0,TDriveUnit(EDriveC).Name());
// Filename goes after the path.
aFileName.Append(KContactsIniFileName);
}
/**
Restore server-wide settings from the contacts ini file.
*/
void CIniFileManager::RestoreIniFileSettingsL()
{
// Initial location for Default database
SetDefaultDatabaseDrive(TDriveUnit(EDriveC),EFalse);
TFileName iniFile;
GetIniFileNameL(iniFile);
CDictionaryFileStore* iniStore = IniFileStoreLC(iniFile);
// Load settings
iCurrentItemMap->RestoreL(*iniStore);
iSpeedDialManager->RestoreL(*iniStore);
// Current database
RestoreCurrentDatabaseL(*iniStore);
// Default database location
RestoreDefaultDbDriveL(*iniStore);
// Tidy up
CleanupStack::PopAndDestroy(iniStore);
}
void CIniFileManager::SetDefaultDatabaseDrive(TDriveUnit aDriveUnit, TBool aDriveSet)
{
iDefaultDriveUnit = aDriveUnit;
iDatabaseDriveSet = aDriveSet;
}
/**
Restore the current database filename from the ini file.
*/
void CIniFileManager::RestoreCurrentDatabaseL(CDictionaryFileStore& aStore)
{
if (aStore.IsPresentL(KContactsCurrentDatabaseUid))
{
RDictionaryReadStream stream;
stream.OpenLC(aStore, KContactsCurrentDatabaseUid);
stream >> iCurrentDb;
CleanupStack::PopAndDestroy(); // stream
}
}
/**
Restore the current database filename from the ini file.
*/
void CIniFileManager::RestoreDefaultDbDriveL(CDictionaryFileStore& aStore)
{
if (aStore.IsPresentL(KUidContactsDefaultDatabaseLocation))
{
TDriveUnit driveUnit;
RDictionaryReadStream stream;
stream.OpenLC(aStore, KUidContactsDefaultDatabaseLocation);
driveUnit = stream.ReadInt32L();
CleanupStack::PopAndDestroy(); // stream
SetDefaultDatabaseDrive(driveUnit);
iDbMgrCtrlr.RestoreDatabaseDrive(driveUnit); // restore drive setting in DBManagerController
}
}
void CIniFileManager::RetryStoreOperation()
{
if (iBackupFlag == ERequestSave && !IsActive())
{
// can RunL now
After(0);
}
}
void CIniFileManager::RunL()
{
const TInt error = iStatus.Int();
#ifdef INIFILE_DEBUG_LOG
RDebug::Print(_L("[CNTMODEL] CIniFileManager::RunL() - error %i, iBackupFlag %i\r\n"), error, iBackupFlag);
#endif
// operation isn't cancelled
if (error == KErrNone && iBackupFlag == ERequestSave)
{
SaveIniFileSettingsL(iSaveType, iReplace);
iBackupFlag = ENoSaveRestore;
}
}
TInt CIniFileManager::RunError(TInt aError)
{
#ifdef INIFILE_DEBUG_LOG
RDebug::Print(_L("[CNTMODEL] CIniFileManager::RunError(aError = %i)\r\n"), aError);
#else
aError = aError; // remove compiler warning for unreferenced parameter
#endif
// cannot do anything about the error
// - unless it occurred during a Backup, when it will already be retried
return KErrNone;
}
/**
Save server-wide settings to the contacts model ini file.
*/
void CIniFileManager::SaveIniFileSettingsL(TInt aSaveFlags, TBool aReplace)
{
TFileName iniFile;
GetIniFileNameL(iniFile);
iFs.MkDirAll(iniFile);
if (aReplace)
{
iFs.Delete(iniFile);
}
// Get the ini store
CDictionaryFileStore* iniStore = IniFileStoreLC(iniFile);
// Save settings
if ((aSaveFlags & ESaveCurrentItem) && iCurrentItemMap)
{
iCurrentItemMap->StoreL(*iniStore);
}
if ((aSaveFlags & ESaveSpeedDials) && iSpeedDialManager)
{
iSpeedDialManager->StoreL(*iniStore);
}
// Current database
if (aSaveFlags & ESaveCurrentDatabase)
{
StoreCurrentDatabaseL(*iniStore);
}
// Default database location
if (aSaveFlags & ESaveDefaultDbDrive)
{
StoreDefaultDbDriveL(*iniStore);
}
// Commit
iniStore->CommitL();
// Tidy up
CleanupStack::PopAndDestroy(); // iniStore
}
/**
Return a pointer to the contacts ini file.
*/
CDictionaryFileStore* CIniFileManager::IniFileStoreLC(TFileName& aIniFile)
{
return CDictionaryFileStore::OpenLC(iFs, aIniFile, KContactsIniUid);
}
/**
Save the current database filename to the ini file.
*/
void CIniFileManager::StoreCurrentDatabaseL(CDictionaryFileStore& aStore)
{
RDictionaryWriteStream stream;
stream.AssignLC(aStore, KContactsCurrentDatabaseUid);
stream << iCurrentDb;
stream.CommitL();
CleanupStack::PopAndDestroy(); // stream
}
/**
Save the default database drive to the ini file.
*/
void CIniFileManager::StoreDefaultDbDriveL(CDictionaryFileStore& aStore)
{
if (iDatabaseDriveSet)
{
RDictionaryWriteStream stream;
stream.AssignLC(aStore, KUidContactsDefaultDatabaseLocation);
stream.WriteInt32L(iDefaultDriveUnit);
stream.CommitL();
CleanupStack::PopAndDestroy(); // stream
}
}
TBool& CIniFileManager::DatabaseDriveSet()
{
return iDatabaseDriveSet;
}