--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webservices/wsutils/src/sensoapenvelope.cpp Thu Jan 07 16:19:19 2010 +0200
@@ -0,0 +1,513 @@
+/*
+* 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 <s32strm.h>
+
+#include <SenXmlElement.h>
+#include <SenXmlUtils.h>
+#include <SenDomFragment.h>
+
+#include "SenSoapEnvelope.h"
+#include "SenSoapFault.h"
+#include "senlogger.h"
+
+#ifdef _SENDEBUG
+namespace
+ {
+ _LIT8(KVersionMismatchFormat8, "Fault.SOAP1.2 : %S");
+ }
+
+#endif // _SENDEBUG
+
+EXPORT_C CSenSoapEnvelope* CSenSoapEnvelope::NewL()
+ {
+ CSenSoapEnvelope* pNew = new (ELeave) CSenSoapEnvelope();
+ CleanupStack::PushL(pNew);
+ pNew->BaseConstructL();
+ CleanupStack::Pop(); // pNew;
+ return pNew;
+ }
+
+EXPORT_C void CSenSoapEnvelope::BaseConstructL(TSOAPVersion aVersion)
+ {
+ if (aVersion != ESOAP12)
+ {
+ CSenBaseFragment::BaseConstructL(KSenSoapEnvelopeXmlns, KSenSoapEnvelopeName, KSenSoapEnvelopeQName);
+ }
+ else
+ {
+ CSenBaseFragment::BaseConstructL(KSenSoap12EnvelopeXmlns, KSenSoapEnvelopeName, KSenSoapEnvelopeQName);
+ }
+ }
+
+EXPORT_C void CSenSoapEnvelope::BaseConstructL()
+ {
+ BaseConstructL(ESOAP11);
+ }
+
+CSenSoapEnvelope::CSenSoapEnvelope()
+: ipBodyFragment(NULL),
+ ipHeaderFragment(NULL),
+ ipSoapAction(NULL),
+ iFault(EFalse)
+ {
+ }
+
+EXPORT_C CSenSoapEnvelope::~CSenSoapEnvelope()
+ {
+ if(ipBodyFragment)
+ {
+ ipBodyFragment->ExtractElement();
+ delete ipBodyFragment;
+ }
+ if(ipHeaderFragment)
+ {
+ ipHeaderFragment->ExtractElement(); // // delegate's element is owned by us
+ delete ipHeaderFragment;
+ }
+ delete ipSoapAction;
+ }
+
+EXPORT_C void CSenSoapEnvelope::StartElementL(const TDesC8& aNsUri,
+ const TDesC8& aLocalName,
+ const TDesC8& aQName,
+ const RAttributeArray& aAttributes)
+ {
+ switch (iState)
+ {
+ case KStateIgnore:
+ {
+ // check if we encounter the start of a soap:Envelope...
+ if(!ipElement && aNsUri == NsUri() &&
+ aLocalName == KSenSoapEnvelopeName)
+ {
+ ipElement = CSenXmlElement::NewL(aNsUri, aLocalName, aQName);
+ }
+ if (ipElement && aLocalName == KSenSoapEnvelopeName && aNsUri!=NsUri())
+ {
+ TLSLOG_FORMAT((KSenFaultsLogChannel, KSenFaultsLogLevel, KVersionMismatchFormat8, &KVersionMismatch()));
+ delete ipElement;
+ ipElement = NULL;
+ CSenBaseFragment::BaseConstructL(aNsUri, aLocalName, aQName);
+ }
+ if(ipElement && ipElement->LocalName() == aLocalName &&
+ ipElement->NamespaceURI() == aNsUri)
+ {
+ if ( ipElement->NsPrefix() != SenXmlUtils::NsPrefix(aQName) )
+ {
+ delete ipElement;
+ ipElement = NULL;
+ CSenBaseFragment::BaseConstructL(aNsUri, aLocalName, aQName);
+ }
+ else
+ {
+ ipElement->Set(aNsUri, aLocalName, aQName);
+ }
+
+ SetAttributesL(aAttributes); // results in
+ }
+
+ else if(aNsUri == NsUri())
+ {
+ // we are interested in SOAP Header
+ if(aLocalName == KSenSoapEnvelopeHeaderName)
+ {
+ iState = KStateParsingSoapHeader;
+
+ // Make sure that header element exists:
+ // == this ensures that we add a "Header"
+ // element to the children:
+ CSenElement& header = HeaderL();
+ header.Set(aNsUri, aLocalName, aQName);
+ header.AddAttributesL(aAttributes);
+ }
+ else if(aLocalName == KSenSoapEnvelopeBodyName)
+ {
+ iState = KStateParsingSoapBody;
+
+ CSenElement& body = BodyL();
+ body.Set(aNsUri, aLocalName, aQName);
+ body.AddAttributesL(aAttributes);
+ }
+ //ESLI-6WEN9V
+ //This case is to handle fault which lies outside the body or without body
+ else if(aLocalName == KSenSoapFaultName)
+ {
+ iFault = ETrue;
+ // delegate parsing to a SOAPFaultFragment to keep
+ // a structured representation.
+ CSenSoapFault* pSOAPFault =
+ CSenSoapFault::NewL(aNsUri, aLocalName, aQName, aAttributes);
+ CleanupStack::PushL(pSOAPFault);
+ // use DOM fragment copy constructor to get correct type
+ // of element inside of it.
+ ipBodyFragment = CSenDomFragment::NewL(*pSOAPFault);
+ CleanupStack::PopAndDestroy(); // pSOAPFault
+ ipBodyFragment->SetOwner(*this);
+ BodyL().AddElementL(ipBodyFragment->AsElement());
+ ipBodyFragment->ParseWithL(*Reader());
+ }
+ //ESLI-6WEN9V
+ }
+ break;
+ }
+ case KStateParsingSoapHeader:
+ {
+ ParseHeaderL(aNsUri, aLocalName, aQName, aAttributes);
+ }
+ break;
+ case KStateParsingSoapBody:
+ {
+ if(ipBodyFragment)
+ {
+ ipBodyFragment->ExtractElement();
+ delete ipBodyFragment;
+ ipBodyFragment = NULL;
+ }
+
+ // check if we encounter a Fault
+ if (aLocalName == KSenSoapFaultName)
+ {
+ iFault = ETrue;
+ // delegate parsing to a SOAPFaultFragment to keep
+ // a structured representation.
+ CSenSoapFault* pSOAPFault =
+ CSenSoapFault::NewL(aNsUri, aLocalName, aQName, aAttributes);
+ CleanupStack::PushL(pSOAPFault);
+ // use DOM fragment copy constructor to get correct type
+ // of element inside of it.
+ ipBodyFragment = CSenDomFragment::NewL(*pSOAPFault);
+ CleanupStack::PopAndDestroy(); // pSOAPFault
+ ipBodyFragment->SetOwner(*this);
+ BodyL().AddElementL(ipBodyFragment->AsElement());
+ ipBodyFragment->ParseWithL(*Reader());
+ }
+ else
+ {
+ ipBodyFragment =
+ CSenBaseFragment::NewL( aNsUri,
+ aLocalName,
+ aQName,
+ aAttributes);
+
+ ipBodyFragment->SetOwner(*this);
+ BodyL().AddElementL(ipBodyFragment->AsElement());
+ ipBodyFragment->ParseWithL(*Reader());
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+EXPORT_C void CSenSoapEnvelope::EndElementL(const TDesC8& aNsUri,
+ const TDesC8& aLocalName,
+ const TDesC8& /*aQName*/)
+ {
+ switch (iState)
+ {
+ case KStateIgnore:
+ {
+ break;
+ }
+ case KStateParsingSoapHeader:
+ {
+ if (aNsUri == NsUri() && aLocalName == KSenSoapEnvelopeHeaderName)
+ {
+ iState = KStateIgnore;
+ }
+ break;
+ }
+ case KStateParsingSoapBody:
+ {
+ if (aNsUri == NsUri() && aLocalName == KSenSoapEnvelopeBodyName)
+ {
+ iState = KStateIgnore;
+ }
+/*
+ else
+ {
+ if(ipBodyFragment)
+ {
+ //ipBodyFragment->EnsureNamespacesL();
+ }
+ }
+*/
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+EXPORT_C TPtrC8 CSenSoapEnvelope::SetBodyL(const TDesC8& aBody)
+ {
+ return BodyL().SetContentL(aBody);
+ }
+
+EXPORT_C CSenElement& CSenSoapEnvelope::BodyL()
+ {
+ CSenElement& envelope = this->AsElement();
+ CSenElement* pBody = envelope.Element(NsUri(), KSenSoapEnvelopeBodyName);
+ if (pBody == NULL)
+ {
+ pBody = &envelope.AddElementL(NsUri(), KSenSoapEnvelopeBodyName);
+ }
+ return *pBody;
+ }
+
+EXPORT_C CSenElement& CSenSoapEnvelope::HeaderL()
+ {
+ CSenElement& envelope = this->AsElement();
+ CSenElement* pHeader = envelope.Element(NsUri(), KSenSoapEnvelopeHeaderName);
+ if (!pHeader)
+ {
+ // add it
+ CSenElement& body = BodyL();
+ pHeader = envelope.CreateElementL(envelope.NsPrefix(), KSenSoapEnvelopeHeaderName);
+ if (pHeader)
+ {
+ envelope.InsertElementL(*pHeader,body);
+ }
+ }
+ return *pHeader;
+ }
+
+EXPORT_C CSenElement& CSenSoapEnvelope::AddHeaderL(CSenElement& aHeaderElement)
+ {
+ return (HeaderL().AddElementL(aHeaderElement));
+ }
+
+EXPORT_C void CSenSoapEnvelope::ParseHeaderL(const TDesC8& aNsUri,
+ const TDesC8& aLocalName,
+ const TDesC8& aQName,
+ const RAttributeArray& aAttributes)
+ {
+ if(ipHeaderFragment)
+ {
+ ipHeaderFragment->ExtractElement();
+ delete ipHeaderFragment;
+ ipHeaderFragment = NULL;
+ }
+ ipHeaderFragment = CSenDomFragment::NewL(aNsUri, aLocalName, aQName, aAttributes);
+ ipHeaderFragment->SetOwner(*this); // to ensure we will return to this class' endElement method
+
+ HeaderL().AddElementL(ipHeaderFragment->AsElement()); // transfers ownership
+ ipHeaderFragment->ParseWithL(*iXmlReader);
+ }
+
+
+EXPORT_C HBufC8* CSenSoapEnvelope::BodyAsStringL()
+ {
+ CSenElement& body = BodyL();
+
+
+ HBufC8* bodyAsXML = NULL;
+
+ // Note, that difference to Jave ref-implementation here is,
+ // that in *EVERY* case, no matter if SOAP BODY has no child
+ // element at all OR if it has one or more childer, the whole
+ // <S:Body> element is ALWAYS returned -- [never just the only
+ // child, and never a of zero-length string, even if no children]
+ CSenElement* pDetachedElement = body.DetachL();
+ if(pDetachedElement)
+ {
+ CleanupStack::PushL(pDetachedElement);
+ bodyAsXML = pDetachedElement->AsXmlL();
+ CleanupStack::PopAndDestroy(); // pDetachedElement
+ return bodyAsXML;
+ }
+
+ // Function now returns NULL only if SOAP-ENV does not contain
+ // a body at all(!)
+ return bodyAsXML;
+ }
+
+EXPORT_C TBool CSenSoapEnvelope::IsFault()
+ {
+ return iFault;
+ }
+
+// NOTE: caller takes ownership of the NEW fault element
+EXPORT_C CSenSoapFault* CSenSoapEnvelope::DetachFaultL()
+ {
+ CSenElement* pNotOwned = this->BodyL().Element(NsUri(), KSenSoapFaultName);
+ if(pNotOwned)
+ {
+ CSenElement* pDetached = pNotOwned->DetachL();
+ if(pDetached)
+ {
+ CleanupStack::PushL(pDetached);
+ CSenSoapFault* pAnswer = CSenSoapFault::NewL(*pDetached);
+ CleanupStack::PopAndDestroy(); // pDetached
+ return pAnswer;
+ }
+ }
+ return NULL;
+ }
+
+
+EXPORT_C CSenSoapFault* CSenSoapEnvelope::FaultL()
+ {
+ CSenSoapFault* pFault = NULL;
+ if(iFault)
+ {
+ // trust that the element is actually
+ // CSenSoapFault added in StartElementL()
+
+ pFault = (CSenSoapFault*)this->BodyL().Element(NsUri(), KSenSoapFaultName);
+
+ }
+ return pFault;
+ }
+
+EXPORT_C TPtrC8 CSenSoapEnvelope::SetSoapActionL(const TDesC8& aSoapAction)
+ {
+
+ _LIT8(KQuote, "\"");
+
+ HBufC8* pTemp = HBufC8::NewLC(aSoapAction.Length()+(2*KQuote().Length()));
+
+ TPtr8 temp = pTemp->Des();
+
+ if(aSoapAction != KNullDesC8()
+ && !SenXmlUtils::StartsWith(aSoapAction, KQuote))
+ {
+ temp.Append(KQuote);
+ }
+
+ temp.Append(aSoapAction);
+
+ if(aSoapAction != KNullDesC8() && !SenXmlUtils::EndsWith(*pTemp, KQuote))
+ {
+ temp.Append(KQuote);
+ }
+
+ if(ipSoapAction)
+ {
+ delete ipSoapAction;
+ ipSoapAction = NULL;
+ }
+
+ ipSoapAction = pTemp;
+
+ CleanupStack::Pop(); // pTemp is now safe
+ return SoapAction2();
+ }
+
+
+EXPORT_C TPtrC8 CSenSoapEnvelope::SoapAction()
+ {
+ if(ipSoapAction)
+ {
+ return ipSoapAction->Des();
+ }
+ else
+ {
+ return KSoapActionHeaderValueEmpty();
+ }
+
+ }
+
+
+EXPORT_C void CSenSoapEnvelope::ParseL(const TDesC8& aXml)
+ {
+ CSenBaseFragment::ParseL(aXml);
+// CSenElement& envelope = this->AsElement();
+
+ /*
+ // SOAP Header is not mandatory:
+ CSenElement* pHeader = envelope.Element(KSenSoapEnvelopeXmlns, KSenSoapEnvelopeHeaderName);
+ if(!pHeader)
+ {
+ User::Leave(KErrSenNoSoapHeader);
+ }
+ */
+
+ // We could check body, but then this class could not
+ // be used in cases, where header is parsed from file
+ // or some other source, prior setting the body via
+ // SetBody()
+
+ /*
+ CSenElement* pBody = envelope.Element(KSenSoapEnvelopeXmlns, KSenSoapEnvelopeBodyName);
+ if(!pBody)
+ {
+ User::Leave(KErrSenNoSoapBody);
+ }
+ */
+ }
+
+EXPORT_C TBool CSenSoapEnvelope::HasHeader()
+ {
+ CSenElement& envelope = this->AsElement();
+ // True, if element exists, false otherwise:
+ return (envelope.Element(NsUri(), KSenSoapEnvelopeHeaderName) != NULL);
+ }
+
+EXPORT_C TBool CSenSoapEnvelope::HasBody()
+ {
+ CSenElement& envelope = this->AsElement();
+ // True, if element exists, false otherwise:
+ return (envelope.Element(NsUri(), KSenSoapEnvelopeBodyName) != NULL);
+ }
+
+EXPORT_C TSOAPVersion CSenSoapEnvelope::SoapVersion()
+ {
+ if( NsUri() == KSenSoap12EnvelopeXmlns )
+ {
+ return ESOAP12;
+ }
+ else
+ {
+ return ESOAP11;
+ }
+ }
+
+
+EXPORT_C TPtrC8 CSenSoapEnvelope::SoapAction2()
+ {
+ if(ipSoapAction)
+ {
+ return ipSoapAction->Des();
+ }
+ else
+ {
+ // Note, that zero-length descriptor must be returned
+ // if SetSoapActionL() has not been called. Otherwise,
+ // when passing transport properties over IPC boundary,
+ // code cannot determine whether the caller, who utilizes
+ // CSenSoapEnvelope wishes to override any underlying
+ // value of SOAPAction with "empty" value (== "").
+ // If SOAPAction is set in CSenSoapEnvelope, it is stronger
+ // than message level (SendL/SubmitL in CSenServiceConnection)
+ // or session level (SetTransportPropertiesL) definitions.
+ return KNullDesC8();
+ }
+
+ }
+
+// End of File