1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3
* The contents of this file are subject to the Mozilla Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/MPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is Mozilla.
15
* The Initial Developer of the Original Code is Netscape
16
* Communications. Portions created by Netscape Communications are
17
* Copyright (C) 2001 by Netscape Communications. All
21
* Vidur Apparao <vidur@netscape.com> (original author)
24
#include "nsWSDLLoader.h"
27
#include "nsIDOMEvent.h"
28
#include "nsIDOMEventTarget.h"
29
#include "nsNetUtil.h"
32
#include "nsIContent.h"
33
#include "nsINodeInfo.h"
34
#include "nsIDOMDocument.h"
35
#include "nsIDOM3Node.h"
38
#include "nsReadableUtils.h"
41
#include "nsIXPConnect.h"
42
#include "nsIScriptSecurityManager.h"
43
#include "nsIPrincipal.h"
46
#include "nsIServiceManager.h"
47
#include "nsIComponentManager.h"
50
#include "nsISOAPMessage.h"
53
#include "nsIPrefService.h"
55
#define SCHEMA_2001_NAMESPACE "http://www.w3.org/2001/XMLSchema"
56
#define SCHEMA_1999_NAMESPACE "http://www.w3.org/1999/XMLSchema"
58
////////////////////////////////////////////////////////////
60
// nsWSDLAtoms implementation
62
////////////////////////////////////////////////////////////
65
nsIAtom* nsWSDLAtoms::sDefinitions_atom = nsnull;
66
nsIAtom* nsWSDLAtoms::sImport_atom = nsnull;
67
nsIAtom* nsWSDLAtoms::sTypes_atom = nsnull;
68
nsIAtom* nsWSDLAtoms::sMessage_atom = nsnull;
69
nsIAtom* nsWSDLAtoms::sPortType_atom = nsnull;
70
nsIAtom* nsWSDLAtoms::sBinding_atom = nsnull;
71
nsIAtom* nsWSDLAtoms::sService_atom = nsnull;
72
nsIAtom* nsWSDLAtoms::sPort_atom = nsnull;
73
nsIAtom* nsWSDLAtoms::sOperation_atom = nsnull;
74
nsIAtom* nsWSDLAtoms::sPart_atom = nsnull;
75
nsIAtom* nsWSDLAtoms::sDocumentation_atom = nsnull;
76
nsIAtom* nsWSDLAtoms::sInput_atom = nsnull;
77
nsIAtom* nsWSDLAtoms::sOutput_atom = nsnull;
78
nsIAtom* nsWSDLAtoms::sFault_atom = nsnull;
80
nsIAtom* nsWSDLAtoms::sBody_atom = nsnull;
81
nsIAtom* nsWSDLAtoms::sHeader_atom = nsnull;
82
nsIAtom* nsWSDLAtoms::sHeaderFault_atom = nsnull;
83
nsIAtom* nsWSDLAtoms::sAddress_atom = nsnull;
85
nsIAtom* nsWSDLAtoms::sSchema_atom = nsnull;
87
#define SET_AND_CHECK_ATOM(_atom, _val) \
89
_atom = NS_NewAtom(_val); \
91
return NS_ERROR_OUT_OF_MEMORY; \
95
nsWSDLAtoms::CreateWSDLAtoms()
97
NS_ASSERTION(!sDefinitions_atom, "nsWSDLAtoms already created!");
99
SET_AND_CHECK_ATOM(sDefinitions_atom, "definitions");
100
SET_AND_CHECK_ATOM(sImport_atom, "import");
101
SET_AND_CHECK_ATOM(sTypes_atom, "types");
102
SET_AND_CHECK_ATOM(sMessage_atom, "message");
103
SET_AND_CHECK_ATOM(sPortType_atom, "portType");
104
SET_AND_CHECK_ATOM(sBinding_atom, "binding");
105
SET_AND_CHECK_ATOM(sService_atom, "service");
106
SET_AND_CHECK_ATOM(sPort_atom, "port");
107
SET_AND_CHECK_ATOM(sOperation_atom, "operation");
108
SET_AND_CHECK_ATOM(sPart_atom, "part");
109
SET_AND_CHECK_ATOM(sDocumentation_atom, "documentation");
110
SET_AND_CHECK_ATOM(sInput_atom, "input");
111
SET_AND_CHECK_ATOM(sOutput_atom, "output");
112
SET_AND_CHECK_ATOM(sFault_atom, "fault");
114
SET_AND_CHECK_ATOM(sBody_atom, "body");
115
SET_AND_CHECK_ATOM(sHeader_atom, "header");
116
SET_AND_CHECK_ATOM(sHeaderFault_atom, "headerFault");
117
SET_AND_CHECK_ATOM(sAddress_atom, "address");
119
SET_AND_CHECK_ATOM(sSchema_atom, "schema");
125
nsWSDLAtoms::DestroyWSDLAtoms()
127
NS_IF_RELEASE(sDefinitions_atom);
128
NS_IF_RELEASE(sImport_atom);
129
NS_IF_RELEASE(sTypes_atom);
130
NS_IF_RELEASE(sMessage_atom);
131
NS_IF_RELEASE(sPortType_atom);
132
NS_IF_RELEASE(sBinding_atom);
133
NS_IF_RELEASE(sService_atom);
134
NS_IF_RELEASE(sPort_atom);
135
NS_IF_RELEASE(sOperation_atom);
136
NS_IF_RELEASE(sPart_atom);
137
NS_IF_RELEASE(sDocumentation_atom);
138
NS_IF_RELEASE(sInput_atom);
139
NS_IF_RELEASE(sOutput_atom);
140
NS_IF_RELEASE(sFault_atom);
142
NS_IF_RELEASE(sBody_atom);
143
NS_IF_RELEASE(sHeader_atom);
144
NS_IF_RELEASE(sHeaderFault_atom);
145
NS_IF_RELEASE(sAddress_atom);
147
NS_IF_RELEASE(sSchema_atom);
150
////////////////////////////////////////////////////////////
152
// nsWSDLLoader implementation
154
////////////////////////////////////////////////////////////
156
nsWSDLLoader::nsWSDLLoader()
160
nsWSDLLoader::~nsWSDLLoader()
164
NS_IMPL_ISUPPORTS1_CI(nsWSDLLoader, nsIWSDLLoader)
169
PRBool disabled = PR_FALSE;
170
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
172
if (NS_FAILED(prefBranch->GetBoolPref("xml.xmlextras.soap.wsdl.disabled",
174
// We default to enabling WSDL, it'll only be disabled if
175
// specificly disabled in the prefs.
181
return NS_ERROR_WSDL_NOT_ENABLED;
184
if (!nsWSDLAtoms::sDefinitions_atom) {
185
nsresult rv = nsWSDLAtoms::CreateWSDLAtoms();
195
nsWSDLLoader::GetResolvedURI(const nsAString& aWSDLURI, const char* aMethod,
199
nsCOMPtr<nsIXPCNativeCallContext> cc;
200
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
202
xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
207
rv = cc->GetJSContext(&cx);
211
nsCOMPtr<nsIScriptSecurityManager> secMan =
212
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
216
nsCOMPtr<nsIURI> baseURI;
217
nsCOMPtr<nsIPrincipal> principal;
218
rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
219
if (NS_SUCCEEDED(rv)) {
220
principal->GetURI(getter_AddRefs(baseURI));
223
rv = NS_NewURI(aURI, aWSDLURI, nsnull, baseURI);
227
rv = secMan->CheckLoadURIFromScript(cx, *aURI);
229
// Security check failed. The above call set a JS exception. The
230
// following lines ensure that the exception is propagated.
231
cc->SetExceptionWasThrown(PR_TRUE);
236
rv = NS_NewURI(aURI, aWSDLURI, nsnull);
244
// Internal helper called by Load() and Loadasync(). If aListener is
245
// non-null, it's an async load, if it's null, it's sync.
247
nsWSDLLoader::doLoad(const nsAString& wsdlURI, const nsAString& portName,
248
nsIWSDLLoadListener *aListener, nsIWSDLPort **_retval)
250
nsCOMPtr<nsIURI> resolvedURI;
251
nsresult rv = GetResolvedURI(wsdlURI, aListener ? "loadAsync" : "load",
252
getter_AddRefs(resolvedURI));
257
nsCOMPtr<nsIDOMEventListener> listener;
258
nsWSDLLoadRequest* request = new nsWSDLLoadRequest(!aListener, aListener,
261
return NS_ERROR_OUT_OF_MEMORY;
266
resolvedURI->GetSpec(spec);
268
rv = request->LoadDefinition(NS_ConvertUTF8toUCS2(spec));
270
if (NS_SUCCEEDED(rv) && !aListener) {
271
request->GetPort(_retval);
277
/* nsIWSDLService load (in AString wsdlURI, in AString portName); */
279
nsWSDLLoader::Load(const nsAString& wsdlURI, const nsAString& portName,
280
nsIWSDLPort **_retval)
282
NS_ENSURE_ARG_POINTER(_retval);
285
return doLoad(wsdlURI, portName, nsnull, _retval);
288
/* void loadAsync (in AString wsdlURI, in AString portName,
289
in nsIWSDLLoadListener listener); */
291
nsWSDLLoader::LoadAsync(const nsAString& wsdlURI, const nsAString& portName,
292
nsIWSDLLoadListener *aListener)
294
NS_ENSURE_ARG(aListener);
296
return doLoad(wsdlURI, portName, aListener, nsnull);
299
////////////////////////////////////////////////////////////
301
// nsWSDLLoadRequest implementation
303
////////////////////////////////////////////////////////////
304
nsWSDLLoadRequest::nsWSDLLoadRequest(PRBool aIsSync,
305
nsIWSDLLoadListener* aListener,
306
const nsAString& aPortName)
307
: mListener(aListener), mIsSync(aIsSync), mPortName(aPortName)
311
nsWSDLLoadRequest::~nsWSDLLoadRequest()
313
while (GetCurrentContext() != nsnull) {
318
NS_IMPL_ISUPPORTS1(nsWSDLLoadRequest, nsIDOMEventListener)
321
IsElementOfNamespace(nsIDOMElement* aElement, const nsAString& aNamespace)
323
nsAutoString namespaceURI;
324
aElement->GetNamespaceURI(namespaceURI);
325
return namespaceURI.Equals(aNamespace);
329
nsWSDLLoadRequest::LoadDefinition(const nsAString& aURI)
333
if (!mSchemaLoader) {
334
mSchemaLoader = do_GetService(NS_SCHEMALOADER_CONTRACTID, &rv);
340
mRequest = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
345
const nsAString& empty = EmptyString();
346
rv = mRequest->OpenRequest(NS_LITERAL_CSTRING("GET"),
347
NS_ConvertUTF16toUTF8(aURI), !mIsSync, empty,
353
// Force the mimetype of the returned stream to be xml.
354
rv = mRequest->OverrideMimeType(NS_LITERAL_CSTRING("text/xml"));
360
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mRequest));
362
return NS_ERROR_UNEXPECTED;
365
rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
370
rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, PR_FALSE);
376
rv = mRequest->Send(nsnull);
382
nsCOMPtr<nsIDOMDocument> document;
383
rv = mRequest->GetResponseXML(getter_AddRefs(document));
388
nsCOMPtr<nsIDOMElement> element;
390
document->GetDocumentElement(getter_AddRefs(element));
392
if (IsElementOfNamespace(element,
393
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
394
rv = PushContext(document, aURI);
399
rv = ResumeProcessing();
407
else if (IsElementOfNamespace(element,
408
NS_LITERAL_STRING(SCHEMA_2001_NAMESPACE)) ||
409
IsElementOfNamespace(element,
410
NS_LITERAL_STRING(SCHEMA_1999_NAMESPACE))) {
411
nsCOMPtr<nsISchema> schema;
412
rv = mSchemaLoader->ProcessSchemaElement(element,
413
getter_AddRefs(schema));
415
return NS_ERROR_WSDL_SCHEMA_PROCESSING_ERROR;
418
nsAutoString targetNamespace;
419
schema->GetTargetNamespace(targetNamespace);
421
nsStringKey key(targetNamespace);
422
mTypes.Put(&key, schema);
425
rv = NS_ERROR_WSDL_NOT_WSDL_ELEMENT; // element of unknown namespace
429
return NS_ERROR_WSDL_NOT_WSDL_ELEMENT;
437
nsWSDLLoadRequest::ContineProcessingTillDone()
441
rv = ResumeProcessing();
443
if (NS_FAILED(rv) || (rv == NS_ERROR_WSDL_LOADPENDING)) {
448
} while (GetCurrentContext() != nsnull);
453
/* void handleEvent (in nsIDOMEvent event); */
455
nsWSDLLoadRequest::HandleEvent(nsIDOMEvent *event)
458
nsAutoString eventType;
460
event->GetType(eventType);
462
if (eventType.Equals(NS_LITERAL_STRING("load"))) {
463
nsCOMPtr<nsIDOMDocument> document;
465
rv = mRequest->GetResponseXML(getter_AddRefs(document));
467
nsCOMPtr<nsIDOMElement> element;
469
document->GetDocumentElement(getter_AddRefs(element));
471
if (IsElementOfNamespace(element,
472
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
473
nsCOMPtr<nsIChannel> channel;
474
nsCOMPtr<nsIURI> uri;
477
mRequest->GetChannel(getter_AddRefs(channel));
480
channel->GetURI(getter_AddRefs(uri));
486
rv = PushContext(document, NS_ConvertUTF8toUCS2(spec));
488
if (NS_SUCCEEDED(rv)) {
489
rv = ContineProcessingTillDone();
492
else if (IsElementOfNamespace(element,
493
NS_LITERAL_STRING(SCHEMA_2001_NAMESPACE)) ||
494
IsElementOfNamespace(element,
495
NS_LITERAL_STRING(SCHEMA_1999_NAMESPACE))) {
496
nsCOMPtr<nsISchema> schema;
497
rv = mSchemaLoader->ProcessSchemaElement(element,
498
getter_AddRefs(schema));
500
return NS_ERROR_WSDL_SCHEMA_PROCESSING_ERROR;
503
nsAutoString targetNamespace;
504
schema->GetTargetNamespace(targetNamespace);
506
nsStringKey key(targetNamespace);
507
mTypes.Put(&key, schema);
509
rv = ContineProcessingTillDone();
512
rv = NS_ERROR_WSDL_NOT_WSDL_ELEMENT; // element of unknown namespace
516
rv = NS_ERROR_WSDL_NOT_WSDL_ELEMENT;
521
mListener->OnError(rv, NS_LITERAL_STRING("Failure processing WSDL document"));
525
else if (eventType.Equals(NS_LITERAL_STRING("error"))) {
526
mListener->OnError(NS_ERROR_WSDL_LOADING_ERROR,
527
NS_LITERAL_STRING("Failure loading"));
531
if (GetCurrentContext() == nsnull) {
533
mListener->OnLoad(mPort);
536
mListener->OnError(NS_ERROR_WSDL_BINDING_NOT_FOUND,
537
NS_LITERAL_STRING("Binding not found"));
546
nsWSDLLoadRequest::ResumeProcessing()
550
nsWSDLLoadingContext* context = GetCurrentContext();
552
return NS_ERROR_UNEXPECTED;
555
nsCOMPtr<nsIDOMElement> element;
556
context->GetRootElement(getter_AddRefs(element));
557
PRUint32 childIndex = context->GetChildIndex();
559
nsChildElementIterator iterator(element,
560
NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
561
nsCOMPtr<nsIDOMElement> childElement;
562
nsCOMPtr<nsIAtom> tagName;
564
// If we don't yet have a port, find the service element, create one
565
// and record the port's its binding name
566
if (mBindingName.IsEmpty()) {
567
// The service element tends to be at the end of WSDL files, so
568
// this would be more efficient if we iterated from last to first
570
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
571
getter_AddRefs(tagName))) &&
573
if (tagName == nsWSDLAtoms::sService_atom) {
574
rv = ProcessServiceElement(childElement);
582
iterator.Reset(childIndex);
583
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
584
getter_AddRefs(tagName))) &&
586
if (tagName == nsWSDLAtoms::sImport_atom) {
587
rv = ProcessImportElement(childElement,
588
iterator.GetCurrentIndex()+1);
590
(rv == NS_ERROR_WSDL_LOADPENDING)) {
594
else if (tagName == nsWSDLAtoms::sTypes_atom) {
595
rv = ProcessTypesElement(childElement);
600
else if (tagName == nsWSDLAtoms::sMessage_atom) {
601
rv = ProcessMessageElement(childElement);
606
else if (tagName == nsWSDLAtoms::sPortType_atom) {
607
rv = ProcessPortTypeElement(childElement);
612
else if (tagName == nsWSDLAtoms::sBinding_atom) {
613
nsAutoString name, targetNamespace;
614
childElement->GetAttribute(NS_LITERAL_STRING("name"), name);
615
context->GetTargetNamespace(targetNamespace);
617
// Only process binding for the requested port
618
// XXX We should be checking the binding namespace as
619
// well, but some authors are not qualifying their
621
if (mBindingName.Equals(name)) {
622
rv = ProcessBindingElement(childElement);
634
nsWSDLLoadRequest::GetPort(nsIWSDLPort** aPort)
637
NS_IF_ADDREF(*aPort);
643
nsWSDLLoadRequest::PushContext(nsIDOMDocument* aDocument,
644
const nsAString& aURISpec)
646
nsWSDLLoadingContext* context = new nsWSDLLoadingContext(aDocument,
649
return NS_ERROR_OUT_OF_MEMORY;
652
mContextStack.AppendElement((void*)context);
657
nsWSDLLoadingContext*
658
nsWSDLLoadRequest::GetCurrentContext()
660
PRUint32 count = mContextStack.Count();
662
return NS_STATIC_CAST(nsWSDLLoadingContext*,
663
mContextStack.ElementAt(count-1));
670
nsWSDLLoadRequest::PopContext()
672
PRUint32 count = mContextStack.Count();
674
nsWSDLLoadingContext* context =
675
NS_STATIC_CAST(nsWSDLLoadingContext*, mContextStack.ElementAt(count-1));
677
mContextStack.RemoveElementAt(count-1);
682
nsWSDLLoadRequest::GetSchemaElement(const nsAString& aName,
683
const nsAString& aNamespace,
684
nsISchemaElement** aSchemaComponent)
686
nsStringKey key(aNamespace);
687
nsCOMPtr<nsISupports> sup = dont_AddRef(mTypes.Get(&key));
688
nsCOMPtr<nsISchema> schema(do_QueryInterface(sup));
690
return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
693
nsCOMPtr<nsISchemaElement> element;
694
schema->GetElementByName(aName, getter_AddRefs(element));
696
return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
699
*aSchemaComponent = element;
700
NS_IF_ADDREF(*aSchemaComponent);
706
nsWSDLLoadRequest::GetSchemaType(const nsAString& aName,
707
const nsAString& aNamespace,
708
nsISchemaType** aSchemaComponent)
710
if (aNamespace.Equals(NS_LITERAL_STRING(SCHEMA_2001_NAMESPACE)) ||
711
aNamespace.Equals(NS_LITERAL_STRING(SCHEMA_1999_NAMESPACE))) {
712
nsCOMPtr<nsISchemaCollection> collection(do_QueryInterface(mSchemaLoader));
713
return collection->GetType(aName, aNamespace, aSchemaComponent);
716
nsStringKey key(aNamespace);
717
nsCOMPtr<nsISupports> sup = dont_AddRef(mTypes.Get(&key));
718
nsCOMPtr<nsISchema> schema(do_QueryInterface(sup));
720
return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
723
nsCOMPtr<nsISchemaType> type;
724
schema->GetTypeByName(aName, getter_AddRefs(type));
726
return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
729
*aSchemaComponent = type;
730
NS_IF_ADDREF(*aSchemaComponent);
736
nsWSDLLoadRequest::GetMessage(const nsAString& aName,
737
const nsAString& aNamespace,
738
nsIWSDLMessage** aMessage)
740
nsAutoString keyStr(aName);
741
keyStr.Append(aNamespace);
743
nsStringKey key(keyStr);
745
nsCOMPtr<nsISupports> sup = dont_AddRef(mMessages.Get(&key));
746
nsCOMPtr<nsIWSDLMessage> message(do_QueryInterface(sup));
748
return NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT;
752
NS_IF_ADDREF(*aMessage);
758
nsWSDLLoadRequest::GetPortType(const nsAString& aName,
759
const nsAString& aNamespace,
762
nsAutoString keyStr(aName);
763
keyStr.Append(aNamespace);
765
nsStringKey key(keyStr);
767
nsCOMPtr<nsISupports> sup = dont_AddRef(mPortTypes.Get(&key));
768
nsCOMPtr<nsIWSDLPort> port(do_QueryInterface(sup));
770
return NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT;
774
NS_IF_ADDREF(*aPort);
780
ParseQualifiedName(nsIDOMElement* aContext, const nsAString& aQualifiedName,
781
nsAString& aPrefix, nsAString& aLocalName,
782
nsAString& aNamespaceURI)
784
nsReadingIterator<PRUnichar> pos, begin, end;
786
aQualifiedName.BeginReading(begin);
787
aQualifiedName.EndReading(end);
790
if (FindCharInReadable(PRUnichar(':'), pos, end)) {
791
CopyUnicodeTo(begin, pos, aPrefix);
792
CopyUnicodeTo(++pos, end, aLocalName);
795
CopyUnicodeTo(begin, end, aLocalName);
798
nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aContext));
800
return NS_ERROR_UNEXPECTED;
803
return node->LookupNamespaceURI(aPrefix, aNamespaceURI);
808
nsWSDLLoadRequest::ProcessImportElement(nsIDOMElement* aElement,
813
// XXX Is there a need to record the namespace? Can it be different
814
// from the targetNamespace of the imported file?
816
nsAutoString location, documentLocation;
817
aElement->GetAttribute(NS_LITERAL_STRING("location"), location);
819
nsWSDLLoadingContext* context = GetCurrentContext();
821
return NS_ERROR_UNEXPECTED;
823
context->GetDocumentLocation(documentLocation);
825
nsCOMPtr<nsIURI> uri, baseURI;
826
rv = NS_NewURI(getter_AddRefs(baseURI), documentLocation);
831
rv = NS_NewURI(getter_AddRefs(uri), location, nsnull, baseURI);
836
// Fix ( bug 202478 ) a potential stack overflow by
837
// preventing the wsdl file from loading if it was
838
// already loaded via the import element.
839
PRUint32 count = mImportList.Count();
841
for (i = 0; i < count; i++) {
843
mImportList[i]->Equals(uri, &equal);
845
// Looks like this uri has already been loaded.
846
// Loading it again will end up in an infinite loop.
847
return NS_ERROR_WSDL_RECURSIVE_IMPORT;
851
mImportList.AppendObject(uri);
856
rv = LoadDefinition(NS_ConvertUTF8toUCS2(spec.get()));
862
context->SetChildIndex(aIndex);
863
return NS_ERROR_WSDL_LOADPENDING;
870
nsWSDLLoadRequest::ProcessTypesElement(nsIDOMElement* aElement)
872
static const char* kSchemaNamespaces[] =
874
SCHEMA_1999_NAMESPACE,
875
SCHEMA_2001_NAMESPACE
877
static const PRUint32 kSchemaNamespacesLength =
878
sizeof(kSchemaNamespaces) / sizeof(const char*);
882
nsChildElementIterator iterator(aElement,
883
kSchemaNamespaces, kSchemaNamespacesLength);
884
nsCOMPtr<nsIDOMElement> childElement;
885
nsCOMPtr<nsIAtom> tagName;
887
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
888
getter_AddRefs(tagName))) &&
890
if (tagName == nsWSDLAtoms::sSchema_atom) {
891
nsCOMPtr<nsISchema> schema;
892
rv = mSchemaLoader->ProcessSchemaElement(childElement,
893
getter_AddRefs(schema));
895
return NS_ERROR_WSDL_SCHEMA_PROCESSING_ERROR;
898
nsAutoString targetNamespace;
899
schema->GetTargetNamespace(targetNamespace);
901
nsStringKey key(targetNamespace);
902
mTypes.Put(&key, schema);
910
nsWSDLLoadRequest::ProcessAbstractPartElement(nsIDOMElement* aElement,
911
nsWSDLMessage* aMessage)
916
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
918
nsCOMPtr<nsIWSDLPart> part;
919
nsWSDLPart* partInst = new nsWSDLPart(name);
921
return NS_ERROR_OUT_OF_MEMORY;
925
nsCOMPtr<nsISchemaComponent> schemaComponent;
926
nsAutoString elementQName, typeQName;
927
aElement->GetAttribute(NS_LITERAL_STRING("element"), elementQName);
928
aElement->GetAttribute(NS_LITERAL_STRING("type"), typeQName);
930
if (!elementQName.IsEmpty()) {
931
nsAutoString elementPrefix, elementLocalName, elementNamespace;
933
rv = ParseQualifiedName(aElement, elementQName, elementPrefix,
934
elementLocalName, elementNamespace);
939
nsCOMPtr<nsISchemaElement> schemaElement;
940
rv = GetSchemaElement(elementLocalName, elementNamespace,
941
getter_AddRefs(schemaElement));
946
schemaComponent = schemaElement;
948
else if (!typeQName.IsEmpty()) {
949
nsAutoString typePrefix, typeLocalName, typeNamespace;
951
rv = ParseQualifiedName(aElement, typeQName, typePrefix, typeLocalName,
957
nsCOMPtr<nsISchemaType> schemaType;
958
rv = GetSchemaType(typeLocalName, typeNamespace,
959
getter_AddRefs(schemaType));
964
schemaComponent = schemaType;
967
partInst->SetTypeInfo(typeQName, elementQName, schemaComponent);
968
aMessage->AddPart(part);
974
nsWSDLLoadRequest::ProcessMessageElement(nsIDOMElement* aElement)
979
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
981
nsCOMPtr<nsIWSDLMessage> message;
982
nsWSDLMessage* messageInst = new nsWSDLMessage(name);
984
return NS_ERROR_OUT_OF_MEMORY;
986
message = messageInst;
988
nsChildElementIterator iterator(aElement,
989
NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
990
nsCOMPtr<nsIDOMElement> childElement;
991
nsCOMPtr<nsIAtom> tagName;
993
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
994
getter_AddRefs(tagName))) &&
996
if (tagName == nsWSDLAtoms::sDocumentation_atom) {
997
messageInst->SetDocumentationElement(childElement);
999
else if (tagName == nsWSDLAtoms::sPart_atom) {
1000
rv = ProcessAbstractPartElement(childElement, messageInst);
1001
if (NS_FAILED(rv)) {
1007
nsAutoString targetNamespace;
1008
nsWSDLLoadingContext* context = GetCurrentContext();
1010
return NS_ERROR_UNEXPECTED;
1012
context->GetTargetNamespace(targetNamespace);
1014
name.Append(targetNamespace);
1015
nsStringKey key(name);
1016
mMessages.Put(&key, message);
1022
nsWSDLLoadRequest::ProcessOperationComponent(nsIDOMElement* aElement,
1023
nsIWSDLMessage** aMessage)
1027
nsAutoString messageQName, messagePrefix, messageLocalName, messageNamespace;
1028
aElement->GetAttribute(NS_LITERAL_STRING("message"), messageQName);
1030
rv = ParseQualifiedName(aElement, messageQName, messagePrefix,
1031
messageLocalName, messageNamespace);
1032
if (NS_FAILED(rv)) {
1036
rv = GetMessage(messageLocalName, messageNamespace, aMessage);
1037
if (NS_FAILED(rv)) {
1038
// XXX It seem that some WSDL authors eliminate prefixes
1039
// from qualified names in attribute values, assuming that
1040
// the names will resolve to the targetNamespace, while
1041
// they should technically resolve to the default namespace.
1042
if (messagePrefix.IsEmpty()) {
1043
nsAutoString targetNamespace;
1044
nsWSDLLoadingContext* context = GetCurrentContext();
1046
return NS_ERROR_UNEXPECTED;
1048
context->GetTargetNamespace(targetNamespace);
1049
rv = GetMessage(messageLocalName, targetNamespace, aMessage);
1050
if (NS_FAILED(rv)) {
1060
nsWSDLLoadRequest::ProcessAbstractOperation(nsIDOMElement* aElement,
1063
nsresult rv = NS_OK;
1066
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
1068
nsCOMPtr<nsIWSDLOperation> operation;
1069
nsWSDLOperation* operationInst = new nsWSDLOperation(name);
1070
if (!operationInst) {
1071
return NS_ERROR_OUT_OF_MEMORY;
1073
operation = operationInst;
1075
nsAutoString parameterOrder;
1076
aElement->GetAttribute(NS_LITERAL_STRING("parameterOrder"), parameterOrder);
1077
if (!parameterOrder.IsEmpty()) {
1078
nsReadingIterator<PRUnichar> start, end, delimiter;
1079
parameterOrder.BeginReading(start);
1080
parameterOrder.EndReading(end);
1086
// Find the next delimiter
1087
found = FindCharInReadable(PRUnichar(' '), delimiter, end);
1089
// Use the string from the current start position to the
1091
nsAutoString paramName;
1092
CopyUnicodeTo(start, delimiter, paramName);
1094
if (!paramName.IsEmpty()) {
1095
operationInst->AddParameter(paramName);
1098
// If we did find a delimiter, advance past it
1106
nsChildElementIterator iterator(aElement,
1107
NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
1108
nsCOMPtr<nsIDOMElement> childElement;
1109
nsCOMPtr<nsIAtom> tagName;
1111
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1112
getter_AddRefs(tagName))) &&
1114
nsCOMPtr<nsIWSDLMessage> message;
1115
if (tagName == nsWSDLAtoms::sDocumentation_atom) {
1116
operationInst->SetDocumentationElement(childElement);
1118
else if (tagName == nsWSDLAtoms::sInput_atom) {
1119
rv = ProcessOperationComponent(childElement, getter_AddRefs(message));
1120
if (NS_FAILED(rv)) {
1123
operationInst->SetInput(message);
1125
else if (tagName == nsWSDLAtoms::sOutput_atom) {
1126
rv = ProcessOperationComponent(childElement, getter_AddRefs(message));
1127
if (NS_FAILED(rv)) {
1130
operationInst->SetOutput(message);
1132
else if (tagName == nsWSDLAtoms::sFault_atom) {
1133
rv = ProcessOperationComponent(childElement, getter_AddRefs(message));
1134
if (NS_FAILED(rv)) {
1137
operationInst->AddFault(message);
1141
aPort->AddOperation(operation);
1147
nsWSDLLoadRequest::ProcessPortTypeElement(nsIDOMElement* aElement)
1149
nsresult rv = NS_OK;
1152
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
1154
nsCOMPtr<nsIWSDLPort> port;
1155
nsWSDLPort* portInst = new nsWSDLPort(name);
1157
return NS_ERROR_OUT_OF_MEMORY;
1161
nsChildElementIterator iterator(aElement,
1162
NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
1163
nsCOMPtr<nsIDOMElement> childElement;
1164
nsCOMPtr<nsIAtom> tagName;
1166
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1167
getter_AddRefs(tagName))) &&
1169
if (tagName == nsWSDLAtoms::sDocumentation_atom) {
1170
portInst->SetDocumentationElement(childElement);
1172
else if (tagName == nsWSDLAtoms::sOperation_atom) {
1173
rv = ProcessAbstractOperation(childElement, portInst);
1174
if (NS_FAILED(rv)) {
1180
nsAutoString targetNamespace;
1181
nsWSDLLoadingContext* context = GetCurrentContext();
1183
return NS_ERROR_UNEXPECTED;
1185
context->GetTargetNamespace(targetNamespace);
1187
name.Append(targetNamespace);
1188
nsStringKey key(name);
1189
mPortTypes.Put(&key, port);
1195
nsWSDLLoadRequest::ProcessMessageBinding(nsIDOMElement* aElement,
1196
nsIWSDLMessage* aMessage)
1199
nsChildElementIterator iterator(aElement,
1200
NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE));
1201
nsCOMPtr<nsIDOMElement> childElement;
1202
nsCOMPtr<nsIAtom> tagName;
1204
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1205
getter_AddRefs(tagName))) &&
1207
if (tagName == nsWSDLAtoms::sBody_atom) {
1208
nsAutoString partsStr, useStr, encodingStyle, namespaceStr;
1209
childElement->GetAttribute(NS_LITERAL_STRING("parts"), partsStr);
1210
childElement->GetAttribute(NS_LITERAL_STRING("use"), useStr);
1211
childElement->GetAttribute(NS_LITERAL_STRING("encodingStyle"),
1213
childElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
1215
PRUint16 use = nsISOAPPartBinding::USE_LITERAL;
1216
if (useStr.Equals(NS_LITERAL_STRING("encoded"))) {
1217
use = nsISOAPPartBinding::USE_ENCODED;
1220
nsCOMPtr<nsISOAPMessageBinding> messageBinding;
1221
nsSOAPMessageBinding* messageBindingInst =
1222
new nsSOAPMessageBinding(namespaceStr);
1223
if (!messageBindingInst) {
1224
return NS_ERROR_OUT_OF_MEMORY;
1226
messageBinding = messageBindingInst;
1227
nsWSDLMessage* messageInst = NS_REINTERPRET_CAST(nsWSDLMessage*,
1229
messageInst->SetBinding(messageBinding);
1231
nsCOMPtr<nsISOAPPartBinding> binding;
1232
nsSOAPPartBinding* bindingInst =
1233
new nsSOAPPartBinding(nsISOAPPartBinding::LOCATION_BODY, use,
1234
encodingStyle, namespaceStr);
1236
return NS_ERROR_OUT_OF_MEMORY;
1238
binding = bindingInst;
1240
nsCOMPtr<nsIWSDLPart> part;
1241
nsWSDLPart* partInst;
1242
// If there is no explicit parts attribute, this binding applies
1243
// to all the parts.
1244
if (partsStr.IsEmpty()) {
1245
PRUint32 index, count;
1247
aMessage->GetPartCount(&count);
1248
for (index = 0; index < count; index++) {
1249
aMessage->GetPart(index, getter_AddRefs(part));
1250
partInst = NS_REINTERPRET_CAST(nsWSDLPart*, part.get());
1252
partInst->SetBinding(binding);
1257
nsReadingIterator<PRUnichar> start, end, delimiter;
1258
partsStr.BeginReading(start);
1259
partsStr.EndReading(end);
1265
// Find the next delimiter
1266
found = FindCharInReadable(PRUnichar(' '), delimiter, end);
1268
// Use the string from the current start position to the
1270
nsAutoString partName;
1271
CopyUnicodeTo(start, delimiter, partName);
1273
if (!partName.IsEmpty()) {
1274
aMessage->GetPartByName(partName, getter_AddRefs(part));
1275
partInst = NS_REINTERPRET_CAST(nsWSDLPart*, part.get());
1277
partInst->SetBinding(binding);
1281
// If we did find a delimiter, advance past it
1295
nsWSDLLoadRequest::ProcessOperationBinding(nsIDOMElement* aElement,
1298
nsresult rv = NS_OK;
1301
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
1303
nsCOMPtr<nsIWSDLOperation> operation;
1304
aPort->GetOperationByName(name, getter_AddRefs(operation));
1306
return NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT;
1308
nsWSDLOperation* operationInst = NS_REINTERPRET_CAST(nsWSDLOperation*,
1311
nsCOMPtr<nsISOAPOperationBinding> binding;
1312
nsSOAPOperationBinding* bindingInst = new nsSOAPOperationBinding();
1314
return NS_ERROR_OUT_OF_MEMORY;
1316
binding = bindingInst;
1318
nsChildElementIterator iterator(aElement);
1319
nsCOMPtr<nsIDOMElement> childElement;
1320
nsCOMPtr<nsIAtom> tagName;
1322
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1323
getter_AddRefs(tagName))) &&
1325
if ((tagName == nsWSDLAtoms::sDocumentation_atom) &&
1326
IsElementOfNamespace(childElement,
1327
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
1328
bindingInst->SetDocumentationElement(childElement);
1330
else if ((tagName == nsWSDLAtoms::sOperation_atom) &&
1331
IsElementOfNamespace(childElement,
1332
NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE))) {
1333
nsAutoString action, style;
1334
childElement->GetAttribute(NS_LITERAL_STRING("soapAction"), action);
1335
childElement->GetAttribute(NS_LITERAL_STRING("style"), style);
1337
bindingInst->SetSoapAction(action);
1338
if (style.Equals(NS_LITERAL_STRING("rpc"))) {
1339
bindingInst->SetStyle(nsISOAPPortBinding::STYLE_RPC);
1341
else if (style.Equals(NS_LITERAL_STRING("document"))) {
1342
bindingInst->SetStyle(nsISOAPPortBinding::STYLE_DOCUMENT);
1344
// If one isn't explicitly specified, we inherit from the port
1346
nsCOMPtr<nsIWSDLBinding> portBinding;
1347
aPort->GetBinding(getter_AddRefs(portBinding));
1348
nsCOMPtr<nsISOAPPortBinding> soapPortBinding =
1349
do_QueryInterface(portBinding);
1350
if (soapPortBinding) {
1352
soapPortBinding->GetStyle(&styleVal);
1353
bindingInst->SetStyle(styleVal);
1357
else if ((tagName == nsWSDLAtoms::sInput_atom) &&
1358
IsElementOfNamespace(childElement,
1359
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
1360
nsCOMPtr<nsIWSDLMessage> input;
1362
operation->GetInput(getter_AddRefs(input));
1363
rv = ProcessMessageBinding(childElement, input);
1364
if (NS_FAILED(rv)) {
1368
else if ((tagName == nsWSDLAtoms::sOutput_atom) &&
1369
IsElementOfNamespace(childElement,
1370
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
1371
nsCOMPtr<nsIWSDLMessage> output;
1373
operation->GetOutput(getter_AddRefs(output));
1374
rv = ProcessMessageBinding(childElement, output);
1375
if (NS_FAILED(rv)) {
1379
else if ((tagName == nsWSDLAtoms::sFault_atom) &&
1380
IsElementOfNamespace(childElement,
1381
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
1382
// XXX TO BE IMPLEMENTED
1386
operationInst->SetBinding(binding);
1393
nsWSDLLoadRequest::ProcessBindingElement(nsIDOMElement* aElement)
1395
nsresult rv = NS_OK;
1398
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
1400
PRBool foundSOAPBinding;
1401
nsCOMPtr<nsIWSDLBinding> binding;
1402
nsSOAPPortBinding* bindingInst = new nsSOAPPortBinding(name);
1404
return NS_ERROR_OUT_OF_MEMORY;
1406
binding = bindingInst;
1407
bindingInst->SetAddress(mAddress);
1409
nsCOMPtr<nsIWSDLPort> port;
1410
nsAutoString typeQName, typePrefix, typeLocalName, typeNamespace;
1411
aElement->GetAttribute(NS_LITERAL_STRING("type"), typeQName);
1412
rv = ParseQualifiedName(aElement, typeQName, typePrefix, typeLocalName,
1414
if (NS_FAILED(rv)) {
1418
rv = GetPortType(typeLocalName, typeNamespace, getter_AddRefs(port));
1419
if (NS_FAILED(rv)) {
1420
// XXX It seem that some WSDL authors eliminate prefixes
1421
// from qualified names in attribute values, assuming that
1422
// the names will resolve to the targetNamespace, while
1423
// they should technically resolve to the default namespace.
1424
if (typePrefix.IsEmpty()) {
1425
nsWSDLLoadingContext* context = GetCurrentContext();
1427
return NS_ERROR_UNEXPECTED;
1430
nsAutoString targetNamespace;
1431
context->GetTargetNamespace(targetNamespace);
1432
rv = GetPortType(typeLocalName, targetNamespace, getter_AddRefs(port));
1433
if (NS_FAILED(rv)) {
1434
return rv; // Can't find a port type of the specified name
1439
nsChildElementIterator iterator(aElement);
1440
nsCOMPtr<nsIDOMElement> childElement;
1441
nsCOMPtr<nsIAtom> tagName;
1443
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1444
getter_AddRefs(tagName))) &&
1446
if ((tagName == nsWSDLAtoms::sDocumentation_atom) &&
1447
IsElementOfNamespace(childElement,
1448
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
1449
bindingInst->SetDocumentationElement(childElement);
1451
else if ((tagName == nsWSDLAtoms::sBinding_atom) &&
1452
IsElementOfNamespace(childElement,
1453
NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE))) {
1454
// XXX There should be different namespaces for newer versions
1456
bindingInst->SetSoapVersion(nsISOAPPortBinding::SOAP_VERSION_1_1);
1458
nsAutoString style, transport;
1459
childElement->GetAttribute(NS_LITERAL_STRING("style"), style);
1460
childElement->GetAttribute(NS_LITERAL_STRING("transport"), transport);
1462
if (style.Equals(NS_LITERAL_STRING("rpc"))) {
1463
bindingInst->SetStyle(nsISOAPPortBinding::STYLE_RPC);
1465
else if (style.Equals(NS_LITERAL_STRING("document"))) {
1466
bindingInst->SetStyle(nsISOAPPortBinding::STYLE_DOCUMENT);
1468
bindingInst->SetTransport(transport);
1469
foundSOAPBinding = PR_TRUE;
1471
else if ((tagName == nsWSDLAtoms::sOperation_atom) &&
1472
IsElementOfNamespace(childElement,
1473
NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
1474
rv = ProcessOperationBinding(childElement, port);
1475
if (NS_FAILED(rv)) {
1481
if (!foundSOAPBinding) {
1482
// If we don't have a SOAP binding, we can't continue
1483
return NS_ERROR_WSDL_BINDING_NOT_FOUND;
1485
nsWSDLPort* portInst = NS_REINTERPRET_CAST(nsWSDLPort*, port.get());
1486
portInst->SetBinding(binding);
1494
nsWSDLLoadRequest::ProcessPortBinding(nsIDOMElement* aElement)
1496
nsChildElementIterator iterator(aElement);
1497
nsCOMPtr<nsIDOMElement> childElement;
1498
nsCOMPtr<nsIAtom> tagName;
1500
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1501
getter_AddRefs(tagName))) &&
1503
if ((tagName == nsWSDLAtoms::sAddress_atom) &&
1504
IsElementOfNamespace(childElement,
1505
NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE))) {
1506
childElement->GetAttribute(NS_LITERAL_STRING("location"), mAddress);
1514
nsWSDLLoadRequest::ProcessServiceElement(nsIDOMElement* aElement)
1518
nsChildElementIterator iterator(aElement,
1519
NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
1520
nsCOMPtr<nsIDOMElement> childElement;
1521
nsCOMPtr<nsIAtom> tagName;
1523
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1524
getter_AddRefs(tagName))) &&
1526
if (tagName == nsWSDLAtoms::sPort_atom) {
1528
childElement->GetAttribute(NS_LITERAL_STRING("name"), name);
1529
if (name.Equals(mPortName)) {
1530
nsAutoString bindingQName, bindingPrefix;
1532
childElement->GetAttribute(NS_LITERAL_STRING("binding"), bindingQName);
1533
rv = ParseQualifiedName(childElement, bindingQName, bindingPrefix,
1534
mBindingName, mBindingNamespace);
1535
if (NS_FAILED(rv)) {
1536
return rv; // binding of an unknown namespace
1539
rv = ProcessPortBinding(childElement);
1540
if (NS_FAILED(rv)) {