Back to index

lightning-sunbird  0.9+nobinonly
nsWSDLLoader.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.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Vidur Apparao <vidur@netscape.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsIWebServiceErrorHandler.h"
00040 
00041 #include "nsWSDLLoader.h"
00042 
00043 // loading includes
00044 #include "nsIDOMEvent.h"
00045 #include "nsIDOMEventTarget.h"
00046 #include "nsNetUtil.h"
00047 
00048 // content includes
00049 #include "nsIDOMDocument.h"
00050 #include "nsIDOM3Node.h"
00051 
00052 // string includes
00053 #include "nsReadableUtils.h"
00054 
00055 // XPConnect includes
00056 #include "nsIXPConnect.h"
00057 #include "nsIScriptSecurityManager.h"
00058 #include "nsIPrincipal.h"
00059 
00060 // XPCOM includes
00061 #include "nsIServiceManager.h"
00062 #include "nsIComponentManager.h"
00063 #include "nsStaticAtom.h"
00064 
00065 
00066 // XMLExtras includes
00067 #include "nsISOAPMessage.h"
00068 
00069 // pref. includes
00070 #include "nsIPrefService.h"
00071 
00072 #define SCHEMA_2001_NAMESPACE "http://www.w3.org/2001/XMLSchema"
00073 #define SCHEMA_1999_NAMESPACE "http://www.w3.org/1999/XMLSchema"
00074 
00076 //
00077 // nsWSDLAtoms implementation
00078 //
00080 
00081 // define storage for all atoms
00082 #define WSDL_ATOM(_name, _value) nsIAtom* nsWSDLAtoms::_name;
00083 #include "nsWSDLAtomList.h"
00084 #undef WSDL_ATOM
00085 
00086 static const nsStaticAtom atomInfo[] = {
00087 #define WSDL_ATOM(_name, _value) { _value, &nsWSDLAtoms::_name },
00088 #include "nsWSDLAtomList.h"
00089 #undef WSDL_ATOM
00090 };
00091 
00092 nsresult
00093 nsWSDLAtoms::AddRefAtoms()
00094 {
00095   return NS_RegisterStaticAtoms(atomInfo, NS_ARRAY_LENGTH(atomInfo));
00096 }
00097 
00099 //
00100 // nsWSDLLoader implementation
00101 //
00103 
00104 nsWSDLLoader::nsWSDLLoader()
00105 {
00106 }
00107 
00108 nsWSDLLoader::~nsWSDLLoader()
00109 {
00110 }
00111 
00112 NS_IMPL_ISUPPORTS1_CI(nsWSDLLoader, nsIWSDLLoader)
00113 
00114 nsresult
00115 nsWSDLLoader::Init()
00116 {
00117   PRBool disabled = PR_FALSE;
00118   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
00119   if (prefBranch) {
00120     if (NS_FAILED(prefBranch->GetBoolPref("xml.xmlextras.soap.wsdl.disabled",
00121                                           &disabled))) {
00122       // We default to enabling WSDL, it'll only be disabled if
00123       // specificly disabled in the prefs.
00124       disabled = PR_FALSE;
00125     }
00126   }
00127 
00128   return disabled ? NS_ERROR_WSDL_NOT_ENABLED : NS_OK;
00129 }
00130 nsresult
00131 nsWSDLLoader::GetResolvedURI(const nsAString& aWSDLURI, const char* aMethod,
00132                              nsIURI** aURI)
00133 {
00134   nsresult rv;
00135   nsCOMPtr<nsIXPCNativeCallContext> cc;
00136   nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
00137   if(xpc) {
00138     xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
00139   }
00140 
00141   if (cc) {
00142     JSContext* cx;
00143     rv = cc->GetJSContext(&cx);
00144     if (NS_FAILED(rv))
00145       return rv;
00146 
00147     nsCOMPtr<nsIScriptSecurityManager> secMan =
00148       do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00149     if (NS_FAILED(rv))
00150       return rv;
00151 
00152     nsCOMPtr<nsIURI> baseURI;
00153     nsCOMPtr<nsIPrincipal> principal;
00154     rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
00155     if (NS_SUCCEEDED(rv)) {
00156       principal->GetURI(getter_AddRefs(baseURI));
00157     }
00158 
00159     rv = NS_NewURI(aURI, aWSDLURI, nsnull, baseURI);
00160     if (NS_FAILED(rv))
00161       return rv;
00162 
00163     rv = secMan->CheckLoadURIFromScript(cx, *aURI);
00164     if (NS_FAILED(rv)) {
00165       // Security check failed. The above call set a JS exception. The
00166       // following lines ensure that the exception is propagated.
00167       cc->SetExceptionWasThrown(PR_TRUE);
00168       return rv;
00169     }
00170   }
00171   else {
00172     rv = NS_NewURI(aURI, aWSDLURI, nsnull);
00173     if (NS_FAILED(rv))
00174       return rv;
00175   }
00176 
00177   return NS_OK;
00178 }
00179 
00180 // Internal helper called by Load() and Loadasync(). If aListener is
00181 // non-null, it's an async load, if it's null, it's sync.
00182 nsresult
00183 nsWSDLLoader::doLoad(const nsAString& wsdlURI, const nsAString& portName,
00184                      nsIWSDLLoadListener *aListener, nsIWSDLPort **_retval)
00185 {
00186   nsCOMPtr<nsIURI> resolvedURI;
00187   nsresult rv = GetResolvedURI(wsdlURI, aListener ? "loadAsync" : "load",
00188                                getter_AddRefs(resolvedURI));
00189   if (NS_FAILED(rv)) {
00190     return rv;
00191   }
00192 
00193   nsCOMPtr<nsIDOMEventListener> listener;
00194   nsWSDLLoadRequest* request = new nsWSDLLoadRequest(!aListener, aListener,
00195                                                      portName);
00196   if (!request) {
00197     return NS_ERROR_OUT_OF_MEMORY;
00198   }
00199   listener = request;
00200 
00201   nsCAutoString spec;
00202   resolvedURI->GetSpec(spec);
00203 
00204   rv = request->LoadDefinition(NS_ConvertUTF8toUCS2(spec));
00205 
00206   if (NS_SUCCEEDED(rv) && !aListener) {
00207     request->GetPort(_retval);
00208   }
00209 
00210   return rv;
00211 }
00212 
00213 /* nsIWSDLService load (in AString wsdlURI, in AString portName); */
00214 NS_IMETHODIMP
00215 nsWSDLLoader::Load(const nsAString& wsdlURI, const nsAString& portName,
00216                    nsIWSDLPort **_retval)
00217 {
00218   NS_ENSURE_ARG_POINTER(_retval);
00219   *_retval = nsnull;
00220 
00221   return doLoad(wsdlURI, portName, nsnull, _retval);
00222 }
00223 
00224 /* void loadAsync (in AString wsdlURI, in AString portName,
00225    in nsIWSDLLoadListener listener); */
00226 NS_IMETHODIMP
00227 nsWSDLLoader::LoadAsync(const nsAString& wsdlURI, const nsAString& portName,
00228                         nsIWSDLLoadListener *aListener)
00229 {
00230   NS_ENSURE_ARG(aListener);
00231 
00232   return doLoad(wsdlURI, portName, aListener, nsnull);
00233 }
00234 
00236 //
00237 // nsWSDLLoadRequest implementation
00238 //
00240 nsWSDLLoadRequest::nsWSDLLoadRequest(PRBool aIsSync,
00241                                      nsIWSDLLoadListener* aListener,
00242                                      const nsAString& aPortName)
00243   : mListener(aListener), mIsSync(aIsSync), mPortName(aPortName)
00244 {
00245   mErrorHandler = mListener;
00246 
00247   if (!mErrorHandler) {
00248     NS_WARNING("nsWSDLLoadRequest::<init>: Error about interface "
00249                "nsIWebserviceErrorHandler");
00250 
00251   }
00252 }
00253 
00254 nsWSDLLoadRequest::~nsWSDLLoadRequest()
00255 {
00256   while (GetCurrentContext() != nsnull) {
00257     PopContext();
00258   }
00259 }
00260 
00261 NS_IMPL_ISUPPORTS1(nsWSDLLoadRequest, nsIDOMEventListener)
00262 
00263 static inline PRBool
00264 IsElementOfNamespace(nsIDOMElement* aElement, const nsAString& aNamespace)
00265 {
00266        nsAutoString namespaceURI;
00267        aElement->GetNamespaceURI(namespaceURI);
00268        return namespaceURI.Equals(aNamespace);
00269 }
00270 
00271 nsresult
00272 nsWSDLLoadRequest::LoadDefinition(const nsAString& aURI)
00273 {
00274   nsresult rv;
00275 
00276   if (!mSchemaLoader) {
00277     mSchemaLoader = do_GetService(NS_SCHEMALOADER_CONTRACTID, &rv);
00278     if (NS_FAILED(rv)) {
00279       return rv;
00280     }
00281   }
00282 
00283   mRequest = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
00284   if (!mRequest) {
00285     return rv;
00286   }
00287 
00288   const nsAString& empty = EmptyString();
00289   rv = mRequest->OpenRequest(NS_LITERAL_CSTRING("GET"),
00290                              NS_ConvertUTF16toUTF8(aURI), !mIsSync, empty,
00291                              empty);
00292   if (NS_FAILED(rv)) {
00293     return rv;
00294   }
00295 
00296   // Force the mimetype of the returned stream to be xml.
00297   rv = mRequest->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
00298   if (NS_FAILED(rv)) {
00299     return rv;
00300   }
00301 
00302   if (!mIsSync) {
00303     nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mRequest));
00304     if (!target) {
00305       return NS_ERROR_UNEXPECTED;
00306     }
00307 
00308     rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
00309     if (NS_FAILED(rv)) {
00310       return rv;
00311     }
00312 
00313     rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, PR_FALSE);
00314     if (NS_FAILED(rv)) {
00315       return rv;
00316     }
00317   }
00318 
00319   rv = mRequest->Send(nsnull);
00320   if (NS_FAILED(rv)) {
00321     return rv;
00322   }
00323 
00324   if (mIsSync) {
00325     nsCOMPtr<nsIDOMDocument> document;
00326     rv = mRequest->GetResponseXML(getter_AddRefs(document));
00327     if (NS_FAILED(rv)) {
00328       nsAutoString errorMsg(NS_LITERAL_STRING("Failure retrieving XML "));
00329       errorMsg.AppendLiteral("response for WSDL");
00330       NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00331 
00332       return rv;
00333     }
00334 
00335     nsCOMPtr<nsIDOMElement> element;
00336     if (document)
00337       document->GetDocumentElement(getter_AddRefs(element));
00338     if (element) {
00339       if (IsElementOfNamespace(element,
00340                                NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
00341         rv = PushContext(document, aURI);
00342         if (NS_FAILED(rv)) {
00343           nsAutoString elementName;
00344           nsresult rc = element->GetTagName(elementName);
00345           NS_ENSURE_SUCCESS(rc, rc);
00346 
00347           nsAutoString errorMsg;
00348           errorMsg.AppendLiteral("Failure queuing element \"");
00349           errorMsg.Append(elementName);
00350           errorMsg.AppendLiteral("\" to be processed");
00351 
00352           NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00353 
00354           return rv;
00355         }
00356 
00357         rv = ResumeProcessing();
00358 
00359         PopContext();
00360 
00361         if (NS_FAILED(rv)) {
00362           nsAutoString elementName;
00363           nsresult rc = element->GetTagName(elementName);
00364           NS_ENSURE_SUCCESS(rc, rc);
00365 
00366           nsAutoString errorMsg;
00367           errorMsg.AppendLiteral("Failure processing WSDL element \"");
00368           errorMsg.Append(elementName);
00369           errorMsg.AppendLiteral("\"");
00370 
00371           NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00372 
00373           return rv;
00374         }
00375       }
00376       else if (IsElementOfNamespace(element,
00377                              NS_LITERAL_STRING(SCHEMA_2001_NAMESPACE)) ||
00378                IsElementOfNamespace(element,
00379                              NS_LITERAL_STRING(SCHEMA_1999_NAMESPACE))) {
00380         nsCOMPtr<nsISchema> schema;
00381         rv = mSchemaLoader->ProcessSchemaElement(element, mErrorHandler,
00382                                                  getter_AddRefs(schema));
00383         if (NS_FAILED(rv)) {
00384           return NS_ERROR_WSDL_SCHEMA_PROCESSING_ERROR;
00385         }
00386 
00387         nsAutoString targetNamespace;
00388         schema->GetTargetNamespace(targetNamespace);
00389 
00390         nsStringKey key(targetNamespace);
00391         mTypes.Put(&key, schema);
00392       }
00393       else {
00394         // element of unknown namespace
00395         rv = NS_ERROR_WSDL_NOT_WSDL_ELEMENT;
00396         nsAutoString elementName;
00397         nsresult rc = element->GetTagName(elementName);
00398         NS_ENSURE_SUCCESS(rc, rc);
00399 
00400         nsAutoString errorMsg;
00401         errorMsg.AppendLiteral("Failure processing WSDL, element of ");
00402         errorMsg.AppendLiteral("unknown namespace \"");
00403         errorMsg.Append(elementName);
00404         errorMsg.AppendLiteral("\"");
00405 
00406         NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00407 
00408         return rv;        
00409       }
00410     }
00411     else {
00412       nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing WSDL, no document"));
00413       NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_NOT_WSDL_ELEMENT, errorMsg);
00414 
00415       return NS_ERROR_WSDL_NOT_WSDL_ELEMENT;
00416     }
00417   }
00418 
00419   return NS_OK;
00420 }
00421 
00422 nsresult
00423 nsWSDLLoadRequest::ContineProcessingTillDone()
00424 {
00425   nsresult rv;
00426   do {
00427     rv = ResumeProcessing();
00428 
00429     if (NS_FAILED(rv) || (rv == NS_ERROR_WSDL_LOADPENDING)) {
00430       break;
00431     }
00432 
00433     PopContext();
00434   } while (GetCurrentContext() != nsnull);
00435 
00436   return rv;
00437 }
00438 
00439 /* void handleEvent (in nsIDOMEvent event); */
00440 NS_IMETHODIMP
00441 nsWSDLLoadRequest::HandleEvent(nsIDOMEvent *event)
00442 {
00443   nsresult rv;
00444   nsAutoString eventType;
00445 
00446   event->GetType(eventType);
00447 
00448   if (eventType.EqualsLiteral("load")) {
00449     nsCOMPtr<nsIDOMDocument> document;
00450 
00451     rv = mRequest->GetResponseXML(getter_AddRefs(document));
00452     if (document) {
00453       nsCOMPtr<nsIDOMElement> element;
00454 
00455       document->GetDocumentElement(getter_AddRefs(element));
00456       if (element) {
00457         if (IsElementOfNamespace(element,
00458                                  NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
00459           nsCOMPtr<nsIChannel> channel;
00460           nsCOMPtr<nsIURI> uri;
00461           nsCAutoString spec;
00462 
00463           mRequest->GetChannel(getter_AddRefs(channel));
00464 
00465           if (channel) {
00466             channel->GetURI(getter_AddRefs(uri));
00467             if (uri) {
00468               uri->GetSpec(spec);
00469             }
00470           }
00471 
00472           rv = PushContext(document, NS_ConvertUTF8toUCS2(spec));
00473 
00474           if (NS_SUCCEEDED(rv)) {
00475             rv = ContineProcessingTillDone();
00476 
00477             if (NS_FAILED(rv)) {
00478               nsAutoString elementName;
00479               element->GetTagName(elementName);
00480 
00481               NS_ENSURE_SUCCESS(rv, rv);
00482 
00483               nsAutoString errorMsg;
00484               errorMsg.AppendLiteral("Failure processing WSDL element \"");
00485               errorMsg.Append(elementName);
00486               errorMsg.AppendLiteral("\"");
00487               
00488               NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_LOADING_ERROR, errorMsg);
00489 
00490               return NS_ERROR_WSDL_LOADING_ERROR;
00491             }
00492           }
00493           else {
00494             nsAutoString elementName;
00495             element->GetTagName(elementName);
00496 
00497             NS_ENSURE_SUCCESS(rv, rv);
00498 
00499             nsAutoString errorMsg;
00500             errorMsg.AppendLiteral("Failure queuing WSDL element \"");
00501             errorMsg.Append(elementName);
00502             errorMsg.AppendLiteral("\" for processing");
00503 
00504             NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_LOADING_ERROR, errorMsg);
00505 
00506             return NS_ERROR_WSDL_LOADING_ERROR;
00507           }
00508         }
00509         else if (IsElementOfNamespace(element,
00510                                 NS_LITERAL_STRING(SCHEMA_2001_NAMESPACE)) ||
00511                  IsElementOfNamespace(element,
00512                                 NS_LITERAL_STRING(SCHEMA_1999_NAMESPACE))) {
00513           nsCOMPtr<nsISchema> schema;
00514           rv = mSchemaLoader->ProcessSchemaElement(element, mErrorHandler,
00515                                                    getter_AddRefs(schema));
00516           if (NS_FAILED(rv)) {
00517             return NS_ERROR_WSDL_SCHEMA_PROCESSING_ERROR;
00518           }
00519 
00520           nsAutoString targetNamespace;
00521           schema->GetTargetNamespace(targetNamespace);
00522 
00523           nsStringKey key(targetNamespace);
00524           mTypes.Put(&key, schema);
00525 
00526           rv = ContineProcessingTillDone();
00527         }
00528         else {
00529           // element of unknown namespace
00530           nsAutoString elementName;
00531           rv = element->GetTagName(elementName);
00532           NS_ENSURE_SUCCESS(rv, rv);
00533 
00534           rv = NS_ERROR_WSDL_NOT_WSDL_ELEMENT;
00535 
00536           nsAutoString errorMsg;
00537           errorMsg.AppendLiteral("Failure processing WSDL, ");
00538           errorMsg.AppendLiteral("element of unknown namespace \"");
00539           errorMsg.Append(elementName);
00540           errorMsg.AppendLiteral("\"");
00541 
00542           NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00543 
00544           return rv;
00545         }
00546       }
00547       else {
00548         rv = NS_ERROR_WSDL_NOT_WSDL_ELEMENT;
00549         
00550         nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing WSDL document"));
00551         NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00552 
00553         return rv;
00554       }
00555     }
00556     if (NS_FAILED(rv)) {
00557       mListener->OnError(rv, NS_LITERAL_STRING("Failure processing WSDL document"));
00558       return NS_OK;
00559     }
00560   }
00561   else if (eventType.EqualsLiteral("error")) {
00562     nsAutoString errorMsg(NS_LITERAL_STRING("Failure loading WSDL document"));
00563     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_LOADING_ERROR, errorMsg);
00564 
00565     return NS_OK;
00566   }
00567 
00568   if (GetCurrentContext() == nsnull) {
00569     if (mPort) {
00570       mListener->OnLoad(mPort);
00571     }
00572     else {
00573       nsAutoString errorMsg(NS_LITERAL_STRING("WSDL Binding not found"));
00574       NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_BINDING_NOT_FOUND, errorMsg);
00575     }
00576     mRequest = nsnull;
00577   }
00578 
00579   return NS_OK;
00580 }
00581 
00582 nsresult
00583 nsWSDLLoadRequest::ResumeProcessing()
00584 {
00585   nsresult rv = NS_OK;
00586 
00587   nsWSDLLoadingContext* context = GetCurrentContext();
00588   if (!context) {
00589     return NS_ERROR_UNEXPECTED;
00590   }
00591 
00592   nsCOMPtr<nsIDOMElement> element;
00593   context->GetRootElement(getter_AddRefs(element));
00594   PRUint32 childIndex = context->GetChildIndex();
00595 
00596   nsChildElementIterator iterator(element,
00597                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
00598   nsCOMPtr<nsIDOMElement> childElement;
00599   nsCOMPtr<nsIAtom> tagName;
00600 
00601   // If we don't yet have a port, find the service element, create one
00602   // and record the port's its binding name
00603   if (mBindingName.IsEmpty()) {
00604     // The service element tends to be at the end of WSDL files, so
00605     // this would be more efficient if we iterated from last to first
00606     // child...
00607     while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
00608                                               getter_AddRefs(tagName))) &&
00609            childElement) {
00610       if (tagName == nsWSDLAtoms::sService_atom) {
00611         rv = ProcessServiceElement(childElement);
00612         if (NS_FAILED(rv)) {
00613           return rv;
00614         }
00615       }
00616     }
00617   }
00618 
00619   iterator.Reset(childIndex);
00620   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
00621                                             getter_AddRefs(tagName))) &&
00622          childElement) {
00623     if (tagName == nsWSDLAtoms::sImport_atom) {
00624       rv = ProcessImportElement(childElement,
00625                                 iterator.GetCurrentIndex()+1);
00626       if (NS_FAILED(rv) ||
00627           (rv == NS_ERROR_WSDL_LOADPENDING)) {
00628         return rv;
00629       }
00630     }
00631     else if (tagName == nsWSDLAtoms::sTypes_atom) {
00632       rv = ProcessTypesElement(childElement);
00633       if (NS_FAILED(rv)) {
00634         return rv;
00635       }
00636     }
00637     else if (tagName == nsWSDLAtoms::sMessage_atom) {
00638       rv = ProcessMessageElement(childElement);
00639       if (NS_FAILED(rv)) {
00640         return rv;
00641       }
00642     }
00643     else if (tagName == nsWSDLAtoms::sPortType_atom) {
00644       rv = ProcessPortTypeElement(childElement);
00645       if (NS_FAILED(rv)) {
00646         return rv;
00647       }
00648     }
00649     else if (tagName == nsWSDLAtoms::sBinding_atom) {
00650       nsAutoString name, targetNamespace;
00651       childElement->GetAttribute(NS_LITERAL_STRING("name"), name);
00652       context->GetTargetNamespace(targetNamespace);
00653 
00654       // Only process binding for the requested port
00655       // XXX We should be checking the binding namespace as
00656       // well, but some authors are not qualifying their
00657       // binding names
00658       if (mBindingName.Equals(name)) {
00659         rv = ProcessBindingElement(childElement);
00660         if (NS_FAILED(rv)) {
00661           return rv;
00662         }
00663       }
00664     }
00665   }
00666 
00667   return rv;
00668 }
00669 
00670 nsresult
00671 nsWSDLLoadRequest::GetPort(nsIWSDLPort** aPort)
00672 {
00673   *aPort = mPort;
00674   NS_IF_ADDREF(*aPort);
00675 
00676   return NS_OK;
00677 }
00678 
00679 nsresult
00680 nsWSDLLoadRequest::PushContext(nsIDOMDocument* aDocument,
00681                                const nsAString& aURISpec)
00682 {
00683   nsWSDLLoadingContext* context = new nsWSDLLoadingContext(aDocument,
00684                                                            aURISpec);
00685   if (!context) {
00686     return NS_ERROR_OUT_OF_MEMORY;
00687   }
00688 
00689   mContextStack.AppendElement((void*)context);
00690 
00691   return NS_OK;
00692 }
00693 
00694 nsWSDLLoadingContext*
00695 nsWSDLLoadRequest::GetCurrentContext()
00696 {
00697   PRUint32 count = mContextStack.Count();
00698   if (count > 0) {
00699     return NS_STATIC_CAST(nsWSDLLoadingContext*,
00700                           mContextStack.ElementAt(count-1));
00701   }
00702 
00703   return nsnull;
00704 }
00705 
00706 void
00707 nsWSDLLoadRequest::PopContext()
00708 {
00709   PRUint32 count = mContextStack.Count();
00710   if (count > 0) {
00711     nsWSDLLoadingContext* context =
00712       NS_STATIC_CAST(nsWSDLLoadingContext*, mContextStack.ElementAt(count-1));
00713     delete context;
00714     mContextStack.RemoveElementAt(count-1);
00715   }
00716 }
00717 
00718 nsresult
00719 nsWSDLLoadRequest::GetSchemaElement(const nsAString& aName,
00720                                     const nsAString& aNamespace,
00721                                     nsISchemaElement** aSchemaComponent)
00722 {
00723   nsStringKey key(aNamespace);
00724   nsCOMPtr<nsISupports> sup = dont_AddRef(mTypes.Get(&key));
00725   nsCOMPtr<nsISchema> schema(do_QueryInterface(sup));
00726   if (!schema) {
00727     nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing WSDL, "));
00728     errorMsg.AppendLiteral("element is not schema");
00729     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT, errorMsg);
00730 
00731     return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
00732   }
00733 
00734   nsCOMPtr<nsISchemaElement> element;
00735   schema->GetElementByName(aName, getter_AddRefs(element));
00736   if (!element) {
00737     nsAutoString errorMsg;
00738     errorMsg.AppendLiteral("Failure processing WSDL, unknown schema component \"");
00739     errorMsg.Append(aNamespace);
00740     errorMsg.AppendLiteral(":");
00741     errorMsg.Append(aName);
00742     errorMsg.AppendLiteral("\"");
00743 
00744     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT, errorMsg);
00745 
00746     return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
00747   }
00748 
00749   *aSchemaComponent = element;
00750   NS_IF_ADDREF(*aSchemaComponent);
00751 
00752   return NS_OK;
00753 }
00754 
00755 nsresult
00756 nsWSDLLoadRequest::GetSchemaType(const nsAString& aName,
00757                                  const nsAString& aNamespace,
00758                                  nsISchemaType** aSchemaComponent)
00759 {
00760   if (aNamespace.EqualsLiteral(SCHEMA_2001_NAMESPACE) ||
00761       aNamespace.EqualsLiteral(SCHEMA_1999_NAMESPACE)) {
00762     nsCOMPtr<nsISchemaCollection> collection(do_QueryInterface(mSchemaLoader));
00763     return collection->GetType(aName, aNamespace, aSchemaComponent);
00764   }
00765 
00766   nsStringKey key(aNamespace);
00767   nsCOMPtr<nsISupports> sup = dont_AddRef(mTypes.Get(&key));
00768   nsCOMPtr<nsISchema> schema(do_QueryInterface(sup));
00769   if (!schema) {
00770     nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing WSDL, not schema"));
00771     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT, errorMsg);
00772 
00773     return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
00774   }
00775 
00776   nsCOMPtr<nsISchemaType> type;
00777   schema->GetTypeByName(aName, getter_AddRefs(type));
00778   if (!type) {
00779     nsAutoString errorMsg;
00780     errorMsg.AppendLiteral("Failure processing WSDL, unknown schema type \"");
00781     errorMsg.Append(aNamespace);
00782     errorMsg.AppendLiteral(":");
00783     errorMsg.Append(aName);
00784     errorMsg.AppendLiteral("\"");
00785 
00786     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT, errorMsg);
00787 
00788     return NS_ERROR_WSDL_UNKNOWN_SCHEMA_COMPONENT;
00789   }
00790 
00791   *aSchemaComponent = type;
00792   NS_IF_ADDREF(*aSchemaComponent);
00793 
00794   return NS_OK;
00795 }
00796 
00797 nsresult
00798 nsWSDLLoadRequest::GetMessage(const nsAString& aName,
00799                               const nsAString& aNamespace,
00800                               nsIWSDLMessage** aMessage)
00801 {
00802   nsAutoString keyStr(aName);
00803   keyStr.Append(aNamespace);
00804 
00805   nsStringKey key(keyStr);
00806 
00807   nsCOMPtr<nsISupports> sup = dont_AddRef(mMessages.Get(&key));
00808   nsCOMPtr<nsIWSDLMessage> message(do_QueryInterface(sup));
00809   if (!message) {
00810     nsAutoString errorMsg;
00811     errorMsg.AppendLiteral("Failure processing WSDL, unknown WSDL component \"");
00812     errorMsg.Append(aNamespace);
00813     errorMsg.AppendLiteral(":");
00814     errorMsg.Append(aName);
00815     errorMsg.AppendLiteral("\"");
00816 
00817     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT, errorMsg);
00818 
00819     return NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT;
00820   }
00821 
00822   *aMessage = message;
00823   NS_IF_ADDREF(*aMessage);
00824 
00825   return NS_OK;
00826 }
00827 
00828 nsresult
00829 nsWSDLLoadRequest::GetPortType(const nsAString& aName,
00830                                const nsAString& aNamespace,
00831                                nsIWSDLPort** aPort)
00832 {
00833   nsAutoString keyStr(aName);
00834   keyStr.Append(aNamespace);
00835 
00836   nsStringKey key(keyStr);
00837 
00838   nsCOMPtr<nsISupports> sup = dont_AddRef(mPortTypes.Get(&key));
00839   nsCOMPtr<nsIWSDLPort> port(do_QueryInterface(sup));
00840   if (!port) {
00841     nsAutoString errorMsg;
00842     errorMsg.AppendLiteral("Failure processing WSDL, unknown WSDL port type \"");
00843     errorMsg.Append(aNamespace);
00844     errorMsg.AppendLiteral(":");
00845     errorMsg.Append(aName);
00846     errorMsg.AppendLiteral("\"");
00847 
00848     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT, errorMsg);
00849 
00850     return NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT;
00851   }
00852 
00853   *aPort = port;
00854   NS_IF_ADDREF(*aPort);
00855 
00856   return NS_OK;
00857 }
00858 
00859 static nsresult
00860 ParseQualifiedName(nsIDOMElement* aContext, const nsAString& aQualifiedName,
00861                    nsAString& aPrefix, nsAString& aLocalName,
00862                    nsAString& aNamespaceURI)
00863 {
00864   nsReadingIterator<PRUnichar> pos, begin, end;
00865 
00866   aQualifiedName.BeginReading(begin);
00867   aQualifiedName.EndReading(end);
00868   pos = begin;
00869 
00870   if (FindCharInReadable(PRUnichar(':'), pos, end)) {
00871     CopyUnicodeTo(begin, pos, aPrefix);
00872     CopyUnicodeTo(++pos, end, aLocalName);
00873   }
00874   else {
00875     CopyUnicodeTo(begin, end, aLocalName);
00876   }
00877 
00878   nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aContext));
00879   if (!node) {
00880     return NS_ERROR_UNEXPECTED;
00881   }
00882 
00883   return node->LookupNamespaceURI(aPrefix, aNamespaceURI);
00884 }
00885 
00886 
00887 nsresult
00888 nsWSDLLoadRequest::ProcessImportElement(nsIDOMElement* aElement,
00889                                         PRUint32 aIndex)
00890 {
00891   nsresult rv = NS_OK;
00892 
00893   // XXX Is there a need to record the namespace? Can it be different
00894   // from the targetNamespace of the imported file?
00895 
00896   nsAutoString location, documentLocation;
00897   aElement->GetAttribute(NS_LITERAL_STRING("location"), location);
00898 
00899   nsWSDLLoadingContext* context = GetCurrentContext();
00900   if (!context) {
00901     return NS_ERROR_UNEXPECTED;
00902   }
00903   context->GetDocumentLocation(documentLocation);
00904 
00905   nsCOMPtr<nsIURI> uri, baseURI;
00906   rv = NS_NewURI(getter_AddRefs(baseURI), documentLocation);
00907   if (NS_FAILED(rv)) {
00908     nsAutoString errorMsg;
00909     errorMsg.AppendLiteral("Failure processing WSDL, ");
00910     errorMsg.AppendLiteral("cannot find base URI for document location \"");
00911     errorMsg.Append(documentLocation);
00912     errorMsg.AppendLiteral("\" for import \"");
00913     errorMsg.Append(location);
00914     errorMsg.AppendLiteral("\"");
00915 
00916     NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00917 
00918     return rv;
00919   }
00920 
00921   rv = NS_NewURI(getter_AddRefs(uri), location, nsnull, baseURI);
00922   if (NS_FAILED(rv)) {
00923     nsAutoString errorMsg;
00924     errorMsg.AppendLiteral("Failure processing WSDL, Cannot find URI for import \"");
00925     errorMsg.Append(location);
00926     errorMsg.AppendLiteral("\"");
00927 
00928     NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
00929 
00930     return rv;
00931   }
00932 
00933   // Fix ( bug 202478 ) a potential stack overflow by 
00934   // preventing the wsdl file from loading if it was  
00935   // already loaded via the import element.
00936   PRUint32 count = mImportList.Count();
00937   PRUint32 i;
00938   for (i = 0; i < count; i++) {
00939     PRBool equal;  
00940     mImportList[i]->Equals(uri, &equal);
00941     if (equal) {
00942       // Looks like this uri has already been loaded.
00943       // Loading it again will end up in an infinite loop.
00944       nsAutoString errorMsg;
00945       errorMsg.AppendLiteral("Failure processing WSDL, import \"");
00946       errorMsg.Append(location);
00947       errorMsg.AppendLiteral("\" could cause recursive import");
00948 
00949       NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_RECURSIVE_IMPORT, errorMsg);
00950 
00951       return NS_ERROR_WSDL_RECURSIVE_IMPORT;
00952     }
00953   }
00954 
00955   mImportList.AppendObject(uri);
00956   
00957   nsCAutoString spec;
00958   uri->GetSpec(spec);
00959 
00960   rv = LoadDefinition(NS_ConvertUTF8toUCS2(spec.get()));
00961   if (NS_FAILED(rv)) {
00962     return rv;
00963   }
00964 
00965   if (!mIsSync) {
00966     context->SetChildIndex(aIndex);
00967     return NS_ERROR_WSDL_LOADPENDING;
00968   }
00969 
00970   return NS_OK;
00971 }
00972 
00973 nsresult
00974 nsWSDLLoadRequest::ProcessTypesElement(nsIDOMElement* aElement)
00975 {
00976   static const char* kSchemaNamespaces[] =
00977     {
00978       SCHEMA_1999_NAMESPACE,
00979       SCHEMA_2001_NAMESPACE
00980     };
00981   static const PRUint32 kSchemaNamespacesLength =
00982     sizeof(kSchemaNamespaces) / sizeof(const char*);
00983 
00984   nsresult rv = NS_OK;
00985 
00986   nsChildElementIterator iterator(aElement,
00987                                   kSchemaNamespaces, kSchemaNamespacesLength);
00988   nsCOMPtr<nsIDOMElement> childElement;
00989   nsCOMPtr<nsIAtom> tagName;
00990 
00991   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
00992                                             getter_AddRefs(tagName))) &&
00993          childElement) {
00994     // XXX : We need to deal with xs:import elements too.
00995     if (tagName == nsWSDLAtoms::sSchema_atom) {
00996       nsCOMPtr<nsISchema> schema;
00997       rv = mSchemaLoader->ProcessSchemaElement(childElement, mErrorHandler,
00998                                                getter_AddRefs(schema));
00999       if (NS_FAILED(rv)) {
01000         return NS_ERROR_WSDL_SCHEMA_PROCESSING_ERROR;
01001       }
01002 
01003       nsAutoString targetNamespace;
01004       schema->GetTargetNamespace(targetNamespace);
01005 
01006       nsStringKey key(targetNamespace);
01007       mTypes.Put(&key, schema);
01008     }
01009   }
01010 
01011   return NS_OK;
01012 }
01013 
01014 nsresult
01015 nsWSDLLoadRequest::ProcessAbstractPartElement(nsIDOMElement* aElement,
01016                                               nsWSDLMessage* aMessage)
01017 {
01018   nsresult rv = NS_OK;
01019 
01020   nsAutoString name;
01021   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01022 
01023   nsCOMPtr<nsIWSDLPart> part;
01024   nsWSDLPart* partInst = new nsWSDLPart(name);
01025   if (!partInst) {
01026     return NS_ERROR_OUT_OF_MEMORY;
01027   }
01028   part = partInst;
01029 
01030   nsCOMPtr<nsISchemaComponent> schemaComponent;
01031   nsAutoString elementQName, typeQName;
01032   aElement->GetAttribute(NS_LITERAL_STRING("element"), elementQName);
01033   aElement->GetAttribute(NS_LITERAL_STRING("type"), typeQName);
01034 
01035   if (!elementQName.IsEmpty()) {
01036     nsAutoString elementPrefix, elementLocalName, elementNamespace;
01037 
01038     rv = ParseQualifiedName(aElement, elementQName, elementPrefix,
01039                             elementLocalName, elementNamespace);
01040     if (NS_FAILED(rv)) {
01041       return rv;
01042     }
01043 
01044     nsCOMPtr<nsISchemaElement> schemaElement;
01045     rv = GetSchemaElement(elementLocalName, elementNamespace,
01046                           getter_AddRefs(schemaElement));
01047     if (NS_FAILED(rv)) {
01048       nsAutoString errorMsg;
01049       errorMsg.AppendLiteral("Failure processing WSDL, cannot find schema element \"");
01050       errorMsg.Append(elementNamespace);
01051       errorMsg.AppendLiteral(":");
01052       errorMsg.Append(elementLocalName);
01053       errorMsg.AppendLiteral("\"");
01054 
01055       NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
01056 
01057       return rv;
01058     }
01059 
01060     schemaComponent = schemaElement;
01061   }
01062   else if (!typeQName.IsEmpty()) {
01063     nsAutoString typePrefix, typeLocalName, typeNamespace;
01064 
01065     rv = ParseQualifiedName(aElement, typeQName, typePrefix, typeLocalName,
01066                             typeNamespace);
01067     if (NS_FAILED(rv)) {
01068       return rv;
01069     }
01070 
01071     nsCOMPtr<nsISchemaType> schemaType;
01072     rv = GetSchemaType(typeLocalName, typeNamespace,
01073                        getter_AddRefs(schemaType));
01074     if (NS_FAILED(rv)) {
01075       nsAutoString errorMsg;
01076       errorMsg.AppendLiteral("Failure processing WSDL, cannot find schema type \"");
01077       errorMsg.Append(typeNamespace);
01078       errorMsg.AppendLiteral(":");
01079       errorMsg.Append(typeLocalName);
01080       errorMsg.AppendLiteral("\"");
01081 
01082       NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
01083 
01084       return rv;
01085     }
01086 
01087     schemaComponent = schemaType;
01088   }
01089 
01090   partInst->SetTypeInfo(typeQName, elementQName, schemaComponent);
01091   aMessage->AddPart(part);
01092 
01093   return NS_OK;
01094 }
01095 
01096 nsresult
01097 nsWSDLLoadRequest::ProcessMessageElement(nsIDOMElement* aElement)
01098 {
01099   nsresult rv = NS_OK;
01100 
01101   nsAutoString name;
01102   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01103 
01104   nsCOMPtr<nsIWSDLMessage> message;
01105   nsWSDLMessage* messageInst = new nsWSDLMessage(name);
01106   if (!messageInst) {
01107     return NS_ERROR_OUT_OF_MEMORY;
01108   }
01109   message = messageInst;
01110 
01111   nsChildElementIterator iterator(aElement,
01112                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
01113   nsCOMPtr<nsIDOMElement> childElement;
01114   nsCOMPtr<nsIAtom> tagName;
01115 
01116   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01117                                             getter_AddRefs(tagName))) &&
01118          childElement) {
01119     if (tagName == nsWSDLAtoms::sDocumentation_atom) {
01120       messageInst->SetDocumentationElement(childElement);
01121     }
01122     else if (tagName == nsWSDLAtoms::sPart_atom) {
01123       rv = ProcessAbstractPartElement(childElement, messageInst);
01124       if (NS_FAILED(rv)) {
01125         return rv;
01126       }
01127     }
01128   }
01129 
01130   nsAutoString targetNamespace;
01131   nsWSDLLoadingContext* context = GetCurrentContext();
01132   if (!context) {
01133     return NS_ERROR_UNEXPECTED;
01134   }
01135   context->GetTargetNamespace(targetNamespace);
01136 
01137   name.Append(targetNamespace);
01138   nsStringKey key(name);
01139   mMessages.Put(&key, message);
01140 
01141   return NS_OK;
01142 }
01143 
01144 nsresult
01145 nsWSDLLoadRequest::ProcessOperationComponent(nsIDOMElement* aElement,
01146                                              nsIWSDLMessage** aMessage)
01147 {
01148   nsresult rv;
01149 
01150   nsAutoString messageQName, messagePrefix, messageLocalName, messageNamespace;
01151   aElement->GetAttribute(NS_LITERAL_STRING("message"), messageQName);
01152 
01153   rv = ParseQualifiedName(aElement, messageQName, messagePrefix,
01154                           messageLocalName, messageNamespace);
01155   if (NS_FAILED(rv)) {
01156     return rv;
01157   }
01158 
01159   rv = GetMessage(messageLocalName, messageNamespace, aMessage);
01160   if (NS_FAILED(rv)) {
01161     // XXX It seem that some WSDL authors eliminate prefixes
01162     // from qualified names in attribute values, assuming that
01163     // the names will resolve to the targetNamespace, while
01164     // they should technically resolve to the default namespace.
01165     if (messagePrefix.IsEmpty()) {
01166       nsAutoString targetNamespace;
01167       nsWSDLLoadingContext* context = GetCurrentContext();
01168       if (!context) {
01169         return NS_ERROR_UNEXPECTED;
01170       }
01171       context->GetTargetNamespace(targetNamespace);
01172       rv = GetMessage(messageLocalName, targetNamespace, aMessage);
01173       if (NS_FAILED(rv)) {
01174         nsAutoString errorMsg;
01175         errorMsg.AppendLiteral("Failure processing WSDL, cannot find message \"");
01176         errorMsg.Append(targetNamespace);
01177         errorMsg.AppendLiteral(":");
01178         errorMsg.Append(messageLocalName);
01179         errorMsg.AppendLiteral("\"");
01180 
01181         NS_WSDLLOADER_FIRE_ERROR(rv, errorMsg);
01182 
01183         return rv;
01184       }
01185     }
01186   }
01187 
01188   return NS_OK;
01189 }
01190 
01191 nsresult
01192 nsWSDLLoadRequest::ProcessAbstractOperation(nsIDOMElement* aElement,
01193                                             nsWSDLPort* aPort)
01194 {
01195   nsresult rv = NS_OK;
01196 
01197   nsAutoString name;
01198   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01199 
01200   nsCOMPtr<nsIWSDLOperation> operation;
01201   nsWSDLOperation* operationInst = new nsWSDLOperation(name);
01202   if (!operationInst) {
01203     return NS_ERROR_OUT_OF_MEMORY;
01204   }
01205   operation = operationInst;
01206 
01207   nsAutoString parameterOrder;
01208   aElement->GetAttribute(NS_LITERAL_STRING("parameterOrder"), parameterOrder);
01209   if (!parameterOrder.IsEmpty()) {
01210     nsReadingIterator<PRUnichar> start, end, delimiter;
01211     parameterOrder.BeginReading(start);
01212     parameterOrder.EndReading(end);
01213 
01214     PRBool found;
01215     do {
01216       delimiter = start;
01217 
01218       // Find the next delimiter
01219       found = FindCharInReadable(PRUnichar(' '), delimiter, end);
01220 
01221       // Use the string from the current start position to the
01222       // delimiter.
01223       nsAutoString paramName;
01224       CopyUnicodeTo(start, delimiter, paramName);
01225 
01226       if (!paramName.IsEmpty()) {
01227         operationInst->AddParameter(paramName);
01228       }
01229 
01230       // If we did find a delimiter, advance past it
01231       if (found) {
01232         start = delimiter;
01233         ++start;
01234       }
01235     } while (found);
01236   }
01237 
01238   nsChildElementIterator iterator(aElement,
01239                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
01240   nsCOMPtr<nsIDOMElement> childElement;
01241   nsCOMPtr<nsIAtom> tagName;
01242 
01243   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01244                                             getter_AddRefs(tagName))) &&
01245          childElement) {
01246     nsCOMPtr<nsIWSDLMessage> message;
01247     if (tagName == nsWSDLAtoms::sDocumentation_atom) {
01248       operationInst->SetDocumentationElement(childElement);
01249     }
01250     else if (tagName == nsWSDLAtoms::sInput_atom) {
01251       rv = ProcessOperationComponent(childElement, getter_AddRefs(message));
01252       if (NS_FAILED(rv)) {
01253         return rv;
01254       }
01255       operationInst->SetInput(message);
01256     }
01257     else if (tagName == nsWSDLAtoms::sOutput_atom) {
01258       rv = ProcessOperationComponent(childElement, getter_AddRefs(message));
01259       if (NS_FAILED(rv)) {
01260         return rv;
01261       }
01262       operationInst->SetOutput(message);
01263     }
01264     else if (tagName == nsWSDLAtoms::sFault_atom) {
01265       rv = ProcessOperationComponent(childElement, getter_AddRefs(message));
01266       if (NS_FAILED(rv)) {
01267         return rv;
01268       }
01269       operationInst->AddFault(message);
01270     }
01271   }
01272 
01273   aPort->AddOperation(operation);
01274 
01275   return NS_OK;
01276 }
01277 
01278 nsresult
01279 nsWSDLLoadRequest::ProcessPortTypeElement(nsIDOMElement* aElement)
01280 {
01281   nsresult rv = NS_OK;
01282 
01283   nsAutoString name;
01284   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01285 
01286   nsCOMPtr<nsIWSDLPort> port;
01287   nsWSDLPort* portInst = new nsWSDLPort(name);
01288   if (!portInst) {
01289     return NS_ERROR_OUT_OF_MEMORY;
01290   }
01291   port = portInst;
01292 
01293   nsChildElementIterator iterator(aElement,
01294                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
01295   nsCOMPtr<nsIDOMElement> childElement;
01296   nsCOMPtr<nsIAtom> tagName;
01297 
01298   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01299                                             getter_AddRefs(tagName))) &&
01300          childElement) {
01301     if (tagName == nsWSDLAtoms::sDocumentation_atom) {
01302       portInst->SetDocumentationElement(childElement);
01303     }
01304     else if (tagName == nsWSDLAtoms::sOperation_atom) {
01305       rv = ProcessAbstractOperation(childElement, portInst);
01306       if (NS_FAILED(rv)) {
01307         return rv;
01308       }
01309     }
01310   }
01311 
01312   nsAutoString targetNamespace;
01313   nsWSDLLoadingContext* context = GetCurrentContext();
01314   if (!context) {
01315     return NS_ERROR_UNEXPECTED;
01316   }
01317   context->GetTargetNamespace(targetNamespace);
01318 
01319   name.Append(targetNamespace);
01320   nsStringKey key(name);
01321   mPortTypes.Put(&key, port);
01322 
01323   return NS_OK;
01324 }
01325 
01326 nsresult
01327 nsWSDLLoadRequest::ProcessMessageBinding(nsIDOMElement* aElement,
01328                                          nsIWSDLMessage* aMessage)
01329 {
01330 
01331   nsChildElementIterator iterator(aElement,
01332                                   NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE));
01333   nsCOMPtr<nsIDOMElement> childElement;
01334   nsCOMPtr<nsIAtom> tagName;
01335 
01336   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01337                                             getter_AddRefs(tagName))) &&
01338          childElement) {
01339     if (tagName == nsWSDLAtoms::sBody_atom) {
01340       nsAutoString partsStr, useStr, encodingStyle, namespaceStr;
01341       childElement->GetAttribute(NS_LITERAL_STRING("parts"), partsStr);
01342       childElement->GetAttribute(NS_LITERAL_STRING("use"), useStr);
01343       childElement->GetAttribute(NS_LITERAL_STRING("encodingStyle"),
01344                                  encodingStyle);
01345       childElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
01346 
01347       PRUint16 use = nsISOAPPartBinding::USE_LITERAL;
01348       if (useStr.EqualsLiteral("encoded")) {
01349         use = nsISOAPPartBinding::USE_ENCODED;
01350       }
01351 
01352       nsCOMPtr<nsISOAPMessageBinding> messageBinding;
01353       nsSOAPMessageBinding* messageBindingInst =
01354         new nsSOAPMessageBinding(namespaceStr);
01355       if (!messageBindingInst) {
01356         return NS_ERROR_OUT_OF_MEMORY;
01357       }
01358       messageBinding = messageBindingInst;
01359       nsWSDLMessage* messageInst = NS_REINTERPRET_CAST(nsWSDLMessage*,
01360                                                        aMessage);
01361       messageInst->SetBinding(messageBinding);
01362 
01363       nsCOMPtr<nsISOAPPartBinding> binding;
01364       nsSOAPPartBinding* bindingInst =
01365         new nsSOAPPartBinding(nsISOAPPartBinding::LOCATION_BODY, use,
01366                               encodingStyle, namespaceStr);
01367       if (!bindingInst) {
01368         return NS_ERROR_OUT_OF_MEMORY;
01369       }
01370       binding = bindingInst;
01371 
01372       nsCOMPtr<nsIWSDLPart> part;
01373       nsWSDLPart* partInst;
01374       // If there is no explicit parts attribute, this binding applies
01375       // to all the parts.
01376       if (partsStr.IsEmpty()) {
01377         PRUint32 index, count;
01378 
01379         aMessage->GetPartCount(&count);
01380         for (index = 0; index < count; index++) {
01381           aMessage->GetPart(index, getter_AddRefs(part));
01382           partInst = NS_REINTERPRET_CAST(nsWSDLPart*, part.get());
01383           if (partInst) {
01384             partInst->SetBinding(binding);
01385           }
01386         }
01387       }
01388       else {
01389         nsReadingIterator<PRUnichar> start, end, delimiter;
01390         partsStr.BeginReading(start);
01391         partsStr.EndReading(end);
01392 
01393         PRBool found;
01394         do {
01395           delimiter = start;
01396 
01397           // Find the next delimiter
01398           found = FindCharInReadable(PRUnichar(' '), delimiter, end);
01399 
01400           // Use the string from the current start position to the
01401           // delimiter.
01402           nsAutoString partName;
01403           CopyUnicodeTo(start, delimiter, partName);
01404 
01405           if (!partName.IsEmpty()) {
01406             aMessage->GetPartByName(partName, getter_AddRefs(part));
01407             partInst = NS_REINTERPRET_CAST(nsWSDLPart*, part.get());
01408             if (partInst) {
01409               partInst->SetBinding(binding);
01410             }
01411           }
01412 
01413           // If we did find a delimiter, advance past it
01414           if (found) {
01415             start = delimiter;
01416             ++start;
01417           }
01418         } while (found);
01419       }
01420     }
01421   }
01422 
01423   return NS_OK;
01424 }
01425 
01426 nsresult
01427 nsWSDLLoadRequest::ProcessOperationBinding(nsIDOMElement* aElement,
01428                                            nsIWSDLPort* aPort)
01429 {
01430   nsresult rv = NS_OK;
01431 
01432   nsAutoString name;
01433   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01434 
01435   nsCOMPtr<nsIWSDLOperation> operation;
01436   aPort->GetOperationByName(name, getter_AddRefs(operation));
01437   if (!operation) {
01438     nsAutoString errorMsg;
01439     errorMsg.AppendLiteral("Failure processing WSDL, cannot find operation \"");
01440     errorMsg.Append(name);
01441     errorMsg.AppendLiteral("\"");
01442 
01443     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT, errorMsg);
01444 
01445     return NS_ERROR_WSDL_UNKNOWN_WSDL_COMPONENT;
01446   }
01447   nsWSDLOperation* operationInst = NS_REINTERPRET_CAST(nsWSDLOperation*,
01448                                                        operation.get());
01449 
01450   nsCOMPtr<nsISOAPOperationBinding> binding;
01451   nsSOAPOperationBinding* bindingInst = new nsSOAPOperationBinding();
01452   if (!bindingInst) {
01453     return NS_ERROR_OUT_OF_MEMORY;
01454   }
01455   binding = bindingInst;
01456 
01457   nsChildElementIterator iterator(aElement);
01458   nsCOMPtr<nsIDOMElement> childElement;
01459   nsCOMPtr<nsIAtom> tagName;
01460 
01461   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01462                                             getter_AddRefs(tagName))) &&
01463          childElement) {
01464     if ((tagName == nsWSDLAtoms::sDocumentation_atom) &&
01465         IsElementOfNamespace(childElement,
01466                              NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
01467       bindingInst->SetDocumentationElement(childElement);
01468     }
01469     else if ((tagName == nsWSDLAtoms::sOperation_atom) &&
01470              IsElementOfNamespace(childElement,
01471                                   NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE))) {
01472       nsAutoString action, style;
01473       childElement->GetAttribute(NS_LITERAL_STRING("soapAction"), action);
01474       childElement->GetAttribute(NS_LITERAL_STRING("style"), style);
01475 
01476       bindingInst->SetSoapAction(action);
01477       if (style.EqualsLiteral("rpc")) {
01478         bindingInst->SetStyle(nsISOAPPortBinding::STYLE_RPC);
01479       }
01480       else if (style.EqualsLiteral("document")) {
01481         bindingInst->SetStyle(nsISOAPPortBinding::STYLE_DOCUMENT);
01482       }
01483       // If one isn't explicitly specified, we inherit from the port
01484       else {
01485         nsCOMPtr<nsIWSDLBinding> portBinding;
01486         aPort->GetBinding(getter_AddRefs(portBinding));
01487         nsCOMPtr<nsISOAPPortBinding> soapPortBinding =
01488           do_QueryInterface(portBinding);
01489         if (soapPortBinding) {
01490           PRUint16 styleVal;
01491           soapPortBinding->GetStyle(&styleVal);
01492           bindingInst->SetStyle(styleVal);
01493         }
01494       }
01495     }
01496     else if ((tagName == nsWSDLAtoms::sInput_atom) &&
01497              IsElementOfNamespace(childElement,
01498                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
01499       nsCOMPtr<nsIWSDLMessage> input;
01500 
01501       operation->GetInput(getter_AddRefs(input));
01502       rv = ProcessMessageBinding(childElement, input);
01503       if (NS_FAILED(rv)) {
01504         return rv;
01505       }
01506     }
01507     else if ((tagName == nsWSDLAtoms::sOutput_atom) &&
01508              IsElementOfNamespace(childElement,
01509                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
01510       nsCOMPtr<nsIWSDLMessage> output;
01511 
01512       operation->GetOutput(getter_AddRefs(output));
01513       rv = ProcessMessageBinding(childElement, output);
01514       if (NS_FAILED(rv)) {
01515         return rv;
01516       }
01517     }
01518     else if ((tagName == nsWSDLAtoms::sFault_atom) &&
01519              IsElementOfNamespace(childElement,
01520                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
01521 
01522       //XXX To be implemented
01523       nsAutoString errorMsg(NS_LITERAL_STRING("Fault management not yet "));
01524       errorMsg.AppendLiteral("implemented in WSDL support");
01525       NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_NOT_IMPLEMENTED, errorMsg);
01526     }
01527   }
01528 
01529   operationInst->SetBinding(binding);
01530 
01531   return NS_OK;
01532 
01533 }
01534 
01535 nsresult
01536 nsWSDLLoadRequest::ProcessBindingElement(nsIDOMElement* aElement)
01537 {
01538   nsresult rv = NS_OK;
01539 
01540   nsAutoString name;
01541   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01542 
01543   PRBool foundSOAPBinding = PR_FALSE;
01544   nsCOMPtr<nsIWSDLBinding> binding;
01545   nsSOAPPortBinding* bindingInst = new nsSOAPPortBinding(name);
01546   if (!bindingInst) {
01547     return NS_ERROR_OUT_OF_MEMORY;
01548   }
01549   binding = bindingInst;
01550   bindingInst->SetAddress(mAddress);
01551 
01552   nsCOMPtr<nsIWSDLPort> port;
01553   nsAutoString typeQName, typePrefix, typeLocalName, typeNamespace;
01554   aElement->GetAttribute(NS_LITERAL_STRING("type"), typeQName);
01555   rv = ParseQualifiedName(aElement, typeQName, typePrefix, typeLocalName,
01556                           typeNamespace);
01557   if (NS_FAILED(rv)) {
01558     return rv;
01559   }
01560 
01561   rv = GetPortType(typeLocalName, typeNamespace, getter_AddRefs(port));
01562   if (NS_FAILED(rv)) {
01563     // XXX It seem that some WSDL authors eliminate prefixes
01564     // from qualified names in attribute values, assuming that
01565     // the names will resolve to the targetNamespace, while
01566     // they should technically resolve to the default namespace.
01567     if (typePrefix.IsEmpty()) {
01568       nsWSDLLoadingContext* context = GetCurrentContext();
01569       if (!context) {
01570         return NS_ERROR_UNEXPECTED;
01571       }
01572 
01573       nsAutoString targetNamespace;
01574       context->GetTargetNamespace(targetNamespace);
01575       rv = GetPortType(typeLocalName, targetNamespace, getter_AddRefs(port));
01576       if (NS_FAILED(rv)) {
01577         return rv;    // Can't find a port type of the specified name
01578       }
01579     }
01580   }
01581 
01582   nsChildElementIterator iterator(aElement);
01583   nsCOMPtr<nsIDOMElement> childElement;
01584   nsCOMPtr<nsIAtom> tagName;
01585 
01586   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01587                                             getter_AddRefs(tagName))) &&
01588          childElement) {
01589     if ((tagName == nsWSDLAtoms::sDocumentation_atom) &&
01590         IsElementOfNamespace(childElement,
01591                              NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
01592       bindingInst->SetDocumentationElement(childElement);
01593     }
01594     else if ((tagName == nsWSDLAtoms::sBinding_atom) &&
01595              IsElementOfNamespace(childElement,
01596                                   NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE))) {
01597       // XXX There should be different namespaces for newer versions
01598       // of SOAP.
01599       bindingInst->SetSoapVersion(nsISOAPPortBinding::SOAP_VERSION_1_1);
01600 
01601       nsAutoString style, transport;
01602       childElement->GetAttribute(NS_LITERAL_STRING("style"), style);
01603       childElement->GetAttribute(NS_LITERAL_STRING("transport"), transport);
01604 
01605       if (style.EqualsLiteral("rpc")) {
01606         bindingInst->SetStyle(nsISOAPPortBinding::STYLE_RPC);
01607       }
01608       else if (style.EqualsLiteral("document")) {
01609         bindingInst->SetStyle(nsISOAPPortBinding::STYLE_DOCUMENT);
01610       }
01611       bindingInst->SetTransport(transport);
01612       foundSOAPBinding = PR_TRUE;
01613     }
01614     else if ((tagName == nsWSDLAtoms::sOperation_atom) &&
01615              IsElementOfNamespace(childElement,
01616                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE))) {
01617       rv = ProcessOperationBinding(childElement, port);
01618       if (NS_FAILED(rv)) {
01619         return rv;
01620       }
01621     }
01622   }
01623 
01624   if (!foundSOAPBinding) {
01625     // If we don't have a SOAP binding, we can't continue
01626     nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing WSDL, "));
01627     errorMsg.AppendLiteral("no SOAP binding found");
01628     NS_WSDLLOADER_FIRE_ERROR(NS_ERROR_WSDL_BINDING_NOT_FOUND, errorMsg);
01629 
01630     return NS_ERROR_WSDL_BINDING_NOT_FOUND;
01631   }
01632   nsWSDLPort* portInst = NS_REINTERPRET_CAST(nsWSDLPort*, port.get());
01633   portInst->SetBinding(binding);
01634 
01635   mPort = port;
01636 
01637   return NS_OK;
01638 }
01639 
01640 nsresult
01641 nsWSDLLoadRequest::ProcessPortBinding(nsIDOMElement* aElement)
01642 {
01643   nsChildElementIterator iterator(aElement);
01644   nsCOMPtr<nsIDOMElement> childElement;
01645   nsCOMPtr<nsIAtom> tagName;
01646 
01647   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01648                                             getter_AddRefs(tagName))) &&
01649          childElement) {
01650     if ((tagName == nsWSDLAtoms::sAddress_atom) &&
01651         IsElementOfNamespace(childElement,
01652                              NS_LITERAL_STRING(NS_WSDL_SOAP_NAMESPACE))) {
01653       childElement->GetAttribute(NS_LITERAL_STRING("location"), mAddress);
01654     }
01655   }
01656 
01657   return NS_OK;
01658 }
01659 
01660 nsresult
01661 nsWSDLLoadRequest::ProcessServiceElement(nsIDOMElement* aElement)
01662 {
01663   nsresult rv;
01664 
01665   nsChildElementIterator iterator(aElement,
01666                                   NS_LITERAL_STRING(NS_WSDL_NAMESPACE));
01667   nsCOMPtr<nsIDOMElement> childElement;
01668   nsCOMPtr<nsIAtom> tagName;
01669 
01670   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01671                                             getter_AddRefs(tagName))) &&
01672          childElement) {
01673     if (tagName == nsWSDLAtoms::sPort_atom) {
01674       nsAutoString name;
01675       childElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01676       if (name.Equals(mPortName)) {
01677         nsAutoString bindingQName, bindingPrefix;
01678 
01679         childElement->GetAttribute(NS_LITERAL_STRING("binding"), bindingQName);
01680         rv = ParseQualifiedName(childElement, bindingQName, bindingPrefix,
01681                                 mBindingName, mBindingNamespace);
01682         if (NS_FAILED(rv)) {
01683           return rv; // binding of an unknown namespace
01684         }
01685 
01686         rv = ProcessPortBinding(childElement);
01687         if (NS_FAILED(rv)) {
01688           return rv;
01689         }
01690 
01691         break;
01692       }
01693     }
01694   }
01695 
01696   return NS_OK;
01697 }