persistentstorage/centralrepository/common/src/heaprepos.cpp
changeset 0 08ec8eefde2f
child 55 44f437012c90
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/centralrepository/common/src/heaprepos.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,443 @@
+// 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:
+// simrepos.cpp
+// 
+//
+
+#include "heaprepos.h"
+
+CHeapRepository* CHeapRepository::NewL(TUid aUid)
+	{
+	CHeapRepository* repos=new (ELeave) CHeapRepository(aUid);
+	return repos;
+	}
+
+CHeapRepository::CHeapRepository(TUid aUid)
+	:iSettings(),iUid(aUid),iSinglePolicies(KGranularity)
+	{
+	}
+
+CHeapRepository::~CHeapRepository()
+	{
+	iSinglePolicies.ResetAndDestroy();
+	iRangePolicies.Close();
+	iDeletedSettings.Close();
+	iSettings.Close();
+	iRangeMeta.Close();
+	}
+
+/**
+Stores the repository in-memory content to the related repository file on drive C.
+If the operation fails, the in-memory content won't match the content of 
+the repository file (which will be kept as it was before the CommitChangesL() call).
+In order to keep the consistency, the in-memory repository content is deleted now
+and restored later, on the next repository operation.
+*/
+TInt CHeapRepository::CommitChanges(RFs& aFs,TUint8 aPersistVersion,const TDesC& aTargetFilePath)
+	{
+	TRAPD(error, DoCommitChangesL(aFs,aPersistVersion,aTargetFilePath));
+	if (error != KErrNone)
+		{	
+		//If the commit fails reset the repository as it is in an inconsistent state
+		ResetContent();
+		}
+	return error;
+	}	
+
+void CHeapRepository::SetMetaDataOnRead(TServerSetting& aSetting, TBool aSingleMetaFound)
+	{
+	TInt isMetaFlagSet = aSetting.Meta() & KMetaDefaultValue;
+	
+	if(!aSingleMetaFound)
+		// No single metadata set for this key
+		{
+		// First check for a matching "range" default metadata
+		// setting
+		TSettingsDefaultMeta* defaultMeta = iRangeMeta.Find(aSetting.Key());
+		if (defaultMeta)
+			{
+			if (isMetaFlagSet)
+				//sets a default meta data
+				//also sets the flag back to indicate that it is a default setting from ROM 
+				//or previous install so it can be replaced later with a new one. 
+				aSetting.SetMeta(defaultMeta->GetDefaultMetadata() | KMetaDefaultValue);
+			else
+				aSetting.SetMeta(defaultMeta->GetDefaultMetadata());
+			}
+		else
+			{
+			// Range value not found, try for a repository default
+			if (isMetaFlagSet)	
+				aSetting.SetMeta(iDefaultMeta | KMetaDefaultValue) ;
+			else
+				aSetting.SetMeta(iDefaultMeta) ;
+			}
+		}
+
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+#ifdef CENTREP_CONV_TOOL
+	if (aSingleMetaFound && aSetting.IsClean() && !aSetting.IsIndividualMeta())
+		aSingleMetaFound=EFalse;
+#endif	
+	aSetting.SetIndividualMeta(aSingleMetaFound);
+#endif			
+	}
+
+TInt CHeapRepository::Create(TServerSetting& aSetting, TSettingsAccessPolicy* &aPolicy, TBool aSingleMetaFound)
+	{
+	if(iSettings.Find(aSetting.Key()))
+		return KErrAlreadyExists;
+	
+	SetMetaDataOnRead( aSetting, aSingleMetaFound);
+	aSetting.SetAccessPolicy(aPolicy);
+
+	return iSettings.OrderedInsert(aSetting);
+	}
+
+// Comparison relation to allow single policies to be inserted in order
+TInt CHeapRepository::CompareKeyIds(const TSettingsAccessPolicy& aSinglePolicy, const TSettingsAccessPolicy& aSinglePolicyIndexItem)
+	{
+	if(aSinglePolicy.iLowKey==aSinglePolicyIndexItem.iLowKey)
+		return 0;
+	return (aSinglePolicy.iLowKey < aSinglePolicyIndexItem.iLowKey)?-1:1;
+	}
+
+// Identity relation to allow single policy for a given key to be found
+TBool CHeapRepository::SinglePolicyMatchOnKey(const TSettingsAccessPolicy& aSinglePolicy, const TSettingsAccessPolicy& aSinglePolicyIndexItem)
+	{
+	return aSinglePolicy.iLowKey==aSinglePolicyIndexItem.iLowKey;
+	}
+
+// returns the read security policy used if there is no per-setting policy at aId
+const TSecurityPolicy& CHeapRepository::GetFallbackReadAccessPolicy(TUint32 aId)
+	{
+	return *(GetFallbackAccessPolicy(aId)->GetReadAccessPolicy());
+	}
+
+// returns the write security policy used if there is no per-setting policy at aId
+const TSecurityPolicy& CHeapRepository::GetFallbackWriteAccessPolicy(TUint32 aId)
+	{
+	return *(GetFallbackAccessPolicy(aId)->GetWriteAccessPolicy());
+	}
+
+// Get pointer to security policy that applies to a given setting
+TSettingsAccessPolicy* CHeapRepository::GetFallbackAccessPolicy(TUint32 aId
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+	,TBool aSkipSingle
+#endif
+	)
+	{
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
+	if (!aSkipSingle)
+		{
+#endif		
+		// Check for single policy
+		TSettingsAccessPolicy policy(aId);
+		TIdentityRelation<TSettingsAccessPolicy> identity(SinglePolicyMatchOnKey);
+		TInt index = iSinglePolicies.Find(&policy, identity);
+		if(KErrNotFound != index)
+			return iSinglePolicies[index];
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS		
+		}
+#endif		
+	
+	// check if the aId falls into any range specified in the ini file
+	TSettingsAccessPolicy* rangePolicy = iRangePolicies.Find(aId);
+	if(rangePolicy)
+		return rangePolicy;
+	
+	// If no single policy or range policy, return default policy
+	return &iDefaultPolicy;
+	}
+
+// this function saves idividual meta as well
+TInt CHeapRepository::ReadSettingSavePolicyL(CIniFileIn& aFile,TServerSetting& aSetting, TSettingsAccessPolicy* &aPolicy, TBool& aSingleMetaFound)
+	{
+	TBool singleReadPolicyFound;
+	TBool singleWritePolicyFound;
+	TSecurityPolicy singleReadPolicy;
+	TSecurityPolicy singleWritePolicy;
+
+	TInt err=aFile.ReadSettingL(aSetting,singleReadPolicy, singleWritePolicy, singleReadPolicyFound, singleWritePolicyFound, aSingleMetaFound);
+	if(err!=KErrNone)
+		return err;
+	
+	// Set up single policies
+	if(!singleReadPolicyFound)
+		singleReadPolicy=GetDefaultReadAccessPolicy();
+	if(!singleWritePolicyFound)
+		singleWritePolicy=GetDefaultWriteAccessPolicy();
+
+	aSetting.PushL();
+	if(singleReadPolicyFound || singleWritePolicyFound)
+		{
+		aPolicy=new (ELeave) TSettingsAccessPolicy(singleReadPolicy,singleWritePolicy,aSetting.Key());
+		CleanupStack::PushL(aPolicy);
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS		
+		//reused single setting high key and mask to indicate whether read or write has been specified
+		//or they are just a default policy
+		if (singleReadPolicyFound)
+			aPolicy->iHighKey=1;
+		if (singleWritePolicyFound)
+			aPolicy->iKeyMask=1;
+#endif		
+		TLinearOrder<TSettingsAccessPolicy> order(&CHeapRepository::CompareKeyIds);
+		iSinglePolicies.InsertInOrderL(aPolicy,order);
+		CleanupStack::Pop(aPolicy);
+		}
+	else
+		{
+		// check if the aId falls into any range specified in the ini file
+		// otherwise set policy to default policy
+		TSettingsAccessPolicy* rangePolicy = iRangePolicies.Find(aSetting.Key());
+		if(rangePolicy)
+			aPolicy=rangePolicy;
+		else
+			aPolicy=&iDefaultPolicy;
+		}
+		
+	aSetting.Pop();
+	return err;
+	}
+		
+#ifdef CENTREP_CONV_TOOL
+void CHeapRepository::DoCommitChangesToIniFileL(RFs& aFs,const TDesC& aOutFileName
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+	,TUint32 aCreVersion
+#endif
+	)
+	{
+	CIniFileOut* out = CIniFileOut::NewLC(aFs,aOutFileName);
+
+	out->WriteHeaderL();
+	out->WriteOwnerSectionL(iOwner);
+	out->WriteTimeStampL(iTimeStamp);
+	out->WriteMetaDataL(iDefaultMeta, iRangeMeta);
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
+	out->WritePlatSecL(GetDefaultAccessPolicy(), iRangePolicies,aCreVersion);
+#else
+	out->WritePlatSecL(GetDefaultReadAccessPolicy(), GetDefaultWriteAccessPolicy(), iRangePolicies);
+#endif	
+
+
+	out->WriteMainSectionHeaderL();
+	for(TInt i=0; i<iSettings.Count(); i++)
+		{
+		const TServerSetting& setting = iSettings[i];
+		if (setting.HasAccessPolicy() && (iSinglePolicies.Find(setting.AccessPolicy()) != KErrNotFound))
+			{
+			out->WriteSettingL(setting, *setting.AccessPolicy()
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS			
+			,aCreVersion
+#endif			
+			);
+			}
+		else
+			{
+			out->WriteSettingL(setting
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS			
+			,aCreVersion
+#endif			
+			);
+			}
+		}
+
+	out->CommitL();
+	CleanupStack::PopAndDestroy(out);//out
+	}
+#endif
+
+void CHeapRepository::DoCommitChangesL(RFs& aFs,TUint8 aPersistVersion,const TDesC& aTargetFilePath) 
+	{
+	CCreGenerator::CommitChangesToCreL(aFs,aPersistVersion,*this, aTargetFilePath);
+	}	
+
+/**
+The method reloads the repository content from a repository file.
+The current repository must be emptied (or must be empty already) before the call is made.
+@param aIniFile A reference to CIniFileIn object, which will be used to load
+				the repository content.
+@leave System-wide error codes.
+@leave KErrGeneral It's probably a programmer's error - current CHeapRepository 
+				   object is partially initialised.
+@leave KErrCorrupt Corrupted repository file.
+*/
+void CHeapRepository::ReloadContentL(CIniFileIn& aIniFile)
+	{
+	// Preconditions - CHeapRepository object should be an empty one.
+	if(!IsEmpty())
+		{
+		User::Leave(KErrGeneral);
+		}
+	TInt err = ReloadContentExceptSettingsL(aIniFile);
+	if(err == KErrCorrupt)
+		{
+		User::Leave(err);
+		}
+	CleanupClosePushL(iRangeMeta);
+	CleanupClosePushL(iRangePolicies);
+	
+	// Settings
+	TServerSetting setting;
+	TSettingsAccessPolicy* policy;
+	TBool singleMetaFound;
+	TCleanupItem tc(SinglePoliciesCleanup, &iSinglePolicies);
+	CleanupStack::PushL(tc);	
+	CleanupClosePushL(iSettings);
+	while((err = ReadSettingSavePolicyL(aIniFile, setting, policy, singleMetaFound)) == KErrNone)
+		{
+		setting.PushL();
+		if(iSettings.IsDefault())
+			{
+			setting.SetClean();			
+			}
+		User::LeaveIfError(Create(setting, policy, singleMetaFound));
+		setting.Pop();
+		}
+	if(err == KErrNotFound)			
+		{
+		err = KErrNone;
+		}
+	User::LeaveIfError(err);
+	CleanupStack::Pop(4,&iRangeMeta);
+	}
+
+/**
+Resets current repository data - actually all of them, which may be loaded from
+the related ini file.
+The iUid data member value is kept as it was at the moment of creation of 
+CHeapRepository object.
+*/
+void CHeapRepository::ResetContent()
+	{
+	iSettings.Reset();
+	iOwner = KNullUid;
+	iTimeStamp = TTime(0);
+
+	for (TInt i=0;i<iSinglePolicies.Count();i++)
+		{
+		delete iSinglePolicies[i];
+		}
+	iSinglePolicies.Reset();
+	iRangePolicies.Reset();
+	TSecurityPolicy emptyPolicy=TSecurityPolicy();
+	iDefaultPolicy = TSettingsAccessPolicy(emptyPolicy,emptyPolicy, KUnspecifiedKey);
+	iDefaultMeta = 0;
+	iRangeMeta.Reset();
+	}
+  
+void CHeapRepository::CreateRepositoryFromCreFileL(RFs& aFs,const TDesC& aFilePath )
+	{
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
+	TUint8 dummyVersion;	
+	CCreGenerator::CreateReposFromCreL(aFs,*this, aFilePath,dummyVersion);
+#else
+	CCreGenerator::CreateReposFromCreL(aFs,*this, aFilePath);
+#endif	
+	}
+
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+void CHeapRepository::CreateRepositoryFromCreFileL(RFs& aFs,const TDesC& aFilePath,TUint8& aCreVersion)
+	{	
+	CCreGenerator::CreateReposFromCreL(aFs,*this, aFilePath,aCreVersion);
+	}
+#endif
+
+void CHeapRepository::ExternalizeCre(TUint8 aPersistVersion,RWriteStream& aStream) const
+	{
+	CCreGenerator::ExternalizeCre(aPersistVersion,*this, aStream);
+	}
+
+
+void CHeapRepository::InternalizeCreL(RReadStream& aStream)
+	{
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
+	TUint8 dummyVersion;
+	CCreGenerator::InternalizeCreL(*this, aStream,dummyVersion);
+#else
+	CCreGenerator::InternalizeCreL(*this, aStream);
+#endif	
+	}
+
+
+void CHeapRepository::SinglePoliciesCleanup(TAny *aPtr)
+	{
+	static_cast<RPointerArray<TSettingsAccessPolicy>*>(aPtr)->ResetAndDestroy();
+	}
+
+TInt CHeapRepository::ReloadContentExceptSettingsL(CIniFileIn& aIniFile)
+	{
+	// Look for an "owner" section
+	TUint32 uidValue(KNullUid.iUid);
+	TInt err = aIniFile.ReadOwnerSectionL(uidValue);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+	iOwner.iUid = uidValue;
+	// Timestamp
+	TTime timeStamp (0);
+	err = aIniFile.ReadTimeStampSectionL(timeStamp);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+	iTimeStamp=timeStamp;
+
+	// Metadata
+	err = aIniFile.ReadDefaultMetaSecSectionL(iDefaultMeta, iRangeMeta);
+	// Even if err == KErrCorrupt, some items might have already been placed in the array
+	CleanupClosePushL(iRangeMeta);
+	if(err == KErrCorrupt)
+		{
+		CleanupStack::PopAndDestroy(&iRangeMeta);
+		return err;
+		}
+
+	// Default read/write policies
+	TBool gotDefaultReadPolicy;
+	TBool gotDefaultWritePolicy;
+	TSecurityPolicy defaultReadPolicy;
+	TSecurityPolicy defaultWritePolicy;
+	err = aIniFile.ReadPlatSecSectionL(defaultReadPolicy, gotDefaultReadPolicy,
+									   defaultWritePolicy, gotDefaultWritePolicy,
+									   iRangePolicies);
+	// Even if err == KErrCorrupt, some items might have already been placed in the array
+	CleanupClosePushL(iRangePolicies);	
+	if(err == KErrCorrupt)
+		{
+		CleanupStack::PopAndDestroy(2,&iRangeMeta);
+		return err;
+		}
+
+	iDefaultPolicy = TSettingsAccessPolicy(defaultReadPolicy,defaultWritePolicy, KUnspecifiedKey);
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
+	if (gotDefaultReadPolicy)
+		iDefaultPolicy.iHighKey=1;
+	if (gotDefaultWritePolicy)
+		iDefaultPolicy.iKeyMask=1;
+#endif	
+	CleanupStack::Pop(2,&iRangeMeta);
+	return KErrNone;
+	}
+
+TBool CHeapRepository::IsEmpty()
+	{
+	if(iSettings.Count() != 0 || iRangeMeta.Count() != 0 ||
+	   iSinglePolicies.Count() != 0 || iRangePolicies.Count() != 0)
+		{
+		return EFalse;
+		}
+	return ETrue;
+	}