diff -r 000000000000 -r 08ec8eefde2f persistentstorage/centralrepository/pccenrep/src/pccenrepimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/centralrepository/pccenrep/src/pccenrepimpl.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,250 @@ +// 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: +// + +#include "pccenrepimpl.h" + +_LIT(KCreExt,".cre"); +_LIT(KTxtExt,".txt"); +_LIT(KOgnExt,".ogn"); +const TInt KExtLength=4; +const TInt KMinReposFileLength=12; + +//dummy fail transaction cleanup operation +void CPcRepImpl::FailTransactionCleanupOperation(TAny* /**aRepository*/) + { + //do nothing + } + +CPcRepImpl* CPcRepImpl::NewL(TUid aRepositoryUid,const TDesC& aInFileName,const TDesC& aOutFileName,TBool aAutoLoading) + { + CPcRepImpl* self=new (ELeave)CPcRepImpl(); + CleanupStack::PushL(self); + self->ConstructL(aRepositoryUid,aInFileName,aOutFileName,aAutoLoading); + CleanupStack::Pop(); + return self; + } + +void CPcRepImpl::ConstructL(TUid aRepositoryUid,const TDesC& aInFileName,const TDesC& aOutFileName,TBool aAutoLoading) + { + User::LeaveIfError(iFs.Connect()); + iRepository=CHeapRepository::NewL(aRepositoryUid); + + TFileName ognFile; // XXXXXXXX.ogn + TBool isOriginal; + + IsOriginalL(aRepositoryUid, aOutFileName, aAutoLoading, ognFile, isOriginal); + iRepository->SettingsArray().SetIsDefault(isOriginal); + if (!aAutoLoading) + { + //verify file name must be in format of XXXXXXXX. that is minimum length is 8+1+3=12 + if (aInFileName.Length()XXXXXXXX. + TPtrC inFileName(aInFileName.Right(KMinReposFileLength)); + TPtrC outFileName(aOutFileName.Right(KMinReposFileLength)); + TUint inRepUid; + TLex parser(inFileName.Left(8)); + TInt ret=parser.Val(inRepUid,EHex); + if (ret!=KErrNone) + (ret==KErrNoMemory)?User::Leave(ret):User::Leave(KErrArgument); + parser.Assign(outFileName.Left(8)); + TUint outRepUid; + ret=parser.Val(outRepUid,EHex); + if (ret!=KErrNone) + (ret==KErrNoMemory)?User::Leave(ret):User::Leave(KErrArgument); + + //now finally verify the extension of the output file + if (aOutFileName.Right(KExtLength).CompareF(KCreExt())!=0) + User::Leave(KErrArgument); + if (aInFileName.Right(KExtLength).CompareF(KTxtExt())==0) + { + iRepository->SetUid(TUid::Uid(inRepUid)); + CIniFileIn* iniFile=NULL; + ret=CIniFileIn::NewLC(iFs,iniFile,aInFileName); + User::LeaveIfError(ret); + iRepository->ReloadContentL(*iniFile); + CleanupStack::PopAndDestroy(); + } + else if (aInFileName.Right(KExtLength).CompareF(KCreExt())==0) + { + iRepository->SetUid(TUid::Uid(inRepUid)); + iRepository->CreateRepositoryFromCreFileL(iFs,aInFileName); + } + else + User::Leave(KErrArgument); + iOutFileName=aOutFileName.AllocL(); + } + else + { + //auto mode look for CRE first then TXT + TFileName crefile; + crefile.AppendNumFixedWidth(aRepositoryUid.iUid,EHex,8); + crefile.Append(KCreExt()); + TInt ret=KErrNone; + TRAP(ret,iRepository->CreateRepositoryFromCreFileL(iFs,crefile)); + if (ret!=KErrNone) + { + if (ret!=KErrNotFound) + User::Leave(ret); + //look for TXT now + TFileName file; + file.AppendNumFixedWidth(aRepositoryUid.iUid,EHex,8); + file.Append(KTxtExt()); + CIniFileIn* iniFile=NULL; + ret=CIniFileIn::NewLC(iFs,iniFile,file); + User::LeaveIfError(ret); + iRepository->ReloadContentL(*iniFile); + CleanupStack::PopAndDestroy(); + } + //output is always cre + iOutFileName=crefile.AllocL(); + } + GetSingleMetaArrayL(iSingleMetaArray); + if (isOriginal) + { + // An empty file is generated in the name of .ogn when + // the repository is loaded for the first time. see IsOriginalL(). + RFile file; + User::LeaveIfError(file.Create(iFs, ognFile, EFileWrite)); + file.Close(); + } + iInitialised=ETrue; + } + +CPcRepImpl::~CPcRepImpl() + { + /** persist to cre on destructor */ + if (iRepository && iInitialised) + Flush(); + + iFs.Close(); + iSingleMetaArray.Close(); + delete iRepository; + delete iOutFileName; + } + +TInt CPcRepImpl::Flush() + { +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + return iRepository->CommitChanges(iFs,KPersistFormatSupportsIndMetaIndicator,*iOutFileName); +#else + return iRepository->CommitChanges(iFs,KPersistFormatVersion,*iOutFileName); +#endif + } + +void CPcRepImpl::MoveL(TUint32 aSourcePartialKey, TUint32 aTargetPartialKey,TUint32 aMask, TUint32& aErrorKey) + { + RSettingPointerArray sourceSettings; + CleanupClosePushL(sourceSettings); + TInt error=iRepository->SettingsArray().Find(aSourcePartialKey & aMask, aMask, sourceSettings); + + //dont fail transaction if source settings is empty + if (error!=KErrNone) + { + aErrorKey = aSourcePartialKey; + User::Leave(error); + } + else if (sourceSettings.Count() == 0) + { + aErrorKey = aSourcePartialKey; + User::Leave(KErrNotFound); + } + + for (TInt i=0;iKey(); + TUint32 targetKey = sourceKey ^ ((aSourcePartialKey & aMask) ^ (aTargetPartialKey & aMask)); + TServerSetting* targetSetting = GetSetting(targetKey); + if (targetSetting && !targetSetting->IsDeleted()) + { + aErrorKey=targetKey; + User::Leave(KErrAlreadyExists); + } + } + + TRAPD(err,error = MOperationLogic::MoveL(aSourcePartialKey,aTargetPartialKey,aMask,aErrorKey, sourceSettings)); + + //the Move operation logic only mark it as deleted, now remove it from the settings list + RemoveAnyMarkDeleted(); + + User::LeaveIfError(err); + User::LeaveIfError(error); + + CleanupStack::PopAndDestroy(&sourceSettings); + } + +void CPcRepImpl::DeleteRangeL(TUint32 aPartialKey, TUint32 aMask,TUint32& aErrorKey) + { + RSettingPointerArray sourceSettings; + CleanupClosePushL(sourceSettings); + TInt error=FindSettings(aPartialKey & aMask, aMask, sourceSettings); + if (error==KErrNotFound) + { + aErrorKey=aPartialKey; + } + User::LeaveIfError(error); + DeleteSettingsRangeL(sourceSettings,aPartialKey,aErrorKey); + RemoveAnyMarkDeleted(); + CleanupStack::PopAndDestroy(&sourceSettings); + } + +void CPcRepImpl::GetSingleMetaArrayL(RSingleMetaArray& aMetaArray) + { + TInt numSettings = iRepository->SettingsArray().Count(); + aMetaArray.Reset(); + aMetaArray.ReserveL(numSettings); + for (TInt i = 0; i < numSettings; i++) + { + TUint32 key = iRepository->SettingsArray()[i].Key(); + TUint32 meta = iRepository->SettingsArray()[i].Meta(); + TSettingSingleMeta metaItem(key, meta); + aMetaArray.AppendL(metaItem); + } + } + +// This function is used to identify wether the repository is loaded for the first +// time or not. The purpose of this function is to determine whether entries of a +// repository should be set clean during initializing process. At symbian side, this +// flag is only set when load from ROM, but at PC side, there is no ROM, so the clean +// flag is set when load for the first time to keep consistency with Symbian side Library. +void CPcRepImpl::IsOriginalL(TUid aUid, const TDesC& aOutFile, TBool aAutoLoading, TFileName& aOgnFileName, TBool& aIsOriginal) + { + if (!aAutoLoading) + { + TInt len = aOutFile.Length(); + aOgnFileName = aOutFile.Left(len - KExtLength); + } + else + { + aOgnFileName.AppendNumFixedWidth(aUid.iUid,EHex,8); + } + aOgnFileName.Append(KOgnExt()); + + RFile file; + TInt err = file.Open(iFs,aOgnFileName,EFileRead|EFileShareReadersOnly); + file.Close(); + if (err != KErrNone) + { + if (err == KErrNotFound || err == KErrPathNotFound) + { + aIsOriginal = ETrue; + return; + } + else + User::Leave(err); + } + aIsOriginal = EFalse; + }