sysstatemgmt/systemstatemgr/cmd/src/ssmcommandlistimpl.cpp
changeset 0 4e1aa6a622a0
child 3 a811597961f0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstatemgr/cmd/src/ssmcommandlistimpl.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,488 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <s32strm.h>
+#include <ssm/ssmstatemanager.h>
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+#include <e32cmn.h>
+#endif
+#include <ssm/ssmcommand.h>
+#include <ssm/ssmcommandfactory.h>
+#include "ssmcommandlistimpl.h"
+#include "ssmdebug.h"
+#include "ssmpanic.h"
+#include "ssmcommandbase.h"
+#include "ssmcommandparameters.h"
+#include "ssmdeferreddeleter.h"
+
+#define __IN_RANGE( x, y ) ( (x >= 0) && (x < y) )
+
+
+//
+// Construct a CSsmCommandListImplImpl object
+//
+CSsmCommandListImpl* CSsmCommandListImpl::NewL()
+	{
+	CSsmCommandListImpl* self = new(ELeave) CSsmCommandListImpl;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Used to create an instance of CSsmCommandListImpl class from CSsmCommandListImpl object
+Must be used only by CLE
+@param aSsmCommandListImpl CSsmCommandListImpl reference
+@param aUtilProvider CSsmCommandUtilProvider pointer
+@return A pointer to an object of type CSsmCommandListImpl.
+*/
+CSsmCommandListImpl* CSsmCommandListImpl::NewL(const CSsmCommandListImpl* aSsmCommandListImpl, CSsmCommandUtilProvider* aUtilProvider)
+    {
+    CSsmCommandListImpl* self = new(ELeave) CSsmCommandListImpl;
+    CleanupStack::PushL(self);
+    self->ConstructL(aSsmCommandListImpl, aUtilProvider);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CSsmCommandListImpl::CSsmCommandListImpl()
+	{
+	}
+
+void CSsmCommandListImpl::ConstructL()
+	{
+//iDeferredDeleter is initialized inside the ConstuctL... when CLE constructs the commandlist
+//where as for unit testing we need to construct the iDeferredDeleter here for testing purposes
+#ifdef SSM_CMD_TESTFRAMEWORK
+	iDeferredDeleter = CSsmDeferredDeleter::NewL();
+#endif
+	iResourceFileName.CreateL(0);
+	}
+/**
+Used to reconstruct the commandlist from the commandlist recieved from SSM server.
+It should be used only by CLE.
+@param CSsmCommandListImpl aSsmCommandListImpl pointer 
+@param CSsmCommandUtilProvider aUtilProvider pointer
+ */
+void CSsmCommandListImpl::ConstructL(const CSsmCommandListImpl* aSsmCommandListImpl, CSsmCommandUtilProvider* aUtilProvider)
+    {
+    SetDelayBetweenCommands(aSsmCommandListImpl->DelayBetweenCommands());
+
+    // It is ok for this pointer to be passed between threads as the policy
+    // will remain loaded until CLE returns
+    SetConditionalCallback(aSsmCommandListImpl->ConditionalCallback());
+    
+    iDeferredDeleter = CSsmDeferredDeleter::NewL();
+    
+#ifndef SYMBIAN_SSM_FLEXIBLE_MERGE
+    // Write out the resource filename
+    iResourceFileName.ReAllocL(aSsmCommandListImpl->iResourceFileName.Size());
+#endif
+
+    const TInt count = aSsmCommandListImpl->iCmdList.Count();
+    TArray<MSsmCommand*> deferredList = PendingDeferred();
+    for (TInt i = 0; i < count; i++)
+        {
+        CSsmCommandBase* cmd = SsmCommandFactory::ConstructCommandFromCommandLC(*aSsmCommandListImpl->iCmdList[i], deferredList,aUtilProvider);
+        
+        const TSsmCommandType cmdType = cmd->Type();
+        
+        if (ESsmCmdMultipleWait == cmdType)
+            {
+            iDeferredList.Reset();
+            }
+        else if (ESsmDeferredWaitForSignal == cmd->ExecutionBehaviour()) 
+            {
+            iDeferredList.AppendL(cmd);
+            }
+        iCmdList.AppendL(cmd);
+        CleanupStack::Pop(cmd);
+        }
+    }
+
+//
+// Destructor
+//
+CSsmCommandListImpl::~CSsmCommandListImpl()
+	{
+	const TInt count = iCmdList.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		if (iCmdList[i])
+			iCmdList[i]->Release();
+		}
+
+	iCmdList.Close();
+	iDeferredList.Close();
+	
+	delete iDeferredDeleter;
+	delete iResourceFile;
+	iResourceFileName.Close();
+	}
+
+
+//
+// Read a set of commands into the list from a stream
+//
+void CSsmCommandListImpl::InternalizeL( RReadStream& aReadStream , CSsmCommandUtilProvider* aUtilProvider )
+	{
+	if( (0 != iCmdList.Count()) ||  (0 != iDeferredList.Count()) )
+		{
+		SSMLOGLEAVE( KErrAlreadyExists );
+		}
+
+	iDelayBetweenCommands = aReadStream.ReadInt32L();
+	// It is ok for this pointer to be passed between threads as the policy
+	// will remain loaded until CLE returns
+	iConditionalCallback = reinterpret_cast<MSsmConditionalCallback*>(aReadStream.ReadInt32L());
+	
+	// Read in the resource filename
+	iResourceFileName.ReAllocL(aReadStream.ReadInt32L());
+	aReadStream.ReadL(iResourceFileName);
+	
+	TUint32 count = aReadStream.ReadUint32L();
+	while (count--)
+		{
+		TInt conditionalInformation = aReadStream.ReadInt32L();
+		const TSsmCommandType type = static_cast<TSsmCommandType>(aReadStream.ReadUint16L());
+		TArray<MSsmCommand*> deferredList = PendingDeferred();
+		CSsmCommandBase* cmd = SsmCommandFactory::ConstructCommandFromStreamLC(type, aReadStream, deferredList);
+		
+		// The ssmswppolicyserver and ssmswppolicycli code internalizes and externalizes 
+		// the commandlist in order to pass the it from server to the client. 
+		// This commandlist is not executed by ssmswppolicycli, it just passes it to the cle where the commandlist is executed 
+		// and hence it does not require the utilprovider to be passed in to this method.
+		if (aUtilProvider)
+			{
+			cmd->SetUtilProvider(*aUtilProvider);
+			}
+		else
+			{
+			DEBUGPRINT1(_L("CSsmCommandListImpl::InternalizeL used by  ssmswppolicycli code so Utilprovider is not required"));
+			}
+
+		cmd->SetConditionalInformation(conditionalInformation);
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+		if( cmd->ConditionalInformation() != 0 )
+			{
+			HBufC* tempFileName = HBufC::NewLC(aReadStream, KMaxFileName);
+			cmd->SetCommandResourceFileNameL(*tempFileName);
+			CleanupStack::PopAndDestroy(tempFileName);
+			}
+#endif
+		AppendL(cmd);
+		CleanupStack::Pop(cmd);
+		}
+	
+	}
+
+
+//
+// Write a set of commands from the list to a stream
+//
+void CSsmCommandListImpl::ExternalizeL( RWriteStream& aWriteStream ) const
+	{
+	aWriteStream.WriteInt32L(iDelayBetweenCommands);
+	// It is ok for this pointer to be passed between threads as the policy
+	// will remain loaded until CLE returns
+	aWriteStream.WriteInt32L(reinterpret_cast<TInt>(iConditionalCallback));
+	
+	// Write out the resource filename
+	aWriteStream.WriteInt32L(iResourceFileName.Length());
+	aWriteStream.WriteL(iResourceFileName);
+	
+	const TInt count = iCmdList.Count();
+	aWriteStream.WriteUint32L(count);
+
+	for (TInt i = 0; i < count; i++)
+		{
+		const MSsmCommand* const cmd = iCmdList[i];
+		// Write out the conditional information
+		aWriteStream.WriteInt32L(cmd->ConditionalInformation());
+		// Write out the type
+		const TSsmCommandType type = cmd->Type();
+		aWriteStream.WriteInt16L(type);
+		// Write out the command specific information
+		cmd->ExternalizeL(aWriteStream);
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+		if (cmd->ConditionalInformation())
+			{
+			const CSsmCommandBase* cmdBase = static_cast<const CSsmCommandBase*>(cmd);
+			if (cmdBase)
+				{
+				aWriteStream << cmdBase->GetCommandResourceFileName();
+				}
+			}
+#endif
+		}
+	}
+
+
+//
+// Execute a specific command in the list
+//@panic ECmdListBadIdx if the index value is out of range
+//@panic ECmdNullPtr if the information used to create command is null
+void CSsmCommandListImpl::Execute( const TInt aIndex, TRequestStatus& aStatus )
+	{
+	DEBUGPRINT2A("CSsmCommandListImpl::Execute - List Count() = %d", Count());
+	
+	__ASSERT_DEBUG( __IN_RANGE(aIndex, iCmdList.Count()), PanicNow(KPanicCmdList, ECmdListBadIdx));
+	__ASSERT_DEBUG( iCmdList[ aIndex ], PanicNow(KPanicCmdList, ECmdNullPtr));
+	
+	MSsmCommand* cmd = iCmdList[ aIndex ];
+	if( cmd )
+		{
+		// Load the resource file if there is conditional information
+		if( cmd->ConditionalInformation() != 0 )
+			{
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+			CSsmCommandBase* cmdBase = static_cast<CSsmCommandBase*>(cmd);
+			if (cmdBase)
+				{
+				if (iResourceFileName != cmdBase->GetCommandResourceFileName())
+					{
+					TInt length = cmdBase->GetCommandResourceFileNameLength();
+					if (iResourceFileName.MaxLength() < length)
+						{
+						TRAPD(err, iResourceFileName.ReAllocL(length));
+						//iResourceFileName is set to KNullDesC if there is any error(like KErrNoMemory)
+						//InitialiseResourceFileL() leaves in this case and can be handled by evaluate condition
+						iResourceFileName = (err == KErrNone) ? cmdBase->GetCommandResourceFileName() : KNullDesC;
+						}
+					else
+						{
+						iResourceFileName = cmdBase->GetCommandResourceFileName();
+						}
+					if (iResourceFile)
+						{
+						delete iResourceFile;
+						iResourceFile = NULL;
+						}
+					}
+				}
+#endif
+			// TRAP_IGNORE is used here as if this method fails then
+			// iResourceFile will be null, but evaluate condition can handle
+			// iResourceFile being null.
+			TRAP_IGNORE(InitialiseResourceFileL());
+			}
+		if(iCmdList[ aIndex ]->EvaluateCondition(iConditionalCallback, iResourceFile))
+			{
+			// Condition is true so execute the command
+			iCmdList[ aIndex ]->Execute( aStatus );
+			}
+		else
+			{
+			// Condition is false so complete aStatus immediately
+			// The EvaluateCondition() method will have set the command
+			// correctly to allow completion of deferred wait for signal commands
+			TRequestStatus* trs = &aStatus;
+			aStatus = KRequestPending;
+			User::RequestComplete(trs, KErrNone);
+			}
+		}
+	
+	}
+
+
+//
+// Cancel a specific command in the list
+//@panic ECmdListBadIdx if the index value is out of range
+//@panic ECmdNullPtr if the information used to create command is null
+void CSsmCommandListImpl::ExecuteCancel( const TInt aIndex )
+	{
+	__ASSERT_DEBUG( __IN_RANGE(aIndex, iCmdList.Count()), PanicNow(KPanicCmdList, ECmdListBadIdx));
+	__ASSERT_DEBUG( iCmdList[ aIndex ], PanicNow(KPanicCmdList, ECmdNullPtr));
+	
+	if( iCmdList[aIndex] )
+		{
+		iCmdList[ aIndex ]->ExecuteCancel();
+		}
+	}
+
+//
+// Count of items in the list
+//
+TInt CSsmCommandListImpl::Count()const
+	{
+	return iCmdList.Count();
+	}
+
+const MSsmCommand* CSsmCommandListImpl::operator[](TInt aIndex) const
+	{
+	return iCmdList[aIndex];
+	}
+
+void CSsmCommandListImpl::AppendL(MSsmCommand* aCmd)
+	{
+	if (!aCmd)
+		{
+		SSMLOGLEAVE(KErrArgument);
+		}
+	
+	const TSsmCommandType cmdType = aCmd->Type();	
+	DEBUGPRINT2A("Adding command type: %d", cmdType);
+	
+    if (ESsmCmdPublishSystemState == cmdType) 
+        {
+        ++iPublishSysStateCmdCount;
+        }
+    else if (ESsmCmdPublishSwp == cmdType) 
+        {
+        ++iPublishSwpCmdCount;
+        }
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+	TLinearOrder<MSsmCommand> order(CSsmCommandListImpl::ComparePriority);
+	iCmdList.InsertInOrderAllowRepeatsL(aCmd,order);
+#else
+	iCmdList.AppendL(aCmd);
+#endif  // SYMBIAN_SSM_FLEXIBLE_MERGE	
+	}
+
+void CSsmCommandListImpl::GetDataToValidateCommandlist(TInt& aPublishSystemStateCount, TInt& aPublishSwpCount)  const
+	{
+	aPublishSystemStateCount = iPublishSysStateCmdCount;
+	aPublishSwpCount = iPublishSwpCmdCount;
+	}
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+TInt CSsmCommandListImpl::ComparePriority(const MSsmCommand& aFirst, const MSsmCommand& aSecond)
+	{
+	const CSsmCommandBase* const firstCommand = static_cast<const CSsmCommandBase*>(&aFirst);
+	const CSsmCommandBase* const secondCommand = static_cast<const CSsmCommandBase*>(&aSecond);
+	
+	return (secondCommand->Priority() - firstCommand->Priority());
+	}
+#endif
+
+TArray<MSsmCommand*> CSsmCommandListImpl::PendingDeferred() const
+	{
+	return iDeferredList.Array();
+	}
+
+void CSsmCommandListImpl::SetDelayBetweenCommands(TInt aDelayBetweenCommands)
+	{
+	iDelayBetweenCommands = aDelayBetweenCommands;
+	}
+
+TInt CSsmCommandListImpl::DelayBetweenCommands() const
+	{
+	return iDelayBetweenCommands;
+	}
+
+/**
+@panic ECmdNullPtr if the information used to create command is null	
+*/
+void CSsmCommandListImpl::DeferredDelete()
+	{
+	__ASSERT_DEBUG(iDeferredDeleter, PanicNow(KPanicCmdList, ECmdNullPtr));
+	TInt indexOfPendingCommand = PendingCommandIndex();
+
+	if ((KErrNotFound == indexOfPendingCommand) || !iDeferredDeleter)
+		{
+		delete this;
+		}
+	else
+		{
+		iDeferredDeleter->DeferredDelete(this);
+		iDeferredDeleter = NULL;
+		}
+	}
+
+TInt CSsmCommandListImpl::PendingCommandIndex()
+	{
+	TInt index = KErrNotFound;
+	const TInt count = iCmdList.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		MSsmCommand* cmd = iCmdList[i];
+		// command list can not be deleted if any deferred command is pending
+		if (cmd->IsDeferred() && (KRequestPending == cmd->CompletionStatus()))
+			{
+			index = i;
+			break;
+			}
+		}
+	return index;
+	}
+
+void CSsmCommandListImpl::InitialiseResourceFileL()
+	{
+	if(!iResourceFile)
+		{
+		// Need to load and allocate the resource file
+		RFs rfs;
+		User::LeaveIfError(rfs.Connect());
+		CleanupClosePushL(rfs);
+		RFile file;
+		User::LeaveIfError(file.Open(rfs, iResourceFileName, EFileRead | EFileShareReadersOnly));
+		CleanupClosePushL(file);
+		// read entire resource file into a buffer
+		TInt fileSize;
+		User::LeaveIfError(file.Size(fileSize));
+		RBuf8 buf;
+		buf.CreateL(fileSize);
+		CleanupClosePushL(buf);
+		User::LeaveIfError(file.Read(buf));
+		// Create the resource file
+		iResourceFile = CResourceFile::NewL(buf);
+		
+		// Clean up everything
+		CleanupStack::PopAndDestroy(&buf);
+		CleanupStack::PopAndDestroy(&file);
+		CleanupStack::PopAndDestroy(&rfs);
+		}
+	}
+
+void CSsmCommandListImpl::SetResourceFileNameL(const TDesC& aFileName)
+	{
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+	// this is not needed in other case as there is only one resource file per substate
+	TInt length = iResourceFileName.MaxLength();
+	if (length < aFileName.Length())
+		{
+		iResourceFileName.ReAllocL(aFileName.Length());		
+		}
+#else
+	iResourceFileName.ReAllocL(aFileName.Length());
+#endif
+	iResourceFileName.Copy(aFileName);
+	// Clear iResourceFile as it is no longer in sync with iResourceFileName
+	if(iResourceFile)
+		{
+		delete iResourceFile;
+		iResourceFile = NULL;
+		}
+	}
+
+void CSsmCommandListImpl::SetConditionalCallback(MSsmConditionalCallback& aCallBack)
+	{
+	iConditionalCallback = &aCallBack;
+	}
+
+MSsmConditionalCallback& CSsmCommandListImpl::ConditionalCallback() const
+    {
+    return *iConditionalCallback;
+    }
+
+/**
+  Returns command's severity.
+ */		
+TCmdErrorSeverity CSsmCommandListImpl::Severity(TInt aCommandIndex)const
+	{
+	return iCmdList[aCommandIndex]->Severity();	;
+	}