diff -r 000000000000 -r 62f9d29f7211 webservices/wsrestplugin/src/senrestservicesession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webservices/wsrestplugin/src/senrestservicesession.cpp Thu Jan 07 16:19:19 2010 +0200 @@ -0,0 +1,419 @@ +/* +* Copyright (c) 2002-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: +* +*/ + + + + + + + + + + + + +// INCLUDE FILES +#include "senrestservicesession.h" +#include "senservicesession.h" +#include "SenSoapMessage.h" +#include "senwsdescription.h" +#include "msencoreservicemanager.h" +#include "msenremoteserviceconsumer.h" +#include "SenXmlUtils.h" +#include "SenDateUtils.h" +#include "msentransport.h" +#include "SenServiceConnection.h" +#include "sendebug.h" +#include "senlogger.h" +// #include "SenHttpTransportProperties.h" + +CSenRestServiceSession* CSenRestServiceSession::NewL(MSIF& aFramework) + { + CSenRestServiceSession* pNew = + CSenRestServiceSession::NewLC(aFramework); + CleanupStack::Pop(); + return pNew; + } + +CSenRestServiceSession* CSenRestServiceSession::NewLC(MSIF& aFramework) + { + CSenRestServiceSession* pNew = + new (ELeave) CSenRestServiceSession(ERestServiceSession, + aFramework); + CleanupStack::PushL(pNew); + pNew->ConstructL(); + return pNew; + } + +CSenRestServiceSession::CSenRestServiceSession(TDescriptionClassType aType, MSIF& aFramework) +: CSenWebServiceSession(aType, aFramework) + { + } + +void CSenRestServiceSession::ConstructL() + { + // sets the local name to "ServiceDescription" and + // initiates the inner ipElement + CSenWebServiceSession::ConstructL(); + } + +CSenRestServiceSession::~CSenRestServiceSession() + { + } + +// Override compute status to make REST sessions to be ALWAYS valid (ready) +TInt CSenRestServiceSession::ComputeStatusL() + { + // session is ready, if an endpoint is defined + return CSenServiceSession::ComputeStatusL(); + } + +TInt CSenRestServiceSession::SendSoapL( const TDesC8& aSoapMessage, + const TDesC8& aTransportProperties, + MSenRemoteServiceConsumer& aConsumer, + TInt& aTxnId, + HBufC8*& /*aRevalidationError*/ ) + { + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenRestServiceSession::SendSoapL"); + TPtrC8 endpoint = Endpoint(); +#ifdef _SENDEBUG + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("- Endpoint: %S"), &endpoint)); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Request (%d bytes):"), aSoapMessage.Length())); + CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,(aSoapMessage)); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); +#endif + + + + TInt retVal( aConsumer.TransportL().SendL( endpoint, + aSoapMessage, + aTransportProperties, + *this, + aConsumer, + aTxnId) ); + CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Transaction ID: %d"), aTxnId)); + return retVal; + } + +TInt CSenRestServiceSession::SubmitSoapL(const TDesC8& aSoapMessage, + const TDesC8& aTransportProperties, + MSenRemoteServiceConsumer& aConsumer, + HBufC8*& aResponse) + { + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenRestServiceSession::SubmitSoapL"); + TPtrC8 endpoint = Endpoint(); +#ifdef _SENDEBUG + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("- Endpoint: %S"), &endpoint)); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Request (%d bytes):"), aSoapMessage.Length())); + CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,(aSoapMessage)); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); +#endif + + MSenTransport& transport = aConsumer.TransportL(); + SetFrameworkPropertiesL(transport); + TInt retVal = transport.SubmitL( endpoint, + aSoapMessage, + aTransportProperties, + aResponse, + aConsumer); + if ( !aResponse ) + { + // response was NULL: probably either out + // of heap or some transport malfunction. + return retVal; + } + else if ( aResponse->Length() < KSenSoapEnvelopeName().Length()*2 ) + { + // no use parsing, Envelope -root element not there + // deliver non-soap body to consumer + return retVal; + } + + CleanupStack::PushL(aResponse); + + CSenSoapMessage* pResponseSoapMsg = NULL; + TInt leaveCode(KErrNone); + + // attempt to parse the response + // here. SOAP faults are to be + // searched after, + + TInt parseRetCode(KErrNone); + TRAP( leaveCode, (parseRetCode = + ParseResponseL(*aResponse, pResponseSoapMsg)) ); + + if(leaveCode!=KErrNone) + { + // THE RESPONSE could not be parsed + delete pResponseSoapMsg; + + // THE RESPONSE IS NOT SOAP + if(retVal==KErrNone) + { + // indicate with return value, that response is + // invalid - even though submit was ok, the + // response could NOT be parsed! + retVal = leaveCode; + } + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"(NOK) Response is not a SOAP message"); + } + else + { + + if (parseRetCode != KErrNone) + { + CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("(NOK) Parsing SOAP msg failed (%d)"), + parseRetCode)); + + if(retVal==KErrNone) // submit was ok + { + // indicate with return value, that response is + // invalid - even though submit was ok, the + // response could NOT be parsed! + retVal = parseRetCode; + } + + // THE RESPONSE could not be parsed + delete pResponseSoapMsg; + } + else + { + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"REST: (OK) Response is a SOAP message"); + CleanupStack::PushL(pResponseSoapMsg); + + TBool completeServerMessages(ETrue); + HasFacetL(KCompleteMessagesFacet, completeServerMessages); + + // response is OK and in SOAP form. + if(pResponseSoapMsg) + { + if (pResponseSoapMsg->IsFault()) + { + // response is SOAP fault + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"REST: Response is a SOAP fault."); + retVal = KErrSenSoapFault; + + if (!completeServerMessages) + { + // try to detach the SOAP fault + HBufC8* pDetached = NULL; + CleanupStack::Pop(pResponseSoapMsg); + retVal = CSenWebServiceSession::HandleSoapFaultL(pResponseSoapMsg, pDetached); + if(retVal == KErrSenSoapFault || retVal == KErrNone) + { + // KErrNone means that original fault was handled + // properly and we now have the wanted result + // and consumer may receive it (message body) + + // Note: currently we don't handle any SOAP faults + // in WebServiceSession class, so KErrNone should + // not be returned. The OR clause (||) here is + // only for future extensions. + delete aResponse; + aResponse = NULL; + aResponse = pDetached; + pDetached = NULL; + } + else if(retVal == KErrNotFound) + { + // SOAP fault element could not be found + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"REST: Major; SOAP fault element not found \ + even though assumed SOAP fault."); + retVal = KErrSenInternal; + } + } + else + { + CleanupStack::PopAndDestroy(pResponseSoapMsg); + } + } + else + { + // Check complete server messages on/off + if (!completeServerMessages) + { + HBufC8* pBody = pResponseSoapMsg->BodyAsStringL(); + if(pBody) + { + delete aResponse; + aResponse = NULL; + aResponse = pBody; + pBody = NULL; + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"- Detached SOAP message body."); + } + } + CleanupStack::PopAndDestroy(pResponseSoapMsg); + } + } + } + } + +#ifdef _SENDEBUG + if(aResponse) + { + CleanupStack::PushL(aResponse); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"--------------------------------------------------"); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"CSenRestServiceSession::SubmitSoapL:"); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Response (%d bytes):"), + aResponse->Length())); + CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,(*aResponse)); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"--------------------------------------------------"); + CleanupStack::Pop(); // aResponse + } +#endif + CleanupStack::Pop(); // aResponse + return retVal; + } + +TInt CSenRestServiceSession::CompleteServerMessagesOnOffL(const TBool& aCompleteOnOff) + { + // Now REST SIF supports CompleteServerMessagesOnOff + return CSenServiceSession::CompleteServerMessagesOnOffL(aCompleteOnOff); + } + + +TInt CSenRestServiceSession::SubmitL( const TDesC8& aMessage, + const TDesC8& aTransportProperties, + MSenRemoteServiceConsumer& aConsumer, + HBufC8*& aResponse ) + { + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenRestServiceSession::SubmitL(TDesC8&)"); + TPtrC8 endpoint = Endpoint(); +#ifdef _SENDEBUG + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Endpoint: %S"), &endpoint)); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Request (%d bytes):"), aMessage.Length())); + CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,(aMessage)); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); +#endif + + MSenTransport& transport = aConsumer.TransportL(); + SetFrameworkPropertiesL( transport ); + TInt retVal( transport.SubmitL( endpoint, + aMessage, + aTransportProperties, + aResponse, + aConsumer) ); + +#ifdef _SENDEBUG + if(aResponse) + { + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"---------------------------------------------------"); + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenRestServiceSession::SubmitL:"); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Response (%d bytes):"), aResponse->Length())); + CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,( *aResponse )); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"---------------------------------------------------"); + } +#endif + + return retVal; + } + + +TInt CSenRestServiceSession::SendL( const TDesC8& aMessage, + const TDesC8& aTransportProperties, + MSenRemoteServiceConsumer& aConsumer, + TInt& aTxnId, + HBufC8*& /* aRevalidationError*/ ) + { + // One could call the base class implementation in CSenServiceSession as well... + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenRestServiceSession::SendL"); + TPtrC8 endpoint = Endpoint(); +#ifdef _SENDEBUG + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Endpoint: %S"), &endpoint)); + CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Request (%d bytes):"), aMessage.Length())); + CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,( aMessage )); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////"); +#endif + + MSenTransport& transport = aConsumer.TransportL(); + SetFrameworkPropertiesL(transport); + + TInt retVal ( transport.SendL( endpoint, + aMessage, + aTransportProperties, + *this, + aConsumer, + aTxnId) ); + CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Transaction id: %d"), aTxnId)); + return retVal; + } + + + + +TInt CSenRestServiceSession::SendToConsumerL(HBufC8* apMessage, + const TInt aTxnId, + MSenRemoteServiceConsumer& aConsumer, + MSenProperties* aResponseTransportProperties) + { + TInt retVal(KErrNone); + + aConsumer.HandleMessageL(apMessage, aTxnId, aResponseTransportProperties); + + return retVal; + } + +// THIS IS WHAT TRANSPORT SEES: +TInt CSenRestServiceSession::SendErrorToConsumerL(const TInt aErrorCode, + HBufC8* apError, + const TInt aTxnId, + MSenRemoteServiceConsumer& aConsumer, + MSenProperties* aResponseTransportProperties) + { + TInt retVal(KErrNone); + + retVal = HandleErrorL(aErrorCode, apError, aTxnId, aConsumer, aResponseTransportProperties); + return retVal; + } + +TInt CSenRestServiceSession::HandleErrorL(const TInt aErrorCode, + HBufC8* apError, + const TInt aTxnId, + MSenRemoteServiceConsumer& aConsumer, + MSenProperties* aResponseTransportProperties) + { + TInt retVal(KErrNone); + // Implementation does not handle non-SOAP errors. + retVal = aConsumer.HandleErrorL(apError, aErrorCode, aTxnId, aResponseTransportProperties); + return retVal; + } + +TBool CSenRestServiceSession::HasSuperClass( TDescriptionClassType aType ) + { + if( aType == MSenServiceDescription::EWebServiceSession ) // direct superclass! + { + // If asked type is the know *direct* father/mother, return true: + return ETrue; + } + else + { + // Otherwise, ask from superclass (chain, recursively) + return CSenWebServiceSession::HasSuperClass( aType ); + } + } + +// TEMPORARY: remove when "message context"- and "transport factory taking +// properties from all layers"- tasks are ready +TInt CSenRestServiceSession::SetFrameworkPropertiesL(MSenTransport& aTransport) + { + return iFramework.SetTransportPropertiesL(aTransport); + } +// End of File