--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/server/src/ncdbaseoperation.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1191 @@
+/*
+* Copyright (c) 2006 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 <s32mem.h>
+
+#include "ncdbaseoperation.h"
+#include "catalogsbasemessage.h"
+#include "catalogsdebug.h"
+#include "ncdqueryimpl.h"
+#include "ncd_cp_queryresponseimpl.h"
+#include "ncd_cp_query.h"
+#include "catalogsutils.h"
+#include "ncdoperationobserver.h"
+#include "ncd_pp_information.h"
+#include "catalogssession.h"
+#include "ncdoperationremovehandler.h"
+#include "ncd_pp_error.h"
+#include "ncd_pp_expiredcacheddata.h"
+#include "ncdnodeidentifier.h"
+#include "ncdnodemanager.h"
+#include "catalogscontext.h"
+#include "ncddeviceinteractionfactory.h"
+#include "ncddeviceservice.h"
+#include "ncdquerytextitem.h"
+#include "ncdparser.h"
+#include "ncdprotocoldefaultobserver.h"
+#include "catalogsconstants.h"
+#include "ncdexpirednode.h"
+#include "ncdrequestbase.h"
+#include "ncdproviderutils.h"
+#include "ncderrors.h"
+#include "ncdgeneralmanager.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+CNcdBaseOperation::~CNcdBaseOperation()
+ {
+ DLTRACEIN((""));
+
+ if ( iRemoveHandler )
+ {
+ iRemoveHandler->RemoveOperation( *this );
+ }
+
+ iObservers.Close();
+ if ( iActiveQuery )
+ {
+ iActiveQuery->InternalRelease();
+ }
+ if ( iPendingMessage )
+ {
+ DLTRACE(("Message pending"));
+ // Operation destroyed unexpectedly when a message was still pending
+ iPendingMessage->CompleteAndRelease( KErrDied );
+ }
+
+ iEmbeddedDataQuerys.ResetAndDestroy();
+ for( TInt i = 0 ; i < iPendingQuerys.Count() ; i++ )
+ {
+ iPendingQuerys[i]->InternalRelease();
+ }
+ iPendingQuerys.Close();
+ delete iRunner;
+ iExpiredNodes.ResetAndDestroy();
+ for ( TInt i = 0 ; i < iCompletedQuerys.Count() ; i++ )
+ {
+ iCompletedQuerys[i]->InternalRelease();
+ }
+ iCompletedQuerys.Reset();
+ DLTRACEOUT((""));
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::Start()
+ {
+ DLTRACEIN((""));
+ if ( iOperationState == EStateStopped )
+ {
+ // Op not yet running, start it
+ iOperationState = EStateRunning;
+ TInt err = RunOperation();
+ DLTRACE(("Returned from RunOperation()"));
+ DLTRACEOUT((""));
+ return err;
+ }
+ else
+ {
+ // Op already started.
+ DLTRACEOUT((""));
+ return KErrInUse;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::AddObserverL(
+ MNcdOperationObserver* aObserver )
+ {
+ DLTRACEIN((""));
+ DASSERT( aObserver );
+ iObservers.AppendL( aObserver );
+ }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::RemoveObserver(
+ MNcdOperationObserver* aObserver )
+ {
+ DLTRACEIN((""));
+ TInt index = iObservers.Find( aObserver );
+ if ( index != KErrNotFound )
+ {
+ iObservers.Remove( index );
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TNcdOperationType CNcdBaseOperation::Type() const
+ {
+ DLTRACEIN((""));
+ return iOperationType;
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::HandleStartMessage(
+ MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN((""));
+ DASSERT( ! iPendingMessage );
+ if ( iOperationState == EStateStopped )
+ {
+ iPendingMessage = aMessage;
+ TInt err = Start();
+ DLTRACE(( "Start returned with: %d", err ));
+ }
+ else
+ {
+ DLTRACE(("Operation already started"));
+ // Operation already started.
+ TInt err = CompleteMessage( aMessage, ENCDOperationMessageCompletionError,
+ KErrInUse );
+ if ( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ DLTRACEOUT((""));
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::HandleCancelMessage(
+ MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN((""));
+ // release pending message if any
+ if ( iPendingMessage )
+ {
+ DLTRACE(("Completing pending message"));
+
+ // Completing the message so no memory is pending in the
+ // framework because of it.
+ iPendingMessage->CompleteAndRelease( KErrCancel );
+ iPendingMessage = NULL;
+ }
+
+ // iOperationState has to be set to EStateCancelled before
+ // cancelling purchase operation.
+ // See CNcdPurchaseOperationImpl::HandleSmsEvent()
+ iOperationState = EStateCancelled;
+ Cancel();
+
+ aMessage->CompleteAndRelease( KErrNone );
+
+ DLTRACEOUT((""));
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::HandleContinueMessage(
+ MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN(( "iOperationState: %d", iOperationState ));
+ DASSERT( ! iPendingMessage );
+ if ( iOperationState == EStateRunning )
+ {
+ DLTRACE(("iOperationState == EStateRunning"));
+ // Message is just stored here, it will be completed
+ // when progress has been made.
+ iPendingMessage = aMessage;
+ iOperationState = EStateRunning;
+
+ RunOperation();
+ DLTRACE(("Returned from RunOperation()"));
+ }
+ else if ( iOperationState == EStateQuery )
+ {
+ DLTRACE(("iOperationState == EStateQuery"));
+ // A query is pending and has not yet been sent to proxy
+ TInt err = CompleteMessage( aMessage, ENCDOperationMessageCompletionQuery,
+ *iActiveQuery,
+ KErrNone );
+ if( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ else if ( iOperationState == EStateSendExpirationInfo )
+ {
+ DLTRACE(("iOperationState == EStateSendExpirationInfo"));
+ iOperationState = EStateRunning;
+ iPendingMessage = aMessage;
+ TInt err = SendExpirationInfo( iExpiredNodes );
+ if( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ else
+ {
+ iExpiredNodes.ResetAndDestroy();
+ if ( iActiveQuery )
+ {
+ // there's a query pending, change state accordingly
+ iOperationState = EStateQuery;
+ }
+ }
+ }
+ else
+ {
+ DLTRACE(("Not waiting for a continue message!"));
+ // Fail operation can't complete the message if it's not set
+ // to iPendingMessage
+ iPendingMessage = aMessage;
+
+ // Not waiting for a continue message.
+ FailOperation( KErrNotReady );
+ }
+ DLTRACEOUT((""));
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::HandleQueryResponseMessage(
+ MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN((""));
+ DASSERT( ! iPendingMessage );
+ if ( iOperationState == EStateQuery )
+ {
+ DASSERT( iActiveQuery );
+ // store message, it will be completed later
+ iPendingMessage = aMessage;
+ iOperationState = EStateRunning;
+
+ DLINFO(("input length= %d",iPendingMessage->InputLength()));
+
+ TRAPD( err,
+ {
+ HBufC8* des = HBufC8::NewLC( iPendingMessage->InputLength() );
+ TPtr8 ptr = des->Des();
+ iPendingMessage->ReadInput( ptr );
+ RDesReadStream stream( *des );
+ CleanupReleasePushL( stream );
+ iActiveQuery->InternalizeL( stream );
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( des );
+ QueryHandledL( iActiveQuery );
+ }); // TRAP
+
+ if( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+
+
+
+ // Should handle cases where both expired info and querys have been received
+ /*else if( iExpiredNodes.Count() > 0 )
+ {
+ DLTRACE(("Expired nodes received previously, send to proxy"));
+ TInt err = SendExpirationInfo( iExpiredNodes );
+ if( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }*/
+ }
+ else
+ {
+ DLTRACE(("Not waiting for a query"));
+ // Not waiting for a query response message.
+ TInt err = CompleteMessage( aMessage, ENCDOperationMessageCompletionError,
+ KErrNotReady );
+ if ( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle initialization messages
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::HandleInitMessage( MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN( ( "" ) );
+ if ( iOperationState == EStateStopped )
+ {
+ // this will probably cause an error in the proxy, remove?
+ if ( iPendingMessage )
+ {
+ DLTRACE( ( "MESSAGE PENDING! THIS CAN NOT BE!" ) );
+ iPendingMessage->CompleteAndRelease( KErrAlreadyExists );
+ DASSERT( 0 );
+ }
+ iPendingMessage = aMessage;
+ Initialize();
+ }
+ else
+ {
+ // Operation already started.
+ TInt err = CompleteMessage( aMessage,
+ ENCDOperationMessageCompletionError,
+ KErrInUse );
+ if ( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ DLTRACEOUT((""));
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Handles release messages
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::HandleReleaseMessage( MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN((""));
+ if ( iPendingMessage )
+ {
+
+ // Notice that because we complete the iPendingMessage here the
+ // client has to say AsyncMessageSenderDown() to the
+ // ClientServer so the client won't receive this
+ // iPendingMessage. iPendingMessage is released here so no memory
+ // is pending because of it.
+ DLTRACE(("Releasing pending message"));
+ iPendingMessage->CompleteAndRelease( KErrCancel );
+ iPendingMessage = NULL;
+ DLTRACE(("Message released"));
+ }
+
+ MCatalogsSession& requestSession( aMessage->Session() );
+ DLTRACE(("Getting handle"));
+ TInt handle( aMessage->Handle() );
+
+ DLTRACE(("Completing message"));
+ aMessage->CompleteAndRelease( KErrNone );
+ DLTRACE(("Removing object"));
+ requestSession.RemoveObject( handle );
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::CompleteMessage( MCatalogsBaseMessage* & aMessage,
+ TNcdOperationMessageCompletionId aId,
+ const MNcdSendable& aSendableObject,
+ TInt aStatus )
+ {
+ DLTRACEIN((""));
+ DLTRACE(("Handle: %d", aMessage->Handle()));
+ TRAPD(err,
+ {
+ DLTRACE(("new buf"));
+ CBufBase* buf = CBufFlat::NewL( 30 );
+ CleanupStack::PushL( buf );
+ RBufWriteStream stream( *buf );
+ CleanupClosePushL( stream );
+ stream.WriteInt32L( aId );
+ aSendableObject.ExternalizeL( stream );
+ CleanupStack::PopAndDestroy( &stream );
+ TPtrC8 ptr = buf->Ptr( 0 );
+ DLTRACE(("complete msg"));
+ DASSERT((aMessage != NULL));
+ aMessage->CompleteAndReleaseL( ptr, aStatus );
+ DLTRACE(("pop buf"));
+ CleanupStack::PopAndDestroy( buf );
+ DLTRACE(("done"));
+ });
+ if( err != KErrNone )
+ {
+ aMessage->CompleteAndRelease( aStatus );
+ }
+ aMessage = NULL;
+ DLTRACEOUT(("error=%d", err));
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::CompleteMessage(MCatalogsBaseMessage* & aMessage,
+ TNcdOperationMessageCompletionId aId,
+ TInt aStatus )
+ {
+ DLTRACEIN((""));
+ DASSERT((aMessage));
+ DLTRACE(("Handle: %d", aMessage->Handle()));
+ TRAPD(err,
+ {
+ HBufC8* buffer = HBufC8::NewLC( sizeof(TInt) );
+ TPtr8 bufferPtr( buffer->Des() );
+ RDesWriteStream desWriteStream( bufferPtr );
+ CleanupClosePushL( desWriteStream );
+ desWriteStream.WriteInt32L( aId );
+ CleanupStack::PopAndDestroy( &desWriteStream );
+ aMessage->CompleteAndReleaseL( *buffer, aStatus );
+ CleanupStack::PopAndDestroy( buffer );
+ });
+ if( err != KErrNone )
+ {
+ aMessage->CompleteAndRelease( aStatus );
+ }
+ aMessage = NULL;
+ DLTRACEOUT(("error=%d", err));
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::CompleteMessage( MCatalogsBaseMessage*& aMessage,
+ TNcdOperationMessageCompletionId aId,
+ const MNcdSendable& aSendableObject,
+ RPointerArray<CNcdNodeIdentifier>& aNodes,
+ TInt aStatus )
+ {
+ DLTRACEIN(("Handle: %i", aMessage->Handle()));
+
+ TRAPD(err,
+ {
+ CBufBase* buf = CBufFlat::NewL( KBufExpandSize );
+ CleanupStack::PushL( buf );
+ RBufWriteStream stream( *buf );
+ CleanupClosePushL( stream );
+ stream.WriteInt32L( aId );
+ aSendableObject.ExternalizeL( stream );
+ stream.WriteInt32L( aNodes.Count() );
+ DLINFO(("Node loop: %d", aNodes.Count()));
+ for ( TInt i = 0 ; i < aNodes.Count() ; i++ )
+ {
+ aNodes[i]->ExternalizeL( stream );
+ }
+ CleanupStack::PopAndDestroy( &stream );
+ TPtrC8 ptr = buf->Ptr( 0 );
+ aMessage->CompleteAndReleaseL( ptr, aStatus );
+ CleanupStack::PopAndDestroy( buf );
+ });
+ if( err != KErrNone )
+ {
+ aMessage->CompleteAndRelease( aStatus );
+ }
+ aMessage = NULL;
+ DLTRACEOUT((""));
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::CompleteMessage( MCatalogsBaseMessage*& aMessage,
+ TNcdOperationMessageCompletionId aId,
+ RPointerArray<CNcdExpiredNode>& aExpiredNodes,
+ TInt aStatus )
+ {
+ DLTRACEIN(("Handle: %i", aMessage->Handle()));
+
+ TRAPD(err,
+ {
+ CBufBase* buf = CBufFlat::NewL( KBufExpandSize );
+ CleanupStack::PushL( buf );
+ RBufWriteStream stream( *buf );
+ CleanupClosePushL( stream );
+ stream.WriteInt32L( aId );
+ stream.WriteInt32L( aExpiredNodes.Count() );
+ for ( TInt i = 0 ; i < aExpiredNodes.Count() ; i++ )
+ {
+ aExpiredNodes[i]->ExternalizeL( stream );
+ }
+ CleanupStack::PopAndDestroy( &stream );
+ TPtrC8 ptr = buf->Ptr( 0 );
+ aMessage->CompleteAndReleaseL( ptr, aStatus );
+ CleanupStack::PopAndDestroy( buf );
+ });
+ if( err != KErrNone )
+ {
+ aMessage->CompleteAndRelease( aStatus );
+ }
+ DLINFO(("message null"));
+ aMessage = NULL;
+ DLTRACEOUT((""));
+
+ return err;
+ }
+
+MCatalogsSession& CNcdBaseOperation::Session()
+ {
+ return iSession;
+ }
+
+TBool CNcdBaseOperation::IsSubOperation()
+ {
+ return iIsSubOperation;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Progress getter
+// ---------------------------------------------------------------------------
+//
+const TNcdSendableProgress& CNcdBaseOperation::Progress() const
+ {
+ return iProgress;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle setter
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::SetHandle( TInt aHandle )
+ {
+ iHandle = aHandle;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle getter
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::Handle() const
+ {
+ return iHandle;
+ }
+
+// ---------------------------------------------------------------------------
+// From class CCatalogsCommunicable
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::ReceiveMessage(
+ MCatalogsBaseMessage* aMessage,
+ TInt aFunctionNumber )
+ {
+ DLTRACEIN((_L("Handle: %i, aFunctionNumber=%d"), aMessage->Handle(),
+ aFunctionNumber));
+
+
+ switch ( aFunctionNumber )
+ {
+ case ENCDOperationFunctionStart:
+ {
+ HandleStartMessage( aMessage );
+ break;
+ }
+ case ENCDOperationFunctionCancel:
+ {
+ HandleCancelMessage( aMessage );
+ break;
+ }
+ case ENCDOperationFunctionContinue:
+ {
+ HandleContinueMessage( aMessage );
+ break;
+ }
+ case ENCDOperationFunctionQueryResponse:
+ {
+ HandleQueryResponseMessage( aMessage );
+ break;
+ }
+ case ENCDOperationFunctionInit:
+ {
+ HandleInitMessage( aMessage );
+ break;
+ }
+
+ case ENCDOperationFunctionRelease:
+ {
+ HandleReleaseMessage( aMessage );
+ break;
+ }
+
+ }
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::CounterPartLost( const MCatalogsSession& aSession )
+ {
+ DLTRACEIN((""));
+ Cancel();
+ if ( iPendingMessage )
+ {
+ // This function may be called whenever -- when the message is waiting
+ // response or when the message does not exist. The life time of the message
+ // ends shortly after CompleteAndRelease is called.
+ iPendingMessage->CounterPartLost( aSession );
+ }
+ }
+
+void CNcdBaseOperation::QueryL( MNcdConfigurationProtocolQuery* aData )
+ {
+ DLTRACEIN((""));
+ // querys from embedded data end up here, just store them
+
+ // maybe this should not be added to the array if it's an autenthication
+ // query? on the other hand it could be referred from somewhere else.
+ CleanupDeletePushL( aData );
+ iEmbeddedDataQuerys.AppendL( aData );
+ CleanupStack::Pop( aData );
+ // special case: authentication query, should actually come in
+ // information/Messages according to protocol but CGW sends it in
+ // embeddedData/Queries.
+ //
+ if( aData->Semantics() == MNcdQuery::ESemanticsAuthenticationQuery )
+ {
+ iPendingQuerys.AppendL( CNcdQuery::NewLC( *aData ) );
+ CleanupStack::Pop();
+ }
+ DLTRACEOUT((""));
+ }
+
+void CNcdBaseOperation::InformationL(
+ MNcdPreminetProtocolInformation* aData )
+ {
+ DLTRACEIN(("aData: %X", aData));
+ CleanupDeletePushL( aData );
+ DLTRACE(("Handling queries"));
+ // store querys from information response
+ // the inheriting operation will handle these if needed
+ for ( TInt i = 0 ; i < aData->MessageCount() ; i++ )
+ {
+ CNcdQuery* query = CNcdQuery::NewLC( aData->MessageL(i) );
+ iPendingQuerys.AppendL( query );
+ CleanupStack::Pop( query );
+ }
+
+ DLTRACE(("Checking for expired cached data"));
+
+ // handle expired cached data
+ const MNcdPreminetProtocolExpiredCachedData* expiredData =
+ aData->ExpiredCachedData();
+
+ if ( expiredData )
+ {
+ DLTRACE(("Handling expired data"));
+ RPointerArray<CNcdExpiredNode> expiredNodes;
+ CleanupResetAndDestroyPushL( expiredNodes );
+ iNodeManager->SetNodesExpiredByMetadataL( *expiredData,
+ iSession.Context().FamilyId(),
+ aData->Namespace(),
+ expiredNodes );
+ ExpirationInfoReceived( this, expiredNodes );
+ CleanupStack::PopAndDestroy( &expiredNodes );
+ }
+
+ DLTRACE(("Should handle stuff"));
+
+ DASSERT( iParser );
+ CleanupStack::Pop( aData );
+ iParser->DefaultObserver().InformationL( aData );
+ DLTRACEOUT((""));
+ }
+
+void CNcdBaseOperation::ErrorL( MNcdPreminetProtocolError* /* aData */ )
+ {
+ DLTRACEIN((""));
+ //switch
+
+ }
+
+void CNcdBaseOperation::Progress( CNcdBaseOperation& /*aOperation*/ )
+ {
+ DLTRACEIN(("default implementation, does nothing"));
+ }
+
+void CNcdBaseOperation::QueryReceived( CNcdBaseOperation& /*aOperation*/,
+ CNcdQuery* /*aQuery*/ )
+ {
+ DLTRACEIN(("default implementation, does nothing"));
+ }
+
+void CNcdBaseOperation::OperationComplete( CNcdBaseOperation* /*aOperation*/,
+ TInt /*aError*/ )
+ {
+ DLTRACEIN(("default implementation, does nothing"));
+ }
+
+void CNcdBaseOperation::ExpirationInfoReceived( CNcdBaseOperation* /*aOperation*/,
+ RPointerArray<CNcdExpiredNode>& aExpiredNodes )
+ {
+ DLTRACEIN((""));
+ if ( iIsSubOperation )
+ {
+ DLINFO(( "Subop, inform observers of expiration info" ));
+ // send to observer
+ for( TInt i = 0 ; i < iObservers.Count() ; i++ )
+ {
+ iObservers[i]->ExpirationInfoReceived( this, aExpiredNodes );
+ }
+ }
+ else
+ {
+ if( iPendingMessage )
+ {
+ DLINFO(( "Message exists, send expiration info" ));
+ // message available, send
+ TInt err = SendExpirationInfo( aExpiredNodes );
+ if( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ else
+ {
+ DLINFO(( "Message does not exist, cannot send expiration info" ));
+ // no message, store
+ iOperationState = EStateSendExpirationInfo;
+ for( TInt i = 0 ; i < aExpiredNodes.Count() ; i++ )
+ {
+ TRAPD( err, iExpiredNodes.AppendL( aExpiredNodes[i] ) );//TRAPD
+ if( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ aExpiredNodes.Reset();
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+CNcdBaseOperation::CNcdBaseOperation(
+ CNcdGeneralManager& aGeneralManager,
+ MNcdOperationRemoveHandler* aRemoveHandler,
+ TNcdOperationType aOperationType,
+ MCatalogsSession& aSession,
+ TBool aIsSubOperation )
+ : iGeneralManager( aGeneralManager ),
+ iError( KErrNone ),
+ iRemoveHandler( aRemoveHandler ),
+ iOperationType( aOperationType ),
+ iOperationState( EStateStopped ),
+ iSession( aSession ),
+ iIsSubOperation( aIsSubOperation ),
+ iNodeManager( &aGeneralManager.NodeManager() )
+ {
+ DLTRACEIN((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CNcdBaseOperation::ConstructL()
+ {
+ DLTRACEIN((""));
+ }
+
+// ---------------------------------------------------------------------------
+// Empty initializer
+// ---------------------------------------------------------------------------
+//
+TInt CNcdBaseOperation::Initialize()
+ {
+ DLTRACEIN( ( "THIS SHOULD NOT BE CALLED" ) );
+ DASSERT( 0 );
+ return KErrNone;
+ }
+
+void CNcdBaseOperation::ChangeToPreviousStateL()
+ {
+ DLTRACEIN(("SHOULD NEVER BE CALLED, ERROR!"))
+ DASSERT(0);
+ }
+
+void CNcdBaseOperation::HandleEngineQueryItemsL( CNcdQuery* aQuery )
+ {
+ DLTRACEIN((""));
+ aQuery->InternalAddRef();
+ for ( TInt i = 0 ; i < aQuery->ItemCount() ; i++ )
+ {
+ CNcdQueryItem& queryItem = aQuery->QueryItemL( i );
+ switch ( queryItem.Semantics() )
+ {
+ case MNcdQueryItem::ESemanticsImei:
+ {
+ MNcdQueryTextItem* textQueryItem = NULL;
+ textQueryItem = queryItem.QueryInterfaceLC< MNcdQueryTextItem >();
+ DASSERT( textQueryItem );
+ // get imei from device service
+ MNcdDeviceService* deviceService =
+ NcdDeviceInteractionFactory::CreateDeviceServiceLC();
+ textQueryItem->SetTextL( deviceService->ImeiL() );
+ CleanupStack::PopAndDestroy( deviceService );
+ CleanupStack::PopAndDestroy( textQueryItem );
+ break;
+ }
+ default:
+ {
+ // not an engine query item
+ break;
+ }
+ }
+ }
+ aQuery->InternalRelease();
+ }
+
+MNcdConfigurationProtocolQueryResponse* CNcdBaseOperation::CreateResponseL(
+ CNcdQuery& aQuery )
+ {
+ DLTRACEIN((""));
+ if ( aQuery.Response() == MNcdQuery::ENoResponse )
+ {
+ User::Leave( KErrNotReady );
+ }
+ CNcdConfigurationProtocolQueryResponseImpl* queryResponse =
+ CNcdConfigurationProtocolQueryResponseImpl::NewLC();
+ AssignDesL( queryResponse->iId, aQuery.Id() );
+ DLINFO((_L("Added query id=%S"), queryResponse->iId ));
+
+ if( aQuery.Response() == MNcdQuery::ERejected )
+ {
+ // query has been cancelled
+ queryResponse->iCancel = ETrue;
+ }
+ else
+ {
+ // query has been accepted, add response values
+ for ( TInt i = 0 ; i < aQuery.ItemCount() ; i++ )
+ {
+ CNcdQueryItem& item = aQuery.QueryItemL( i );
+ if ( item.IsOptional() && ! item.IsSet() )
+ {
+ continue;
+ }
+ if ( !item.IsSet() )
+ {
+ User::Leave( KErrNotReady );
+ }
+ CNcdConfigurationProtocolQueryResponseValueImpl* value =
+ CNcdConfigurationProtocolQueryResponseValueImpl::NewLC();
+ AssignDesL( value->iId, item.Id() );
+ HBufC* valueDes = item.ValueL().AllocLC();
+ value->iValues.AppendL( valueDes );
+ CleanupStack::Pop( valueDes );
+ queryResponse->iResponses.AppendL( value );
+ CleanupStack::Pop( value );
+ DLINFO((_L("Added query item response id=%S, value=%S"),
+ value->iId, valueDes ));
+ }
+ }
+
+ CleanupStack::Pop( queryResponse );
+
+ return queryResponse;
+ }
+
+
+void CNcdBaseOperation::QueryReceivedL( CNcdQuery* aQuery )
+ {
+ DLTRACEIN((""));
+ aQuery->InternalAddRef();
+ iOperationState = EStateQuery;
+ DASSERT( ! iActiveQuery );
+ iActiveQuery = aQuery;
+ HandleEngineQueryItemsL( iActiveQuery );
+ if ( iActiveQuery->ItemCount() > 0 && iActiveQuery->AllItemsSet() )
+ {
+ // all items set by engine, accept and complete
+ DLTRACEIN(("all items set by engine -> complete"));
+ iActiveQuery->SetResponseL( MNcdQuery::EAccepted );
+ iOperationState = EStateRunning;
+ QueryHandledL( iActiveQuery );
+ DLTRACEOUT((""));
+ return;
+ }
+ else if ( iIsSubOperation )
+ {
+ DASSERT( iObservers.Count() > 0 )
+ // this is a sub operation send the query to observer
+ // maybe there should be only one observer/parent
+ iObservers[0]->QueryReceived( *this, aQuery );
+ }
+ else if ( iPendingMessage )
+ {
+ TInt err = CompleteMessage( iPendingMessage, ENCDOperationMessageCompletionQuery,
+ *iActiveQuery, KErrNone );
+ if ( err != KErrNone )
+ {
+ FailOperation( err );
+ }
+ }
+ DLTRACEOUT((""));
+ }
+
+void CNcdBaseOperation::CompleteCallback()
+ {
+ for ( TInt i = 0 ; i < iObservers.Count() ; i++ )
+ {
+ iObservers[i]->OperationComplete( this, iError );
+ }
+ }
+
+void CNcdBaseOperation::ContinueOperationL()
+ {
+ DLTRACEIN((""));
+ if( !iRunner )
+ {
+ iRunner = CNcdAsyncRunner::NewL( this );
+ }
+ iRunner->Start();
+ }
+
+TInt CNcdBaseOperation::SendExpirationInfo(
+ RPointerArray<CNcdExpiredNode>& aExpiredNodes )
+ {
+ DLTRACEIN((""));
+ if( iPendingMessage )
+ {
+ return CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionExpirationInfo,
+ aExpiredNodes,
+ iError );
+ }
+ return KErrNotFound;
+ }
+
+TBool CNcdBaseOperation::QueryCompletedL( CNcdQuery* /*aQuery*/ )
+ {
+ DLTRACEIN(("THIS SHOULD NOT BE CALLED! ERROR!"));
+ DASSERT( 0 );
+ return EFalse;
+ }
+
+CNcdQuery* CNcdBaseOperation::ActiveQuery()
+ {
+ if( iActiveQuery )
+ {
+ iActiveQuery->InternalAddRef();
+ return iActiveQuery;
+ }
+ return NULL;
+ }
+
+TInt CNcdBaseOperation::QueryEntityCount()
+ {
+ return iEmbeddedDataQuerys.Count();
+ }
+
+const MNcdConfigurationProtocolQuery& CNcdBaseOperation::QueryEntityL(
+ const TDesC& aId )
+ {
+ MNcdConfigurationProtocolQuery* query = NULL;
+ for ( TInt i = 0 ; i < iEmbeddedDataQuerys.Count() ; i++ )
+ {
+ if( iEmbeddedDataQuerys[i]->Id() == aId )
+ {
+ query = iEmbeddedDataQuerys[i];
+ break;
+ }
+ }
+ if ( query == NULL )
+ {
+ User::Leave( KErrNotFound );
+ }
+ return *query;
+ }
+
+void CNcdBaseOperation::ContinueOperation()
+ {
+ RunOperation();
+ }
+
+void CNcdBaseOperation::FailOperation( TInt aError )
+ {
+ DLTRACEIN(("aError: %d",aError));
+ iError = aError;
+ Cancel();
+ if( iIsSubOperation )
+ {
+ // send to observer
+ for( TInt i = 0 ; i < iObservers.Count() ; i++ )
+ {
+ iObservers[i]->OperationComplete( this, iError );
+ }
+ }
+ else if ( iPendingMessage )
+ {
+ // complete message with error code, possible error message is ignored
+ // as the operation has already failed
+ CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionError,
+ iError );
+ }
+ }
+
+void CNcdBaseOperation::AddQueryResponsesL( CNcdRequestBase* aRequest )
+ {
+ DLTRACEIN((""));
+ // add querys
+ for ( TInt i = 0 ; i < iCompletedQuerys.Count() ; i++ )
+ {
+ CNcdQuery* query = iCompletedQuerys[i];
+ DASSERT(( query->Response() == MNcdQuery::EAccepted ||
+ query->Response() == MNcdQuery::ERejected ));
+ MNcdConfigurationProtocolQueryResponse* queryResponse =
+ CreateResponseL( *query );
+ CleanupStack::PushL( queryResponse );
+ aRequest->AddQueryResponseL( queryResponse );
+ CleanupStack::Pop( queryResponse );
+ }
+ }
+
+void CNcdBaseOperation::HandleQuerysL()
+ {
+ DLTRACEIN((""));
+ if ( iPendingQuerys.Count() > 0 )
+ {
+ // still a query left, send it to proxy
+ CNcdQuery* query = iPendingQuerys[0];
+ // Should set "is secure uri" flag
+ // remove from array
+ iPendingQuerys.Remove(0);
+ // handle query
+ CNcdBaseOperation::QueryReceivedL( query );
+ // release own reference
+ query->InternalRelease();
+ }
+ else
+ {
+ if( iCompletedQuerys.Count() > 0 )
+ {
+ // there are completed querys that need to be responded to
+ // -> resend request with the query responses
+ ResendRequestL();
+ }
+ else
+ {
+ // all queries handled, continue operation normally
+ ContinueOperationL();
+ }
+ }
+ }
+
+void CNcdBaseOperation::QueryHandledL( CNcdQuery* aQuery )
+ {
+ DLTRACEIN((""));
+ DASSERT( aQuery == iActiveQuery )
+ DASSERT( aQuery->Response() == MNcdQuery::EAccepted ||
+ aQuery->Response() == MNcdQuery::ERejected )
+
+ // this may leave (e.g. in some cases when the query has been rejected )
+ TBool handled = QueryCompletedL( aQuery );
+ if ( !handled && aQuery->ItemCount() > 0 )
+ {
+ if( aQuery->Response() == MNcdQuery::EAccepted )
+ {
+ // query was not handled in the inheriting op, but was accepted
+ // add it to the list for later retrieval
+ iCompletedQuerys.AppendL( aQuery );
+ }
+ else if( aQuery->Semantics() == MNcdQuery::ESemanticsAuthenticationQuery &&
+ aQuery->Response() == MNcdQuery::ERejected )
+ {
+ // special case; server want's query responses for rejected authentication
+ // queries, so add it to the list
+ iCompletedQuerys.AppendL( aQuery );
+ }
+ else if( aQuery->Response() == MNcdQuery::ERejected
+ && !aQuery->IsOptional() )
+ {
+ // a rejected, and mandatory, query was not handled -> fail the operation
+ User::Leave( KNcdErrorMandatoryQueryRejected );
+ }
+ else
+ {
+ // optional query rejected, release own reference to it
+ iActiveQuery->InternalRelease();
+ }
+ }
+ else
+ {
+ // query has been handled or has no items (i.e. server message)
+ // release own reference to it
+ iActiveQuery->InternalRelease();
+ }
+ // active query is now handled, set to null
+ iActiveQuery = NULL;
+ // handle querys if some are still left
+ HandleQuerysL();
+ }
+
+TInt CNcdBaseOperation::QueriesPending()
+ {
+ DLTRACEIN((""));
+ return iPendingQuerys.Count();
+ }
+
+void CNcdBaseOperation::ResendRequestL()
+ {
+ DLTRACEIN((""));
+ ChangeToPreviousStateL();
+ ContinueOperationL();
+ }
+
+void CNcdBaseOperation::ClearCompletedQueries()
+ {
+ DLTRACEIN((""));
+ for ( TInt i = 0 ; i < iCompletedQuerys.Count() ; i++ )
+ {
+ iCompletedQuerys[i]->InternalRelease();
+ }
+ iCompletedQuerys.Reset();
+ }