persistentstorage/centralrepository/pccenrep/src/pccenrepimpl.cpp
changeset 0 08ec8eefde2f
--- /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.<cre/txt> that is minimum length is 8+1+3=12
+		if (aInFileName.Length()<KMinReposFileLength || aOutFileName.Length()<KMinReposFileLength)
+			User::Leave(KErrArgument);
+		//verify it is in the format of <path>XXXXXXXX.<cre/txt>
+		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 <Repository Uid>.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;i<sourceSettings.Count();i++)
+		{
+		TServerSetting* ts=sourceSettings[i];
+		TUint32 sourceKey = ts->Key();
+		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;
+	}