xdmprotocols/XcapProtocol/XcapOperations/src/XcapRetrieval.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:05:17 +0200
changeset 0 c8caa15ef882
child 12 e6a66db4e9d0
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* 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:   CXcapRetrieval
*
*/




// INCLUDES
#include "XcapCache.h"
#include "XcapAppUsage.h"
#include "XcapDocument.h"
#include "XcapProtocol.h"
#include "XcapRetrieval.h"
#include "XcapUriParser.h"
#include "XdmXmlParser.h"
#include "XcapHttpReqGet.h"
#include "XcapHttpTransport.h"
#include "XcapOperationFactory.h"

// ================= MEMBER FUNCTIONS =======================

// ---------------------------------------------------------
// C++ constructor can NOT contain any code, that
// might leave.
// ---------------------------------------------------------
//
CXcapRetrieval::CXcapRetrieval( CXcapDocument& aParentDoc,
                                CXcapDocumentNode* aTargetNode,
                                CXcapOperationFactory& aOperationFactory ) :
                                CXcapHttpOperation( aParentDoc, aTargetNode, aOperationFactory ),
                                iCacheOperation( EFalse ),
                                iOperationType( aTargetNode == NULL ?
                                EXdmDocument : EXdmPartialDocument )                                  
    {
    }

// ---------------------------------------------------------
// CXcapRetrieval::NewL
//
// ---------------------------------------------------------
//
CXcapRetrieval* CXcapRetrieval::NewL( CXcapDocument& aParentDoc,
                                      CXcapDocumentNode* aTargetNode,
                                      CXcapOperationFactory& aOperationFactory )
    {
    CXcapRetrieval* self = new ( ELeave ) CXcapRetrieval( aParentDoc, aTargetNode, aOperationFactory );
    CleanupStack::PushL( self );
    self->BaseConstructL();
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

// ---------------------------------------------------------
// CXcapRetrieval::ConstructL
//
// ---------------------------------------------------------
//
void CXcapRetrieval::ConstructL()
    {
#ifdef _DEBUG
    iOperationFactory.WriteToLog( _L8( "-> CXcapRetrieval::ConstructL" ) );  
#endif
    CXcapHttpReqGet* request = Transport().GetL( iTargetDoc.Name() );
    CleanupStack::PushL( request );
    User::LeaveIfError( iRequestQueue.Append( request ) );
    request->SetExpiryTimeL( NULL, KDefaultHttpRequestTimeout * 1000000 );
    CleanupStack::Pop();  //request
    if( iOperationType != EXdmDocument && iDocumentSubset != NULL )
        {
        iUriParser->SetDocumentSubset( iDocumentSubset );
        //Add namespace mappings
        User::LeaveIfError( iTargetDoc.ApplicationUsage().Validate(
                            *iDocumentSubset, iUriParser, ETrue ) );
        }
#ifdef _DEBUG
    iOperationFactory.WriteToLog( _L8( "<- CXcapRetrieval::ConstructL" ) );  
#endif
    }

// ---------------------------------------------------------
// CXcapRetrieval::ExecuteL
//
// ---------------------------------------------------------
//
void CXcapRetrieval::ExecuteL()
    {
    #ifdef _DEBUG
        iOperationFactory.WriteToLog( _L8( "CXcapRetrieval::ExecuteL()" ) );  
    #endif
    TPtrC8 eTag = iTargetDoc.ETag();
    if( eTag.Length() > 0 )
        {
        #ifdef _DEBUG
            iOperationFactory.WriteToLog( _L8( " Using ETag \"%S\" - Length: %d" ),
                                               &eTag, eTag.Length() );  
        #endif
        //iActiveRequest->SetHeaderL( KHttpHeaderIfNoneMatch, eTag );
        }
    TRAPD( error, iUriParser->ParseL( iActiveRequest->RequestUriL() ) );
    if( error == KErrNone )
        {
        TPtrC8 uri = iUriParser->DesC8();
        HBufC8* escape = CXcapHttpOperation::EscapeLC( uri );
        iActiveRequest->UpdateRequestUriL( escape->Des() );
        CleanupStack::PopAndDestroy();  //escape
        #ifdef _DEBUG
            iOperationFactory.WriteToLog( _L8( " New URI: %S" ), &uri );  
        #endif
        }
    }
        
// ---------------------------------------------------------
// CXcapRetrieval::OperationCompleteL
//
/* const TDesC8& aETag, 
   const TDesC& aDocumentName,
   const TDesC8& aRootLocation,
   const TDesC8& aResponseData*/
// ---------------------------------------------------------
//
void CXcapRetrieval::OperationCompleteL()
    {
    #ifdef _DEBUG
        iOperationFactory.WriteToLog( _L8( "CXcapRetrieval::OperationCompleteL()" ) );  
    #endif
    TInt generalErr = ReinterpretStatus( iRequestData->iHttpStatus );
    if( generalErr == KErrNone )
        {
        #ifdef _DEBUG
            iOperationFactory.WriteToLog( _L8( " No general errors found" ) );  
        #endif
        iCacheOperation ? HandleCacheOperationL() : HandleNetworkOperationL();
        }
    else
        {
        #ifdef _DEBUG
            iOperationFactory.WriteToLog( _L8( " General errors found - Status: %d  Error: %d" ),
                                                   iRequestData->iHttpStatus, generalErr );  
        #endif
        iCompleted = ETrue;
        iResult = generalErr;
        }
    }

// ---------------------------------------------------------
// CXcapRetrieval::HandleCacheOperationL
//
// ---------------------------------------------------------
//
void CXcapRetrieval::HandleCacheOperationL()
    {
    #ifdef _DEBUG
        iOperationFactory.WriteToLog( _L8( "CXcapRetrieval::HandleCacheOperationL() - Operation type: %d  Target node: %x" ),
                                           iOperationType, iDocumentSubset );  
    #endif
    TPtrC8 responseData = Descriptor( iRequestData->iResponseData );
    iOperationType == EXdmDocument && iDocumentSubset == NULL ? 
        iXmlParser->ParseDocumentL( &iTargetDoc, responseData ) :
        iXmlParser->ParseDocumentL( &iTargetDoc, responseData, iDocumentSubset );
    iCompleted = ETrue;
    }
    
// ---------------------------------------------------------
// CXcapRetrieval::HandleNetworkOperationL
//
// ---------------------------------------------------------
//
void CXcapRetrieval::HandleNetworkOperationL()
    {
    #ifdef _DEBUG
        iOperationFactory.WriteToLog( _L8( "CXcapRetrieval::HandleNetworkOperationL()" ) );  
    #endif
    TPtrC name = iTargetDoc.Name();
    TPtrC8 root = Transport().RootUri();
    switch( iRequestData->iHttpStatus )
        {
        case 200:           //ETag was stale
            {
            #ifdef _DEBUG
                iOperationFactory.WriteToLog( _L8( " Status 200 - ETag was stale" ) );  
            #endif
            TPtrC8 responseData = Descriptor( iRequestData->iResponseData );
            if( responseData.Length() <= 0 )
                break;
            if( iOperationType == EXdmDocument )
                {
                TPtrC8 eTag = Descriptor( iRequestData->iETag );
                //If the ETag has not changed, server should return
                //304 (Not modified), but just in case, let's check the 
                //ETag value, anyway.
                if( eTag.Length() > 0 && eTag.Compare( iTargetDoc.ETag() ) != 0 )
                    {
                    iTargetDoc.SetETag( eTag );
                    RXcapCache* cache = iTargetDoc.Protocol().Cache();
                    if( cache && !( iOptionFlags & KNoCache ) )
                        cache->Store( iTargetDoc.ETag(), name, root, responseData  );
                    }
                else
                    {
                    #ifdef _DEBUG
                        iOperationFactory.WriteToLog( _L8( " ETag values match, do not update cache" ) );  
                    #endif
                    }
                iXmlParser->ParseDocumentL( &iTargetDoc, responseData );
                }
            else if( iOperationType == EXdmPartialDocument )
                {
                #ifdef _DEBUG  
                    iOperationFactory.WriteToLog( _L8( " Parse a partial document" ) );  
                #endif
                //The target node must be emptied before inserting new content
                iDocumentSubset->SetEmptyNode( ETrue );
                iDocumentSubset->SetEmptyNode( EFalse );
                iXmlParser->ParseDocumentL( responseData, iDocumentSubset );
               	}
            iCompleted = ETrue;
            }
            break;
        case 304:
            {
            RXcapCache* cache = iTargetDoc.Protocol().Cache();
            if( cache )
                {
                #ifdef _DEBUG   //ETag is up to date - cache still valid
                    iOperationFactory.WriteToLog( _L8( " Status 304 - Cached version is valid" ) );  
                #endif
                TInt length = iTargetDoc.DataLength();
                __ASSERT_DEBUG( length > 0, User::Panic( _L( "CXcapRetrieval" ), 1 ) );
                delete iRequestData->iResponseData;
                iRequestData->iResponseData = NULL;
                iRequestData->iResponseData = HBufC8::NewL( length );
                TPtr8 desc( iRequestData->iResponseData->Des() );
                cache->FetchDocumentContent( desc, name, root );
                if( iOperationType == EXdmDocument && !iTargetDoc.DocumentRoot() )
                	{
                	#ifdef _DEBUG  
                    	iOperationFactory.WriteToLog( _L8( " No content => parse cached document" ) );  
                	#endif
					iXmlParser->ParseDocumentL( &iTargetDoc, desc );
                	}
               	else if( iOperationType == EXdmPartialDocument )
               		{
               		#ifdef _DEBUG  
                    	iOperationFactory.WriteToLog( _L8( " Parse a partial document" ) );  
                	#endif
					iXmlParser->ParseDocumentL( &iTargetDoc, desc, iDocumentSubset );
               		}
                }
            iCompleted = ETrue;
            }
            break;
        default:
            #ifdef _DEBUG
                iOperationFactory.WriteToLog( _L8( " Default case - Status: %d" ),
                                                   iRequestData->iHttpStatus );  
            #endif
            iCompleted = ETrue;
            break;
        }
    }
  
// ---------------------------------------------------------
// CXcapRetrieval::OperationFailedL
//
// ---------------------------------------------------------
//
void CXcapRetrieval::OperationFailedL()
    {
    #ifdef _DEBUG
        iOperationFactory.WriteToLog( _L8( "CXcapRetrieval::OperationFailedL() - Error: %d" ),
                                        iStatus.Int() );  
    #endif
    if( iStatus.Int() >= KErrNone )
        {
        TInt status = iActiveRequest->ResponseData()->iHttpStatus;
        TInt completion = iActiveRequest->ResponseData()->iCompletion;
        iResult = status < KErrNone || completion < KErrNone ? status : ReinterpretStatus( status );
        }
    else iResult = iStatus.Int();
    iCompleted = ETrue;
    }
    
// ---------------------------------------------------------
// CXcapRetrieval::Result
//
// ---------------------------------------------------------
//
TInt CXcapRetrieval::Result() const
    {
    return iRequestData->iCompletion;
    }

// ---------------------------------------------------------
// CXcapRetrieval::~CXcapRetrieval
//
// ---------------------------------------------------------
//
CXcapRetrieval::~CXcapRetrieval()
    {
    #ifdef _DEBUG
        iOperationFactory.WriteToLog( _L8( "CXcapRetrieval::~CXcapRetrieval()" ) );  
    #endif
    }

//  End of File