webservices/wsutils/src/sensoapenvelope.cpp
changeset 0 62f9d29f7211
--- /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