extra: import at 3.0.1 beta 1
[mozilla-extra.git] / extensions / webservices / soap / src / nsSOAPMessage.cpp
blob0c8d8a1f36750a989a720c3f41c27df6c126b5bf
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsIServiceManager.h"
39 #include "nsMemory.h"
40 #include "nsIComponentManager.h"
41 #include "nsSOAPUtils.h"
42 #include "nsSOAPMessage.h"
43 #include "nsSOAPParameter.h"
44 #include "nsSOAPHeaderBlock.h"
45 #include "nsSOAPException.h"
46 #include "nsIDOMDocument.h"
47 #include "nsIDOMAttr.h"
48 #include "nsIDOMParser.h"
49 #include "nsIDOMElement.h"
50 #include "nsIDOMNamedNodeMap.h"
52 static NS_DEFINE_CID(kDOMParserCID, NS_DOMPARSER_CID);
53 /////////////////////////////////////////////
56 /////////////////////////////////////////////
58 nsSOAPMessage::nsSOAPMessage()
62 nsSOAPMessage::~nsSOAPMessage()
66 NS_IMPL_ISUPPORTS1(nsSOAPMessage, nsISOAPMessage)
67 /* attribute nsIDOMDocument message; */
68 NS_IMETHODIMP nsSOAPMessage::GetMessageMoz(nsIDOMDocument * *aMessage)
70 NS_ENSURE_ARG_POINTER(aMessage);
71 *aMessage = mMessage;
72 NS_IF_ADDREF(*aMessage);
73 return NS_OK;
76 NS_IMETHODIMP nsSOAPMessage::SetMessageMoz(nsIDOMDocument * aMessage)
78 mMessage = aMessage;
79 return NS_OK;
82 /* readonly attribute nsIDOMElement envelope; */
83 NS_IMETHODIMP nsSOAPMessage::GetEnvelope(nsIDOMElement * *aEnvelope)
85 NS_ENSURE_ARG_POINTER(aEnvelope);
87 if (mMessage) {
88 nsCOMPtr<nsIDOMElement> root;
89 mMessage->GetDocumentElement(getter_AddRefs(root));
90 if (root) {
91 nsAutoString namespaceURI;
92 nsAutoString name;
93 nsresult rc = root->GetNamespaceURI(namespaceURI);
94 if (NS_FAILED(rc))
95 return rc;
96 rc = root->GetLocalName(name);
97 if (NS_FAILED(rc))
98 return rc;
99 if (name.Equals(gSOAPStrings->kEnvelopeTagName)
100 && (namespaceURI.
101 Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_2])
102 || namespaceURI.
103 Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_1]))) {
104 *aEnvelope = root;
105 NS_ADDREF(*aEnvelope);
106 return NS_OK;
110 *aEnvelope = nsnull;
111 return NS_OK;
114 /* readonly attribute PRUint16 version; */
115 NS_IMETHODIMP nsSOAPMessage::GetVersion(PRUint16 * aVersion)
117 NS_ENSURE_ARG_POINTER(aVersion);
118 if (mMessage) {
119 nsCOMPtr<nsIDOMElement> root;
120 mMessage->GetDocumentElement(getter_AddRefs(root));
121 if (root) {
122 nsAutoString namespaceURI;
123 nsAutoString name;
124 nsresult rc = root->GetNamespaceURI(namespaceURI);
125 if (NS_FAILED(rc))
126 return rc;
127 rc = root->GetLocalName(name);
128 if (NS_FAILED(rc))
129 return rc;
130 if (name.Equals(gSOAPStrings->kEnvelopeTagName)) {
131 if (namespaceURI.
132 Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_2])) {
133 *aVersion = nsISOAPMessage::VERSION_1_2;
134 return NS_OK;
135 } else if (namespaceURI.
136 Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_1])) {
137 *aVersion = nsISOAPMessage::VERSION_1_1;
138 return NS_OK;
143 *aVersion = nsISOAPMessage::VERSION_UNKNOWN;
144 return NS_OK;
147 /* Internal method for getting envelope and version */
148 PRUint16 nsSOAPMessage::GetEnvelopeWithVersion(nsIDOMElement * *aEnvelope)
150 if (mMessage) {
151 nsCOMPtr<nsIDOMElement> root;
152 mMessage->GetDocumentElement(getter_AddRefs(root));
153 if (root) {
154 nsAutoString namespaceURI;
155 nsAutoString name;
156 root->GetNamespaceURI(namespaceURI);
157 root->GetLocalName(name);
158 if (name.Equals(gSOAPStrings->kEnvelopeTagName)) {
159 if (namespaceURI.
160 Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_2])) {
161 *aEnvelope = root;
162 NS_ADDREF(*aEnvelope);
163 return nsISOAPMessage::VERSION_1_2;
164 } else if (namespaceURI.
165 Equals(*gSOAPStrings->kSOAPEnvURI[nsISOAPMessage::VERSION_1_1])) {
166 *aEnvelope = root;
167 NS_ADDREF(*aEnvelope);
168 return nsISOAPMessage::VERSION_1_1;
173 *aEnvelope = nsnull;
174 return nsISOAPMessage::VERSION_UNKNOWN;
177 /* readonly attribute nsIDOMElement header; */
178 NS_IMETHODIMP nsSOAPMessage::GetHeader(nsIDOMElement * *aHeader)
180 NS_ENSURE_ARG_POINTER(aHeader);
181 nsCOMPtr<nsIDOMElement> env;
182 PRUint16 version = GetEnvelopeWithVersion(getter_AddRefs(env));
183 if (env) {
184 nsSOAPUtils::GetSpecificChildElement(nsnull, env,
185 *gSOAPStrings->kSOAPEnvURI[version],
186 gSOAPStrings->kHeaderTagName,
187 aHeader);
188 } else {
189 *aHeader = nsnull;
191 return NS_OK;
194 /* readonly attribute nsIDOMElement body; */
195 NS_IMETHODIMP nsSOAPMessage::GetBody(nsIDOMElement * *aBody)
197 NS_ENSURE_ARG_POINTER(aBody);
198 nsCOMPtr<nsIDOMElement> env;
199 PRUint16 version = GetEnvelopeWithVersion(getter_AddRefs(env));
200 if (env) {
201 nsSOAPUtils::GetSpecificChildElement(nsnull, env,
202 *gSOAPStrings->kSOAPEnvURI[version],
203 gSOAPStrings->kBodyTagName, aBody);
204 } else {
205 *aBody = nsnull;
207 return NS_OK;
210 /* attribute DOMString actionURI; */
211 NS_IMETHODIMP nsSOAPMessage::GetActionURI(nsAString & aActionURI)
213 aActionURI.Assign(mActionURI);
214 return NS_OK;
217 NS_IMETHODIMP nsSOAPMessage::SetActionURI(const nsAString & aActionURI)
219 mActionURI.Assign(aActionURI);
220 return NS_OK;
223 /* readonly attribute AString methodName; */
224 NS_IMETHODIMP nsSOAPMessage::GetMethodName(nsAString & aMethodName)
226 nsCOMPtr<nsIDOMElement> body;
227 GetBody(getter_AddRefs(body));
228 if (body) {
229 nsCOMPtr<nsIDOMElement> method;
230 nsSOAPUtils::GetFirstChildElement(body, getter_AddRefs(method));
231 if (method) {
232 body->GetLocalName(aMethodName);
233 return NS_OK;
236 aMethodName.Truncate();
237 return NS_OK;
240 /* readonly attribute AString targetObjectURI; */
241 NS_IMETHODIMP nsSOAPMessage::
242 GetTargetObjectURI(nsAString & aTargetObjectURI)
244 nsCOMPtr<nsIDOMElement> body;
245 GetBody(getter_AddRefs(body));
246 if (body) {
247 nsCOMPtr<nsIDOMElement> method;
248 nsSOAPUtils::GetFirstChildElement(body, getter_AddRefs(method));
249 if (method) {
250 nsCOMPtr<nsISOAPEncoding> encoding;
251 PRUint16 version;
252 nsresult rv = GetEncodingWithVersion(method, &version, getter_AddRefs(encoding));
253 if (NS_FAILED(rv))
254 return rv;
255 nsAutoString temp;
256 rv = method->GetNamespaceURI(temp);
257 if (NS_FAILED(rv))
258 return rv;
259 return encoding->GetInternalSchemaURI(temp, aTargetObjectURI);
262 aTargetObjectURI.Truncate();
263 return NS_OK;
266 NS_IMETHODIMP
267 nsSOAPMessage::Encode(PRUint16 aVersion, const nsAString & aMethodName,
268 const nsAString & aTargetObjectURI,
269 PRUint32 aHeaderBlockCount,
270 nsISOAPHeaderBlock ** aHeaderBlocks,
271 PRUint32 aParameterCount,
272 nsISOAPParameter ** aParameters)
274 static NS_NAMED_LITERAL_STRING(realEmptySOAPDocStr1,
275 "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:enc=\"http://schemas.xmlsoap.org/soap/encoding/\"><env:Header/><env:Body/></env:Envelope>");
276 static NS_NAMED_LITERAL_STRING(realEmptySOAPDocStr2,
277 "<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>");
278 static const nsAString *kEmptySOAPDocStr[] = {
279 &realEmptySOAPDocStr1, &realEmptySOAPDocStr2
282 if (aVersion != nsISOAPMessage::VERSION_1_1
283 && aVersion != nsISOAPMessage::VERSION_1_2)
284 return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_BAD_VALUE","Cannot encode message blocks without a valid SOAP version specified.");
286 // Construct the message skeleton
288 nsresult rv;
289 nsCOMPtr<nsIDOMNode> ignored;
290 nsCOMPtr<nsIDOMParser> parser = do_CreateInstance(kDOMParserCID, &rv);
291 if (NS_FAILED(rv))
292 return rv;
294 rv = parser->ParseFromString(nsPromiseFlatString(*kEmptySOAPDocStr[aVersion]).get(),
295 "application/xml", getter_AddRefs(mMessage));
296 if (NS_FAILED(rv))
297 return rv;
299 // Declare the default encoding. This should always be non-null, but may be empty string.
301 nsCOMPtr<nsISOAPEncoding> encoding;
302 rv = GetEncoding(getter_AddRefs(encoding));
303 if (NS_FAILED(rv))
304 return rv;
305 nsCOMPtr<nsIDOMElement> envelope;
306 rv = GetEnvelope(getter_AddRefs(envelope));
307 if (NS_FAILED(rv))
308 return rv;
309 if (envelope) {
310 nsAutoString enc;
311 rv = mEncoding->GetStyleURI(enc);
312 if (NS_FAILED(rv))
313 return rv;
314 if (!enc.IsEmpty()) {
315 rv = envelope->SetAttributeNS(*gSOAPStrings->kSOAPEnvURI[aVersion],
316 gSOAPStrings->kEncodingStyleAttribute, enc);
317 if (NS_FAILED(rv))
318 return rv;
321 // Declare the schema namespaces, taking into account any mappings that are present.
323 nsAutoString temp;
324 nsAutoString temp2;
325 temp.Assign(gSOAPStrings->kXMLNamespacePrefix);
326 temp.Append(gSOAPStrings->kXSPrefix);
327 rv = encoding->GetExternalSchemaURI(gSOAPStrings->kXSURI, temp2);
328 if (NS_FAILED(rv))
329 return rv;
330 rv = envelope->SetAttributeNS(gSOAPStrings->kXMLNamespaceNamespaceURI, temp, temp2);
331 if (NS_FAILED(rv))
332 return rv;
333 temp.Assign(gSOAPStrings->kXMLNamespacePrefix);
334 temp.Append(gSOAPStrings->kXSIPrefix);
335 rv = encoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, temp2);
336 if (NS_FAILED(rv))
337 return rv;
338 rv = envelope->SetAttributeNS(gSOAPStrings->kXMLNamespaceNamespaceURI, temp, temp2);
339 if (NS_FAILED(rv))
340 return rv;
342 // Encode and add headers, if any were specified
344 if (aHeaderBlockCount) {
345 nsCOMPtr<nsIDOMElement> parent;
346 rv = GetHeader(getter_AddRefs(parent));
347 if (NS_FAILED(rv))
348 return rv;
349 nsCOMPtr<nsISOAPHeaderBlock> header;
350 nsCOMPtr<nsIDOMElement> element;
351 nsAutoString name;
352 nsAutoString namespaceURI;
353 PRUint32 i;
354 for (i = 0; i < aHeaderBlockCount; i++) {
355 header = aHeaderBlocks[i];
356 if (!header)
357 return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_NULL_HEADER","Cannot encode null in header array.");
358 rv = header->GetElement(getter_AddRefs(element));
359 if (element) {
360 nsCOMPtr<nsIDOMNode> node1;
361 node1 = element;
362 nsCOMPtr<nsIDOMNode> node2;
363 rv = mMessage->ImportNode(node1, PR_TRUE, getter_AddRefs(node1));
364 if (NS_FAILED(rv))
365 return rv;
366 rv = parent->AppendChild(node2, getter_AddRefs(node1));
367 if (NS_FAILED(rv))
368 return rv;
369 element = do_QueryInterface(node1);
370 } else {
371 rv = header->GetNamespaceURI(namespaceURI);
372 if (NS_FAILED(rv))
373 return rv;
374 rv = header->GetName(name);
375 if (NS_FAILED(rv))
376 return rv;
377 nsAutoString actorURI;
378 rv = header->GetActorURI(actorURI);
379 if (NS_FAILED(rv))
380 return rv;
381 PRBool mustUnderstand;
382 rv = header->GetMustUnderstand(&mustUnderstand);
383 if (NS_FAILED(rv))
384 return rv;
385 rv = header->GetEncoding(getter_AddRefs(encoding));
386 if (NS_FAILED(rv))
387 return rv;
388 if (!encoding) {
389 rv = GetEncoding(getter_AddRefs(encoding));
390 if (NS_FAILED(rv))
391 return rv;
393 nsCOMPtr<nsISchemaType> schemaType;
394 rv = header->GetSchemaType(getter_AddRefs(schemaType));
395 if (NS_FAILED(rv))
396 return rv;
397 nsCOMPtr<nsIVariant> value;
398 rv = header->GetValue(getter_AddRefs(value));
399 if (NS_FAILED(rv))
400 return rv;
401 rv = encoding->Encode(value, namespaceURI, name,
402 schemaType, nsnull, parent,
403 getter_AddRefs(element));
404 if (NS_FAILED(rv))
405 return rv;
406 if (!actorURI.IsEmpty()) {
407 element->SetAttributeNS(gSOAPStrings->kSOAPEnvPrefix,
408 gSOAPStrings->kActorAttribute, actorURI);
409 if (NS_FAILED(rv))
410 return rv;
412 if (mustUnderstand) {
413 element->SetAttributeNS(gSOAPStrings->kSOAPEnvPrefix,
414 gSOAPStrings->kMustUnderstandAttribute,
415 gSOAPStrings->kTrueA);
416 if (NS_FAILED(rv))
417 return rv;
419 if (mEncoding != encoding) {
420 nsAutoString enc;
421 encoding->GetStyleURI(enc);
422 element->
423 SetAttributeNS(*gSOAPStrings->kSOAPEnvURI[aVersion],
424 gSOAPStrings->kEncodingStyleAttribute, enc);
429 nsCOMPtr<nsIDOMElement> body;
430 rv = GetBody(getter_AddRefs(body));
431 if (NS_FAILED(rv))
432 return rv;
434 // Only produce a call element if mMethodName was non-empty
436 if (!aMethodName.IsEmpty()) {
437 nsAutoString temp;
438 rv = encoding->GetExternalSchemaURI(aTargetObjectURI, temp);
439 nsCOMPtr<nsIDOMElement> call;
440 rv = mMessage->CreateElementNS(temp, aMethodName,
441 getter_AddRefs(call));
442 if (NS_FAILED(rv))
443 return rv;
444 nsCOMPtr<nsIDOMNode> ignored;
445 rv = body->AppendChild(call, getter_AddRefs(ignored));
446 if (NS_FAILED(rv))
447 return rv;
448 body = call;
450 // Encode and add all of the parameters into the body
452 nsCOMPtr<nsISOAPParameter> param;
453 nsCOMPtr<nsIDOMElement> element;
454 nsCOMPtr<nsISOAPEncoding> newencoding;
455 nsAutoString name;
456 nsAutoString namespaceURI;
457 PRUint32 i;
458 for (i = 0; i < aParameterCount; i++) {
459 param = aParameters[i];
460 if (!param)
461 return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_NULL_PARAMETER","Cannot encode null in parameter array.");
462 rv = param->GetElement(getter_AddRefs(element));
463 if (element) {
464 nsCOMPtr<nsIDOMNode> node1;
465 node1 = element;
466 nsCOMPtr<nsIDOMNode> node2;
467 rv = mMessage->ImportNode(node1, PR_TRUE, getter_AddRefs(node2));
468 if (NS_FAILED(rv))
469 return rv;
470 rv = body->AppendChild(node2, getter_AddRefs(node1));
471 if (NS_FAILED(rv))
472 return rv;
473 element = do_QueryInterface(node1);
474 } else {
475 rv = param->GetNamespaceURI(namespaceURI);
476 if (NS_FAILED(rv))
477 return rv;
478 rv = param->GetName(name);
479 if (NS_FAILED(rv))
480 return rv;
481 rv = param->GetEncoding(getter_AddRefs(newencoding));
482 if (NS_FAILED(rv))
483 return rv;
484 if (!newencoding) {
485 newencoding = encoding;
487 nsCOMPtr<nsISchemaType> schemaType;
488 rv = param->GetSchemaType(getter_AddRefs(schemaType));
489 if (NS_FAILED(rv))
490 return rv;
491 nsCOMPtr<nsIVariant> value;
492 rv = param->GetValue(getter_AddRefs(value));
493 if (NS_FAILED(rv))
494 return rv;
495 rv = newencoding->Encode(value, namespaceURI, name,
496 schemaType, nsnull, body,
497 getter_AddRefs(element));
498 if (NS_FAILED(rv))
499 return rv;
500 if (encoding != newencoding) {
501 nsAutoString enc;
502 newencoding->GetStyleURI(enc);
503 element->SetAttributeNS(*gSOAPStrings->kSOAPEnvURI[aVersion],
504 gSOAPStrings->kEncodingStyleAttribute, enc);
508 return NS_OK;
512 * Internally used to track down the encoding to be used at the headers
513 * or parameters. We know the version is legal, or we couldn't have
514 * found a starting point, so it is used but not checked again. We
515 * also know that since there is a version, there is an encoding.
517 nsresult
518 nsSOAPMessage::GetEncodingWithVersion(nsIDOMElement * aFirst,
519 PRUint16 * aVersion,
520 nsISOAPEncoding ** aEncoding)
522 nsCOMPtr<nsISOAPEncoding> encoding;
523 nsresult rv = GetEncoding(getter_AddRefs(encoding));
524 if (NS_FAILED(rv))
525 return rv;
526 rv = GetVersion(aVersion);
527 if (NS_FAILED(rv))
528 return rv;
529 nsCOMPtr<nsIDOMElement> element = aFirst;
531 // Check for stray encodingStyle attributes. If none found, then
532 // use empty string encoding style.
534 nsAutoString style;
535 for (;;) {
536 nsCOMPtr<nsIDOMAttr> enc;
537 rv = element->GetAttributeNodeNS(*gSOAPStrings->kSOAPEnvURI[*aVersion],
538 gSOAPStrings->kEncodingStyleAttribute,
539 getter_AddRefs(enc));
540 if (NS_FAILED(rv))
541 return rv;
542 if (enc) {
543 rv = enc->GetNodeValue(style);
544 if (NS_FAILED(rv))
545 return rv;
546 break;
547 } else {
548 nsCOMPtr<nsIDOMNode> next;
549 rv = element->GetParentNode(getter_AddRefs(next));
550 if (NS_FAILED(rv))
551 return rv;
552 if (next) {
553 PRUint16 type;
554 rv = next->GetNodeType(&type);
555 if (NS_FAILED(rv))
556 return rv;
557 if (type != nsIDOMNode::ELEMENT_NODE) {
558 next = nsnull;
561 if (next) {
562 element = do_QueryInterface(next);
563 } else {
564 break;
568 return encoding->GetAssociatedEncoding(style, PR_TRUE, aEncoding);
571 /* void getHeaderBlocks (out PRUint32 aCount, [array, size_is (aCount), retval] out nsISOAPHeaderBlock aHeaderBlocks); */
572 NS_IMETHODIMP
573 nsSOAPMessage::GetHeaderBlocks(PRUint32 * aCount,
574 nsISOAPHeaderBlock *** aHeaderBlocks)
576 NS_ENSURE_ARG_POINTER(aHeaderBlocks);
577 nsISOAPHeaderBlock** headerBlocks = nsnull;
578 *aCount = 0;
579 *aHeaderBlocks = nsnull;
580 int count = 0;
581 int length = 0;
583 nsCOMPtr<nsIDOMElement> element;
584 nsresult rv = GetHeader(getter_AddRefs(element));
585 if (NS_FAILED(rv) || !element)
586 return rv;
587 nsCOMPtr<nsISOAPEncoding> encoding;
588 PRUint16 version;
589 rv = GetEncodingWithVersion(element, &version, getter_AddRefs(encoding));
590 if (NS_FAILED(rv))
591 return rv;
592 nsCOMPtr<nsIDOMElement> next;
594 nsCOMPtr<nsISOAPHeaderBlock> header;
595 nsSOAPUtils::GetFirstChildElement(element, getter_AddRefs(next));
596 while (next) {
597 if (length == count) {
598 length = length ? 2 * length : 10;
599 headerBlocks =
600 (nsISOAPHeaderBlock * *)nsMemory::Realloc(headerBlocks,
601 length *
602 sizeof(*headerBlocks));
604 element = next;
605 header = do_CreateInstance(NS_SOAPHEADERBLOCK_CONTRACTID);
606 if (!header) {
607 rv = NS_ERROR_OUT_OF_MEMORY;
608 break;
610 header->Init(nsnull, version);
612 (headerBlocks)[(count)] = header;
613 NS_ADDREF((headerBlocks)[(count)]);
614 (count)++;
616 rv = header->SetElement(element);
617 if (NS_FAILED(rv))
618 break;
619 rv = header->SetEncoding(encoding);
620 if (NS_FAILED(rv))
621 break;
622 nsSOAPUtils::GetNextSiblingElement(element, getter_AddRefs(next));
624 if (NS_SUCCEEDED(rv)) {
625 if (count) {
626 headerBlocks =
627 (nsISOAPHeaderBlock * *)nsMemory::Realloc(headerBlocks,
628 count *
629 sizeof(*headerBlocks));
632 else {
633 while (--count >= 0) {
634 NS_IF_RELEASE(headerBlocks[count]);
636 count = 0;
637 nsMemory::Free(headerBlocks);
638 headerBlocks = nsnull;
640 *aCount = count;
641 *aHeaderBlocks = headerBlocks;
642 return rv;
645 /* void getParameters (in boolean aDocumentStyle, out PRUint32 aCount, [array, size_is (aCount), retval] out nsISOAPParameter aParameters); */
646 NS_IMETHODIMP
647 nsSOAPMessage::GetParameters(PRBool aDocumentStyle, PRUint32 * aCount,
648 nsISOAPParameter *** aParameters)
650 NS_ENSURE_ARG_POINTER(aParameters);
651 nsISOAPParameter** parameters = nsnull;
652 *aCount = 0;
653 *aParameters = nsnull;
654 int count = 0;
655 int length = 0;
656 nsCOMPtr<nsIDOMElement> element;
657 nsresult rv = GetBody(getter_AddRefs(element));
658 if (NS_FAILED(rv) || !element)
659 return rv;
660 nsCOMPtr<nsIDOMElement> next;
661 nsCOMPtr<nsISOAPParameter> param;
662 nsSOAPUtils::GetFirstChildElement(element, getter_AddRefs(next));
663 if (!aDocumentStyle) {
664 element = next;
665 if (!element)
666 return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_MISSING_METHOD","Cannot decode rpc-style message due to missing method element.");
667 nsSOAPUtils::GetFirstChildElement(element, getter_AddRefs(next));
669 nsCOMPtr<nsISOAPEncoding> encoding;
670 PRUint16 version;
671 rv = GetEncodingWithVersion(element, &version, getter_AddRefs(encoding));
672 if (NS_FAILED(rv))
673 return rv;
674 while (next) {
675 if (length == count) {
676 length = length ? 2 * length : 10;
677 parameters =
678 (nsISOAPParameter * *)nsMemory::Realloc(parameters,
679 length *
680 sizeof(*parameters));
682 element = next;
683 param = do_CreateInstance(NS_SOAPPARAMETER_CONTRACTID);
684 if (!param) {
685 rv = NS_ERROR_OUT_OF_MEMORY;
686 break;
688 parameters[count] = param;
689 NS_ADDREF(parameters[count]);
690 count++;
692 rv = param->SetElement(element);
693 if (NS_FAILED(rv))
694 break;
695 rv = param->SetEncoding(encoding);
696 if (NS_FAILED(rv))
697 break;
698 nsSOAPUtils::GetNextSiblingElement(element, getter_AddRefs(next));
700 if (NS_SUCCEEDED(rv)) {
701 if (count) {
702 parameters =
703 (nsISOAPParameter * *)nsMemory::Realloc(parameters,
704 count *
705 sizeof(*parameters));
708 else {
709 while (--count >= 0) {
710 NS_IF_RELEASE(parameters[count]);
712 count = 0;
713 nsMemory::Free(parameters);
714 parameters = nsnull;
716 *aCount = count;
717 *aParameters = parameters;
718 return rv;
721 /* attribute nsISOAPEncoding encoding; */
722 NS_IMETHODIMP nsSOAPMessage::GetEncoding(nsISOAPEncoding * *aEncoding)
724 NS_ENSURE_ARG_POINTER(aEncoding);
725 if (!mEncoding) {
726 PRUint16 version;
727 nsresult rc = GetVersion(&version);
728 if (NS_FAILED(rc))
729 return rc;
730 if (version != nsISOAPMessage::VERSION_UNKNOWN) {
731 nsCOMPtr<nsISOAPEncoding> encoding =
732 do_CreateInstance(NS_SOAPENCODING_CONTRACTID);
733 if (!encoding)
734 return NS_ERROR_OUT_OF_MEMORY;
735 if (version == nsISOAPMessage::VERSION_1_1) {
736 rc = encoding->
737 GetAssociatedEncoding(gSOAPStrings->kSOAPEncURI11,
738 PR_FALSE, getter_AddRefs(mEncoding));
740 else {
741 rc = encoding->
742 GetAssociatedEncoding(gSOAPStrings->kSOAPEncURI,
743 PR_FALSE, getter_AddRefs(mEncoding));
745 if (NS_FAILED(rc))
746 return rc;
749 *aEncoding = mEncoding;
750 NS_IF_ADDREF(*aEncoding);
751 return NS_OK;
754 NS_IMETHODIMP nsSOAPMessage::SetEncoding(nsISOAPEncoding * aEncoding)
756 mEncoding = aEncoding;
757 return NS_OK;