policymanagement/policyengine/policyengineserver/src/PolicyStorage.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 21:00:49 +0200
changeset 2 5594fba90824
parent 0 b497e44ab2fc
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* Copyright (c) 2002-2004 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 policymanagement components
*
*/


// INCLUDE FILES

#include "PolicyStorage.h"
#include "PolicyEngineServer.h"
#include "ElementBase.h"
#include "XACMLconstants.h"
#include "PolicyParser.h"
#include "SettingEnforcementManager.h"
#include "debug.h"
#include "ErrorCodes.h"
#include "PolicyEnginePrivateCRKeys.h"

#include "policymnginternalpskeys.h"
#include <centralrepository.h>
#include "CentRepToolClient.h"
#include <e32property.h>
#include <s32file.h>


_LIT( KCDrive, "C:\\private\\10207815\\");
_LIT( KZDrive, "Z:\\private\\10207815\\");
_LIT( KCDriveLetter, "C:");
_LIT( KZDriveLetter, "Z:");
_LIT( KFileExtensio, ".txt");
_LIT( KBackupPath, "C:\\private\\10207815\\backup\\");
_LIT8( KEmptyBackup, "|Empty|");
_LIT( KServerIdFile, "C:\\private\\10207815\\serverids.dat");
_LIT( KServerIdFileTmp, "C:\\private\\10207815\\backup\\serverids.tmp");

const TInt KUidLength = 10;
const TInt KFileNameLength = 14;
const TChar KElementStartMark		 = '<';
const TInt KFullFileNameLength = 80;
const TInt KDriveLetterLength = 2;
// not in use anymore: KSettingSpaceLength = 100;
const TInt KCacheLimit = 100;




// ==================== LOCAL FUNCTIONS ====================

TInt CompareIDs( TUint32 const& aId1, TUint32 const& aId2)
{
	if ( aId1 == aId2) return 0;
	return ( aId1 < aId2 ? -1 : 1 );
}

TInt CompareStrings( HBufC8 const& aString1, HBufC8 const& aString2)
{
	return aString1.Compare( aString2);
}


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

CPolicyStorage* CPolicyStorage::iPolicyStorage = 0;

// -----------------------------------------------------------------------------
// CPolicyStorage::CPolicyStorage()
// -----------------------------------------------------------------------------
//

CPolicyStorage::CPolicyStorage()
{
}

// -----------------------------------------------------------------------------
// CPolicyStorage::~CPolicyStorage()
// -----------------------------------------------------------------------------
//

CPolicyStorage::~CPolicyStorage()
{
	RDEBUG("CPolicyStorage::~CPolicyStorage()");
	delete iCentRep;
	delete iCentRepBackup;
	delete iParser;

	//release memory used in element cache	
	for ( TInt i(0); i < iElementCache.Count(); i++)
	{
		CElementBase * element = iElementCache[i];
		__ASSERT_ALWAYS ( element->iReferenceCount == 0, User::Panic(PolicyStoragePanic, KErrGeneral));

				
		delete element;
	}

	//release memory used in depricated element cache
	for ( TInt i(0); i < iDepricatedElements.Count(); i++)
	{
		CElementBase * element = iDepricatedElements[i];
		__ASSERT_ALWAYS ( element->iReferenceCount == 0, User::Panic(PolicyStoragePanic, KErrGeneral));

				
		delete element;
	}

	//release memory used in depricated element cache
	for ( TInt i(0); i < iEditedElements.Count(); i++)
	{
		CElementBase * element = iEditedElements[i];
		__ASSERT_ALWAYS ( element->iReferenceCount == 0, User::Panic(PolicyStoragePanic, KErrGeneral));

				
		delete element;
	}
	
	//release resources
	iElementCache.Close();
	iDepricatedElements.Close();
	iEditedElements.Close();
	iSearchedUids.Close();
	
	iServerIdList.ResetAndDestroy();
	iServerIdList.Close();
	
	iInvalidServerIds.ResetAndDestroy();
	iInvalidServerIds.Close();

	
	iRFs.Close();
}


// -----------------------------------------------------------------------------
// CPolicyStorage::PolicyStorage()
// -----------------------------------------------------------------------------
//
CPolicyStorage * CPolicyStorage::PolicyStorage()
{
	return iPolicyStorage;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::ConstructL()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::ConstructL()
{
	RDEBUG("PolicyEngineServer: CPolicyStorage::ConstructL - start");

	iCommitted = ETrue;
	//open sessions to repotories and file server
	iCentRep = CRepository::NewL( KPolicyEngineRepositoryID);
	RDEBUG("PolicyEngineServer: Connected to repository");
	iCentRepBackup = CRepository::NewL( KPolicyEngineBackupRepositoryID);
	RDEBUG("PolicyEngineServer: Connected to backup repository");
	User::LeaveIfError( iRFs.Connect() );
	
	//Create and set up parser
	iParser = CPolicyParser::NewL( this);
	RDEBUG("PolicyEngineServer: Policy parser created");
	iParser->SetExternalIdChecked( KNoExternalIdCheck);
	
	//check commit state (restore and/or delete backup if needed)
	CheckCommitStateL();
	
	//load server id list...
	LoadServerIdListL();

	RDEBUG("PolicyEngineServer: CPolicyStorage::ConstructL - end");
}

// -----------------------------------------------------------------------------
// CPolicyStorage::NewL()
// -----------------------------------------------------------------------------
//

CPolicyStorage * CPolicyStorage::NewL()
{
	CPolicyStorage * self = new(ELeave) CPolicyStorage();
	
	CleanupStack::PushL( self);
	self->ConstructL();
	CleanupStack::Pop( self);
	
	return self;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::ReleaseElements()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::ReleaseElements()
{
	RDEBUG("PolicyEngineServer: Try to release unused elements!");


	//release memory used in element cache	
	for ( TInt i(0); i < iElementCache.Count(); i++)
	{
		CElementBase * element = iElementCache[i];
		if ( element->iReferenceCount == 0)
		{
			delete element;
			iElementCache.Remove(i--);
			RDEBUG_2("PolicyEngineServer: Element removed from cache (Cache count %d)", iElementCache.Count());
		}
	}

	//release memory used in depricated element cache
	for ( TInt i(0); i < iDepricatedElements.Count(); i++)
	{
		CElementBase * element = iDepricatedElements[i];
		if ( element->iReferenceCount == 0)
		{
			delete element;
			iDepricatedElements.Remove(i--);
			RDEBUG_2("PolicyEngineServer: Element removed from cache (Depricated element count %d)", iDepricatedElements.Count());
		}
	}
}


// -----------------------------------------------------------------------------
// CPolicyStorage::SetElementL()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::SetElementL( TUint32 aId, const TDesC8& aDescription)
{
	//resolve element file name
	TBuf<KUidLength> elementFile;
	elementFile.NumFixedWidth( aId, EDecimal, KUidLength);

	//buffer for file name (C-drive)
	TBuf<KFullFileNameLength> fileName;
	fileName.Append( KCDrive);
	fileName.Append( elementFile);
	fileName.Append( KFileExtensio);


	RDEBUG_2("PolicyEngineServer: Write element to disk (%S)", &fileName);
	MakeBackupL( fileName);

	//try open existing file
	RFile file;
	TInt err = file.Open( iRFs, fileName, EFileWrite);
	

	if ( err == KErrPathNotFound)
	{
		err = CreatePaths();
		
		//this ensures, that also element file will be created
		if ( err == KErrNone)
		{
			err = KErrNotFound;
		}
	}
	
	//and if file doesn't not exist create it
	if ( err == KErrNotFound  )
	{
		err = file.Create( iRFs, fileName, EFileWrite);
	}
	
	//write to file...
	if ( err == KErrNone)
	{
		err = file.Write( 0, aDescription);
	}
	
	//...and set size
	if ( err == KErrNone )
	{
		err = file.SetSize( aDescription.Length());
		if ( err == KErrNone )
		{
			err = file.Flush();
		}
	}	
	
	file.Close();

	RDEBUG_2("PolicyEngineServer: Write OK (%S)", &fileName);
	
	return err;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::MakeBackUpL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::MakeBackupL( const TDesC& aFileName)
{
	//buffer for file name (C-drive)
	TBuf<KFullFileNameLength> backupName;
	backupName.Append( KBackupPath);
	backupName.Append( aFileName.Right( KFileNameLength));
	
	CFileMan * fileMan = CFileMan::NewL( iRFs);
	
	//create backup
	TInt err = fileMan->Copy( aFileName, backupName, 0);
	delete fileMan;
	
	//if file doesn't exist in workarea, create empty file which indicates that in original state file is not exist
	if ( err == KErrNotFound)
	{
		RFile file;
		CleanupClosePushL( file);
		User::LeaveIfError( file.Create( iRFs, backupName, EFileWrite));

		RDEBUG_2("PolicyEngineServer: Element backup: %S indicates new element in policy storage", &backupName);
	
		CleanupStack::PopAndDestroy( &file);
	}
	else
	{
		User::LeaveIfError( err);
		RDEBUG_3("PolicyEngineServer: Element backup: %S -> %S", &aFileName, &backupName);
	}

}

// -----------------------------------------------------------------------------
// CPolicyStorage::MakeBackUpL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::MakeBackupL( const TUint32& aSettingId)
{
	//TInt settings
	TInt value = 0;
	TInt err = iCentRep->Get( aSettingId, value);
	RDEBUG_2("PolicyEngineServer: Backup for CentRep value setting: %d", aSettingId);
	
	//for "empty backup"
	if ( err == KErrNotFound )
	{
		//Set backupvalue
		TInt err = iCentRepBackup->Create( aSettingId, KEmptyBackup);
		
		//if value is already exist, it is a original value of setting is must be saved
		if ( err == KErrAlreadyExists)
		{
			err = KErrNone;
		}
				
		//Leave if backupfails
		User::LeaveIfError( err);		
	}
	else
	{
		//Set backupvalue
		TInt err = iCentRepBackup->Create( aSettingId, value);
		
		if ( err == KErrAlreadyExists)
		{
			//if value is already exist, it is a original value of setting is must be saved
			err = KErrNone;
		}
				
		//Leave if backupfails
		User::LeaveIfError( err);		
	}
}

void CPolicyStorage::RestoreBackupL()
{
	//Open directory and get file list
	RDir dir;
	CleanupClosePushL( dir);
	
	TInt err = dir.Open( iRFs, KBackupPath, KEntryAttNormal);

	//create private and backuppaths	
	if ( err == KErrPathNotFound)
	{
		CreatePaths();
		err = dir.Open( iRFs, KBackupPath, KEntryAttNormal);
	}
	
	User::LeaveIfError( err);
	err = KErrNone;

	do 
	{
		//read entries (files)
		TEntryArray array;
		err = dir.Read( array);
		if ( KErrEof != err)
		{
			User::LeaveIfError( err);
		}
	
		for ( TInt i = 0; i < array.Count(); i++)
		{
			const TEntry& entry = array[i];
		
			//original file name
			TBuf<KFullFileNameLength> fileName;
			fileName.Append( KCDrive);
			fileName.Append( entry.iName);

			//if file size is zero, remove file from work directory
			if ( entry.iSize == 0)
			{
				RDEBUG_2("PolicyEngineServer: Restoring backup: %S removed", &fileName);
				
				TInt err = iRFs.Delete( fileName);
				if ( err == KErrNotFound)
				{	
					err = KErrNone;	
				}
				
				User::LeaveIfError( err );
			}
			else
			{
				//Create backup file name
				TBuf<KFullFileNameLength> backupName;
				backupName.Append( KBackupPath);
				backupName.Append( entry.iName);
			
				//otherwise copy file to work directory
				CFileMan * fileMan = CFileMan::NewL( iRFs);
				CleanupStack::PushL( fileMan);
			
				//Copy file to work directory
				User::LeaveIfError( fileMan->Copy( backupName, fileName));
				RDEBUG_3("PolicyEngineServer: Restoring backup: %S -> %S", &backupName, &fileName);
	
	
				CleanupStack::Pop( fileMan);  //fileMan		
			}
		}
	} while ( err == KErrNone);
	
	//id list 
	RArray<TUint32> ids;
	CleanupClosePushL( ids);
	
	//find all ids
	iCentRepBackup->FindL( 0, 0x0, ids);

	for ( TInt i(0); i < ids.Count(); i++)
	{
		TUint32 id = ids[i];
		RDEBUG_2("PolicyEngineServer: Restoring centrep setting %d", id);
	
		//get value
		TBuf8<200> buffer;
		TInt err = iCentRepBackup->Get( id, buffer);
		
		if ( err != KErrNone)
		{
			TInt value = 0;
			User::LeaveIfError( iCentRepBackup->Get( id, value));
			User::LeaveIfError( iCentRep->Set( id, value));
		}
		else
		{
			if ( buffer == KEmptyBackup)
			{
				User::LeaveIfError( iCentRep->Delete( id));
			}
			else
			{
				User::LeaveIfError( iCentRep->Set( id, buffer));
			}
		}
	}
	
	CleanupStack::PopAndDestroy(2, &dir);	//RArray<TUint32>, RDir
}

// -----------------------------------------------------------------------------
// CPolicyStorage::RemoveBackupL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::RemoveBackupL()
{
	//Open directory and get file list
	RDir dir;
	CleanupClosePushL( dir);
	
	TInt err = dir.Open( iRFs, KBackupPath, KEntryAttNormal);

	//create private and backuppaths	
	if ( err == KErrPathNotFound)
	{
		CreatePaths();
		err = dir.Open( iRFs, KBackupPath, KEntryAttNormal);
	}
	
	User::LeaveIfError( err);
	err = KErrNone;

	do 
	{
		//read entries (files)
		TEntryArray array;
		err = dir.Read( array);
		if ( KErrEof != err)
		{
			User::LeaveIfError( err);
		}	
	
		for ( TInt i = 0; i < array.Count(); i++)
		{
			const TEntry& entry = array[i];
		
			TBuf<KFullFileNameLength> backupName;
			backupName.Append( KBackupPath);
			backupName.Append( entry.iName);
	
			RDEBUG_2("Policy Engine: Remove backup file %S", &backupName);
			User::LeaveIfError( iRFs.Delete( backupName));
		}
	} while ( err == KErrNone);
	
	//id list 
	RArray<TUint32> ids;
	CleanupClosePushL( ids);
	
	//find all ids
	iCentRepBackup->FindL( 0, 0x0, ids);

	for ( TInt i(0); i < ids.Count(); i++)
	{
		RDEBUG_2("Policy Engine: Remove centrep backup %d", ids[i]);
		User::LeaveIfError( iCentRepBackup->Delete( ids[i]));
	}
	
	CleanupStack::PopAndDestroy(2, &dir);	//RArray<TUint32> 	
}


// -----------------------------------------------------------------------------
// CPolicyStorage::ActivateEnforcementFlagL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::ActivateEnforcementFlagL( KSettingEnforcements aSetting)
{
	TUint32 id = KEnforcementStates + aSetting;

	MakeBackupL( id);
	TInt err = iCentRep->Set( id, ETrue);
	
	if ( KErrNotFound == err)
	{
		err = iCentRep->Create( id, ETrue);
	}

	User::LeaveIfError( err);
}

// -----------------------------------------------------------------------------
// CPolicyStorage::DeactivateEnforcementFlagL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::DeactivateEnforcementFlagL( KSettingEnforcements aSetting)
{
	TUint32 id = KEnforcementStates + aSetting;

	MakeBackupL( id);
	TInt err = iCentRep->Set( id, EFalse);
	
	if ( KErrNotFound == err)
	{
		err = iCentRep->Create( id, EFalse);
	}
	
	User::LeaveIfError( err);
}



// -----------------------------------------------------------------------------
// CPolicyStorage::GetElementL()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::GetElementL( TUint32 aId, HBufC8*& aDescription)
{
	//parse element file name
	TBuf<KUidLength> elementFile;
	elementFile.NumFixedWidth( aId, EDecimal, KUidLength);

	//buffer for file name (C-drive)
	TBuf<KFullFileNameLength> fileName;
	fileName.Append( KCDrive);
	fileName.Append( elementFile);
	fileName.Append( KFileExtensio);
	
	//try open file from C-drive
	RFile file;
	CleanupClosePushL( file);
	TInt err = file.Open( iRFs, fileName, EFileRead);
	
	//and if file does not exist in C-drive try again from z-drive
	if ( err == KErrNotFound || err == KErrPathNotFound)
	{
		fileName.Replace( 0, KDriveLetterLength, KZDriveLetter);
		err = file.Open( iRFs, fileName, EFileRead);
	}
	
	//resolve file size
	TInt size = 0;
	if ( err == KErrNone)
	{
		err = file.Size( size);
	}
	
	//empty file in the RAM-drive indicates that ROM-file is deleted
	if ( err == KErrNone && size)	
	{
		//create buffer for element
		aDescription = HBufC8::NewLC( size);
		TPtr8 ptr = aDescription->Des();
		
		//read file to buffer and remove buffer from cleanupstack
		file.Read( ptr);
		CleanupStack::Pop( aDescription);		
	}
	
	__ASSERT_ALWAYS( aDescription, User::Panic(PolicyStoragePanic, KErrGeneral));
		
	CleanupStack::PopAndDestroy( &file);		
	
	return err;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::DeleteElement()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::DeleteElementL( TUint32 aElementId)
{
	//parse element file name
	TBuf<KUidLength> elementFile;
	elementFile.NumFixedWidth( aElementId, EDecimal, KUidLength);

	//buffer for file name (C-drive)
	TBuf<KFullFileNameLength> fileName;
	fileName.Append( KCDrive);
	fileName.Append( elementFile);
	fileName.Append( KFileExtensio);
	
	
	//make backup	
	MakeBackupL( fileName);


	//if the ROM-drive contains file, we can't delete it, create empty file (c-drive) to indicate that file is deleted
	fileName.Replace( 0, KDriveLetterLength, KZDriveLetter);
	RFile file;
	TInt err = file.Open( iRFs, fileName, EFileRead);
	file.Close();
	
	fileName.Replace( 0, KDriveLetterLength, KCDriveLetter);
		
	if ( err == KErrNone)
	{
		CleanupClosePushL( file);
		User::LeaveIfError( file.Create( iRFs, fileName, EFileWrite	));
		User::LeaveIfError( file.Flush());
		CleanupStack::PopAndDestroy( &file);
	}
	else
	{
		//if file is only in the ROM-drive
		User::LeaveIfError( iRFs.Delete( fileName));
	}
	
}





// -----------------------------------------------------------------------------
// CPolicyStorage::SaveElementL()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::SaveElementL(  TUint32 aElementId, HBufC8 * aElementDescription)
{	
	//write element
	return SetElementL( aElementId, *aElementDescription);
}

// -----------------------------------------------------------------------------
// CPolicyStorage::CheckElementL()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::CheckElementL( CElementBase * aElement)
{
	if ( aElement->iElementState == ENotLoaded || aElement->iElementState == ENotLoadedEditableElement)	
	{
		TBool addEditCache = (  aElement->iElementState == ENotLoaded ? EFalse : ETrue);
		LoadElementL( aElement, addEditCache);
		
		if ( aElement->iElementState == ENotLoaded)
		{	
			aElement->iElementState = ECacheElement;
		}
		else
		{
			aElement->iElementState = EEditableCacheElement;
		}
	}
}

// -----------------------------------------------------------------------------
// CPolicyStorage::LoadElementL()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::LoadElementL( CElementBase * aElement, TBool aAddToEditableCache)
{
	__ASSERT_ALWAYS( aElement, User::Panic(PolicyStoragePanic, KErrGeneral));

	//load element description		
	HBufC8 * description = NULL;
	User::LeaveIfError( GetElementL( aElement->GetId(), description));
	CleanupStack::PushL( description);
	TPtr8 ptr(description->Des());
		
	TNativeElementTypes elementType = aElement->ElementType();
			
	//find parent element mapping for policies, policysets and rules
	if ( elementType == ERule || elementType == EPolicy || elementType == EPolicySet )
	{
		TInt index = ptr.Locate( KParentListStartMark); 
		
		TPtrC8 ptrParent;
		if ( index != KErrNotFound)
		{
			//separate description and parent id list
			ptrParent.Set( ptr.Mid( index));
			ptr = ptr.Left( index);
		}
			
		//and decode and add parant mapping
		while ( index != KErrNotFound)
		{
			ptrParent.Set( ptrParent.Mid(1));
			index = ptrParent.Locate(KParentListStartMark);
		
			TPtrC8 elementId( ptrParent);

			if ( index != KErrNotFound)
			{
				elementId.Set( ptrParent.Left( index));
				ptrParent.Set( ptrParent.Mid( index));
			}
		
			TUint32 policySystemid;
			TLex8 lex( elementId);
			User::LeaveIfError( lex.Val( policySystemid, EDecimal));
			
			aElement->AddParentIdL( policySystemid);
		}
	}

	//parse object
	User::LeaveIfError( iParser->ParseNativeObjects( aElement, ptr, aAddToEditableCache));

		
	CleanupStack::PopAndDestroy( description);	
}



void CPolicyStorage::AddNewElementL( CElementBase * aElement)
{
	aElement->iElementState = ENewElement;
	AddElementL( iEditedElements, aElement);
	aElement->iReferenceCount = 0;	
	
	RDEBUG_2("PolicyEngineServer: New editable element (element count %d)", iEditedElements.Count());
}


// -----------------------------------------------------------------------------
// CPolicyStorage::GetEditableElementL()
// -----------------------------------------------------------------------------
//
CElementBase * CPolicyStorage::GetEditableElementL( const TDesC8& aPolicyId )
{
	TUint32 settingId = MapRealIdL( aPolicyId, EFalse);
	
	CElementBase * element = NULL;
	
	if ( settingId )
	{
		element = GetEditableElementL( settingId);	
	}
	
	return element;
}



// -----------------------------------------------------------------------------
// CPolicyStorage::GetEditableElementL()
// -----------------------------------------------------------------------------
//
CElementBase * CPolicyStorage::GetEditableElementL( const TUint32 aElementId )
{
	//check from edit cache
	CElementBase * element = FindElement( iEditedElements, aElementId);
	
	//if doesn't not exits
	if ( element == NULL)
	{
		//create new element
		element = ElementHelper::CreateNewElementL( aElementId);

		//Aff element to edited element cache
		element->iElementState = ENotLoadedEditableElement;
		AddElementL( iEditedElements, element);
		element->iReferenceCount = 0;	

	}
	
	//if element is deleted return NULL
	if ( element->iElementState == EDeletedEditableElement)
	{
		element = NULL;
	}
	
	return element;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::GetElement()
// -----------------------------------------------------------------------------
//


CElementBase * CPolicyStorage::GetElementL( TUint32 aElementId)
{
	CElementBase * element = NULL;
	

	if ( element == NULL)
	{
		element = FindElement( iElementCache, aElementId);
	}
	
	if ( element == NULL)
	{
		element = ElementHelper::CreateNewElementL( aElementId);
		element->iElementState = ENotLoaded;
		AddElementL( iElementCache, element);
		element->iReferenceCount = 0;	
		
		RDEBUG_2("PolicyEngineServer: New cache element (element cache count %d)", iElementCache.Count());
		
		//release unused eleements from cache
		if ( iEditedElements.Count() > KCacheLimit)
		{
			RDEBUG_2("PolicyEngineServer: Cache limit exceeded (%d)", KCacheLimit);
			ReleaseElements();
		}
	}
		
	return element;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::GetElement()
// -----------------------------------------------------------------------------
//

CElementBase * CPolicyStorage::GetElementL( const TDesC8& iPolicyId )
{
	//map external id to internal id 
	TUint32 settingId = MapRealIdL( iPolicyId, ETrue);
	
	CElementBase * element = NULL;
	
	//and if valid mapping exists, get element from storage
	if ( settingId )
	{
		element = GetElementL( settingId);	
	}
	
	return element;	
}


// -----------------------------------------------------------------------------
// CPolicyStorage::FindElement()
// -----------------------------------------------------------------------------
//

CElementBase * CPolicyStorage::FindElement( RArray<CElementBase*> &aElementList, const TUint32 aElementId)
{
	__UHEAP_MARK;

	TLinearOrder<CElementBase*> linearOrder(&ElementHelper::CompareElements);
	CElementBase referenceElement( aElementId);
	
	TInt index = aElementList.FindInOrder( &referenceElement, linearOrder);
	
	CElementBase * element = NULL;
	if ( index >= 0)
	{
		element = aElementList[index];
	}
	
	__UHEAP_MARKEND;
	
	return element;

}



// -----------------------------------------------------------------------------
// CPolicyStorage::AddElementL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::AddElementL( RArray<CElementBase*> &aElementList, CElementBase * aElement)
{
	TLinearOrder<CElementBase*> linearOrder(&ElementHelper::CompareElements);
	aElementList.InsertInOrder( aElement, linearOrder);
}



// -----------------------------------------------------------------------------
// CPolicyStorage::MapRealId()
// -----------------------------------------------------------------------------
//
TUint32 CPolicyStorage::MapRealIdL( const TDesC8& aElementRealId, const TBool aOnlyCommitted)
{
	iSearchedUids.Reset();
	TUint32 retVal = 0;
	
	if ( !aOnlyCommitted )
	{
		retVal = GetEditedMappingsL( aElementRealId);	
	}
	
	if ( !retVal)
	{
		retVal = GetCommittedMappingsL( aElementRealId);	
	}
	
		
	if ( !retVal)
	{
		retVal = GetMappingsFromDriveL( aElementRealId, EDriveC, EFalse);	
	}

	if ( !retVal)
	{
		retVal = GetMappingsFromDriveL( aElementRealId, EDriveZ, EFalse);	
	}

	return retVal;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::GetEditedMappingsL()
// -----------------------------------------------------------------------------
//

TUint32 CPolicyStorage::GetEditedMappingsL( const TDesC8& aElementRealId)
{
	//seach matching external ids from edited elements
	TLinearOrder<TUint32> linearOrder( &CompareIDs);

	for ( TInt i(0); i < iEditedElements.Count(); i++)
	{
		CElementBase * element = iEditedElements[i];
			
		if ( element->iElementType == ERule || element->iElementType == EPolicy || element->iElementType == EPolicySet)
		{
			CheckElementL( element);
		
			if ( element->iElementState == EEditableCacheElement ||  element->iElementState == EEditedElement)
			{
				if ( aElementRealId.Compare( *(element->iExternalId)) == 0)
				{
					iSearchedUids.InsertInOrder( element->GetId(), linearOrder);
					return element->iElementId;
				}
			}
		}
	}
	
	return 0;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::GetCommittedMappingsL()
// -----------------------------------------------------------------------------
//
TUint32 CPolicyStorage::GetCommittedMappingsL( const TDesC8& aElementRealId)
{
	//seach matching external ids from edited elements
	TLinearOrder<TUint32> linearOrder( &CompareIDs);

	for ( TInt i(0); i < iElementCache.Count(); i++)
	{
		CElementBase * element = iElementCache[i];
			
		if ( element->iElementType == ERule || element->iElementType == EPolicy || element->iElementType == EPolicySet)
		{
			if ( iSearchedUids.Find( element->GetId()) >= 0)
			{
				CheckElementL( element);
		
				if ( element->iElementState == ECacheElement)
				{
					if ( aElementRealId.Compare( *(element->iExternalId)) == 0)
					{
						iSearchedUids.InsertInOrder( element->GetId(), linearOrder);
						return element->iElementId;
					}
				}
			}
		}
	}
	
	return 0;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::GetMappingsFromDriveL()
// -----------------------------------------------------------------------------
//
TUint32 CPolicyStorage::GetMappingsFromDriveL( const TDesC8& aElementRealId, TDriveNumber aDrive, TBool aUpdateList)
{
	//Select correct drive
	TPtrC bathPtr( KCDrive);
	
	if ( aDrive == EDriveZ)
	{
		bathPtr.Set( KZDrive);
	}
	
	//Open directory and get file list 
	RDir dir;
	CleanupClosePushL( dir);
	
	TInt err = dir.Open( iRFs, bathPtr, KEntryAttNormal);

	User::LeaveIfError( err);
	err = KErrNone;
	
	TUint32 retVal = 0;

	do 
	{
		//read entries (files)
		TEntryArray array;
		err = dir.Read( array);
		if ( KErrEof != err)
		{
			User::LeaveIfError( err);
		}	
	
		for ( TInt i = 0; i < array.Count(); i++)
		{
			const TEntry& entry = array[i];
		
			TPtrC ptr = entry.iName;
			TInt index = ptr.Locate('.');
			User::LeaveIfError( index);
			
			TLex lex( ptr.Left( index));
			TUint32 id;
			lex.Val( id, EDecimal);			
			TInt type = id & 0xff;
			
			if ( type == ERule || type == EPolicy || type == EPolicySet )
			{
				TBuf<150> file = bathPtr;
				file.Append( entry.iName);
			
				if ( ReadRealIdL( file, aElementRealId, aDrive))
				{
					retVal = id;	
				
					if ( aUpdateList)
					{
						TLinearOrder<HBufC8> linearOrder( &CompareStrings);	
						iInvalidServerIds.InsertInOrder( aElementRealId.AllocL(), linearOrder);
					}
					
					break;
				}
			}
		}
	} while ( err == KErrNone && !retVal);
	
	CleanupStack::PopAndDestroy( &dir);	//RArray<TUint32> 

	return retVal;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::ReadRealIdL()
// -----------------------------------------------------------------------------
//
TBool CPolicyStorage::ReadRealIdL( const TDesC& aFileName, const TDesC8& aElementRealId, TDriveNumber aDrive)
{
	TBool retVal = EFalse;

	//open file
	RFile file;

	TInt err = KErrNone;
	
	//check first from c-drive
	if ( aDrive == EDriveZ)
	{
		TBuf<100> buf( aFileName);
		buf.Replace( 0, KDriveLetterLength, KCDriveLetter);
		
		err = file.Open( iRFs, buf, EFileRead);
	}
	else
	{
		err = KErrNotFound;
	}

	if ( err == KErrNotFound)
	{
		err = file.Open( iRFs, aFileName, EFileRead);
	}
	
	CleanupClosePushL( file);
	if ( err == KErrNone)
	{
		TInt size;
		User::LeaveIfError( file.Size( size));
		
		if ( size )
		{
			HBufC8* content = HBufC8::NewLC( size);
			TPtr8 ptr = content->Des();
			
			User::LeaveIfError( file.Read( ptr));

			TInt index = ptr.FindF( aElementRealId);
			if ( index > 0)
			{
				if ( ptr[ index + aElementRealId.Length()] == '"' && ptr[ index - 1] == '"')
				{
					TInt identifierIndex = ptr.FindF(  PolicyLanguage::Rule::RuleId[ENative]);
					TInt length = 0;
					if ( identifierIndex < 0 )
					{
						identifierIndex = ptr.FindF(  PolicyLanguage::Policy::PolicyId[ENative]);
					    length = PolicyLanguage::Policy::PolicyId[ENative].Length();
						if ( identifierIndex < 0 )
						{
							identifierIndex = ptr.FindF(  PolicyLanguage::PolicySet::PolicySetId[ENative]);
						    length = PolicyLanguage::PolicySet::PolicySetId[ENative].Length();
						}
					}
					else
					{
						length = PolicyLanguage::Rule::RuleId[ENative].Length();
					}

					if ( (identifierIndex + length  +2 ) == index)
					{
						retVal = ETrue;
					}
				}
			}
						
			CleanupStack::PopAndDestroy( content);
		}
			
	}

	CleanupStack::PopAndDestroy( &file);
	return retVal;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::ResetRealIdValidTest()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::ResetRealIdValidTest()
{
	iInvalidServerIds.ResetAndDestroy();
}



// -----------------------------------------------------------------------------
// CPolicyStorage::IsRealIdValidL()
// -----------------------------------------------------------------------------
//

TBool CPolicyStorage::IsRealIdValidL( const TDesC8& aElementRealId)
{	
	iSearchedUids.Reset();
	TLinearOrder<HBufC8> linearOrder( &CompareStrings);	
	
	HBufC8 * buf = aElementRealId.Alloc();
	if ( iInvalidServerIds.Find( buf) >= 0 )
	{
		delete buf;
		return EFalse;
	}
	delete buf;
	
	
	TUint32 id = GetEditedMappingsL( aElementRealId);
	
	if ( !id )
	{
		id = GetCommittedMappingsL( aElementRealId);	
	}
	
	if (!id)
	{	
		id = GetMappingsFromDriveL( aElementRealId, EDriveC, ETrue);
	}

	if (!id)
	{	
		id = GetMappingsFromDriveL( aElementRealId, EDriveZ, ETrue);
	}
	
	if ( !id)
	{
		iInvalidServerIds.InsertInOrder( aElementRealId.AllocL(), linearOrder);
	}
	
	return !id;	
}

// -----------------------------------------------------------------------------
// CPolicyStorage::CreateId()
// -----------------------------------------------------------------------------
//

TUint32 CPolicyStorage::CreateIdL( TNativeElementTypes &aType)
{
	__UHEAP_MARK;

	TUint32 nextFreeId = KNextFreeId;
	TUint32 nextId(0);
	TInt id(0);
	TInt err( KErrNone);

	do
	{
		if ( id == 0)
		{
			//get next free id from CentRep
			err = iCentRep->Get( nextFreeId, id);
		}

		if ( err != KErrNone)
		{
			id = 1;
		}
		
		//reset counter
		if ( id > 0xFFFFFF )
		{
			id = 0;
		}
	
		//increase next free id value 
		nextId = id++;

		//create id (combination id next free id and element type)
		nextId = nextId << 8;
		nextId = nextId | aType;


	    RDEBUG_2("PolicyEngineServer: Next free id: %d", nextId);
	}
	while ( !IsIdValidL( nextId));

	//backup value
	MakeBackupL( KNextFreeId);
	
	//save new value
	if ( err != KErrNone)
	{
		User::LeaveIfError( iCentRep->Create( KNextFreeId, id));
	}
	else
	{
		User::LeaveIfError( iCentRep->Set( KNextFreeId, id));
	}

	 
	__UHEAP_MARKEND; 
	 
	return nextId;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::GetEditedElements()
// -----------------------------------------------------------------------------
//
TBool CPolicyStorage::IsIdValidL( const TUint32& aId)
{
    RDEBUG("PolicyEngineServer: CPolicyStorage::IsIdValidL");


	//parse element file name
	TBuf<KUidLength> elementFile;
	elementFile.NumFixedWidth( aId, EDecimal, KUidLength);

	//buffer for file name (C-drive)
	TBuf<KFullFileNameLength> fileName;
	fileName.Append( KCDrive);
	fileName.Append( elementFile);
	fileName.Append( KFileExtensio);
	
	//try open file from C-drive
	RFile file;
	CleanupClosePushL( file);
	TInt err = file.Open( iRFs, fileName, EFileRead);
	
	//and if file does not exist in C-drive try again from z-drive
	if ( err == KErrNotFound || err == KErrPathNotFound)
	{
		fileName.Replace( 0, KDriveLetterLength, KZDriveLetter);
		err = file.Open( iRFs, fileName, EFileRead);
	}
	
	CleanupStack::PopAndDestroy( &file);		

#ifdef __DEBUG
 	if ( err == KErrNotFound)
 	{
 		RDEBUG("PolicyEngineServer: Id is not valid!");
 	}
#endif
	
	return err == KErrNotFound;
}



// -----------------------------------------------------------------------------
// CPolicyStorage::GetEditedElements()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::GetEditedElementsL( CSettingEnforcementManager* aSEManager)
{
	//Check is element changed
	for ( TInt i(0); i < iEditedElements.Count(); i++)
	{
		CElementBase * element = iEditedElements[i];
		__ASSERT_ALWAYS ( element->iReferenceCount == 0, User::Panic(PolicyStoragePanic, KErrGeneral));

		switch ( element->iElementState)
		{
			//these states indicates changes
			case EDeletedEditableElement:
			case ENewElement:
			case EEditedElement:
				//add element to modified element list
				aSEManager->AddModifiedElementL( element);
			break;
			default:
			break;
		}
	
	}
}

// -----------------------------------------------------------------------------
// CPolicyStorage::ResetEditableMemory()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::ResetEditableMemory()
{
	//release memory used in edited element cache
	for ( TInt i(0); i < iEditedElements.Count();)
	{
		CElementBase * element = iEditedElements[i];
		__ASSERT_ALWAYS ( element->iReferenceCount == 0, User::Panic(PolicyStoragePanic, KErrGeneral));
		delete element;
		iEditedElements.Remove( i);
	}

    RDEBUG("PolicyEngineServer: Edited elements removed!");
}

// -----------------------------------------------------------------------------
// CPolicyStorage::SaveEditableMemoryL()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::SaveEditableMemoryL()
{
    RDEBUG("PolicyEngineServer: Save new and modified elements");


	//save modified elements
	for ( TInt i(0); i < iEditedElements.Count(); i++)
	{
		CElementBase * element = iEditedElements[i];
		__ASSERT_ALWAYS ( element->iReferenceCount == 0, User::Panic(PolicyStoragePanic, KErrGeneral));

		TInt elementChanged = ETrue;
	
		switch ( element->iElementState)
		{
			case EDeletedEditableElement:
				//delete element and remove possible id mappings...
				RDEBUG_2("Element is deleted (id %d)", element->GetId());
				element->DeleteElementL();
			break;
			case ENewElement:
				//save element (Save new elements recursive)
				element->SaveElementL( ETrue);
				RDEBUG_2("New element (id %d)", element->GetId());
			break;
			case EEditedElement:
				//save element (not recursive)
				RDEBUG_2("Element is modified (id %d)", element->GetId());
				element->SaveElementL( EFalse);
			break;
			default:
				//no changes in elements
				elementChanged = EFalse;
			break;
		}
	
		if ( elementChanged )
		{
			//find elements from element cache (by id) 
			CElementBase referenceElement( element->GetId());
			TLinearOrder<CElementBase*> linearOrder(&ElementHelper::CompareElements);
			TInt index = iElementCache.FindInOrder( &referenceElement, linearOrder);
	
			//if eleement is in the element cache remove it to depricated list
			//Next time element is used it will be loaded from RAM
			if ( index >= 0)
			{
				CElementBase * cacheElement = iElementCache[index];
				iElementCache.Remove( index);
		
				if ( element->iReferenceCount == 0 )
				{
					delete cacheElement;
				}
			else
				{
					cacheElement->iElementState = EDepricated;
					iDepricatedElements.AppendL( cacheElement);
					RDEBUG_2("PolicyEngineServer: Depricated element list", iDepricatedElements.Count());
				}
			}
		}
	}
}

// -----------------------------------------------------------------------------
// CPolicyStorage::CheckCommitStateL()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::CheckCommitStateL()
{
	RDEBUG( "PolicyEngineServer: CPolicyStorage::CheckCommitStateL");

	TInt state;	
	iCentRep->Get( KCommitFlag, state);
	
	if ( state == EFalse)
	{
		RDEBUG( "PolicyEngineServer: Commit flag is not set, restore backup....");
		//if commit state is "not committed" restore backup files
		RestoreBackupL();
	}

	//Check also commit state in centreptool
	RCentRepTool centRepTool;
	User::LeaveIfError( centRepTool.Connect());
	TInt err = centRepTool.CheckCommitState();
	centRepTool.Close();
	
	if ( state)
	{
		//commit server id list
		CFileMan * fileMan = CFileMan::NewL( iRFs);
	
		//create backup
		err = fileMan->Copy( KServerIdFileTmp, KServerIdFile, CFileMan::EOverWrite);	
		
		if ( err == KErrNone || err == KErrNotFound)
		{
			fileMan->Delete( KServerIdFileTmp, 0);
			err = KErrNone;	
		}
		
		delete fileMan;
	}
	
	
	//if restore ok, turn commit flag to true state which indicates that storages are in valid state
	if ( err == KErrNone)
	{
		RDEBUG( "PolicyEngineServer: Set commit flag on!");
		iCentRep->Set( KCommitFlag, ETrue);
	}

	//remove back files
	RDEBUG( "PolicyEngineServer: Remove backup!");
	RemoveBackupL();
}

// -----------------------------------------------------------------------------
// CPolicyStorage::StartCommitSessionL()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::StartCommitSessionL()
{
	//Only ONE management session can be active!
	__ASSERT_ALWAYS ( iCommitted, User::Panic( Panics::PolicyStoragePanic, KErrCorrupt));

	iCommitted = EFalse;

	//Set storage state to "Not committed", ensures rollback in error situations
	iCentRep->Set( KCommitFlag, EFalse);	
}

// -----------------------------------------------------------------------------
// CPolicyStorage::CreatePathsL()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::CreatePaths()
{
	//create directory
	RDEBUG("PolicyEngineServer: Create private path");
	TInt err = iRFs.CreatePrivatePath( EDriveC);
	
	if ( err == KErrNone || err == KErrAlreadyExists )
	{
		//create also backup path
		RDEBUG("PolicyEngineServer: Create backup path");
		err = iRFs.MkDir( KBackupPath);
	}
	
	return err;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::CommitChangesL()
// -----------------------------------------------------------------------------
//

void CPolicyStorage::CommitChangesL( TBool aAcceptCommit)
{
	RDEBUG("PolicyEngineServer: Commit changes!");

	if ( !aAcceptCommit)
	{
		//if commit is not accepted, restore files!
		RDEBUG("PolicyEngineServer: Commit is not accepted");
		CheckCommitStateL();
	}

	//Set storage state to "Committed"
	RDEBUG("PolicyEngineServer: Set commit flag state to committed");
	iCentRep->Set( KCommitFlag, ETrue);
	
	if ( aAcceptCommit)
	{
		//This removes all backups
		CheckCommitStateL();
	}
	
	
	//Commit changes
	iCommitted = ETrue;
	
	RDEBUG("PolicyEngineServer: Commit changes - end");
}

// -----------------------------------------------------------------------------
// CPolicyStorage::AddNewServerId()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::AddNewServerId( const TDesC8& aServerId)
{
	TRAPD( err,	
	iServerIdList.AppendL( aServerId.AllocL());
	SaveServerIdListL());
	
	if ( err != KErrNone)
	{
		TRAP( err,	LoadServerIdListL());
	}
	
	return err;	
}

// -----------------------------------------------------------------------------
// CPolicyStorage::RemoveServerId()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::RemoveServerId( const TDesC8& aServerId)
{
	for ( TInt i(0); i < iServerIdList.Count(); i++)
	{
		if ( *(iServerIdList[i]) == aServerId)
		{
			delete (iServerIdList[i]);
			iServerIdList.Remove( i);
			break;
		}
	}

	TRAPD( err,	SaveServerIdListL());
	
	if ( err != KErrNone)
	{
		TRAP( err,	LoadServerIdListL());
	}
	
	return err;
}

// -----------------------------------------------------------------------------
// CPolicyStorage::ResetServerIdList()
// -----------------------------------------------------------------------------
//
TInt CPolicyStorage::ResetServerIdList()
{
	iServerIdList.ResetAndDestroy();

	TRAPD( err,	SaveServerIdListL());
	
	if ( err != KErrNone)
	{
		TRAP( err,	LoadServerIdListL());
	}
	
	return err;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::PrintServerIdList()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::PrintServerIdList()
{
	for ( TInt i(0); i < iServerIdList.Count(); i++)
	{
		TPtrC8 ptr = *iServerIdList[i];

		RDEBUG8_2("CPolicyStorage::PrintServerIdList() Server id: (%S)", &ptr);
	}
}


// -----------------------------------------------------------------------------
// CPolicyStorage::SaveServerIdList()
// -----------------------------------------------------------------------------
//
TBool CPolicyStorage::IsServerIdValid( const TDesC8& aServerId)
{
	for ( TInt i(0); i < iServerIdList.Count(); i++)
	{
		if ( *(iServerIdList[i]) == aServerId)
		{
			return ETrue;
		}
	}	
	
	return EFalse;
}


// -----------------------------------------------------------------------------
// CPolicyStorage::SaveServerIdList()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::SaveServerIdListL()
{
	__UHEAP_MARK;

	//Open file stream. RFile ownership changes for CDirectFileStore
	RFile file;
	CleanupClosePushL( file);
	User::LeaveIfError( file.Replace( iRFs, KServerIdFileTmp, EFileWrite));
		
	CDirectFileStore * directFileStore = CDirectFileStore::NewL( file);
	CleanupStack::Pop( &file);
	CleanupStack::PushL( directFileStore);

	//setup write stream
	directFileStore->SetTypeL( TUidType(KDirectFileStoreLayoutUid, KNullUid, KPolicyEngineRepositoryID)) ; 
		
	RStoreWriteStream rootStream ;
	TStreamId rootStreamId = rootStream.CreateLC(*directFileStore) ;

	//Externalize
	TInt32 count = iServerIdList.Count();
	rootStream << count;
	
	for ( TInt i(0); i < count; i++)
	{
		rootStream << *(iServerIdList[i]);
	}

	rootStream.CommitL();

	directFileStore->SetRootL(rootStreamId);
	directFileStore->CommitL();

	//destroy
	CleanupStack::PopAndDestroy( 2, directFileStore);	
	
	__UHEAP_MARKEND;	
}

// -----------------------------------------------------------------------------
// CPolicyStorage::LoadServerIdList()
// -----------------------------------------------------------------------------
//
void CPolicyStorage::LoadServerIdListL()
{
	RDEBUG("CPolicyStorage: LoadServerIdListL()");

	RFile file;
	iServerIdList.ResetAndDestroy();

	//Open file
	TInt err = file.Open( iRFs, KServerIdFile, EFileRead);
	
	if ( err == KErrNotFound)
	{
		RDEBUG("CPolicyStorage: ServerID file not found!");
		return;
	}
	
	User::LeaveIfError( err);

	//Open file stream
	CDirectFileStore* directFileStore = CDirectFileStore::FromLC ( file);
	TStreamId rootStreamId = directFileStore->Root() ;
	
	//setup read stream
	RStoreReadStream rootStream ;
	rootStream.OpenLC( *directFileStore, rootStreamId);

	//Internalize
	TInt32 count;
	rootStream >> count;
	
	for ( TInt i(0); i < count; i++)
	{
		HBufC8 * buf = HBufC8::NewLC( rootStream, 200);
		iServerIdList.AppendL( buf);
		CleanupStack::Pop( buf);
	}

	PrintServerIdList();
	
	CleanupStack::PopAndDestroy( 2, directFileStore);
}



// -----------------------------------------------------------------------------
// TElementReserver::TElementReserver()
// -----------------------------------------------------------------------------
//

TElementReserver::TElementReserver()
	: iElement( NULL), iElements( NULL), iElementList( NULL)
	{	
	}

// -----------------------------------------------------------------------------
// TElementReserver::TElementReserver()
// -----------------------------------------------------------------------------
//

TElementReserver::TElementReserver( CElementBase * aElement)
	: iElement( aElement), iElements( NULL), iElementList( NULL)
	{
	//reserve element
	aElement->ReserveElement();
	}

// -----------------------------------------------------------------------------
// TElementReserver::TElementReserver()
// -----------------------------------------------------------------------------
//

TElementReserver::TElementReserver( RElementContainer* aElements)
	: iElement( NULL), iElements( aElements), iElementList( NULL)
	{
	//Reserver all elements in element list
	for (TInt i(0); i < iElements->Count(); i++)
		{
		(*iElements)[i]->iElement->ReserveElement();
		}
	}

// -----------------------------------------------------------------------------
// TElementReserver::~TElementReserver()
// -----------------------------------------------------------------------------
//

TElementReserver::~TElementReserver()
	{
	DoRelease();
	}

// -----------------------------------------------------------------------------
// TElementReserver::ReserveL()
// -----------------------------------------------------------------------------
//

void TElementReserver::ReserveL( CElementBase* aElement)
{
	//create new element list if needed
	if (!iElementList)
	{
		iElementList = new (ELeave) RElementList();
	}

	//add element to list and reserve it
	iElementList->AppendL( aElement);
	aElement->ReserveElement();
}

// -----------------------------------------------------------------------------
// TElementReserver::DoRelease()
// -----------------------------------------------------------------------------
//


void TElementReserver::Release()
	{	
	}


void TElementReserver::DoRelease()
{
	//release eleements...
	if ( iElement )
	{
		iElement->ReleaseElement();
	}
	else if ( iElements )
	{
		for (TInt i(0); i < iElements->Count(); i++)
		{
			(*iElements)[i]->iElement->ReleaseElement();
		}		
	}
	else if ( iElementList)
	{
		for (TInt i(0); i < iElementList->Count(); i++)
		{
			(*iElementList)[i]->ReleaseElement();
		}		
		
		iElementList->Close();
		delete iElementList;
		iElementList = NULL;	
	}
}