diff -r 000000000000 -r 62f9d29f7211 webservices/wsutils/src/sensoapenvelope.cpp --- /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 + +#include +#include +#include + +#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 + // 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