--- /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(); ;
+ }