diff -r 000000000000 -r ba25891c3a9e ncdengine/provider/server/src/ncdbaseoperation.cpp --- /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 + +#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& 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& 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 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& 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& 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(); + }