sysstatemgmt/systemstatemgr/cmd/src/ssmcommandlistresourcereaderimpl.cpp
changeset 0 4e1aa6a622a0
child 3 a811597961f0
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "ssmcommandlistresourcereaderimpl.h"
       
    17 
       
    18 #include <bautils.h>
       
    19 #include <barsc2.h>
       
    20 #include <ssm/ssmcommandlist.h>
       
    21 #include <ssm/ssmconditionalcallback.h>
       
    22 
       
    23 #include <ssm/ssmcommandfactory.h>
       
    24 #include <ssm/ssmcommand.h>
       
    25 #include "ssmcommandbase.h"
       
    26 #include "ssmcommandparameters.h"
       
    27 #include "ssmcommandlistinterface.h"
       
    28 #include "ssmdebug.h"
       
    29 #include "ssmpanic.h"
       
    30 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
    31 #include "ssmcommandlistimpl.h"
       
    32 #endif
       
    33 
       
    34 CSsmCommandListResourceReaderImpl* CSsmCommandListResourceReaderImpl::NewL(RFs& aFs, const TDesC& aCommandListPath, MSsmConditionalCallback& aConditionalCallback)
       
    35 	{
       
    36 	CSsmCommandListResourceReaderImpl* self = new(ELeave) CSsmCommandListResourceReaderImpl();
       
    37 	CleanupStack::PushL(self);
       
    38 	self->ConstructL(aFs, aCommandListPath, aConditionalCallback);
       
    39 	CleanupStack::Pop(self);
       
    40 	return self;
       
    41 	}
       
    42 
       
    43 CSsmCommandListResourceReaderImpl::CSsmCommandListResourceReaderImpl()
       
    44 	{
       
    45 	}
       
    46 
       
    47 CSsmCommandListResourceReaderImpl::~CSsmCommandListResourceReaderImpl()
       
    48 	{
       
    49 	delete iPreparer;
       
    50 	delete iInitialiser;
       
    51 	delete iResourcePool;
       
    52 	}
       
    53 
       
    54 void CSsmCommandListResourceReaderImpl::ConstructL(RFs& aFs, const TDesC& aCommandListPath, MSsmConditionalCallback& aConditionalCallback)
       
    55 	{
       
    56 	iResourcePool = new(ELeave) CResourcePool;
       
    57 	iInitialiser = CInitialiser::NewL(aFs, aCommandListPath, *iResourcePool);
       
    58 	iPreparer = new(ELeave) CPreparer(*iResourcePool, aConditionalCallback);
       
    59 	}
       
    60 
       
    61 void CSsmCommandListResourceReaderImpl::Initialise(TRequestStatus& aStatus)
       
    62 	{
       
    63 	__ASSERT_ALWAYS(!Busy(), PanicNow(KPanicCmdResourceReader, EInUse1));
       
    64 	iInitialiser->Start(aStatus);
       
    65 	}
       
    66 
       
    67 void CSsmCommandListResourceReaderImpl::InitialiseCancel()
       
    68 	{
       
    69 	iInitialiser->Cancel();
       
    70 	}
       
    71 
       
    72 void CSsmCommandListResourceReaderImpl::PrepareCommandList(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmState& aState, TRequestStatus& aStatus)
       
    73 	{
       
    74 	__ASSERT_ALWAYS(!Busy(), PanicNow(KPanicCmdResourceReader, EInUse2));
       
    75 	iPreparer->Start(aCommandList, aCommandListId, aState, aStatus);
       
    76 	}
       
    77 
       
    78 void CSsmCommandListResourceReaderImpl::PrepareCommandList(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmSwp& aSwp, TRequestStatus& aStatus)
       
    79 	{
       
    80 	__ASSERT_ALWAYS(!Busy(), PanicNow(KPanicCmdResourceReader, EInUse3));
       
    81 	iPreparer->Start(aCommandList, aCommandListId, aSwp, aStatus);
       
    82 	}
       
    83 
       
    84 void CSsmCommandListResourceReaderImpl::PrepareCommandListCancel()
       
    85 	{
       
    86 	iPreparer->Cancel();
       
    87 	}
       
    88 
       
    89 TBool CSsmCommandListResourceReaderImpl::IsCommandListReady() const
       
    90 	{
       
    91 	// enables caller to find out if the command list they passed
       
    92 	// to PrepareCommandList is fully prepared or not
       
    93 	return iPreparer->IsCommandListReady();
       
    94 	}
       
    95 
       
    96 TBool CSsmCommandListResourceReaderImpl::Busy() const
       
    97 	{
       
    98 	return iInitialiser->IsActive() || iPreparer->IsActive();
       
    99 	}
       
   100 
       
   101 void CSsmCommandListResourceReaderImpl::GetCommandListIdsL(RArray<TInt>& aArray) const
       
   102 	{
       
   103 	iResourcePool->GetCommandListIdsL(aArray);
       
   104 	}
       
   105 
       
   106 // CResourcePool
       
   107 CSsmCommandListResourceReaderImpl::CResourcePool::CResourcePool()
       
   108 	{
       
   109 	}
       
   110 
       
   111 CSsmCommandListResourceReaderImpl::CResourcePool::~CResourcePool()
       
   112 	{
       
   113 	iMappings.Close();
       
   114 	iResourceFiles.ResetAndDestroy();
       
   115 	iResourceFileNames.ResetAndDestroy();
       
   116 	}
       
   117 
       
   118 TBool CSsmCommandListResourceReaderImpl::CResourcePool::IsEmpty() const
       
   119 	{
       
   120 	return !(iMappings.Count() > 0);
       
   121 	}
       
   122 
       
   123 void CSsmCommandListResourceReaderImpl::CResourcePool::Reset()
       
   124 	{
       
   125 	iMappings.Reset();
       
   126 	iResourceFiles.ResetAndDestroy();
       
   127 	iResourceFileNames.ResetAndDestroy();
       
   128 	}
       
   129 
       
   130 void CSsmCommandListResourceReaderImpl::CResourcePool::AppendL(const CResourceFile* aResourceFile)
       
   131 	{
       
   132 	iResourceFiles.AppendL(aResourceFile);
       
   133 	}
       
   134 
       
   135 void CSsmCommandListResourceReaderImpl::CResourcePool::AppendL(const TDesC& aFileName)
       
   136 	{
       
   137 	HBufC* name = aFileName.AllocLC();
       
   138 	iResourceFileNames.AppendL(name);
       
   139 	CleanupStack::Pop(name);
       
   140 	}
       
   141 
       
   142 
       
   143 void CSsmCommandListResourceReaderImpl::CResourcePool::AppendL(const TMapping& aMapping)
       
   144 	{
       
   145 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE 
       
   146 	//check if the mapping already exists
       
   147 	TInt index = iMappings.Find(aMapping);
       
   148 	if (index != KErrNotFound)
       
   149 		{
       
   150 		DEBUGPRINT2(_L("Duplicate Substate found at index: %d"), index);
       
   151 		}
       
   152 	TInt err = iMappings.InsertInSignedKeyOrderAllowRepeats(aMapping);
       
   153 #else
       
   154 	TInt err = iMappings.InsertInSignedKeyOrder(aMapping); 
       
   155     if(KErrAlreadyExists == err) 
       
   156 		{ 
       
   157 		PanicNow(KPanicCmdResourceReader, EDuplicateSubstateInCommandList); 
       
   158 		} 
       
   159 #endif
       
   160     User::LeaveIfError(err);     
       
   161 	}
       
   162 
       
   163 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   164 // This function will get all the mappings which have the same commandlistId's (substates) into aMappingArray
       
   165 void CSsmCommandListResourceReaderImpl::CResourcePool::UpdateMappingArrayL(TInt aCommandListId, RArray<TMapping>& aMappingArray) const
       
   166 	{
       
   167 	aMappingArray.Reset();
       
   168 	TMapping mapping(aCommandListId, 0, NULL);
       
   169 	const TInt mappingCount = iMappings.Count();
       
   170 	TInt mappingIndex = iMappings.FindL(mapping);
       
   171 
       
   172 	for(; mappingIndex < mappingCount; ++mappingIndex)
       
   173 		{
       
   174 		aMappingArray.AppendL(iMappings[mappingIndex]);
       
   175 		if ((mappingIndex >= (mappingCount - 1)) || (iMappings[mappingIndex].iCommandListId !=
       
   176 		iMappings[mappingIndex + 1].iCommandListId))
       
   177 			{
       
   178 			//Breaking as it reached end of array or completed appending the mappings for
       
   179 			//the given commandlist id
       
   180 			break;
       
   181 			}
       
   182 		}
       
   183 	DEBUGPRINT3(_L("Mapping Array for substate %d Contains %d entries"), iMappings[mappingIndex].iCommandListId, aMappingArray.Count());
       
   184 	}
       
   185 
       
   186 #else
       
   187 CSsmCommandListResourceReaderImpl::TMapping CSsmCommandListResourceReaderImpl::CResourcePool::MappingL(TInt aCommandListId) const
       
   188 	{
       
   189 	TMapping mapping(aCommandListId, 0, NULL);
       
   190 	const TInt index = iMappings.FindL(mapping);
       
   191 	return iMappings[index];
       
   192 	}
       
   193 
       
   194 #endif
       
   195 void CSsmCommandListResourceReaderImpl::CResourcePool::GetCommandListIdsL(RArray<TInt>& aArray) const
       
   196 	{
       
   197 	TInt count = iMappings.Count();
       
   198 	__ASSERT_ALWAYS(count > 0, PanicNow(KPanicCmdResourceReader, ENotInitialized3));
       
   199 	if (aArray.Count() != 0)
       
   200 		{
       
   201 		SSMLOGLEAVE(KErrArgument);
       
   202 		}
       
   203 	aArray.ReserveL(count);
       
   204 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   205 	TInt i = 0;
       
   206 	for(i = 0; i < iMappings.Count() - 1 ; ++i)
       
   207 		{
       
   208 		if(iMappings[i].iCommandListId != iMappings[i+1].iCommandListId)
       
   209 			{
       
   210 			aArray.AppendL(iMappings[i].iCommandListId);
       
   211 			}
       
   212 		}
       
   213 	//append the last element anyway as it is already compared
       
   214 	aArray.AppendL(iMappings[i].iCommandListId);
       
   215 	aArray.Compress();
       
   216 		
       
   217 	DEBUGPRINT2(_L("The number of substates in resource files : %d"),iMappings.Count() );
       
   218 	DEBUGPRINT2(_L("The number of substates after filtering duplicates : %d"),aArray.Count());
       
   219 #else
       
   220 	for(TInt i = 0; i < count; ++i)
       
   221 		{
       
   222 		aArray.AppendL(iMappings[i].iCommandListId);
       
   223 		}
       
   224 #endif
       
   225 	}
       
   226 
       
   227 const TDesC& CSsmCommandListResourceReaderImpl::CResourcePool::FileNameForResourceFileL(const CResourceFile* aResourceFile) const
       
   228 	{
       
   229 	TInt count = iResourceFiles.Count();
       
   230 	for(TInt i = 0; i < count; ++i)
       
   231 		{
       
   232 		if(iResourceFiles[i] == aResourceFile)
       
   233 			{
       
   234 			return *iResourceFileNames[i];
       
   235 			}
       
   236 		}
       
   237 	SSMLOGLEAVE(KErrNotFound);
       
   238 	return KNullDesC16();
       
   239 	}
       
   240 
       
   241 // CActiveBase
       
   242 CSsmCommandListResourceReaderImpl::CActiveBase::CActiveBase(TInt aPriority)
       
   243 	:CActive(aPriority), iAction(EIdle)
       
   244 	{
       
   245 	}
       
   246 
       
   247 CSsmCommandListResourceReaderImpl::CActiveBase::~CActiveBase()
       
   248 	{
       
   249 	}
       
   250 
       
   251 void CSsmCommandListResourceReaderImpl::CActiveBase::Start()
       
   252 	{
       
   253 	TRequestStatus* status = &iStatus;
       
   254 	User::RequestComplete(status, KErrNone);
       
   255 	SetActive();
       
   256 	}
       
   257 
       
   258 void CSsmCommandListResourceReaderImpl::CActiveBase::CompleteClientRequest(TInt aReason)
       
   259 	{
       
   260 	if (iRequestStatus)
       
   261 		{
       
   262 		User::RequestComplete(iRequestStatus, aReason);
       
   263 		iRequestStatus = NULL;
       
   264 		}
       
   265 	}
       
   266 
       
   267 // CInitialiser
       
   268 CSsmCommandListResourceReaderImpl::CInitialiser* CSsmCommandListResourceReaderImpl::CInitialiser::NewL(RFs& aFs, const TDesC& aCommandListPath, CResourcePool& aResourcePool)
       
   269 	{
       
   270 	CInitialiser* self = new(ELeave) CInitialiser(aFs, aResourcePool);
       
   271 	CleanupStack::PushL(self);
       
   272 	self->ConstructL(aCommandListPath);
       
   273 	CleanupStack::Pop(self);
       
   274 	return self;
       
   275 	}
       
   276 
       
   277 CSsmCommandListResourceReaderImpl::CInitialiser::CInitialiser(RFs& aFs, CResourcePool& aResourcePool)
       
   278 	:CActiveBase(EPriorityStandard),  iFs(aFs), iResourcePool(aResourcePool)
       
   279 	{
       
   280 	CActiveScheduler::Add(this);
       
   281 	}
       
   282 
       
   283 CSsmCommandListResourceReaderImpl::CInitialiser::~CInitialiser()
       
   284 	{
       
   285 	Cancel();
       
   286 	ResetToUninitialisedState();
       
   287 	iPath.Close();
       
   288 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   289 	iSystemDrivePath.Close();
       
   290 #endif
       
   291 	}
       
   292 
       
   293 void CSsmCommandListResourceReaderImpl::CInitialiser::ResetToUninitialisedState()
       
   294 	{
       
   295 	delete iResourceFileEntries;
       
   296 	iResourceFileEntries = NULL;
       
   297 	iEntryIndex = 0;
       
   298 	iResourcePool.Reset();
       
   299 	iAction = EIdle;
       
   300 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   301 	delete iRssFileEntriesInSysDrive;
       
   302 	iRssFileEntriesInSysDrive = NULL;
       
   303 #endif
       
   304 	}
       
   305 
       
   306 void CSsmCommandListResourceReaderImpl::CInitialiser::ConstructL(const TDesC& aCommandListPath)
       
   307 	{
       
   308 	if (aCommandListPath.Length() == 0)
       
   309 		{
       
   310 		SSMLOGLEAVE(KErrArgument);
       
   311 		}
       
   312 	iPath.CreateL(aCommandListPath);
       
   313 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   314 	// get the system drive char and create system drive path 
       
   315 	TChar systemDriveChar = iFs.GetSystemDriveChar();
       
   316 	//append the system drive
       
   317 	iSystemDrivePath.CreateL(iPath.MaxLength());
       
   318 	iSystemDrivePath.Append(systemDriveChar);
       
   319 	//append the system drive path which is same as ROM drive path minus ROM drive char 
       
   320 	iSystemDrivePath.Append(iPath.Right(iPath.Length()-1));
       
   321 #endif
       
   322 	}
       
   323 
       
   324 void CSsmCommandListResourceReaderImpl::CInitialiser::Start(TRequestStatus& aStatus)
       
   325 	{
       
   326 	__ASSERT_ALWAYS(iRequestStatus == NULL, PanicNow(KPanicCmdResourceReader, EInUse1));
       
   327 	aStatus = KRequestPending;
       
   328 	iRequestStatus = &aStatus;
       
   329 
       
   330 	iAction = EInitialiseFirstStep;
       
   331 	CActiveBase::Start();
       
   332 	}
       
   333 
       
   334 /**
       
   335 @panic ENonNullResourceFileEntries if the Resource File Entries is Not Null
       
   336 @panic ENullResourceFileEntries if the Resource File Entries is Null
       
   337 @panic EInvalidRunLAction if the RunL Action is invalid
       
   338 */
       
   339 void CSsmCommandListResourceReaderImpl::CInitialiser::RunL()
       
   340 	{
       
   341 	SSMLOGLEAVEIFERROR(iStatus.Int());
       
   342 
       
   343 	switch (iAction)
       
   344 		{
       
   345 	case EInitialiseFirstStep:
       
   346 		DoInitialiseFirstStepL();
       
   347 		break;
       
   348 	case EInitialiseNextStep:
       
   349 		DoInitialiseNextStepL();
       
   350 		break;
       
   351 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   352 	case EInitialiseSysDriveStep:
       
   353 		DoInitialiseSysDriveStepL();
       
   354 		break;		
       
   355 #endif
       
   356 	default:
       
   357 		PanicNow(KPanicCmdResourceReader, EInvalidRunLAction);
       
   358 		break;
       
   359 		}
       
   360 
       
   361 	if (iAction == EIdle)
       
   362 		{
       
   363 		CompleteClientRequest(KErrNone); // must not leave between here and end of RunL
       
   364 		return;
       
   365 		}
       
   366 
       
   367 	CActiveBase::Start(); // run again
       
   368 	}
       
   369 
       
   370 void CSsmCommandListResourceReaderImpl::CInitialiser::DoCancel()
       
   371 	{
       
   372 	// iStatus is always completed before this object is set active, so no need to complete iStatus with KErrCancel
       
   373 	CompleteClientRequest(KErrCancel);
       
   374 	ResetToUninitialisedState();
       
   375 	}
       
   376 
       
   377 TInt CSsmCommandListResourceReaderImpl::CInitialiser::RunError(TInt aError)
       
   378 	{
       
   379 	DEBUGPRINT2(_L("Resource reader initialiser reason (%d)"), aError);
       
   380 	CompleteClientRequest(aError);
       
   381 	ResetToUninitialisedState();
       
   382 	return KErrNone;
       
   383 	}
       
   384 
       
   385 void CSsmCommandListResourceReaderImpl::CInitialiser::DoInitialiseFirstStepL()
       
   386 	{
       
   387 	if (!iResourcePool.IsEmpty())
       
   388 		{
       
   389 		// already initialised, don't count this as an error
       
   390 		iAction = EIdle;
       
   391 		return;
       
   392 		}
       
   393 
       
   394 	// get list of command list resource filenames
       
   395 	TFileName path(iPath);
       
   396 	_LIT(KStar, "*");
       
   397 	path.Append(KStar);
       
   398 	const TUid KUidResourceFile = {0x101f4a6b};
       
   399 	__ASSERT_ALWAYS(iResourceFileEntries == NULL, PanicNow(KPanicCmdResourceReader, ENonNullResourceFileEntries));
       
   400 	// The error cannot be KErrPathNotFound as fallback will be used if there is not startup path
       
   401 	// Even if there are no resource files, this succeeds
       
   402 	// User::LeaveIfError handles other error conditions
       
   403 	User::LeaveIfError(iFs.GetDir(path, TUidType(KUidResourceFile, TUid::Uid(KUidSsmCommandListResourceFile)), ESortNone, iResourceFileEntries));
       
   404 	iEntryIndex = iResourceFileEntries->Count();
       
   405 
       
   406 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   407 	DEBUGPRINT2(_L("Number of resource files in ROM Drive : %d"),iEntryIndex );
       
   408 	// Now, get list of command list resource filenames from system drive too
       
   409 	TFileName sysPath(iSystemDrivePath);
       
   410 	sysPath.Append(KStar);
       
   411 	TInt err = (iFs.GetDir(sysPath, TUidType(KUidResourceFile, TUid::Uid(KUidSsmCommandListResourceFile)), ESortNone, iRssFileEntriesInSysDrive));
       
   412 	if (KErrNone == err)
       
   413 		{
       
   414 		iSysDriveEntryIndex = iRssFileEntriesInSysDrive->Count();
       
   415 		DEBUGPRINT2(_L("Number of resource files in System Drive : %d"),iSysDriveEntryIndex );
       
   416 		}
       
   417 	// all other error conditions are ignored as there is no compulsion for resource files to be present on system drive
       
   418 	else if(KErrPathNotFound == err)
       
   419 		{
       
   420 		//the path for SCLs on system drive does not exist
       
   421 		DEBUGPRINT1(_L("System Drive does not contain command lists"));
       
   422 		}
       
   423 	if(iEntryIndex == 0 && iSysDriveEntryIndex == 0)
       
   424 		{
       
   425 		DEBUGPRINT3(_L("Command list resource file directories (%S) and (%S) do not contain any command list resource files"), &path, &sysPath);
       
   426 		SSMLOGLEAVE(KErrNotFound);
       
   427 		}
       
   428 #else
       
   429 	if (iEntryIndex == 0)
       
   430 		{
       
   431 		DEBUGPRINT2(_L("Command list resource file directory (%S) does not contain any command list resource files"), &path);
       
   432 		SSMLOGLEAVE(KErrNotFound);
       
   433 		}
       
   434 #endif
       
   435 	iAction = EInitialiseNextStep;
       
   436 	}
       
   437 
       
   438 void CSsmCommandListResourceReaderImpl::CInitialiser::DoInitialiseNextStepL()
       
   439 	{
       
   440 	__ASSERT_ALWAYS(iResourceFileEntries != NULL, PanicNow(KPanicCmdResourceReader, ENullResourceFileEntries));
       
   441 	if (iEntryIndex--)
       
   442 		{
       
   443 		TFileName filename(iPath);
       
   444 		filename.Append((*iResourceFileEntries)[iEntryIndex].iName);
       
   445 		CResourceFile* const resourceFile = OpenResourceFileL(filename);
       
   446 		ParseFileL(resourceFile);
       
   447 		}
       
   448 
       
   449 	else
       
   450 		{
       
   451 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   452 		iAction = EInitialiseSysDriveStep;
       
   453 #else
       
   454 		// initialisation complete
       
   455 		iAction = EIdle;
       
   456 #endif
       
   457 		delete iResourceFileEntries;
       
   458 		iResourceFileEntries = NULL;
       
   459 		}
       
   460 	}
       
   461 
       
   462 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   463 void CSsmCommandListResourceReaderImpl::CInitialiser::DoInitialiseSysDriveStepL()
       
   464 	{
       
   465 	if (iSysDriveEntryIndex--)
       
   466 		{
       
   467 		TFileName filename(iSystemDrivePath);
       
   468 		filename.Append((*iRssFileEntriesInSysDrive)[iSysDriveEntryIndex].iName);
       
   469 		CResourceFile* const resourceFile = OpenResourceFileL(filename);
       
   470 		ParseFileL(resourceFile);
       
   471 		}
       
   472 	else
       
   473 		{
       
   474 		// initialisation complete
       
   475 		iAction = EIdle;
       
   476 		delete iRssFileEntriesInSysDrive;
       
   477 		iRssFileEntriesInSysDrive = NULL;
       
   478 		}
       
   479 	}
       
   480 #endif
       
   481 CResourceFile* CSsmCommandListResourceReaderImpl::CInitialiser::OpenResourceFileL(const TDesC& aFileName)
       
   482 	{
       
   483 
       
   484 	// open the resource file
       
   485 	RFile file;
       
   486 	CleanupClosePushL(file);
       
   487 	User::LeaveIfError(file.Open(iFs, aFileName, EFileRead | EFileShareReadersOnly));
       
   488 
       
   489 	// read entire resource file into a buffer
       
   490 	TInt fileSize;
       
   491 	User::LeaveIfError(file.Size(fileSize));
       
   492 	RBuf8 buf;
       
   493 	buf.CreateL(fileSize);
       
   494 	CleanupClosePushL(buf);
       
   495 	User::LeaveIfError(file.Read(buf));
       
   496 
       
   497 	// create a CResourceFile from the buffer and add it to array (the CResourceFile takes its own copy of the buffer)
       
   498 	CResourceFile* const resourceFile = CResourceFile::NewL(buf);
       
   499 	CleanupStack::PushL(resourceFile);
       
   500 	iResourcePool.AppendL(resourceFile);
       
   501 	CleanupStack::Pop(resourceFile);
       
   502 	iResourcePool.AppendL(aFileName);
       
   503 	CleanupStack::PopAndDestroy(&buf);
       
   504 	CleanupStack::PopAndDestroy(&file);
       
   505 	return resourceFile;
       
   506 	}
       
   507 
       
   508 void CSsmCommandListResourceReaderImpl::CInitialiser::ParseFileL(CResourceFile* aResourceFile)
       
   509 	{
       
   510 	// read root resource
       
   511 	RResourceReader rootReader;
       
   512 	const TInt KRootResourceId = 1;
       
   513 	rootReader.OpenLC(aResourceFile, KRootResourceId);
       
   514 	const TSsmResourceVersion version = static_cast<TSsmResourceVersion>(rootReader.ReadInt16L());
       
   515 	if (version != ESsmInitialVersion)
       
   516 		{
       
   517 		SSMLOGLEAVE(KErrNotSupported);
       
   518 		}
       
   519 	const TInt reserved1 = rootReader.ReadInt16L(); // skip SSM_COMMAND_LIST_ROOT.reserved1
       
   520 	const TInt commandListMappingResourceId = rootReader.ReadInt32L();
       
   521 	if (commandListMappingResourceId <= 0)
       
   522 		{
       
   523 		DEBUGPRINT1(_L("Command list resource file contains no mappings"));
       
   524 		SSMLOGLEAVE(KErrNotFound);
       
   525 		}
       
   526 	CleanupStack::PopAndDestroy(&rootReader);
       
   527 
       
   528 	// read mapping resource
       
   529 	RResourceReader mappingReader;
       
   530 	mappingReader.OpenLC(aResourceFile, commandListMappingResourceId);
       
   531 	const TInt mappingCount = mappingReader.ReadInt16L();
       
   532 	if (!mappingCount)
       
   533 		{
       
   534 		DEBUGPRINT1(_L("Command list resource file contains no mappings"));
       
   535 		SSMLOGLEAVE(KErrNotFound);
       
   536 		}
       
   537 	for (TInt i = 0; i < mappingCount; i++)
       
   538 		{
       
   539 		// add each mapping to the pool
       
   540 		TUint commandListId = mappingReader.ReadUint32L();
       
   541 		TInt resourceId = mappingReader.ReadInt32L();
       
   542 		TMapping mapping(commandListId, resourceId, aResourceFile);
       
   543 		iResourcePool.AppendL(mapping);
       
   544 		}
       
   545 	CleanupStack::PopAndDestroy(&mappingReader);
       
   546 	}
       
   547 
       
   548 // CPreparer
       
   549 CSsmCommandListResourceReaderImpl::CPreparer::CPreparer(const CResourcePool& aResourcePool, MSsmConditionalCallback& aConditionalCallback)
       
   550 	:CActiveBase(EPriorityStandard), iResourcePool(aResourcePool), iConditionalCallback(aConditionalCallback), iSwpChange(0, 0), iMapping(0, 0, NULL)
       
   551 	{
       
   552 	CActiveScheduler::Add(this);
       
   553 	}
       
   554 
       
   555 CSsmCommandListResourceReaderImpl::CPreparer::~CPreparer()
       
   556 	{
       
   557 	Cancel();
       
   558 	ResetReadyForNextPrepare();
       
   559 	}
       
   560 
       
   561 void CSsmCommandListResourceReaderImpl::CPreparer::Start(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmState& aState, TRequestStatus& aStatus)
       
   562 	{
       
   563 	__ASSERT_ALWAYS(iRequestStatus == NULL, PanicNow(KPanicCmdResourceReader, EInUse2));
       
   564 	__ASSERT_ALWAYS(!iResourcePool.IsEmpty(), PanicNow(KPanicCmdResourceReader, ENotInitialized));
       
   565 	aStatus = KRequestPending;
       
   566 	iRequestStatus = &aStatus;
       
   567 
       
   568 	iCommandList = &aCommandList;
       
   569 	iCommandListId = aCommandListId;
       
   570 	iState = aState;
       
   571 	iCommandListReady = EFalse;
       
   572 
       
   573 	iAction = EPrepareFirstStep;
       
   574 	CActiveBase::Start();
       
   575 	}
       
   576 
       
   577 void CSsmCommandListResourceReaderImpl::CPreparer::Start(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmSwp& aSwp, TRequestStatus& aStatus)
       
   578 	{
       
   579 	__ASSERT_ALWAYS(iRequestStatus == NULL, PanicNow(KPanicCmdResourceReader, EInUse3));
       
   580 	__ASSERT_ALWAYS(!iResourcePool.IsEmpty(), PanicNow(KPanicCmdResourceReader, ENotInitialized2));
       
   581 	aStatus = KRequestPending;
       
   582 	iRequestStatus = &aStatus;
       
   583 
       
   584 	iCommandList = &aCommandList;
       
   585 	iCommandListId = aCommandListId;
       
   586 	iSwpChange = aSwp;
       
   587 	iCommandListReady = EFalse;
       
   588 
       
   589 	iAction = EPrepareFirstStep;
       
   590 	CActiveBase::Start();
       
   591 	}
       
   592 
       
   593 /**
       
   594 @panic EInvalidRunLAction if the RunL Action is invalid
       
   595 */
       
   596 void CSsmCommandListResourceReaderImpl::CPreparer::RunL()
       
   597 	{
       
   598 	SSMLOGLEAVEIFERROR(iStatus.Int());
       
   599 
       
   600 	switch (iAction)
       
   601 		{
       
   602 	case EPrepareFirstStep:
       
   603 		DoPrepareFirstStepL();
       
   604 		break;
       
   605 	case EPrepareNextStep:
       
   606 		DoPrepareNextStepL();
       
   607 		break;
       
   608 	default:
       
   609 		PanicNow(KPanicCmdResourceReader, EInvalidRunLAction);
       
   610 		break;
       
   611 		}
       
   612 
       
   613 	if (iAction == EIdle)
       
   614 		{
       
   615 		CompleteClientRequest(KErrNone); // must not leave between here and end of RunL
       
   616 		return;
       
   617 		}
       
   618 
       
   619 	CActiveBase::Start(); // run again
       
   620 	}
       
   621 
       
   622 void CSsmCommandListResourceReaderImpl::CPreparer::DoCancel()
       
   623 	{
       
   624 	// iStatus is always completed before this object is set active, so no need to complete iStatus with KErrCancel
       
   625 	CompleteClientRequest(KErrCancel);
       
   626 	ResetReadyForNextPrepare();
       
   627 	}
       
   628 
       
   629 TInt CSsmCommandListResourceReaderImpl::CPreparer::RunError(TInt aError)
       
   630 	{
       
   631 	DEBUGPRINT2(_L("Resource reader preparer reason (%d)"), aError);
       
   632 	CompleteClientRequest(aError);
       
   633 	ResetReadyForNextPrepare();
       
   634 	return KErrNone;
       
   635 	}
       
   636 
       
   637 TBool CSsmCommandListResourceReaderImpl::CPreparer::IsCommandListReady()
       
   638 	{
       
   639 	// enables caller to find out if the command list they passed
       
   640 	// to PrepareCommandList is fully prepared or not
       
   641 	if (iCommandListReady)
       
   642 		{
       
   643 		iCommandListReady = EFalse;
       
   644 		return ETrue;
       
   645 		}
       
   646 	return EFalse;
       
   647 	}
       
   648 
       
   649 void CSsmCommandListResourceReaderImpl::CPreparer::ResetReadyForNextPrepare()
       
   650 	{
       
   651 	iListReader.Close();
       
   652 	iCommandIndex = 0;
       
   653 	iCommandListReady = EFalse;
       
   654 	iAction = EIdle;
       
   655 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   656 	iCommandIndexInRssFile.Reset();
       
   657 	iMappingArray.Reset();
       
   658 #endif
       
   659 	}
       
   660 
       
   661 
       
   662 void CSsmCommandListResourceReaderImpl::CPreparer::DoPrepareFirstStepL()
       
   663 	{
       
   664 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   665 	iCurrentCommandListInMapping = 0;
       
   666 	iResourcePool.UpdateMappingArrayL(iCommandListId,iMappingArray);
       
   667 	TInt substateCount = iMappingArray.Count();
       
   668 	iCommandIndexInRssFile.ReserveL(substateCount);
       
   669 	
       
   670 	// get number of commands from all the lists
       
   671 	for(TInt substateIndex = 0; substateIndex < substateCount; ++substateIndex )
       
   672 		{
       
   673 		iListReader.OpenL(iMappingArray[substateIndex].iResourceFile, iMappingArray[substateIndex].iResourceId);
       
   674 		//advancing the pointer to point to number of commands in list
       
   675 		iListReader.AdvanceL(sizeof(TInt32));
       
   676 		iCommandIndexInRssFile.AppendL(iListReader.ReadUint16L());
       
   677 		iCommandIndex +=  iCommandIndexInRssFile[substateIndex]; 
       
   678 		iListReader.Close();
       
   679 		}
       
   680 	//open the first resource id and read the commands.
       
   681 	iListReader.OpenL(iMappingArray[iCurrentCommandListInMapping].iResourceFile, iMappingArray[iCurrentCommandListInMapping].iResourceId);
       
   682 	// the delay between the commands is read from only the frist command list. In case of other lists, it is ignored.
       
   683 	iCommandList->SetDelayBetweenCommands(iListReader.ReadInt32L());
       
   684 	iCommandList->SetResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMappingArray[iCurrentCommandListInMapping].iResourceFile));
       
   685 	//skip reading command count again and jump to command resourceId
       
   686 	iListReader.AdvanceL(sizeof(TUint16));
       
   687 #else
       
   688 	iMapping = iResourcePool.MappingL(iCommandListId);
       
   689 	iListReader.OpenL(iMapping.iResourceFile, iMapping.iResourceId);
       
   690 	iCommandList->SetDelayBetweenCommands(iListReader.ReadInt32L());
       
   691 	iCommandIndex = iListReader.ReadUint16L(); // command count
       
   692 
       
   693 	// Set up the resource file name for this list
       
   694 	iCommandList->SetResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMapping.iResourceFile));
       
   695 #endif
       
   696 	
       
   697 	// Set up the conditional callback
       
   698 	iCommandList->SetConditionalCallback(iConditionalCallback);
       
   699 	
       
   700 	iAction = EPrepareNextStep;
       
   701 	}
       
   702 
       
   703 void CSsmCommandListResourceReaderImpl::CPreparer::DoPrepareNextStepL()
       
   704 	{
       
   705 	const TInt KBatchSize = 5; // Max number of commands prepared per RunL, this may need to be adjusted if responsiveness is a problem
       
   706 	iBatchIndex = KBatchSize;
       
   707 			
       
   708 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   709 	TBool inProgress = ETrue;
       
   710 	while (inProgress && iBatchIndex --)
       
   711 		{
       
   712 		if (iCommandIndexInRssFile[iCurrentCommandListInMapping] == 0 )
       
   713 			{
       
   714 			//the current command list is parsed and all commands added
       
   715 			// go to the next commnad list
       
   716 			++iCurrentCommandListInMapping;
       
   717 			
       
   718 			if ( (iCurrentCommandListInMapping+1) > iCommandIndexInRssFile.Count() )
       
   719 				{
       
   720 				// all command lists are processed. Set the inProgress flag to "EFalse" 
       
   721 				inProgress = EFalse;
       
   722 				break;
       
   723 				}
       
   724 			else
       
   725 				{
       
   726 				//open the next resource id and read the commands
       
   727 				iListReader.Close();
       
   728 				iListReader.OpenL(iMappingArray[iCurrentCommandListInMapping].iResourceFile, iMappingArray[iCurrentCommandListInMapping].iResourceId);
       
   729 				// skipping delay between commands as it is already set from first rss file
       
   730 				iListReader.AdvanceL(sizeof(TInt32));
       
   731 				iCommandList->SetResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMappingArray[iCurrentCommandListInMapping].iResourceFile));
       
   732 				//skip reading command count again and jump to command resourceId
       
   733 				iListReader.AdvanceL(sizeof(TUint16));
       
   734 				}
       
   735 			}
       
   736 		DEBUGPRINT2A("The value of RssFile's current command is %d ", iCommandIndexInRssFile[iCurrentCommandListInMapping]);
       
   737 #else
       
   738 	while(iCommandIndex && iBatchIndex--)
       
   739 		{
       
   740 		--iCommandIndex; // Note: can't decrement in while expression above, incase iBatchIndex is zero
       
   741 #endif
       
   742 		// open command resource
       
   743 		const TInt commandResourceId = iListReader.ReadInt32L();
       
   744 		DEBUGPRINT2A("Reading command resource id %x", commandResourceId);
       
   745 		RResourceReader commandReader;
       
   746 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   747 		commandReader.OpenLC(iMappingArray[iCurrentCommandListInMapping].iResourceFile, commandResourceId);
       
   748 #else
       
   749 		commandReader.OpenLC(iMapping.iResourceFile, commandResourceId);
       
   750 #endif
       
   751 		// read conditional imformation
       
   752 		const TInt conditionalInfoResourceId = commandReader.ReadInt32L();
       
   753 
       
   754 		// read command type
       
   755 		const TSsmCommandType type = static_cast<TSsmCommandType>(commandReader.ReadInt16L());
       
   756 		commandReader.RewindL(sizeof(TInt16)); // commands expect reader to be pointing to the command type
       
   757 		
       
   758 		// construct command and add to command list
       
   759 		TRAPD(err, AddCommandToListL(type, commandReader, conditionalInfoResourceId));
       
   760 		if(KErrNone != err)
       
   761 			{
       
   762 			DEBUGPRINT2A("Failed to add command of type: %d", type);
       
   763 			}
       
   764 		SSMLOGLEAVEIFERROR(err);
       
   765 		CleanupStack::PopAndDestroy(&commandReader);
       
   766 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE	
       
   767 		--(iCommandIndexInRssFile[iCurrentCommandListInMapping]);
       
   768 		--iCommandIndex;
       
   769 #endif
       
   770 		}
       
   771 	
       
   772 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   773 	if (inProgress == EFalse || iCommandIndex == 0) // list preparation complete
       
   774 #else
       
   775 	if (iCommandIndex == 0) // list preparation complete
       
   776 #endif
       
   777 		{
       
   778 		ResetReadyForNextPrepare();
       
   779 		iCommandListReady = ETrue;
       
   780 		}
       
   781 	}
       
   782 
       
   783 void CSsmCommandListResourceReaderImpl::CPreparer::AddCommandToListL(TSsmCommandType aType, RResourceReader& aCommandReader, TInt aConditionalInfoResourceId)
       
   784 	{
       
   785 	// construct command from resource and add to list
       
   786 	CSsmCommandBase* cmd = NULL;
       
   787 
       
   788 	switch (aType)
       
   789 		{
       
   790 	case ESsmCmdPublishSwp:
       
   791 			{
       
   792 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   793 			TSsmCommandParameters params(aCommandReader, iMappingArray[iCurrentCommandListInMapping].iResourceFile, aConditionalInfoResourceId, iSwpChange);
       
   794 #else
       
   795 			TSsmCommandParameters params(aCommandReader, iMapping.iResourceFile, aConditionalInfoResourceId, iSwpChange);
       
   796 #endif
       
   797 			cmd = SsmCommandFactory::ConstructCommandFromResourceLC(aType, params);
       
   798 			break;
       
   799 			}
       
   800 	case ESsmCmdPublishSystemState:
       
   801 			{
       
   802 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   803 			TSsmCommandParameters params(aCommandReader, iMappingArray[iCurrentCommandListInMapping].iResourceFile, aConditionalInfoResourceId, iState);
       
   804 #else
       
   805 			TSsmCommandParameters params(aCommandReader, iMapping.iResourceFile, aConditionalInfoResourceId, iState);
       
   806 #endif
       
   807 			cmd = SsmCommandFactory::ConstructCommandFromResourceLC(aType, params);
       
   808 			break;
       
   809 			}
       
   810 	default:
       
   811 			{
       
   812 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   813 			TSsmCommandParameters params(aCommandReader, iMappingArray[iCurrentCommandListInMapping].iResourceFile, aConditionalInfoResourceId);
       
   814 #else
       
   815 			TSsmCommandParameters params(aCommandReader, iMapping.iResourceFile, aConditionalInfoResourceId);
       
   816 #endif
       
   817 			cmd = SsmCommandFactory::ConstructCommandFromResourceLC(aType, params);
       
   818 			break;
       
   819 			}
       
   820 		}
       
   821 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   822 	// Load the resource file if there is conditional information
       
   823 	if( cmd && cmd->ConditionalInformation() != 0 )
       
   824 		{
       
   825 		//Only if there is conditional information, we will set the command's resource filename
       
   826 		cmd->SetCommandResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMappingArray[iCurrentCommandListInMapping].iResourceFile));
       
   827 		}
       
   828 #endif
       
   829 	//In the case of flexible merge the commands are appended in the commandlist based on priority. 
       
   830 	iCommandList->AppendL(cmd);
       
   831 	CleanupStack::Pop(cmd);
       
   832 	}
       
   833 
       
   834