Back to index

lightning-sunbird  0.9+nobinonly
nsSOAPMessage.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsIServiceManager.h"
00039 #include "nsMemory.h"
00040 #include "nsIComponentManager.h"
00041 #include "nsSOAPUtils.h"
00042 #include "nsSOAPMessage.h"
00043 #include "nsSOAPParameter.h"
00044 #include "nsSOAPHeaderBlock.h"
00045 #include "nsSOAPException.h"
00046 #include "nsIDOMDocument.h"
00047 #include "nsIDOMAttr.h"
00048 #include "nsIDOMParser.h"
00049 #include "nsIDOMElement.h"
00050 #include "nsIDOMNamedNodeMap.h"
00051 
00052 static NS_DEFINE_CID(kDOMParserCID, NS_DOMPARSER_CID);
00054 //
00055 //
00057 
00058 nsSOAPMessage::nsSOAPMessage()
00059 {
00060 }
00061 
00062 nsSOAPMessage::~nsSOAPMessage()
00063 {
00064 }
00065 
00066 NS_IMPL_ISUPPORTS1(nsSOAPMessage, nsISOAPMessage)
00067 /* attribute nsIDOMDocument message; */
00068 NS_IMETHODIMP nsSOAPMessage::GetMessage(nsIDOMDocument * *aMessage)
00069 {
00070   NS_ENSURE_ARG_POINTER(aMessage);
00071   *aMessage = mMessage;
00072   NS_IF_ADDREF(*aMessage);
00073   return NS_OK;
00074 }
00075 
00076 NS_IMETHODIMP nsSOAPMessage::SetMessage(nsIDOMDocument * aMessage)
00077 {
00078   mMessage = aMessage;
00079   return NS_OK;
00080 }
00081 
00082 /* readonly attribute nsIDOMElement envelope; */
00083 NS_IMETHODIMP nsSOAPMessage::GetEnvelope(nsIDOMElement * *aEnvelope)
00084 {
00085   NS_ENSURE_ARG_POINTER(aEnvelope);
00086 
00087   if (mMessage) {
00088     nsCOMPtr<nsIDOMElement> root;
00089     mMessage->GetDocumentElement(getter_AddRefs(root));
00090     if (root) {
00091       nsAutoString namespaceURI;
00092       nsAutoString name;
00093       nsresult rc = root->GetNamespaceURI(namespaceURI);
00094       if (NS_FAILED(rc))
00095         return rc;
00096       rc = root->GetLocalName(name);
00097       if (NS_FAILED(rc))
00098         return rc;
00099       if (name.Equals(gSOAPStrings->kEnvelopeTagName)
00100           && (namespaceURI.
00101               Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_2])
00102               || namespaceURI.
00103               Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_1]))) {
00104         *aEnvelope = root;
00105         NS_ADDREF(*aEnvelope);
00106         return NS_OK;
00107       }
00108     }
00109   }
00110   *aEnvelope = nsnull;
00111   return NS_OK;
00112 }
00113 
00114 /* readonly attribute PRUint16 version; */
00115 NS_IMETHODIMP nsSOAPMessage::GetVersion(PRUint16 * aVersion)
00116 {
00117   NS_ENSURE_ARG_POINTER(aVersion);
00118   if (mMessage) {
00119     nsCOMPtr<nsIDOMElement> root;
00120     mMessage->GetDocumentElement(getter_AddRefs(root));
00121     if (root) {
00122       nsAutoString namespaceURI;
00123       nsAutoString name;
00124       nsresult rc = root->GetNamespaceURI(namespaceURI);
00125       if (NS_FAILED(rc))
00126         return rc;
00127       rc = root->GetLocalName(name);
00128       if (NS_FAILED(rc))
00129         return rc;
00130       if (name.Equals(gSOAPStrings->kEnvelopeTagName)) {
00131         if (namespaceURI.
00132             Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_2])) {
00133           *aVersion = nsISOAPMessage::VERSION_1_2;
00134           return NS_OK;
00135         } else if (namespaceURI.
00136                    Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_1])) {
00137           *aVersion = nsISOAPMessage::VERSION_1_1;
00138           return NS_OK;
00139         }
00140       }
00141     }
00142   }
00143   *aVersion = nsISOAPMessage::VERSION_UNKNOWN;
00144   return NS_OK;
00145 }
00146 
00147 /* Internal method for getting  envelope and  version */
00148 PRUint16 nsSOAPMessage::GetEnvelopeWithVersion(nsIDOMElement * *aEnvelope)
00149 {
00150   if (mMessage) {
00151     nsCOMPtr<nsIDOMElement> root;
00152     mMessage->GetDocumentElement(getter_AddRefs(root));
00153     if (root) {
00154       nsAutoString namespaceURI;
00155       nsAutoString name;
00156       root->GetNamespaceURI(namespaceURI);
00157       root->GetLocalName(name);
00158       if (name.Equals(gSOAPStrings->kEnvelopeTagName)) {
00159         if (namespaceURI.
00160             Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_2])) {
00161           *aEnvelope = root;
00162           NS_ADDREF(*aEnvelope);
00163           return nsISOAPMessage::VERSION_1_2;
00164         } else if (namespaceURI.
00165                    Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_1])) {
00166           *aEnvelope = root;
00167           NS_ADDREF(*aEnvelope);
00168           return nsISOAPMessage::VERSION_1_1;
00169         }
00170       }
00171     }
00172   }
00173   *aEnvelope = nsnull;
00174   return nsISOAPMessage::VERSION_UNKNOWN;
00175 }
00176 
00177 /* readonly attribute nsIDOMElement header; */
00178 NS_IMETHODIMP nsSOAPMessage::GetHeader(nsIDOMElement * *aHeader)
00179 {
00180   NS_ENSURE_ARG_POINTER(aHeader);
00181   nsCOMPtr<nsIDOMElement> env;
00182   PRUint16 version = GetEnvelopeWithVersion(getter_AddRefs(env));
00183   if (env) {
00184     nsSOAPUtils::GetSpecificChildElement(nsnull, env,
00185                                          *gSOAPStrings->kSOAPEnvURI[version],
00186                                          gSOAPStrings->kHeaderTagName,
00187                                          aHeader);
00188   } else {
00189     *aHeader = nsnull;
00190   }
00191   return NS_OK;
00192 }
00193 
00194 /* readonly attribute nsIDOMElement body; */
00195 NS_IMETHODIMP nsSOAPMessage::GetBody(nsIDOMElement * *aBody)
00196 {
00197   NS_ENSURE_ARG_POINTER(aBody);
00198   nsCOMPtr<nsIDOMElement> env;
00199   PRUint16 version = GetEnvelopeWithVersion(getter_AddRefs(env));
00200   if (env) {
00201     nsSOAPUtils::GetSpecificChildElement(nsnull, env,
00202                                          *gSOAPStrings->kSOAPEnvURI[version],
00203                                          gSOAPStrings->kBodyTagName, aBody);
00204   } else {
00205     *aBody = nsnull;
00206   }
00207   return NS_OK;
00208 }
00209 
00210 /* attribute DOMString actionURI; */
00211 NS_IMETHODIMP nsSOAPMessage::GetActionURI(nsAString & aActionURI)
00212 {
00213   aActionURI.Assign(mActionURI);
00214   return NS_OK;
00215 }
00216 
00217 NS_IMETHODIMP nsSOAPMessage::SetActionURI(const nsAString & aActionURI)
00218 {
00219   mActionURI.Assign(aActionURI);
00220   return NS_OK;
00221 }
00222 
00223 /* readonly attribute AString methodName; */
00224 NS_IMETHODIMP nsSOAPMessage::GetMethodName(nsAString & aMethodName)
00225 {
00226   nsCOMPtr<nsIDOMElement> body;
00227   GetBody(getter_AddRefs(body));
00228   if (body) {
00229     nsCOMPtr<nsIDOMElement> method;
00230     nsSOAPUtils::GetFirstChildElement(body, getter_AddRefs(method));
00231     if (method) {
00232       body->GetLocalName(aMethodName);
00233       return NS_OK;
00234     }
00235   }
00236   aMethodName.Truncate();
00237   return NS_OK;
00238 }
00239 
00240 /* readonly attribute AString targetObjectURI; */
00241 NS_IMETHODIMP nsSOAPMessage::
00242 GetTargetObjectURI(nsAString & aTargetObjectURI)
00243 {
00244   nsCOMPtr<nsIDOMElement> body;
00245   GetBody(getter_AddRefs(body));
00246   if (body) {
00247     nsCOMPtr<nsIDOMElement> method;
00248     nsSOAPUtils::GetFirstChildElement(body, getter_AddRefs(method));
00249     if (method) {
00250       nsCOMPtr<nsISOAPEncoding> encoding;
00251       PRUint16 version;
00252       nsresult rv = GetEncodingWithVersion(method, &version, getter_AddRefs(encoding));
00253       if (NS_FAILED(rv))
00254         return rv;
00255       nsAutoString temp;
00256       rv = method->GetNamespaceURI(temp);
00257       if (NS_FAILED(rv))
00258         return rv;
00259       return encoding->GetInternalSchemaURI(temp, aTargetObjectURI);
00260     }
00261   }
00262   aTargetObjectURI.Truncate();
00263   return NS_OK;
00264 }
00265 
00266 NS_IMETHODIMP
00267     nsSOAPMessage::Encode(PRUint16 aVersion, const nsAString & aMethodName,
00268                           const nsAString & aTargetObjectURI,
00269                           PRUint32 aHeaderBlockCount,
00270                           nsISOAPHeaderBlock ** aHeaderBlocks,
00271                           PRUint32 aParameterCount,
00272                           nsISOAPParameter ** aParameters)
00273 {
00274   static NS_NAMED_LITERAL_STRING(realEmptySOAPDocStr1,
00275                         "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:enc=\"http://schemas.xmlsoap.org/soap/encoding/\"><env:Header/><env:Body/></env:Envelope>");
00276   static NS_NAMED_LITERAL_STRING(realEmptySOAPDocStr2,
00277                         "<env:Envelope xmlns:env=\"http://www.w3.org/2001/09/soap-envelope\" xmlns:enc=\"http://www.w3.org/2001/09/soap-encoding\"><env:Header/><env:Body/></env:Envelope>");
00278   static const nsAString *kEmptySOAPDocStr[] = {
00279     &realEmptySOAPDocStr1, &realEmptySOAPDocStr2
00280   };
00281 
00282   if (aVersion != nsISOAPMessage::VERSION_1_1
00283       && aVersion != nsISOAPMessage::VERSION_1_2)
00284     return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_BAD_VALUE","Cannot encode message blocks without a valid SOAP version specified.");
00285 
00286 //  Construct the message skeleton
00287 
00288   nsresult rv;
00289   nsCOMPtr<nsIDOMNode> ignored;
00290   nsCOMPtr<nsIDOMParser> parser = do_CreateInstance(kDOMParserCID, &rv);
00291   if (NS_FAILED(rv))
00292     return rv;
00293 
00294   rv = parser->ParseFromString(nsPromiseFlatString(*kEmptySOAPDocStr[aVersion]).get(),
00295                                "application/xml", getter_AddRefs(mMessage));
00296   if (NS_FAILED(rv))
00297     return rv;
00298 
00299 //  Declare the default encoding.  This should always be non-null, but may be empty string.
00300 
00301   nsCOMPtr<nsISOAPEncoding> encoding;
00302   rv = GetEncoding(getter_AddRefs(encoding));
00303   if (NS_FAILED(rv))
00304     return rv;
00305   nsCOMPtr<nsIDOMElement> envelope;
00306   rv = GetEnvelope(getter_AddRefs(envelope));
00307   if (NS_FAILED(rv))
00308     return rv;
00309   if (envelope) {
00310     nsAutoString enc;
00311     rv = mEncoding->GetStyleURI(enc);
00312     if (NS_FAILED(rv))
00313       return rv;
00314     if (!enc.IsEmpty()) {
00315       rv = envelope->SetAttributeNS(*gSOAPStrings->kSOAPEnvURI[aVersion],
00316                                     gSOAPStrings->kEncodingStyleAttribute, enc);
00317         if (NS_FAILED(rv))
00318           return rv;
00319     }
00320   }
00321 //  Declare the schema namespaces, taking into account any mappings that are present.
00322 
00323   nsAutoString temp;
00324   nsAutoString temp2;
00325   temp.Assign(gSOAPStrings->kXMLNamespacePrefix);
00326   temp.Append(gSOAPStrings->kXSPrefix);
00327   rv = encoding->GetExternalSchemaURI(gSOAPStrings->kXSURI, temp2);
00328   if (NS_FAILED(rv))
00329     return rv;
00330   rv = envelope->SetAttributeNS(gSOAPStrings->kXMLNamespaceNamespaceURI, temp, temp2);
00331   if (NS_FAILED(rv))
00332     return rv;
00333   temp.Assign(gSOAPStrings->kXMLNamespacePrefix);
00334   temp.Append(gSOAPStrings->kXSIPrefix);
00335   rv = encoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, temp2);
00336   if (NS_FAILED(rv))
00337     return rv;
00338   rv = envelope->SetAttributeNS(gSOAPStrings->kXMLNamespaceNamespaceURI, temp, temp2);
00339   if (NS_FAILED(rv))
00340     return rv;
00341 
00342 //  Encode and add headers, if any were specified 
00343 
00344   if (aHeaderBlockCount) {
00345     nsCOMPtr<nsIDOMElement> parent;
00346     rv = GetHeader(getter_AddRefs(parent));
00347     if (NS_FAILED(rv))
00348       return rv;
00349     nsCOMPtr<nsISOAPHeaderBlock> header;
00350     nsCOMPtr<nsIDOMElement> element;
00351     nsAutoString name;
00352     nsAutoString namespaceURI;
00353     PRUint32 i;
00354     for (i = 0; i < aHeaderBlockCount; i++) {
00355       header = aHeaderBlocks[i];
00356       if (!header)
00357         return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_NULL_HEADER","Cannot encode null in header array.");
00358       rv = header->GetElement(getter_AddRefs(element));
00359       if (element) {
00360         nsCOMPtr<nsIDOMNode> node1;
00361         node1 = element;
00362         nsCOMPtr<nsIDOMNode> node2;
00363         rv = mMessage->ImportNode(node1, PR_TRUE, getter_AddRefs(node1));
00364         if (NS_FAILED(rv))
00365           return rv;
00366         rv = parent->AppendChild(node2, getter_AddRefs(node1));
00367         if (NS_FAILED(rv))
00368           return rv;
00369         element = do_QueryInterface(node1);
00370       } else {
00371         rv = header->GetNamespaceURI(namespaceURI);
00372         if (NS_FAILED(rv))
00373           return rv;
00374         rv = header->GetName(name);
00375         if (NS_FAILED(rv))
00376           return rv;
00377         nsAutoString actorURI;
00378         rv = header->GetActorURI(actorURI);
00379         if (NS_FAILED(rv))
00380           return rv;
00381         PRBool mustUnderstand;
00382         rv = header->GetMustUnderstand(&mustUnderstand);
00383         if (NS_FAILED(rv))
00384           return rv;
00385         rv = header->GetEncoding(getter_AddRefs(encoding));
00386         if (NS_FAILED(rv))
00387           return rv;
00388         if (!encoding) {
00389           rv = GetEncoding(getter_AddRefs(encoding));
00390           if (NS_FAILED(rv))
00391             return rv;
00392         }
00393         nsCOMPtr<nsISchemaType> schemaType;
00394         rv = header->GetSchemaType(getter_AddRefs(schemaType));
00395         if (NS_FAILED(rv))
00396           return rv;
00397         nsCOMPtr<nsIVariant> value;
00398         rv = header->GetValue(getter_AddRefs(value));
00399         if (NS_FAILED(rv))
00400           return rv;
00401         rv = encoding->Encode(value, namespaceURI, name,
00402                               schemaType, nsnull, parent,
00403                               getter_AddRefs(element));
00404         if (NS_FAILED(rv))
00405           return rv;
00406         if (!actorURI.IsEmpty()) {
00407           element->SetAttributeNS(gSOAPStrings->kSOAPEnvPrefix,
00408                                   gSOAPStrings->kActorAttribute, actorURI);
00409           if (NS_FAILED(rv))
00410             return rv;
00411         }
00412         if (mustUnderstand) {
00413           element->SetAttributeNS(gSOAPStrings->kSOAPEnvPrefix,
00414                                   gSOAPStrings->kMustUnderstandAttribute,
00415                                   gSOAPStrings->kTrueA);
00416           if (NS_FAILED(rv))
00417             return rv;
00418         }
00419         if (mEncoding != encoding) {
00420           nsAutoString enc;
00421           encoding->GetStyleURI(enc);
00422           element->
00423               SetAttributeNS(*gSOAPStrings->kSOAPEnvURI[aVersion],
00424                              gSOAPStrings->kEncodingStyleAttribute, enc);
00425         }
00426       }
00427     }
00428   }
00429   nsCOMPtr<nsIDOMElement> body;
00430   rv = GetBody(getter_AddRefs(body));
00431   if (NS_FAILED(rv))
00432     return rv;
00433 
00434 //  Only produce a call element if mMethodName was non-empty
00435 
00436   if (!aMethodName.IsEmpty()) {
00437     nsAutoString temp;
00438     rv = encoding->GetExternalSchemaURI(aTargetObjectURI, temp);
00439     nsCOMPtr<nsIDOMElement> call;
00440     rv = mMessage->CreateElementNS(temp, aMethodName,
00441                                    getter_AddRefs(call));
00442     if (NS_FAILED(rv))
00443       return rv;
00444     nsCOMPtr<nsIDOMNode> ignored;
00445     rv = body->AppendChild(call, getter_AddRefs(ignored));
00446     if (NS_FAILED(rv))
00447       return rv;
00448     body = call;
00449   }
00450 //  Encode and add all of the parameters into the body
00451 
00452   nsCOMPtr<nsISOAPParameter> param;
00453   nsCOMPtr<nsIDOMElement> element;
00454   nsCOMPtr<nsISOAPEncoding> newencoding;
00455   nsAutoString name;
00456   nsAutoString namespaceURI;
00457   PRUint32 i;
00458   for (i = 0; i < aParameterCount; i++) {
00459     param = aParameters[i];
00460     if (!param)
00461       return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_NULL_PARAMETER","Cannot encode null in parameter array.");
00462     rv = param->GetElement(getter_AddRefs(element));
00463     if (element) {
00464       nsCOMPtr<nsIDOMNode> node1;
00465       node1 = element;
00466       nsCOMPtr<nsIDOMNode> node2;
00467       rv = mMessage->ImportNode(node1, PR_TRUE, getter_AddRefs(node2));
00468       if (NS_FAILED(rv))
00469         return rv;
00470       rv = body->AppendChild(node2, getter_AddRefs(node1));
00471       if (NS_FAILED(rv))
00472         return rv;
00473       element = do_QueryInterface(node1);
00474     } else {
00475       rv = param->GetNamespaceURI(namespaceURI);
00476       if (NS_FAILED(rv))
00477         return rv;
00478       rv = param->GetName(name);
00479       if (NS_FAILED(rv))
00480         return rv;
00481       rv = param->GetEncoding(getter_AddRefs(newencoding));
00482       if (NS_FAILED(rv))
00483         return rv;
00484       if (!newencoding) {
00485         newencoding = encoding;
00486       }
00487       nsCOMPtr<nsISchemaType> schemaType;
00488       rv = param->GetSchemaType(getter_AddRefs(schemaType));
00489       if (NS_FAILED(rv))
00490         return rv;
00491       nsCOMPtr<nsIVariant> value;
00492       rv = param->GetValue(getter_AddRefs(value));
00493       if (NS_FAILED(rv))
00494         return rv;
00495       rv = newencoding->Encode(value, namespaceURI, name,
00496                                schemaType, nsnull, body,
00497                                getter_AddRefs(element));
00498       if (NS_FAILED(rv))
00499         return rv;
00500       if (encoding != newencoding) {
00501         nsAutoString enc;
00502         newencoding->GetStyleURI(enc);
00503         element->SetAttributeNS(*gSOAPStrings->kSOAPEnvURI[aVersion],
00504                                 gSOAPStrings->kEncodingStyleAttribute, enc);
00505       }
00506     }
00507   }
00508   return NS_OK;
00509 }
00510 
00517 nsresult
00518     nsSOAPMessage::GetEncodingWithVersion(nsIDOMElement * aFirst,
00519                                           PRUint16 * aVersion,
00520                                           nsISOAPEncoding ** aEncoding)
00521 {
00522   nsCOMPtr<nsISOAPEncoding> encoding;
00523   nsresult rv = GetEncoding(getter_AddRefs(encoding));
00524   if (NS_FAILED(rv))
00525     return rv;
00526   rv = GetVersion(aVersion);
00527   if (NS_FAILED(rv))
00528     return rv;
00529   nsCOMPtr<nsIDOMElement> element = aFirst;
00530 
00531   // Check for stray encodingStyle attributes.  If none found, then
00532   // use empty string encoding style.
00533 
00534   nsAutoString style;
00535   for (;;) {
00536     nsCOMPtr<nsIDOMAttr> enc;
00537     rv = element->GetAttributeNodeNS(*gSOAPStrings->kSOAPEnvURI[*aVersion],
00538                                      gSOAPStrings->kEncodingStyleAttribute,
00539                                      getter_AddRefs(enc));
00540     if (NS_FAILED(rv))
00541       return rv;
00542     if (enc) {
00543       rv = enc->GetNodeValue(style);
00544       if (NS_FAILED(rv))
00545         return rv;
00546       break;
00547     } else {
00548       nsCOMPtr<nsIDOMNode> next;
00549       rv = element->GetParentNode(getter_AddRefs(next));
00550       if (NS_FAILED(rv))
00551         return rv;
00552       if (next) {
00553         PRUint16 type;
00554         rv = next->GetNodeType(&type);
00555         if (NS_FAILED(rv))
00556           return rv;
00557         if (type != nsIDOMNode::ELEMENT_NODE) {
00558           next = nsnull;
00559         }
00560       }
00561       if (next) {
00562         element = do_QueryInterface(next);
00563       } else {
00564         break;
00565       }
00566     }
00567   }
00568   return encoding->GetAssociatedEncoding(style, PR_TRUE, aEncoding);
00569 }
00570 
00571 /* void getHeaderBlocks (out PRUint32 aCount, [array, size_is (aCount), retval] out nsISOAPHeaderBlock aHeaderBlocks); */
00572 NS_IMETHODIMP
00573     nsSOAPMessage::GetHeaderBlocks(PRUint32 * aCount,
00574                                    nsISOAPHeaderBlock *** aHeaderBlocks)
00575 {
00576   NS_ENSURE_ARG_POINTER(aHeaderBlocks);
00577   nsISOAPHeaderBlock** headerBlocks = nsnull;
00578   *aCount = 0;
00579   *aHeaderBlocks = nsnull;
00580   int count = 0;
00581   int length = 0;
00582 
00583   nsCOMPtr<nsIDOMElement> element;
00584   nsresult rv = GetHeader(getter_AddRefs(element));
00585   if (NS_FAILED(rv) || !element)
00586     return rv;
00587   nsCOMPtr<nsISOAPEncoding> encoding;
00588   PRUint16 version;
00589   rv = GetEncodingWithVersion(element, &version, getter_AddRefs(encoding));
00590   if (NS_FAILED(rv))
00591     return rv;
00592   nsCOMPtr<nsIDOMElement> next;
00593 
00594   nsCOMPtr<nsISOAPHeaderBlock> header;
00595   nsSOAPUtils::GetFirstChildElement(element, getter_AddRefs(next));
00596   while (next) {
00597     if (length == count) {
00598       length = length ? 2 * length : 10;
00599       headerBlocks =
00600           (nsISOAPHeaderBlock * *)nsMemory::Realloc(headerBlocks,
00601                                                   length *
00602                                                   sizeof(*headerBlocks));
00603     }
00604     element = next;
00605     header = do_CreateInstance(NS_SOAPHEADERBLOCK_CONTRACTID);
00606     if (!header) {
00607       rv = NS_ERROR_OUT_OF_MEMORY;
00608       break;
00609     }
00610     header->Init(nsnull, version);
00611 
00612     (headerBlocks)[(count)] = header;
00613     NS_ADDREF((headerBlocks)[(count)]);
00614     (count)++;
00615 
00616     rv = header->SetElement(element);
00617     if (NS_FAILED(rv))
00618       break;
00619     rv = header->SetEncoding(encoding);
00620     if (NS_FAILED(rv))
00621       break;
00622     nsSOAPUtils::GetNextSiblingElement(element, getter_AddRefs(next));
00623   }
00624   if (NS_SUCCEEDED(rv)) {
00625     if (count) {
00626       headerBlocks =
00627           (nsISOAPHeaderBlock * *)nsMemory::Realloc(headerBlocks,
00628                                                     count *
00629                                                     sizeof(*headerBlocks));
00630     }
00631   }
00632   else {
00633     while (--count >= 0) {
00634       NS_IF_RELEASE(headerBlocks[count]);
00635     }
00636     count = 0;
00637     nsMemory::Free(headerBlocks);
00638     headerBlocks = nsnull;
00639   }
00640   *aCount = count;
00641   *aHeaderBlocks = headerBlocks;
00642   return rv;
00643 }
00644 
00645 /* void getParameters (in boolean aDocumentStyle, out PRUint32 aCount, [array, size_is (aCount), retval] out nsISOAPParameter aParameters); */
00646 NS_IMETHODIMP
00647     nsSOAPMessage::GetParameters(PRBool aDocumentStyle, PRUint32 * aCount,
00648                                  nsISOAPParameter *** aParameters)
00649 {
00650   NS_ENSURE_ARG_POINTER(aParameters);
00651   nsISOAPParameter** parameters = nsnull;
00652   *aCount = 0;
00653   *aParameters = nsnull;
00654   int count = 0;
00655   int length = 0;
00656   nsCOMPtr<nsIDOMElement> element;
00657   nsresult rv = GetBody(getter_AddRefs(element));
00658   if (NS_FAILED(rv) || !element)
00659     return rv;
00660   nsCOMPtr<nsIDOMElement> next;
00661   nsCOMPtr<nsISOAPParameter> param;
00662   nsSOAPUtils::GetFirstChildElement(element, getter_AddRefs(next));
00663   if (!aDocumentStyle) {
00664     element = next;
00665     if (!element)
00666       return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_MISSING_METHOD","Cannot decode rpc-style message due to missing method element.");
00667     nsSOAPUtils::GetFirstChildElement(element, getter_AddRefs(next));
00668   }
00669   nsCOMPtr<nsISOAPEncoding> encoding;
00670   PRUint16 version;
00671   rv = GetEncodingWithVersion(element, &version, getter_AddRefs(encoding));
00672   if (NS_FAILED(rv))
00673     return rv;
00674   while (next) {
00675     if (length == count) {
00676       length = length ? 2 * length : 10;
00677       parameters =
00678           (nsISOAPParameter * *)nsMemory::Realloc(parameters,
00679                                                 length *
00680                                                 sizeof(*parameters));
00681     }
00682     element = next;
00683     param = do_CreateInstance(NS_SOAPPARAMETER_CONTRACTID);
00684     if (!param) {
00685       rv = NS_ERROR_OUT_OF_MEMORY;
00686       break;
00687     }
00688     parameters[count] = param;
00689     NS_ADDREF(parameters[count]);
00690     count++;
00691 
00692     rv = param->SetElement(element);
00693     if (NS_FAILED(rv))
00694       break;
00695     rv = param->SetEncoding(encoding);
00696     if (NS_FAILED(rv))
00697       break;
00698     nsSOAPUtils::GetNextSiblingElement(element, getter_AddRefs(next));
00699   }
00700   if (NS_SUCCEEDED(rv)) {
00701     if (count) {
00702       parameters =
00703           (nsISOAPParameter * *)nsMemory::Realloc(parameters,
00704                                                   count *
00705                                                   sizeof(*parameters));
00706     }
00707   }
00708   else {
00709     while (--count >= 0) {
00710       NS_IF_RELEASE(parameters[count]);
00711     }
00712     count = 0;
00713     nsMemory::Free(parameters);
00714     parameters = nsnull;
00715   }
00716   *aCount = count;
00717   *aParameters = parameters;
00718   return rv;
00719 }
00720 
00721 /* attribute nsISOAPEncoding encoding; */
00722 NS_IMETHODIMP nsSOAPMessage::GetEncoding(nsISOAPEncoding * *aEncoding)
00723 {
00724   NS_ENSURE_ARG_POINTER(aEncoding);
00725   if (!mEncoding) {
00726     PRUint16 version;
00727     nsresult rc = GetVersion(&version);
00728     if (NS_FAILED(rc))
00729       return rc;
00730     if (version != nsISOAPMessage::VERSION_UNKNOWN) {
00731       nsCOMPtr<nsISOAPEncoding> encoding =
00732           do_CreateInstance(NS_SOAPENCODING_CONTRACTID);
00733       if (!encoding)
00734         return NS_ERROR_OUT_OF_MEMORY;
00735       if (version == nsISOAPMessage::VERSION_1_1) {
00736         rc = encoding->
00737             GetAssociatedEncoding(gSOAPStrings->kSOAPEncURI11,
00738                                   PR_FALSE, getter_AddRefs(mEncoding));
00739       }
00740       else {
00741         rc = encoding->
00742             GetAssociatedEncoding(gSOAPStrings->kSOAPEncURI,
00743                                   PR_FALSE, getter_AddRefs(mEncoding));
00744       }
00745       if (NS_FAILED(rc))
00746         return rc;
00747     }
00748   }
00749   *aEncoding = mEncoding;
00750   NS_IF_ADDREF(*aEncoding);
00751   return NS_OK;
00752 }
00753 
00754 NS_IMETHODIMP nsSOAPMessage::SetEncoding(nsISOAPEncoding * aEncoding)
00755 {
00756   mEncoding = aEncoding;
00757   return NS_OK;
00758 }