xdmprotocols/XcapProtocol/XcapOperations/src/XcapHttpOperation.cpp
branchRCL_3
changeset 18 fbd2e7cec7ef
parent 0 c8caa15ef882
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xdmprotocols/XcapProtocol/XcapOperations/src/XcapHttpOperation.cpp	Wed Sep 01 12:23:14 2010 +0100
@@ -0,0 +1,547 @@
+/*
+* 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:   CXcapHttpOperation
+*
+*/
+
+
+
+#include <XdmErrors.h>
+#include <escapeutils.h>
+#include "XcapDocument.h"
+#include "XcapProtocol.h"
+#include "XcapAppUsage.h"
+#include "XcapUriParser.h"
+#include "XdmXmlParser.h"
+#include "XcapHttpRequest.h"
+#include "XdmNodeAttribute.h"
+#include "XcapEngineDefines.h"
+#include "XcapHttpOperation.h"
+#include "XcapHttpContSupplier.h"
+#include "XcapOperationFactory.h"
+
+// ---------------------------------------------------------
+// C++ constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------
+//
+CXcapHttpOperation::CXcapHttpOperation( const CXdmDocument& aTargetDoc,
+                                        CXcapDocumentNode* aDocumentSubset,
+                                        CXcapOperationFactory& aOperationFactory ) :
+                                        CActive( EPriorityStandard ),
+                                        iDocumentSubset( aDocumentSubset ),
+                                        iTargetDoc( ( CXcapDocument& )aTargetDoc ),
+                                        iOperationFactory( aOperationFactory ) 
+                                                                                
+    {
+    }
+
+// ---------------------------------------------------------
+// CXcapHttpOperation::BaseConstructL
+//
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::BaseConstructL()
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "-> CXcapHttpOperation::BaseConstructL" ) ); 
+    #endif
+    iXmlParser = &iTargetDoc.Protocol().Parser();
+    iUriParser = CXcapUriParser::NewL( iTargetDoc, iOperationFactory );
+    #ifdef _DEBUG
+        TPtrC8 contType( iTargetDoc.ApplicationUsage().ContentType() );
+        iOperationFactory.WriteToLog( _L8( " Content-Type: %S" ), &contType ); 
+    #endif
+    CActiveScheduler::Add( this );
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "<- CXcapHttpOperation::BaseConstructL" ) ); 
+    #endif
+    }
+
+// ---------------------------------------------------------
+// Destructor
+//
+// ---------------------------------------------------------
+//
+CXcapHttpOperation::~CXcapHttpOperation()
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::~CXcapHttpOperation()" ) );  
+    #endif
+    delete iUriParser;
+    iRequestQueue.ResetAndDestroy();
+    }
+
+// ---------------------------------------------------------
+// CXcapOperationBase::IsCompleted
+//
+// ---------------------------------------------------------
+//
+TBool CXcapHttpOperation::IsCompleted() const
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapOperationBase::IsCompleted()" ) );  
+    #endif
+    return iCompleted;
+    }
+    
+// ---------------------------------------------------------
+// CXcapOperationBase::CompletionData
+//
+// ---------------------------------------------------------
+//
+const TXdmCompletionData& CXcapHttpOperation::CompletionData() const
+    {
+    return *iRequestData;
+    }
+
+// ---------------------------------------------------------
+// CXcapOperationBase::CompletionData
+//
+// ---------------------------------------------------------
+//
+CXdmDocumentNode* CXcapHttpOperation::TargetNode() const
+    {
+    return iDocumentSubset;
+    }
+    
+// ---------------------------------------------------------
+// CXcapOperationBase::CompletionData
+//
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::Destroy()
+    {
+    delete this;
+    }
+    
+// ---------------------------------------------------------
+// CXcapHttpOperation::Result
+//
+// ---------------------------------------------------------
+//
+TInt CXcapHttpOperation::Result() const
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::Result()" ) );  
+    #endif
+    return iRequestData != NULL ? iRequestData->iHttpStatus : KErrUnknown;
+    }
+
+// ---------------------------------------------------------
+// CXcapHttpOperation::ExecuteL
+//
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::ExecuteL( TRequestStatus& aStatus, TUint aOptions )
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::ExecuteL( &status )" ) );  
+    #endif
+    iOptionFlags = aOptions;
+    iClientStatus = &aStatus;
+    aStatus = KRequestPending;
+    if( !IsActive() )
+        {
+        iActiveRequest = iRequestQueue[iCurrentIndex];
+        TRAPD( error, ExecuteL() );
+        if( error == KErrNone )
+            {
+            if( StartOperationL() )
+                SetActive();
+            else
+                {
+                iFailureData.iCompletion = KXcapErrorNetworkNotAvailabe;
+                User::RequestComplete( iClientStatus, KXcapErrorNetworkNotAvailabe );
+                iRequestData = &iFailureData;
+                }      
+            }
+        else
+            {
+            #ifdef _DEBUG
+                iOperationFactory.WriteToLog( _L8( " Execution failed with %d" ), error );  
+            #endif
+            iFailureData.iCompletion = error;
+            User::RequestComplete( iClientStatus, error );
+            iRequestData = &iFailureData;
+            }
+        }
+    else  //This is a re-run of a previously failed request
+        {
+        if( !StartOperationL() )
+            {
+            #ifdef _DEBUG
+                iOperationFactory.WriteToLog( _L8( " Execution succeeded, network not ready" ) );  
+            #endif
+            User::RequestComplete( iClientStatus, KXcapErrorNetworkNotAvailabe );
+            }
+        }  
+    }
+
+// ---------------------------------------------------------
+// CXcapHttpOperation::ExecuteL
+//       
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::ExecuteL( CXcapHttpRequest* aHttpRequest,
+                                   CXdmDocumentNode* aDocumentNode )
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapAddition::ExecuteL()" ) );  
+    #endif
+    CXdmDocumentNode* node = aDocumentNode == NULL ?
+                             iTargetDoc.DocumentRoot() : aDocumentNode;
+    __ASSERT_ALWAYS( node != NULL, User::Panic( _L( "CXcapAddition" ), 1 ) );
+    User::LeaveIfError( FormatModRequestL( node ) );
+    TRAPD( error, iUriParser->ParseL( aHttpRequest->RequestUriL() ) );
+    if( error == KErrNone )
+        {
+        TPtrC8 uri = iUriParser->DesC8();
+        HBufC8* escape = CXcapHttpOperation::EscapeLC( uri );
+        aHttpRequest->UpdateRequestUriL( escape->Des() );
+        CleanupStack::PopAndDestroy();  //escape
+        }
+    }
+    
+// ---------------------------------------------------------
+// CXcapHttpOperation::StartOperationL
+//
+// ---------------------------------------------------------
+//
+TBool CXcapHttpOperation::StartOperationL()
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::StartOperationL()" ) );  
+    #endif
+    if( iTargetDoc.Protocol().IsNetworkAvailable() )
+        {
+        #ifdef _DEBUG
+            iOperationFactory.WriteToLog( _L8( " All set, dispatch request to transport" ) );  
+        #endif
+        if( iOptionFlags & KUseIntendedIdentity )
+            {
+            TPtrC8 identity( iTargetDoc.Protocol().PublicID() );
+            #ifdef _DEBUG
+                iOperationFactory.WriteToLog( _L8( " Early-IMS set, add X-3GPP-Intended-Identity header" ) );
+                iOperationFactory.WriteToLog( _L8( "  Public ID: %S" ), &identity );  
+            #endif
+            iActiveRequest->SetHeaderL( KHttpHeaderIntIdentity, identity );
+            }
+        iActiveRequest->DispatchRequestL( iStatus );
+        return ETrue;
+        }
+    else return EFalse;
+    }
+    
+// ---------------------------------------------------------
+// CXcapHttpOperation::RunL
+//
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::RunL()
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( 
+        "CXcapHttpOperation::RunL() - Status: %d" ), iStatus.Int() );  
+    #endif
+    TInt count = iRequestQueue.Count();
+    iRequestData = iActiveRequest->ResponseData();
+    __ASSERT_DEBUG( iRequestData != NULL, User::Panic( _L( "CXcapHttpOperation" ), 1 ) );
+    TRAPD( error, iStatus != KErrNone ? OperationFailedL() : OperationCompleteL() );
+    if( error == KErrNone && !iCompleted )
+        SetActive();
+    else
+        {
+        #ifdef _DEBUG
+            iOperationFactory.WriteToLog( _L8( 
+                "  ** Operation completed - Result: %d  Error: %d **" ), iResult, error );  
+        #endif
+        iCurrentIndex = 0;
+        iResult = error < KErrNone ? error : iResult;
+        iRequestData->iCompletion = iResult;
+        User::RequestComplete( iClientStatus, iResult );
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapRetrieval::CancelOperation
+//
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::CancelOperation()
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::CancelOperation()" ) );  
+    #endif
+    if( IsActive() )
+        {
+        #ifdef _DEBUG
+            iOperationFactory.WriteToLog( _L8( "Active, cancel HTTP request" ) );  
+        #endif
+        Cancel();
+        iRequestData = &iFailureData;
+        iFailureData.iCompletion = KErrCancel;
+        User::RequestComplete( iClientStatus, KErrCancel );
+        }
+    }
+    
+// ---------------------------------------------------------
+// CXcapHttpOperation::CancelOperation
+//
+// ---------------------------------------------------------
+//
+void CXcapHttpOperation::DoCancel()
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::DoCancel()" ) );  
+    #endif
+    iRequestQueue[iCurrentIndex]->CancelRequest();   
+    }
+
+// ---------------------------------------------------------
+// CXcapHttpOperation::Descriptor
+//
+// ---------------------------------------------------------
+//
+TPtrC8 CXcapHttpOperation::Descriptor( HBufC8* aBuffer )
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::Descriptor()" ) );  
+    #endif
+    if( aBuffer != NULL )
+        {
+        TPtrC8 descriptor( aBuffer->Des() );
+        return descriptor.Length() > 0 ? descriptor : TPtrC8();
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iOperationFactory.WriteToLog( _L8( " Buffer is NULL, return empty descriptor" ) );  
+        #endif
+        return TPtrC8();
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapHttpOperation::Transport
+//
+// ---------------------------------------------------------
+//
+CXcapHttpTransport& CXcapHttpOperation::Transport() const
+    {
+    return iTargetDoc.Protocol().Transport();
+    }
+    
+// ---------------------------------------------------------
+// CXcapHttpOperation::FormatModRequestL
+//
+// ---------------------------------------------------------
+//
+TInt CXcapHttpOperation::FormatModRequestL( const CXdmDocumentNode* aDocumentNode )
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::FormatModRequestL()" ) );  
+    #endif
+    HBufC8* body = NULL;
+    TInt error = KErrNone;
+    CXcapAppUsage& usage = iTargetDoc.ApplicationUsage();
+    CXcapHttpContSupplier* request = ( CXcapHttpContSupplier* )iActiveRequest;
+    switch( iUriParser->NodeType() )
+        {
+        case EXdmElementAttribute:
+            {
+            CXdmNodeAttribute* attribute = ( CXdmNodeAttribute* )aDocumentNode;
+            body = attribute->EightBitValueLC();
+            request->SetRequestBodyL( body->Des() );
+            CleanupStack::PopAndDestroy();  //body
+            request->SetHeaderL( KHttpHeaderAccept, _L8( "application/xcap-diff+xml" ) );
+            request->SetHeaderL( KHttpHeaderContentType, _L8( "application/xcap-att+xml" ) );
+            }
+            break;
+        case EXdmElementNode:
+            {
+            #ifndef __OVERRIDE_VALIDATION__
+                error = usage.Validate( CONST_CAST( CXdmDocumentNode&, *aDocumentNode ), iUriParser, EFalse );
+            #endif
+            if( error == KErrNone )
+                {
+                #ifdef _DEBUG
+                    iOperationFactory.WriteToLog( _L8( " Validation of a partial document OK" ) );  
+                #endif
+                body = iXmlParser->FormatToXmlLC( EFalse, &iTargetDoc, aDocumentNode );
+                request->SetRequestBodyL( body->Des() );
+                CleanupStack::PopAndDestroy();  //body
+                request->SetHeaderL( KHttpHeaderAccept, _L8( "application/xcap-diff+xml" ) );
+                request->SetHeaderL( KHttpHeaderContentType, _L8( "application/xcap-el+xml" ) );
+                }
+            else
+                {
+                #ifdef _DEBUG
+                    iOperationFactory.WriteToLog( _L8( " Validation failed: %d" ), error );  
+                #endif
+                }
+            }
+            break;
+        default:
+        #ifndef __OVERRIDE_VALIDATION__
+            error = usage.Validate( iTargetDoc, ETrue );
+        #endif
+            if( error == KErrNone )
+                {
+                #ifdef _DEBUG
+                    iOperationFactory.WriteToLog( _L8( " Validation OK" ) );  
+                #endif
+                body = iXmlParser->FormatToXmlLC( ETrue, &iTargetDoc, aDocumentNode );
+                request->SetRequestBodyL( body->Des() );
+                CleanupStack::PopAndDestroy();  //body
+                }
+            else
+                {
+                #ifdef _DEBUG
+                    iOperationFactory.WriteToLog( _L8( " Validation failed: %d" ), error );  
+                #endif
+                }
+            break;
+        }
+    return error;
+    }
+
+// ----------------------------------------------------------
+// CXcapHttpOperation::ReinterpretStatus
+// 
+// ----------------------------------------------------------
+//
+TInt CXcapHttpOperation::ReinterpretStatus( const TInt aHttpStatus ) const
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::ReinterpretStatus()" ) );  
+    #endif
+    switch( aHttpStatus )
+        {
+        case 500:  //Internal Server Error
+        case 501:  //Not Implemented
+        case 502:  //Bad Gateway
+        case 503:  //Service Unavailable
+        case 504:  //Gateway Timeout
+        case 505:  //HTTP Version Not Supported
+        case 405:  //Method Not Allowed
+		case 408:  //Request Timeout
+		case 410:  //Gone
+		case 411:  //Length Required
+		case 413:  //Request Entity Too Large
+		case 414:  //Request-URI Too Long
+		case 415:  //Unsupported Media Type
+		case 416:  //Requested Range Not Satisfiable
+		case 417:  //Expectation Failed
+            return KXcapErrorHttpServer;
+        case 400:
+            return KXcapErrorHttpBadRequest;
+        case 401:
+            return KXcapErrorHttpUnauthorised;
+        case 403:
+            return KXcapErrorHttpForbidden;
+        case 404:
+            return KXcapErrorHttpNotFound;
+        case 409:
+            return KXcapErrorHttpConflict;
+        case 412:
+            return KXcapErrorHttpPrecondFailed;
+        default:
+            return KErrNone;
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapHttpOperation::Escape2LC
+// 
+// ---------------------------------------------------------
+//
+HBufC8* CXcapHttpOperation::Escape2LC( const TDesC& aDescriptor )
+    {
+    HBufC8* eight = EscapeUtils::ConvertFromUnicodeToUtf8L( aDescriptor );
+    CleanupStack::PushL( eight );
+    HBufC8* buf = EscapeUtils::EscapeEncodeL( eight->Des(), EscapeUtils::EEscapeNormal );
+    CleanupStack::PopAndDestroy();  //eight
+    CleanupStack::PushL( buf );
+    return buf;
+    }
+    
+// ---------------------------------------------------------
+// CXcapHttpOperation::EscapeLC
+// 
+// ---------------------------------------------------------
+//
+HBufC8* CXcapHttpOperation::EscapeLC( const TDesC8& aDescriptor )
+    {
+    CBufFlat* buffer = CBufFlat::NewL( 50 );
+    CleanupStack::PushL( buffer );
+    TInt bufPos = 0;
+    TBuf8<10> format;
+    for( TInt i = 0;i < aDescriptor.Length();i++ )
+        {
+        TUint8 byte = aDescriptor[i];
+        if( byte < 0x7F )                 //US-ASCII
+            {
+            switch( byte )
+                {
+                case 0x20:                // ' '
+                case 0x22:                // '"'
+                case 0x3B:                // ';'                 
+                case 0x26:                // '&'                  
+                case 0x3C:                // '<'                  
+                case 0x3E:                // '>'
+                case 0x5B:                // '['
+                case 0x5D:                // ']'                              
+                    format.Append( _L8( "%" ) );
+                    format.AppendFormat( _L8( "%x" ), byte );
+                    break;               
+                default:
+                    format.Append( byte );
+                    break;
+                }
+            }
+        else
+            {
+            format.Append( _L8( "%" ) );  //UNICODE
+            format.AppendFormat( _L8( "%x" ), byte );
+            }
+        buffer->InsertL( bufPos, format );
+        bufPos = bufPos + format.Length();
+        format.Zero();
+        }
+    HBufC8* ret = HBufC8::NewL( buffer->Size() );
+    TPtr8 pointer( ret->Des() );
+    buffer->Read( 0, pointer, buffer->Size() );
+    CleanupStack::PopAndDestroy();  //buffer
+    CleanupStack::PushL( ret );
+    return ret;
+    }
+               
+// ---------------------------------------------------------
+// CXcapHttpOperation::HttpRequest
+//
+// ---------------------------------------------------------
+//
+CXcapHttpRequest* CXcapHttpOperation::HttpRequest() const
+    {
+    #ifdef _DEBUG
+        iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::HttpRequest()" ) );  
+    #endif
+    return iActiveRequest;
+    }
+
+
+
+//  End of File  
+