diff -r 2669f8761a99 -r fbd2e7cec7ef xdmprotocols/XcapProtocol/src/XcapDocument.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xdmprotocols/XcapProtocol/src/XcapDocument.cpp Wed Sep 01 12:23:14 2010 +0100 @@ -0,0 +1,1097 @@ +/* +* Copyright (c) 2005 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: CXcapDocument +* +*/ + + + + +// INCLUDE FILES +#include +#include +#include "XdmOperationFactory.h" +#include "XcapProtocol.h" +#include "XcapDocument.h" +#include "XcapAppUsage.h" +#include "XdmXmlParser.h" +#include "XdmNamespace.h" +#include "CommonDefines.h" +#include "XcapDocumentNode.h" +#include "XcapHttpRequest.h" +#include "XcapHttpOperation.h" +#include "XcapHttpTransport.h" + +// ================= MEMBER FUNCTIONS ======================= +// + + +// ---------------------------------------------------------- +// CXcapDocument::CXcapDocument +// +// ---------------------------------------------------------- +// +CXcapDocument::CXcapDocument( TXdmDocType aDocumentType, + const CXdmEngine& aXdmEngine, + const CXcapProtocol& aXcapProtocol ) : + CXdmDocument( CONST_CAST( CXdmEngine&, aXdmEngine ) ), + iDocumentType( aDocumentType ), + iXcapProtocol( CONST_CAST( CXcapProtocol&, aXcapProtocol ) ) + + { + } + +// ---------------------------------------------------------- +// CXcapDocument::NewL +// +// ---------------------------------------------------------- +// +CXcapDocument* CXcapDocument::NewL( TXdmDocType aDocumentType, + const TDesC& aDocumentName, + const CXdmEngine& aXdmEngine, + const CXcapProtocol& aXcapProtocol ) + { + CXcapDocument* self = new ( ELeave ) CXcapDocument( aDocumentType, aXdmEngine, aXcapProtocol ); + CleanupStack::PushL( self ); + self->BaseConstructL( KXcapOperationFactory, aDocumentName ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// ---------------------------------------------------------- +// CXcapDocument::NewL +// +// ---------------------------------------------------------- +// +CXcapDocument* CXcapDocument::NewL( TXdmDocType aDocumentType, + const TDesC8& aDocumentName, + const CXdmEngine& aXdmEngine, + const CXcapProtocol& aXcapProtocol ) + { + CXcapDocument* self = new ( ELeave ) CXcapDocument( aDocumentType, aXdmEngine, aXcapProtocol ); + CleanupStack::PushL( self ); + self->ConstructL( aDocumentName ); + CleanupStack::Pop(); + return self; + } + +// ---------------------------------------------------------- +// CXcapDocument::ConstructL +// +// ---------------------------------------------------------- +// +void CXcapDocument::ConstructL( const TDesC8& aDocumentName ) + { + BaseConstructL( KXcapOperationFactory, aDocumentName ); + ConstructL(); + } + +// ---------------------------------------------------------- +// CXcapDocument::ConstructL +// +// ---------------------------------------------------------- +// +void CXcapDocument::ConstructL() + { + InstallAppUsageL(); + iErrorRoot = CXcapDocumentNode::NewL( iXdmEngine, iXcapProtocol ); + TPtrC8 root( iXcapProtocol.Transport().RootUri() ); + #ifdef _DEBUG + HBufC8* buf = HBufC8::NewLC( iDocumentName->Des().Length() ); + buf->Des().Copy( iDocumentName->Des() ); + TPtr8 nameDesc( buf->Des() ); + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::ConstructL()" ) ); + iXcapProtocol.WriteToLog( _L8( " Root URI: %S" ), &root ); + iXcapProtocol.WriteToLog( _L8( " Document: %S" ), &nameDesc ); + CleanupStack::PopAndDestroy(); //buf + #endif + RXcapCache* cache = iXcapProtocol.Cache(); + if( cache ) + UpdateDocumentInfoL( cache ); + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Cache disabled, no info for the document" ) ); + #endif + } + CActiveScheduler::Add( this ); + } + +// ---------------------------------------------------- +// CXcapDocument::~CXcapDocument +// +// ---------------------------------------------------- +// +CXcapDocument::~CXcapDocument() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::~CXcapDocument()" ) ); + #endif + Cancel(); + delete iTempCopy; + delete iEightBitName; + delete iDocumentRoot; + delete iErrorRoot; + delete iAppUsage; + iNamespaces.ResetAndDestroy(); + iNamespaces.Close(); + } + +// ---------------------------------------------------------- +// CXcapDocument::ResetContents +// +// ---------------------------------------------------------- +// +void CXcapDocument::ResetContents() + { + iOptions = 0; + delete iDocumentRoot; + iDocumentRoot = NULL; + delete iErrorRoot; + iErrorRoot = NULL; + delete iTempCopy; + iTempCopy = NULL; + iNamespaces.ResetAndDestroy(); + } + +// ---------------------------------------------------------- +// CXcapDocument::UpdateDocumentInfoL +// +// ---------------------------------------------------------- +// +void CXcapDocument::UpdateDocumentInfoL( RXcapCache* aCacheClient ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::UpdateDocumentInfo()" ) ); + #endif + iETagBuffer.Zero(); + TCacheEntryInfo cacheEntryInfo; + TPtrC8 root( iXcapProtocol.Transport().RootUri() ); + TInt error = aCacheClient->FetchDocumentInfo( + iETagBuffer, iDocumentName->Des(), root, cacheEntryInfo ); + if( error == KErrNone ) + { + iLastAccess = cacheEntryInfo.iLastAccess; + iLastModification = cacheEntryInfo.iLastUpdate; + iDataLength = cacheEntryInfo.iDataLength; + #ifdef _DEBUG + const TInt KDateTimeMaxSize = 100; + TBuf8 printBuffer; + TBuf dateTimeBuffer; + _LIT( KDateTimeFormat, "%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S"); + iLastModification.FormatL( dateTimeBuffer, KDateTimeFormat ); + printBuffer.Copy( dateTimeBuffer ); + iXcapProtocol.WriteToLog( _L8( " ETag: %S" ), &iETagBuffer ); + iXcapProtocol.WriteToLog( _L8( " Size: %d bytes" ), iDataLength ); + iXcapProtocol.WriteToLog( _L8( " Time stamp: %S" ), &printBuffer ); + #endif + } + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Cache read complete - Error: %d" ), error ); + #endif + } + } + +// ---------------------------------------------------- +// CXcapDocument::InstallAppUsageL +// +// ---------------------------------------------------- +// +void CXcapDocument::InstallAppUsageL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::InstallAppUsageL()" ) ); + #endif + HBufC8* docName = NULL; + iAppUsage = CXcapAppUsage::NewL( iXdmEngine, iDocumentType ); + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::InstallAppUsageL() type = %d" ), iDocumentType ); + #endif + TPtrC8 auid = iAppUsage->AUID(); + if( IsGlobalTree( auid ) ) + { + docName = HBufC8::NewLC( auid.Length() + KGlobalDirName().Length() + + KXcapGlobalDocName().Length() ); + docName->Des().Copy( auid ); + docName->Des().Append( KGlobalDirName ); + docName->Des().Append( KXcapGlobalDocName ); + delete iDocumentName; + iDocumentName = NULL; + iDocumentName = HBufC::NewL( docName->Des().Length() ); + iDocumentName->Des().Copy( docName->Des() ); + CleanupStack::PopAndDestroy(); //docName + } + else + { + TPtrC8 user = iXcapProtocol.UserName(); + docName = HBufC8::NewLC( auid.Length() + user.Length() + + KUserDirName().Length() + 1 /*'/'*/ + + iDocumentName->Des().Length() ); + docName->Des().Copy( auid ); + docName->Des().Append( KUserDirName ); + docName->Des().Append( user ); + docName->Des().Append( KSlash ); + docName->Des().Append( iDocumentName->Des() ); + delete iDocumentName; + iDocumentName = NULL; + iDocumentName = HBufC::NewL( docName->Des().Length() ); + iDocumentName->Des().Copy( docName->Des() ); + CleanupStack::PopAndDestroy(); //docName + } + + } + +// ---------------------------------------------------- +// CXcapDocument::IsGlobalTree +// +// ---------------------------------------------------- +// +TBool CXcapDocument::IsGlobalTree( const TDesC8& aAuid ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::IsGlobalTree()" ) ); + #endif + TBool found = EFalse; + //Update this array when necessary + const TPtrC8 KGlobalTreeAuids[] = { TPtrC8( KXdmCapabilityUsageAUID ) }; + const TInt count = sizeof( KGlobalTreeAuids ) / sizeof( KGlobalTreeAuids[0] ); + for( TInt i = 0;!found && i < count;i++ ) + found = aAuid.Compare( KGlobalTreeAuids[i] ) == 0; + return found; + } + +// ---------------------------------------------------- +// CXcapDocument::CreateTempCopyL +// +// ---------------------------------------------------- +// +void CXcapDocument::CreateTempCopyL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::CreateTempCopyL()" ) ); + #endif + CXdmDocument* copy = iXdmEngine.CreateDocumentModelL( Name(), iDocumentType ); + iTempCopy = ( CXcapDocument* )copy; + } + +// ---------------------------------------------------- +// CXcapDocument::TempCopyL +// +// ---------------------------------------------------- +// +EXPORT_C CXcapDocument* CXcapDocument::TempCopyL() + { + return CXcapDocument::NewL( iDocumentType, Name(), iXdmEngine, iXcapProtocol ); + } + +// ---------------------------------------------------- +// CXcapDocument::CreateRootL +// +// ---------------------------------------------------- +// +CXdmDocumentNode* CXcapDocument::CreateRootL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXdmDocument::CreateRootL()" ) ); + #endif + delete iDocumentRoot; + iDocumentRoot = NULL; + iDocumentRoot = CXcapDocumentNode::NewL( iXdmEngine, iXcapProtocol ); + return iDocumentRoot; + } + +// ---------------------------------------------------- +// CXcapDocument::AppendPathPartL +// +// ---------------------------------------------------- +// +void CXcapDocument::AppendPathPartL( const TDesC& aString ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::PathPartL()" ) ); + #endif + if( iDocumentRoot != NULL ) + { + CXdmDocumentNode* node = NULL; + CXdmDocumentNode* parent = iDocumentRoot; + while( parent->NextNode() != NULL ) + parent = parent->NextNode(); + node = CXcapDocumentNode::NewL( iXdmEngine, aString, iXcapProtocol, parent ); + parent->SetNextNode( node ); + } + else iDocumentRoot = CXcapDocumentNode::NewL( iXdmEngine, aString, iXcapProtocol ); + } + +// ---------------------------------------------------- +// CXcapDocument::CurrentExtent +// +// ---------------------------------------------------- +// +CXdmDocumentNode* CXcapDocument::CurrentExtent() const + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXdmDocument::CurrentExtent()" ) ); + #endif + CXdmDocumentNode* ret = NULL; + if( iDocumentRoot != NULL ) + { + CXdmDocumentNode* node = iDocumentRoot; + while( node->NextNode() != NULL ) + node = node->NextNode(); + ret = node; + } + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " This document does not yet have a root, leave with KErrGeneral" ) ); + #endif + User::Leave( KErrGeneral ); + } + return ret; + } + +// ---------------------------------------------------- +// CXcapDocument::DocumentRoot +// +// ---------------------------------------------------- +// +CXdmDocumentNode* CXcapDocument::DocumentRoot() const + { + return iDocumentRoot; + } + +// ---------------------------------------------------- +// CXcapDocument::ErrorRoot +// +// ---------------------------------------------------- +// +CXdmDocumentNode* CXcapDocument::ErrorRoot() + { + if( !iErrorRoot ) + { + iErrorRoot = CXcapDocumentNode::NewL( iXdmEngine, iXcapProtocol ); + } + return iErrorRoot; + } + +// ---------------------------------------------------- +// CXcapDocument::ResetSubset +// +// ---------------------------------------------------- +// +EXPORT_C void CXcapDocument::ResetSubset() + { + CXdmDocument::ResetSubset(); + delete iDocumentRoot; + iDocumentRoot = NULL; + iOptions = 0; + } + +// ---------------------------------------------------- +// CXcapDocument::ETag +// +// ---------------------------------------------------- +// +EXPORT_C TDesC8& CXcapDocument::ETag() + { + return iETagBuffer; + } + +// ---------------------------------------------------- +// CXcapDocument::SetETag +// +// ---------------------------------------------------- +// +EXPORT_C void CXcapDocument::SetETag( const TDesC8& aETagDesc ) + { + iETagBuffer.Zero(); + iETagBuffer.Copy( aETagDesc ); + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::SetETag()" ) ); + iXcapProtocol.WriteToLog( _L8( " New ETag: %S" ), &iETagBuffer ); + #endif + } + +// ---------------------------------------------------- +// CXcapDocument::DataLength +// +// ---------------------------------------------------- +// +EXPORT_C TInt CXcapDocument::DataLength() const + { + return iDataLength; + } + +// ---------------------------------------------------- +// CXcapDocument::ApplicationUsage +// +// ---------------------------------------------------- +// +EXPORT_C CXcapAppUsage& CXcapDocument::ApplicationUsage() const + { + return *iAppUsage; + } + +// ---------------------------------------------------- +// CXcapDocument::Protocol +// +// ---------------------------------------------------- +// +EXPORT_C CXcapProtocol& CXcapDocument::Protocol() const + { + return iXcapProtocol; + } + +// ---------------------------------------------------- +// CXcapDocument::RemoveData +// +// ---------------------------------------------------- +// +EXPORT_C void CXcapDocument::RemoveData( CXcapDocumentNode* aDocumentNode ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::RemoveData()" ) ); + #endif + CXcapDocumentNode* parent = ( CXcapDocumentNode* )aDocumentNode->Parent(); + if( parent != NULL ) + parent->RemoveNode( aDocumentNode ); + } + +// ---------------------------------------------------- +// CXcapDocument::StartUpdateL +// +// ---------------------------------------------------- +// +void CXcapDocument::StartUpdateL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::StartUpdateL()" ) ); + #endif + TInt resolverError = 0; + if( iXcapProtocol.IsSimRequestPending( resolverError ) ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " IMS Resolver pending => add to queue" ) ); + #endif + iXcapProtocol.AppendNotifyeeL( this ); + } + else + { + if( resolverError == KErrNone && !IsActive() && iChangeRequests.Count() > 0 ) + { + iUpdateIndex = 0; + iDocumentState = EXdmDocUpdating; + iOperationCount = iChangeRequests.Count(); + ActivateOperationL(); + } + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( + " Already active, no operations or IMS resolver failed => complete with error" ) ); + #endif + TInt error = resolverError == KErrNone ? KErrNotReady : resolverError; + User::RequestComplete( iClientStatus, error ); + } + } + } + +// ---------------------------------------------------- +// CXcapDocument::StartInternalL +// +// ---------------------------------------------------- +// +void CXcapDocument::StartInternalL( TRequestStatus& aStatus ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::StartInternalL()" ) ); + #endif + aStatus = KRequestPending; + iClientStatus = &aStatus; + StartUpdateL(); + } + +// ---------------------------------------------------- +// CXcapDocument::NotifyResolverCompleteL +// +// ---------------------------------------------------- +// +void CXcapDocument::NotifyResolverCompleteL( TInt aError ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::NotifyResolverCompleteL()" ) ); + #endif + if( aError == KErrNone ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " IMS Resolver ready" ) ); + #endif + StartUpdateL(); + } + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " IMS Resolver failed => complete with %d" ), aError ); + #endif + DequeueAll(); + User::RequestComplete( iClientStatus, aError ); + } + } + +// ---------------------------------------------------- +// CXcapDocument::ActivateOperationL +// +// ---------------------------------------------------- +// +void CXcapDocument::ActivateOperationL() + { + MXdmOperation* request = iChangeRequests[iUpdateIndex]; + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::ActivateOperation() - Operation: %x" ), request ); + #endif + if( iDocSubset ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Document subset => set KXdmOption1 and KXdmOption2" ) ); + #endif + SetOption( KXdmOption1 ); + SetOption( KXdmOption2 ); + } + if( iXcapProtocol.AuthType() == EXcapAuthEarlyIms ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " EarlyIMS is in use => set KXdmOption4" ) ); + #endif + SetOption( KXdmOption4 ); + } + request->ExecuteL( iStatus, iOptions ); + SetActive(); + } + +// ---------------------------------------------------- +// CXcapDocument::SetOption +// +// ---------------------------------------------------- +// +void CXcapDocument::SetOption( TInt aOption ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::SetOption()" ) ); + #endif + iOptions |= aOption; + } + +// ---------------------------------------------------- +// CXcapDocument::CancelUpdate +// +// ---------------------------------------------------- +// +void CXcapDocument::CancelUpdate() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::CancelUpdate()" ) ); + #endif + TInt resolverError = 0; + if( iXcapProtocol.IsSimRequestPending( resolverError ) ) + { + iXcapProtocol.CancelImsResolver(); + } + else + { + switch( iDocumentState ) + { + case EResolvingAsyncConflict: + iTempCopy->CancelUpdate(); + break; + default: + { + TInt count = iChangeRequests.Count(); + if( count > 0 ) + { + MXdmOperation* request = iChangeRequests[iUpdateIndex]; + request->CancelOperation(); + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Operation %x cancelled" ), request ); + #endif + } + } + } + } + User::RequestComplete( iClientStatus, KErrCancel ); + } + +// --------------------------------------------------------- +// CXcapDocument::RunL() +// +// --------------------------------------------------------- +// +void CXcapDocument::RunL() + { + #ifdef _DEBUG + HBufC8* buf = HBufC8::NewLC( iDocumentName->Des().Length() ); + buf->Des().Copy( iDocumentName->Des() ); + TPtr8 nameDesc( buf->Des() ); + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::RunL()" ) ); + iXcapProtocol.WriteToLog( _L8( " Name: %S" ), &nameDesc ); + iXcapProtocol.WriteToLog( _L8( " Error: %d" ), iStatus.Int() ); + iXcapProtocol.WriteToLog( _L8( " Update index: %d" ), iUpdateIndex ); + CleanupStack::PopAndDestroy(); //buf + #endif + if( iStatus == KErrNone ) + { + switch( iDocumentState ) + { + case EXdmDocUpdating: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Document state: EXdmDocUpdating" ) ); + #endif + HandleRequestCompletionL(); + break; + case EResolvingAsyncConflict: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Document state: EResolvingAsyncConflict" ) ); + #endif + ResolveAsyncConflictL(); + break; + case ERetryingFailedOperation: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Document state: ERetryingFailedOperation" ) ); + #endif + ResolveAsyncConflictL(); + break; + default: + break; + } + } + else HandleErrorL(); + #ifdef _DEBUG + TInt biggestBlock( 0 ); + TInt memory( User::Available( biggestBlock ) ); + iXcapProtocol.WriteToLog( _L8( "** RunL() completes - Available memory: %d" ), memory ); + #endif + } + +// --------------------------------------------------------- +// CXcapDocument::HandleRequestCompletionL +// +// --------------------------------------------------------- +// +void CXcapDocument::HandleRequestCompletionL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::HandleRequestCompletionL()" ) ); + #endif + MXdmOperation* request = iChangeRequests[iUpdateIndex]; + const TXdmCompletionData& data = request->CompletionData(); + switch( data.iCompletion ) + { + case KInsertConflict: + ResolveAsyncConflictL(); + break; + default: + { + RXcapCache* cache = iXcapProtocol.Cache(); + if( cache ) + UpdateDocumentInfoL( cache ); + DequeueOperation( request ); + CheckOperationQueueL(); + break; + } + } + } + +// --------------------------------------------------------- +// CXcapDocument::ResolveAsyncConflictL +// +// --------------------------------------------------------- +// +void CXcapDocument::ResolveAsyncConflictL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::ResolveAsyncConflictL()" ) ); + #endif + switch( iDocumentState ) + { + //This means the cached version of this document + //is out-of-date and that it needs to be updated. + case EXdmDocUpdating: + { + CreateTempCopyL(); + iTempCopy->SetETag( iETagBuffer ); + iTempCopy->FetchDataL(); + iTempCopy->SaveClientStatus( iStatus ); + iTempCopy->StartUpdateL(); + iDocumentState = EResolvingAsyncConflict; + SetActive(); + } + break; + case EResolvingAsyncConflict: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Async conflict resolved, retry insert" ) ); + #endif + //CheckOperationQueueL() will increment the index + iUpdateIndex--; + SetETag( iTempCopy->ETag() ); + iDocumentState = ERetryingFailedOperation; + CheckOperationQueueL(); + break; + case ERetryingFailedOperation: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Operation retry ready" ) ); + #endif + //Nothing can be done now but instruct the + //client to re-fetch the whole document and + //retry the failed operation. + User::RequestComplete( iClientStatus, KErrPathNotFound ); + break; + default: + break; + } + } + +// --------------------------------------------------------- +// CXcapDocument::HandleErrorL +// +// --------------------------------------------------------- +// +void CXcapDocument::HandleErrorL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::HandleErrorL()" ) ); + #endif + TInt clientCode = KErrGeneral; + MXdmOperation* request = request = iChangeRequests[iUpdateIndex]; + //The TXdmCompletionData is guaranteed to point at something + const TXdmCompletionData& data = request->CompletionData(); + switch( data.iCompletion ) + { + case KErrCancel: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Update cancelled" ) ); + #endif + clientCode = KErrCancel; + break; + case ERetryingFailedOperation: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Operation retry failed" ) ); + #endif + //Nothing can be done now but instruct the + //client to re-fetch the whole document and + //retry the failed operation. + User::RequestComplete( iClientStatus, KXcapErrorUnrecoverableConflict ); + break; + case KXcapErrorHttpConflict: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Conflict, parse error document if available" ) ); + #endif + if( data.iResponseData != NULL ) + { + TInt error = KErrNone; + TPtrC8 errorData( data.iResponseData->Des() ); + TRAP( error, iXcapProtocol.Parser().ParseDocumentL( errorData, ErrorRoot() ) ); + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Parsing completed: %d" ), error ); + ErrorRoot()->Print(); + #endif + //Suppress build warning + error = KErrNone; + } + User::RequestComplete( iClientStatus, KXcapErrorHttpConflict ); + break; + case KXcapErrorNetworkNotAvailabe: + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Network not available, check cache" ) ); + #endif + if( iDataLength > 0 ) + { + RXcapCache* cache = iXcapProtocol.Cache(); + if( cache != NULL ) + { + TPtrC name( Name() ); + TInt error = KErrNone; + TPtrC8 root = iXcapProtocol.Transport().RootUri(); + HBufC8* data = HBufC8::NewLC( iDataLength ); + TPtr8 dataPtr( data->Des() ); + cache->FetchDocumentContent( dataPtr, name, root ); + TRAP( error, iXcapProtocol.Parser().ParseDocumentL( this, dataPtr ) ); + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Parsing completed: %d" ), error ); + #endif + //Suppress build warning + error = KErrNone; + CleanupStack::PopAndDestroy(); //data + } + } + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " No data in cache, nothing to do" ) ); + #endif + } + User::RequestComplete( iClientStatus, KXcapErrorNetworkNotAvailabe ); + } + break; + default: + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Default case - Result: %d" ), data.iCompletion ); + #endif + clientCode = iStatus.Int(); + User::RequestComplete( iClientStatus, clientCode ); + } + DequeueOperation( request ); + } + +// --------------------------------------------------------- +// CXcapDocument::CheckOperationQueueL +// +// --------------------------------------------------------- +// +void CXcapDocument::CheckOperationQueueL() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::CheckOperationQueueL()" ) ); + #endif + iUpdateIndex++; + if( iUpdateIndex < iOperationCount ) + ActivateOperationL(); + else + { + DequeueAll(); + iUpdateIndex = 0; + iXcapProtocol.CheckActivity(); + User::RequestComplete( iClientStatus, KErrNone ); + } + } + +// --------------------------------------------------------- +// CXcapDocument::DequeueOperation +// +// --------------------------------------------------------- +// +void CXcapDocument::DequeueOperation( MXdmOperation* aOperation ) + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::DequeueOperation()" ) ); + #endif + TInt index = iChangeRequests.Find( aOperation ); + if( index >= 0 ) + { + iChangeRequests.Remove( index ); + aOperation->Destroy(); + aOperation = NULL; + } + iOperationCount = iChangeRequests.Count(); + } + +// --------------------------------------------------------- +// CXcapDocument::DequeueAll +// +// --------------------------------------------------------- +// +void CXcapDocument::DequeueAll() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::DequeueAll()" ) ); + #endif + + while (iChangeRequests.Count() ) + { + MXdmOperation* request = iChangeRequests[0]; + iChangeRequests.Remove( 0 ); + request->Destroy(); + request = NULL; + } + } + +// --------------------------------------------------------- +// CXcapDocument::EightBitNameLC +// +// --------------------------------------------------------- +// +HBufC8* CXcapDocument::EightBitNameLC() + { + /*#ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::EightBitNameLC()" ) ); + #endif*/ + __ASSERT_DEBUG( Name().Length() > 0, User::Panic( _L( "CXcapDocument" ), 1 ) ); + HBufC8* buf = HBufC8::NewLC( Name().Length() ); + buf->Des().Copy( Name() ); + return buf; + } + +// --------------------------------------------------------- +// CXcapDocument::DocumentType +// +// --------------------------------------------------------- +// +TXdmDocType CXcapDocument::DocumentType() const + { + return iDocumentType; + } + +// --------------------------------------------------------- +// CXcapDocument::AppendNamespaceL +// +// --------------------------------------------------------- +// +void CXcapDocument::AppendNamespaceL( const TDesC8& aUri, const TDesC8& aPrefix ) + { + CXdmNamespace* ns = CXdmNamespace::NewL( aUri, aPrefix ); + CleanupStack::PushL( ns ); + User::LeaveIfError( iNamespaces.Append( ns ) ); + CleanupStack::Pop(); //ns + } + +// --------------------------------------------------------- +// CXcapDocument::RemoveNamespace +// +// --------------------------------------------------------- +// +void CXcapDocument::RemoveNamespace( const TDesC8& aUri ) + { + TBool found = EFalse; + CXdmNamespace* ns = NULL; + TInt count = iNamespaces.Count(); + for( TInt i = 0;!found && i < count;i++ ) + { + ns = iNamespaces[i]; + if( ns->Uri().Compare( aUri ) == 0 ) + { + found = ETrue; + iNamespaces.Remove( i ); + delete ns; + ns = NULL; + } + } + } + +// --------------------------------------------------------- +// CXcapDocument::Uri +// +// --------------------------------------------------------- +// +TPtrC8 CXcapDocument::Uri( const TDesC8& aPrefix ) const + { + TPtrC8 uri( _L8( "" ) ); + TBool found = EFalse; + TInt count = iNamespaces.Count(); + for( TInt i = 0;!found && i < count ;i++ ) + { + if( iNamespaces[i]->Prefix().Compare( aPrefix ) == 0 ) + { + uri.Set( iNamespaces[i]->Uri() ); + found = ETrue; + } + } + return uri; + } + +// --------------------------------------------------------- +// CXcapDocument::Count +// +// --------------------------------------------------------- +// +TInt CXcapDocument::Count() const + { + return iNamespaces.Count(); + } + +// --------------------------------------------------------- +// CXcapDocument::Prefix +// +// --------------------------------------------------------- +// +TPtrC8 CXcapDocument::Prefix( TInt aIndex ) const + { + TInt count = iNamespaces.Count(); + if( count > 0 && ( aIndex >= 0 && aIndex < count ) ) + return iNamespaces[aIndex]->Prefix(); + else return TPtrC8(); + } + +// --------------------------------------------------------- +// CXcapDocument::Uri +// +// --------------------------------------------------------- +// +TPtrC8 CXcapDocument::Uri( TInt aIndex ) const + { + TInt count = iNamespaces.Count(); + if( count > 0 && ( aIndex >= 0 && aIndex < count ) ) + return iNamespaces[aIndex]->Uri(); + else return TPtrC8(); + } + +// --------------------------------------------------------- +// CXcapDocument::ResetNamespaces +// +// --------------------------------------------------------- +// +void CXcapDocument::ResetNamespaces( ) + { + iNamespaces.ResetAndDestroy(); + } + +// --------------------------------------------------------- +// CXcapDocument::TimeStamp +// +// --------------------------------------------------------- +// +TTime CXcapDocument::TimeStamp() const + { + return iLastModification; + } + +// ---------------------------------------------------- +// CXdmDocument::SaveClientStatus +// +// ---------------------------------------------------- +// +void CXcapDocument::SaveClientStatus( TRequestStatus& aClientStatus ) + { + iClientStatus = &aClientStatus; + } + +// --------------------------------------------------------- +// CXcapDocument::DoCancel +// +// --------------------------------------------------------- +// +void CXcapDocument::DoCancel() + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( "CXcapDocument::DoCancel()" ) ); + #endif + if( iClientStatus ) + { + User::RequestComplete( iClientStatus, KErrCancel ); + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " Request completed" ) ); + #endif + } + else + { + #ifdef _DEBUG + iXcapProtocol.WriteToLog( _L8( " iClientStatus == NULL => do nothing" ) ); + #endif + } + } + + + +