--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webservices/wsibasicplugin/src/senbasicwebservicesession.cpp Thu Jan 07 16:19:19 2010 +0200
@@ -0,0 +1,529 @@
+/*
+* 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 "senbasicwebservicesession.h"
+#include "SenHttpTransportProperties.h" // could be system included (ADO task)
+#include "senservicesession.h"
+#include "SenSoapMessage.h"
+#include "SenSoapConstants.h" // KSenSoapActionHeaderName
+#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 <SenSoapFault.h>
+
+
+CSenBasicWebServiceSession* CSenBasicWebServiceSession::NewL(MSIF& aFramework)
+ {
+ CSenBasicWebServiceSession* pNew =
+ CSenBasicWebServiceSession::NewLC(aFramework);
+ CleanupStack::Pop();
+ return pNew;
+ }
+
+CSenBasicWebServiceSession* CSenBasicWebServiceSession::NewLC(MSIF& aFramework)
+ {
+ CSenBasicWebServiceSession* pNew =
+ new (ELeave) CSenBasicWebServiceSession(EBasicWebServiceSession,
+ aFramework);
+ CleanupStack::PushL(pNew);
+ // bugfix 2004-09-08,
+ // removed faulty call to CSenServiceSession::BaseConstructL
+ pNew->ConstructL();
+ return pNew;
+ }
+
+CSenBasicWebServiceSession::CSenBasicWebServiceSession(
+ TDescriptionClassType aType,
+ MSIF& aFramework)
+:
+CSenWebServiceSession(aType, aFramework)
+ {
+ }
+
+void CSenBasicWebServiceSession::ConstructL()
+ {
+ // Sets the local name to "ServiceDescription" and initiates the inner ipElement
+ CSenWebServiceSession::ConstructL();
+ }
+
+CSenBasicWebServiceSession::~CSenBasicWebServiceSession()
+ {
+ }
+
+// Override compute status to make BWS sessions to be ALWAYS valid (ready)
+TInt CSenBasicWebServiceSession::ComputeStatusL()
+ {
+ // session is ready, if an endpoint is defined
+ return CSenServiceSession::ComputeStatusL();
+ }
+
+TInt CSenBasicWebServiceSession::InitializeFromL(MSenServiceDescription& aServiceDescription)
+ {
+ TLSLOG(KSenCoreServiceManagerLogChannelBase , KMinLogLevel,(_L("CSenWebServiceSession::InitializeFromL")));
+
+ // Call superclass method to initialize facets, transport (endpoint) cue, etc..
+ TInt retVal = CSenWebServiceSession::InitializeFromL(aServiceDescription);
+ CSenWSDescription& xmlSD = (CSenWSDescription&)aServiceDescription;
+ TPtrC8 transportCue = xmlSD.TransportCue();
+ if( transportCue.Length() > 0 )
+ {
+ SetTransportCueL( transportCue );
+ }
+ return retVal;
+ }
+
+
+TInt CSenBasicWebServiceSession::SubmitSoapL( const TDesC8& aSoapMessage,
+ const TDesC8& aTransportProperties,
+ MSenRemoteServiceConsumer& aConsumer,
+ HBufC8*& aResponse )
+ {
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenWsiPlugin::RegisterServiceDescriptionL");
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenBasicWebServiceSession::SubmitSoapL(TDesC8&)");
+ 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("- Message (%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,"WS-I: (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,"WS-I: Response is a SOAP fault.");
+ retVal = KErrSenSoapFault;
+
+ if (!completeServerMessages)
+ {
+ CleanupStack::Pop(pResponseSoapMsg);
+ // try to detach the SOAP fault
+ HBufC8* pDetached = NULL;
+ retVal = 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,"WS-I: 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() , KNormalLogLevel,"- Detached SOAP message body.");
+ }
+ }
+ CleanupStack::PopAndDestroy(pResponseSoapMsg);
+ }
+ }
+ }
+ }
+#ifdef _SENDEBUG
+ if(aResponse)
+ {
+ CleanupStack::PushL(aResponse);
+ CSLOG_L(aConsumer.ConnectionId() , KNormalLogLevel,"- Detached SOAP message body.");
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenBasicWebServiceSession::SubmitSoapL:");
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _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 CSenBasicWebServiceSession::SendSoapL( const TDesC8& aSoapMessage,
+ const TDesC8& aTransportProperties,
+ MSenRemoteServiceConsumer& aConsumer,
+ TInt& aTxnId,
+ HBufC8*& /*aRevalidationError*/ )
+ {
+ TPtrC8 endpoint = Endpoint();
+#ifdef _SENDEBUG
+ CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////");
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenBasicWebServiceSession::SendSoapL:");
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"- Endpoint:");
+ TLSLOG(aConsumer.ConnectionId() , KMinLogLevel,( endpoint ));
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Message (%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.SendL( endpoint,
+ aSoapMessage,
+ aTransportProperties,
+ *this,
+ aConsumer,
+ aTxnId );
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Transaction id: %d"), aTxnId));
+ return retVal;
+ }
+
+TInt CSenBasicWebServiceSession::HttpMethodFromPropertiesL( const TDesC8& aProperties,
+ CSenHttpTransportProperties::TSenHttpMethod& aMethod )
+ {
+ TInt retVal(KErrNotFound);
+ if ( aProperties.Length() > 0 && aProperties.Find(KHttpMethodLocalName)!= KErrNotFound &&
+ (aProperties.Find(KHttpGet)!= KErrNotFound || aProperties.Find(KHttpDelete)!= KErrNotFound) )
+ {
+ // Properties strings are found, now use CSenHttpProperties instance to validate that HTTP
+ // method really is either HTTP GET or HTTP DELETE:
+ CSenHttpTransportProperties* pHttpProperties = CSenHttpTransportProperties::NewLC(); // push tp
+
+ // Parse aProperties into HTTP transport properties object:
+ TInt leaveCode( KErrNone );
+ TRAP( leaveCode, pHttpProperties->ReadFromL( aProperties ); )
+ if ( leaveCode == KErrNone )
+ {
+ CSenHttpTransportProperties::TSenHttpMethod method;
+ retVal = pHttpProperties->HttpMethodL( method );
+ if ( retVal == KErrNone )
+ {
+ aMethod = method;
+ }
+#ifdef _SENDEBUG
+ else
+ {
+ // HttpMethodL failed:
+ TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase , KMinLogLevel, _L8("- HttpMethodL call failed. Error code: (%d)"), retVal));
+ }
+#endif // _SENDEBUG
+ }
+#ifdef _SENDEBUG
+ else
+ {
+ // ReadFromL leaved:
+ TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase , KMinLogLevel, _L8("- Reading (parsing) of HTTP properties failed. Leave code: (%d)"), leaveCode));
+
+ }
+#endif // _SENDEBUG
+ CleanupStack::PopAndDestroy( pHttpProperties ); // de-alloc tp
+ }
+ return retVal;
+ }
+
+
+
+/*
+* @param aMessage contains request which is parsed into a SoapEnvelope object using
+* CSenWebServiceSession::MessageForSendingL and then SendSoapL is called
+*/
+TInt CSenBasicWebServiceSession::SendL( const TDesC8& aMessage,
+ const TDesC8& aTransportProperties,
+ MSenRemoteServiceConsumer& aConsumer,
+ TInt& aTxnId,
+ HBufC8*& aRevalidationError )
+ {
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenBasicWebServiceSession::SendL(TDesC8&, ...)");
+#ifdef _SENDEBUG
+ CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////");
+ TPtrC8 endpoint = Endpoint();
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("- Endpoint: %S"), &endpoint));
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Message (%d bytes):"), aMessage.Length()));
+ CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,( aMessage ));
+ CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////");
+#endif
+ TInt retVal(KErrNone);
+
+ // First check if HTTP GET or DELETE has been spesified via transport properties:
+ // -- in such case, the raw descriptor should be sent "as it is", without wrapping
+ // it inside SOAP Body. This way WS-I can support HTTP GET and DELETE and still
+ // validate that response(s) are SOAP (unlike REST, which does no response validation).
+
+ CSenHttpTransportProperties::TSenHttpMethod httpMethod;
+ TInt readHttpMethodRetVal = HttpMethodFromPropertiesL( aTransportProperties, httpMethod );
+
+ if ( readHttpMethodRetVal == KErrNone &&
+ httpMethod == CSenHttpTransportProperties::ESenHttpGet ||
+ httpMethod == CSenHttpTransportProperties::ESenHttpDelete )
+ {
+ // Perform direct call to service session (and not to web service session!)
+ retVal = CSenServiceSession::SendL( aMessage, aTransportProperties, aConsumer, aTxnId, aRevalidationError);
+ }
+ else
+ {
+ // The request data (UTF-8 descriptor) is expected to be serialized content
+ // for SOAP Body and HTTP GET/DELETE is not taking place.
+ // Proceed in standard way and parse the request with SOAP-ENV:
+ CSenSoapMessage* pMsg = NULL;
+ retVal = CSenWebServiceSession::MessageForSendingL( aMessage, aConsumer.Id(), pMsg );
+ CleanupStack::PushL( pMsg );
+ if ( retVal!=KErrNone )
+ {
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("- MessageForSendingL returned an error: %d"), retVal));
+ CleanupStack::PopAndDestroy( pMsg );
+ }
+ else // no error
+ {
+ HBufC8* pSoapMsg = pMsg->AsXmlL();
+ CleanupStack::PopAndDestroy( pMsg );
+ CleanupStack::PushL( pSoapMsg );
+ retVal = SendSoapL( *pSoapMsg, aTransportProperties, aConsumer, aTxnId, aRevalidationError);
+ CleanupStack::PopAndDestroy( pSoapMsg );
+ }
+ }
+ return retVal;
+ }
+
+/*
+* aMessage contains request which is parsed into a SoapEnvelope object using
+* CSenWebServiceSession::MessageForSendingL and then SubmitSoapL is called
+*/
+TInt CSenBasicWebServiceSession::SubmitL( const TDesC8& aMessage,
+ const TDesC8& aTransportProperties ,
+ MSenRemoteServiceConsumer& aConsumer ,
+ HBufC8*& aResponse )
+ {
+ CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenBasicWebServiceSession::SubmitL(TDesC8&, ...)");
+#ifdef _SENDEBUG
+ CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////");
+ TPtrC8 endpoint = Endpoint();
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("- Endpoint: %S"), &endpoint));
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Message (%d bytes) about to submit:"), aMessage.Length()));
+ CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,( aMessage ));
+ CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"///////////////////////////////////////////////////////");
+#endif
+ TInt retVal(KErrNone);
+ CSenHttpTransportProperties::TSenHttpMethod httpMethod;
+ TInt readHttpMethodRetVal = HttpMethodFromPropertiesL( aTransportProperties, httpMethod );
+
+ if ( readHttpMethodRetVal == KErrNone &&
+ httpMethod == CSenHttpTransportProperties::ESenHttpGet ||
+ httpMethod == CSenHttpTransportProperties::ESenHttpDelete )
+ {
+ // Perform direct call to service session (and not to web service session!)
+ retVal = CSenServiceSession::SubmitL( aMessage, aTransportProperties, aConsumer, aResponse);
+ }
+ else
+ {
+ CSenSoapMessage* pMsg = NULL;
+ retVal = CSenWebServiceSession::MessageForSendingL( aMessage, aConsumer.Id(), pMsg );
+ CleanupStack::PushL(pMsg);
+ if ( retVal!=KErrNone )
+ {
+ CSLOG_FORMAT((aConsumer.ConnectionId() , KMinLogLevel, _L8("- MessageForSendingL returned an error: %d"), retVal));
+ CleanupStack::PopAndDestroy( pMsg );
+ }
+ else // no error
+ {
+ HBufC8* pSoapMsg = pMsg->AsXmlL();
+ CleanupStack::PopAndDestroy( pMsg ); // de-alloc SOAP object after de-serialization
+ CleanupStack::PushL( pSoapMsg );
+ retVal = SubmitSoapL( *pSoapMsg, aTransportProperties, aConsumer, aResponse );
+ CleanupStack::PopAndDestroy( pSoapMsg );
+ }
+ }
+ return retVal;
+ }
+
+
+TBool CSenBasicWebServiceSession::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 direct superclass (may invoke chain of recursive calls)
+ return CSenWebServiceSession::HasSuperClass( aType );
+ }
+ }
+
+
+// TEMPORARY: remove when "message context"- and "transport factory taking
+// properties from all layers"- tasks are ready
+TInt CSenBasicWebServiceSession::SetFrameworkPropertiesL(MSenTransport& aTransport)
+ {
+ return iFramework.SetTransportPropertiesL(aTransport);
+ }
+TInt CSenBasicWebServiceSession::HandleSoapFaultL(CSenSoapMessage* apSOAPMessage,
+ const TInt aErrorCode,
+ const TInt aTxnId,
+ MSenRemoteServiceConsumer& aConsumer,
+ MSenProperties* aResponseTransportProperties)
+ {
+ LOG_WRITE_L("CSenBasicWebServiceSession::HandleSoapFaultL ");
+
+ TInt retVal(KErrNone);
+
+ if ( apSOAPMessage )
+ {
+ CleanupStack::PushL( apSOAPMessage );
+ CSenSoapFault* pDetached = apSOAPMessage->DetachFaultL();
+ if(pDetached)
+ {
+ LOG_WRITE_L("Detached a SOAP fault");
+ CleanupStack::PushL(pDetached);
+ HBufC8* pAsXml = pDetached->AsXmlL();
+ if(pAsXml)
+ {
+ aConsumer.HandleErrorL(pAsXml, KErrSenSoapFault, aTxnId, aResponseTransportProperties);
+ }
+ CleanupStack::PopAndDestroy();
+ retVal = KErrNone;
+ }
+ else
+ {
+ LOG_WRITE_L("No SOAP fault was received.");
+ aConsumer.HandleErrorL(NULL, aErrorCode, aTxnId, aResponseTransportProperties);
+ retVal = KErrSenInternal;
+ }
+ CleanupStack::PopAndDestroy( apSOAPMessage );
+ }
+
+
+
+ return retVal;
+ }
+TInt CSenBasicWebServiceSession::HandleSoapFaultL(CSenSoapMessage* apSOAPMessage,
+ HBufC8*& aResponse)
+{
+ return(CSenWebServiceSession::HandleSoapFaultL(apSOAPMessage,aResponse));
+}
+
+// End of File