Back to index

lightning-sunbird  0.9+nobinonly
wspproxy.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Vidur Apparao (vidur@netscape.com)  (Original author)
00024  *   John Bandhauer (jband@netscape.com)
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "wspprivate.h"
00041 #include "nsAutoPtr.h"
00042 #include "nsIWSDL.h"
00043 #include "nsIWSDLSOAPBinding.h"
00044 #include "nsISchema.h"
00045 #include "nsISOAPParameter.h"
00046 #include "nsISOAPHeaderBlock.h"
00047 #include "nsISOAPEncoding.h"
00048 #include "nsIComponentManager.h"
00049 #include "nsIVariant.h"
00050 #include "nsVoidArray.h"
00051 
00052 #define NS_SOAP_1_1_ENCODING_NAMESPACE \
00053    "http://schemas.xmlsoap.org/soap/encoding/"
00054 #define NS_SOAP_1_2_ENCODING_NAMESPACE \
00055    "http://www.w3.org/2001/09/soap-encoding"
00056 
00057 WSPProxy::WSPProxy()
00058   : mIID(nsnull)
00059 {
00060 }
00061 
00062 WSPProxy::~WSPProxy()
00063 {
00064 }
00065 
00066 NS_IMETHODIMP
00067 WSPProxy::Init(nsIWSDLPort* aPort, nsIInterfaceInfo* aPrimaryInterface,
00068                nsIInterfaceInfoManager* aInterfaceInfoManager,
00069                const nsAString& aQualifier, PRBool aIsAsync)
00070 {
00071   NS_ENSURE_ARG(aPort);
00072   NS_ENSURE_ARG(aPrimaryInterface);
00073 
00074   mPort = aPort;
00075   mPrimaryInterface = aPrimaryInterface;
00076   mInterfaceInfoManager = aInterfaceInfoManager;
00077   mPrimaryInterface->GetIIDShared(&mIID);
00078   mQualifier.Assign(aQualifier);
00079   mIsAsync = aIsAsync;
00080 
00081   nsresult rv;
00082 
00083   mInterfaces = do_CreateInstance(NS_SCRIPTABLE_INTERFACES_CONTRACTID, &rv);
00084   if (!mInterfaces) {
00085     return rv;
00086   }
00087 
00088   rv = mInterfaces->SetManager(mInterfaceInfoManager);
00089   if (NS_FAILED(rv)) {
00090     return rv;
00091   }
00092 
00093   if (mIsAsync) {
00094     // Get the completion method info
00095     const nsXPTMethodInfo* listenerGetter;
00096     rv = mPrimaryInterface->GetMethodInfo(3, &listenerGetter);
00097     if (NS_FAILED(rv)) {
00098       return NS_ERROR_FAILURE;
00099     }
00100     const nsXPTParamInfo& listenerParam = listenerGetter->GetParam(0);
00101     const nsXPTType& type = listenerParam.GetType();
00102     if (!type.IsInterfacePointer()) {
00103       return NS_ERROR_FAILURE;
00104     }
00105     rv = mPrimaryInterface->GetInfoForParam(3, &listenerParam,
00106                                             getter_AddRefs(mListenerInterfaceInfo));
00107     if (NS_FAILED(rv)) {
00108       return rv;
00109     }
00110   }
00111 
00112   return NS_OK;
00113 }
00114 
00115 NS_METHOD
00116 WSPProxy::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
00117 {
00118   NS_ENSURE_ARG_POINTER(aInstancePtr);
00119   NS_ENSURE_NO_AGGREGATION(outer);
00120 
00121   WSPProxy* proxy = new WSPProxy();
00122   if (!proxy) {
00123     return NS_ERROR_OUT_OF_MEMORY;
00124   }
00125 
00126   NS_ADDREF(proxy);
00127   nsresult rv = proxy->QueryInterface(aIID, aInstancePtr);
00128   NS_RELEASE(proxy);
00129   return rv;
00130 }
00131 
00132 NS_IMPL_ADDREF(WSPProxy)
00133 NS_IMPL_RELEASE(WSPProxy)
00134 
00135 NS_IMETHODIMP
00136 WSPProxy::QueryInterface(REFNSIID aIID, void** aInstancePtr)
00137 {
00138   if((mIID && aIID.Equals(*mIID)) || aIID.Equals(NS_GET_IID(nsISupports))) {
00139     *aInstancePtr = NS_STATIC_CAST(nsXPTCStubBase*, this);
00140     NS_ADDREF_THIS();
00141     return NS_OK;
00142   }
00143   else if (aIID.Equals(NS_GET_IID(nsIWebServiceProxy))) {
00144     *aInstancePtr = NS_STATIC_CAST(nsIWebServiceProxy*, this);
00145     NS_ADDREF_THIS();
00146     return NS_OK;
00147   }
00148   else if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
00149     *aInstancePtr = NS_STATIC_CAST(nsIClassInfo*, this);
00150     NS_ADDREF_THIS();
00151     return NS_OK;
00152   }
00153 
00154   return NS_ERROR_NO_INTERFACE;
00155 }
00156 
00158 //
00159 // Implementation of nsXPTCStubBase methods
00160 //
00162 
00178 NS_IMETHODIMP
00179 WSPProxy::CallMethod(PRUint16 methodIndex,
00180                      const nsXPTMethodInfo* info,
00181                      nsXPTCMiniVariant* params)
00182 {
00183   nsresult rv;
00184   nsCOMPtr<nsIWebServiceCallContext> cc;
00185   nsCOMPtr<nsIWSDLBinding> binding;
00186 
00187   if (methodIndex < 3) {
00188     NS_ERROR("WSPProxy: bad method index");
00189     return NS_ERROR_FAILURE;
00190   }
00191 
00192   // The first method in the interface for async callers is the
00193   // one to set the async listener
00194   if (mIsAsync && (methodIndex == 3)) {
00195     nsISupports* listener = NS_STATIC_CAST(nsISupports*, params[0].val.p);
00196     mAsyncListener = listener;
00197     return NS_OK;
00198   }
00199 
00200   PRUint32 methodOffset;
00201   if (mIsAsync) {
00202     methodOffset = 4;
00203   }
00204   else {
00205     methodOffset = 3;
00206   }
00207 
00208   nsCOMPtr<nsIWSDLOperation> operation;
00209   rv = mPort->GetOperation(methodIndex - methodOffset,
00210                            getter_AddRefs(operation));
00211   if (NS_FAILED(rv)) {
00212     return rv;
00213   }
00214 
00215   nsCOMPtr<nsIWSDLMessage> input;
00216   rv = operation->GetInput(getter_AddRefs(input));
00217   if (NS_FAILED(rv)) {
00218     return rv;
00219   }
00220 
00221   // Create the call instance
00222   nsCOMPtr<nsISOAPCall> call = do_CreateInstance(NS_SOAPCALL_CONTRACTID, &rv);
00223   if (NS_FAILED(rv)) {
00224     return rv;
00225   }
00226 
00227   nsCOMPtr<nsISOAPEncoding> encoding =
00228     do_CreateInstance(NS_SOAPENCODING_CONTRACTID, &rv);
00229   if (NS_FAILED(rv)) {
00230     return rv;
00231   }
00232   call->SetEncoding(encoding);
00233 
00234   // Get the method name and target object uri
00235   nsAutoString methodName, targetObjectURI;
00236   rv = operation->GetBinding(getter_AddRefs(binding));
00237   if (NS_FAILED(rv)) {
00238     return rv;
00239   }
00240 
00241   nsCOMPtr<nsISOAPOperationBinding> operationBinding =
00242     do_QueryInterface(binding, &rv);
00243   if (NS_FAILED(rv)) {
00244     return rv;
00245   }
00246 
00247   nsAutoString soapAction;
00248   operationBinding->GetSoapAction(soapAction);
00249   call->SetActionURI(soapAction);
00250 
00251   PRUint16 style;
00252   operationBinding->GetStyle(&style);
00253   // If the style is RPC, find the method name and target object URI.
00254   // If it is document-style, these are both left blank.
00255   if (style == nsISOAPPortBinding::STYLE_RPC) {
00256     operation->GetName(methodName);
00257     rv = input->GetBinding(getter_AddRefs(binding));
00258     if (NS_FAILED(rv)) {
00259       return rv;
00260     }
00261     nsCOMPtr<nsISOAPMessageBinding> messageBinding =
00262       do_QueryInterface(binding, &rv);
00263     if (NS_FAILED(rv)) {
00264       return rv;
00265     }
00266     messageBinding->GetNamespace(targetObjectURI);
00267   }
00268 
00269   // Set the transport URI
00270   rv = mPort->GetBinding(getter_AddRefs(binding));
00271   if (NS_FAILED(rv)) {
00272     return rv;
00273   }
00274   nsCOMPtr<nsISOAPPortBinding> portBinding = do_QueryInterface(binding, &rv);
00275   if (NS_FAILED(rv)) {
00276     return rv;
00277   }
00278 
00279   nsAutoString address;
00280   portBinding->GetAddress(address);
00281   rv = call->SetTransportURI(address);
00282   if (NS_FAILED(rv)) {
00283     return rv;
00284   }
00285 
00286   PRUint16 version;
00287   portBinding->GetSoapVersion(&version);
00288   if (version == nsISOAPMessage::VERSION_UNKNOWN) {
00289     version = nsISOAPMessage::VERSION_1_1;
00290   }
00291 
00292   // Set up the parameters to the call
00293   PRUint32 i, partCount;
00294   input->GetPartCount(&partCount);
00295 
00296   PRUint32 maxParamIndex = info->GetParamCount()-1;
00297 
00298   // Iterate through the parts to figure out how many are
00299   // body vs. header blocks
00300   nsCOMPtr<nsIWSDLPart> part;
00301   PRUint32 headerCount = 0, bodyCount = 0;
00302 
00303   for (i = 0; i < partCount; i++) {
00304     rv = input->GetPart(i, getter_AddRefs(part));
00305     if (NS_FAILED(rv)) {
00306       return rv;
00307     }
00308 
00309     rv = part->GetBinding(getter_AddRefs(binding));
00310     if (NS_FAILED(rv)) {
00311       return rv;
00312     }
00313 
00314     nsCOMPtr<nsISOAPPartBinding> partBinding = do_QueryInterface(binding, &rv);
00315     if (NS_FAILED(rv)) {
00316       return rv;
00317     }
00318 
00319     PRUint16 location;
00320     partBinding->GetLocation(&location);
00321     if (location == nsISOAPPartBinding::LOCATION_HEADER) {
00322       headerCount++;
00323     }
00324     else if (location == nsISOAPPartBinding::LOCATION_BODY) {
00325       bodyCount++;
00326     }
00327   }
00328 
00329   // Allocate parameter and header blocks
00330   nsISOAPParameter** bodyBlocks = nsnull;
00331   if (bodyCount) {
00332     bodyBlocks = NS_STATIC_CAST(nsISOAPParameter**,
00333                       nsMemory::Alloc(bodyCount * sizeof(nsISOAPParameter*)));
00334     if (!bodyBlocks) {
00335       return NS_ERROR_OUT_OF_MEMORY;
00336     }
00337     for (i = 0; i < bodyCount; i++) {
00338       rv = CallCreateInstance(NS_SOAPPARAMETER_CONTRACTID, &bodyBlocks[i]);
00339       if (NS_FAILED(rv)) {
00340         NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(i, bodyBlocks);
00341 
00342         return rv;
00343       }
00344     }
00345   }
00346 
00347   nsISOAPHeaderBlock** headerBlocks = nsnull;
00348   if (headerCount) {
00349     headerBlocks = NS_STATIC_CAST(nsISOAPHeaderBlock**,
00350                    nsMemory::Alloc(headerCount * sizeof(nsISOAPHeaderBlock*)));
00351     if (!headerBlocks) {
00352       if (bodyBlocks) {
00353         NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(bodyCount, bodyBlocks);
00354       }
00355       return NS_ERROR_OUT_OF_MEMORY;
00356     }
00357     for (i = 0; i < headerCount; i++) {
00358       rv = CallCreateInstance(NS_SOAPHEADERBLOCK_CONTRACTID, &headerBlocks[i]);
00359       if (NS_FAILED(rv)) {
00360         if (bodyBlocks) {
00361           NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(bodyCount, bodyBlocks);
00362         }
00363         NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(i, headerBlocks);
00364 
00365         return rv;
00366       }
00367     }
00368   }
00369 
00370   // Now iterate through the parameters and set up the parameter blocks
00371   PRUint32 bodyEntry = 0, headerEntry = 0, paramIndex = 0;
00372   for (i = 0; i < partCount; paramIndex++, i++) {
00373     input->GetPart(i, getter_AddRefs(part));
00374     part->GetBinding(getter_AddRefs(binding));
00375     nsCOMPtr<nsISOAPPartBinding> partBinding = do_QueryInterface(binding);
00376     PRUint16 location;
00377     partBinding->GetLocation(&location);
00378 
00379     nsCOMPtr<nsISOAPBlock> block;
00380     if (location == nsISOAPPartBinding::LOCATION_HEADER) {
00381       block = do_QueryInterface(headerBlocks[headerEntry++]);
00382     }
00383     else if (location == nsISOAPPartBinding::LOCATION_BODY) {
00384       block = do_QueryInterface(bodyBlocks[bodyEntry++]);
00385     }
00386 
00387     if (!block) {
00388       rv = NS_ERROR_FAILURE;
00389       goto call_method_end;
00390     }
00391 
00392     // Get the name, namespaceURI and type of the block based on
00393     // information from the WSDL part. If the schema component
00394     // associated with the part is an element, these values come
00395     // from the schema description of the element. If it is a
00396     // type, then the values are gathered from elsewhere.
00397     nsCOMPtr<nsISchemaComponent> schemaComponent;
00398     rv = part->GetSchemaComponent(getter_AddRefs(schemaComponent));
00399     if (NS_FAILED(rv)) {
00400       goto call_method_end;
00401     }
00402 
00403     nsCOMPtr<nsISchemaType> type;
00404     nsAutoString blockName, blockNamespace;
00405     nsCOMPtr<nsISchemaElement> element = do_QueryInterface(schemaComponent);
00406 
00407     if (element) {
00408       rv = element->GetType(getter_AddRefs(type));
00409       if (NS_FAILED(rv)) {
00410         goto call_method_end;
00411       }
00412 
00413       element->GetName(blockName);
00414       element->GetTargetNamespace(blockNamespace);
00415     }
00416     else {
00417       type = do_QueryInterface(schemaComponent);
00418 
00419       nsAutoString paramName;
00420       part->GetName(paramName);
00421 
00422       blockName.Assign(paramName);
00423       partBinding->GetNamespace(blockNamespace);
00424     }
00425 
00426     block->SetName(blockName);
00427     block->SetNamespaceURI(blockNamespace);
00428     block->SetSchemaType(type);
00429 
00430     nsAutoString encodingStyle;
00431     PRUint16 use;
00432 
00433     partBinding->GetUse(&use);
00434     // XXX Need a way to specify that a block should not be
00435     // encoded.
00436     if (use == nsISOAPPartBinding::USE_ENCODED) {
00437       partBinding->GetEncodingStyle(encodingStyle);
00438       if (!encodingStyle.IsEmpty()) {
00439         nsCOMPtr<nsISOAPEncoding> partEncoding;
00440         encoding->GetAssociatedEncoding(encodingStyle, PR_FALSE,
00441                                         getter_AddRefs(partEncoding));
00442         block->SetEncoding(partEncoding);
00443       }
00444     }
00445 
00446     // Look ahead in the param info array to see if the current part has to be
00447     // treated as an array. If so then get the array length from the current
00448     // param and increment the param index.
00449 
00450     PRUint32 arrayLength;
00451 
00452     if (paramIndex < maxParamIndex &&
00453         info->GetParam((PRUint8)(paramIndex + 1)).GetType().IsArray()) {
00454       arrayLength = params[paramIndex++].val.u32;
00455     }
00456     else {
00457       arrayLength = 0;
00458     }
00459 
00460     NS_ASSERTION(paramIndex <= maxParamIndex,
00461                  "WSDL/IInfo param count mismatch");
00462 
00463     const nsXPTParamInfo& paramInfo = info->GetParam(paramIndex);
00464 
00465     nsCOMPtr<nsIVariant> value;
00466     rv = ParameterToVariant(mPrimaryInterface, methodIndex,
00467                             &paramInfo, params[paramIndex],
00468                             arrayLength, getter_AddRefs(value));
00469     if (NS_FAILED(rv)) {
00470       goto call_method_end;
00471     }
00472 
00473     block->SetValue(value);
00474   }
00475 
00476   // Encode the parameters to the call
00477   rv = call->Encode(version,
00478                     methodName, targetObjectURI,
00479                     headerCount, headerBlocks,
00480                     bodyCount, bodyBlocks);
00481   if (NS_FAILED(rv)) {
00482     goto call_method_end;
00483   }
00484 
00485   WSPCallContext* ccInst;
00486   ccInst = new WSPCallContext(this, call, methodName, operation);
00487   if (!ccInst) {
00488     rv = NS_ERROR_OUT_OF_MEMORY;
00489     goto call_method_end;
00490   }
00491   cc = ccInst;
00492 
00493   if (mIsAsync) {
00494     PRUint8 pcount;
00495     pcount = info->GetParamCount();
00496     // There has to be at least one parameter - the retval.
00497     if (pcount == 0) {
00498       rv = NS_ERROR_FAILURE;
00499       goto call_method_end;
00500     }
00501 
00502 #ifdef DEBUG
00503     // The last one should be the retval.
00504     const nsXPTParamInfo& retParamInfo = info->GetParam(pcount - 1);
00505     if (!retParamInfo.IsRetval()) {
00506       rv = NS_ERROR_FAILURE;
00507       goto call_method_end;
00508     }
00509 
00510     // It should be an interface pointer
00511     const nsXPTType& retType = retParamInfo.GetType();
00512     if (!retType.IsInterfacePointer()) {
00513       rv = NS_ERROR_FAILURE;
00514       goto call_method_end;
00515     }
00516 #endif
00517 
00518     nsIWebServiceCallContext** retval =
00519       NS_STATIC_CAST(nsIWebServiceCallContext**, params[pcount-1].val.p);
00520     if (!retval) {
00521       rv = NS_ERROR_FAILURE;
00522       goto call_method_end;
00523     }
00524     *retval = cc;
00525     NS_ADDREF(*retval);
00526 
00527     rv = ccInst->CallAsync(methodIndex, mAsyncListener);
00528     if (NS_FAILED(rv)) {
00529       goto call_method_end;
00530     }
00531 
00532     mPendingCalls.AppendObject(ccInst);
00533   }
00534   else {
00535     rv = ccInst->CallSync(methodIndex, params);
00536   }
00537 
00538 call_method_end:
00539   if (bodyBlocks) {
00540     NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(bodyCount, bodyBlocks);
00541   }
00542   if (headerBlocks) {
00543     NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(headerCount, headerBlocks);
00544   }
00545   return rv;
00546 }
00547 
00548 nsresult
00549 WSPProxy::ParameterToVariant(nsIInterfaceInfo* aInterfaceInfo,
00550                              PRUint32 aMethodIndex,
00551                              const nsXPTParamInfo* aParamInfo,
00552                              nsXPTCMiniVariant aMiniVariant,
00553                              PRUint32 aArrayLength, nsIVariant** aVariant)
00554 {
00555   nsXPTType type;
00556   nsresult rv = aInterfaceInfo->GetTypeForParam(aMethodIndex, aParamInfo,
00557                                                 0, &type);
00558   if (NS_FAILED(rv)) {
00559     return rv;
00560   }
00561 
00562   uint8 type_tag = type.TagPart();
00563   nsCOMPtr<nsIInterfaceInfo> iinfo;
00564   if (type.IsArray()) {
00565     nsXPTType arrayType;
00566     rv = aInterfaceInfo->GetTypeForParam(aMethodIndex, aParamInfo,
00567                                          1, &arrayType);
00568     if (NS_FAILED(rv)) {
00569       return rv;
00570     }
00571 
00572     if (arrayType.IsInterfacePointer()) {
00573       rv = aInterfaceInfo->GetInfoForParam(aMethodIndex, aParamInfo,
00574                                            getter_AddRefs(iinfo));
00575       if (NS_FAILED(rv)) {
00576         return rv;
00577       }
00578     }
00579     return ArrayXPTCMiniVariantToVariant(arrayType.TagPart(), aMiniVariant,
00580                                          aArrayLength, iinfo, aVariant);
00581   }
00582 
00583   // else
00584 
00585   if (type.IsInterfacePointer()) {
00586     rv = aInterfaceInfo->GetInfoForParam(aMethodIndex, aParamInfo,
00587                                          getter_AddRefs(iinfo));
00588     if (NS_FAILED(rv)) {
00589       return rv;
00590     }
00591   }
00592 
00593   return XPTCMiniVariantToVariant(type_tag, aMiniVariant, iinfo, aVariant);
00594 }
00595 
00596 nsresult
00597 WSPProxy::WrapInPropertyBag(nsISupports* aInstance,
00598                             nsIInterfaceInfo* aInterfaceInfo,
00599                             nsIPropertyBag** aPropertyBag)
00600 {
00601   *aPropertyBag = nsnull;
00602   nsresult rv;
00603   nsCOMPtr<nsIWebServiceComplexTypeWrapper> wrapper =
00604     do_CreateInstance(NS_WEBSERVICECOMPLEXTYPEWRAPPER_CONTRACTID, &rv);
00605   if (NS_FAILED(rv)) {
00606     return rv;
00607   }
00608   rv = wrapper->Init(aInstance, aInterfaceInfo);
00609   if (NS_FAILED(rv)) {
00610     return rv;
00611   }
00612   return CallQueryInterface(wrapper, aPropertyBag);
00613 }
00614 
00615 nsresult
00616 WSPProxy::XPTCMiniVariantToVariant(uint8 aTypeTag, nsXPTCMiniVariant aResult,
00617                                    nsIInterfaceInfo* aInterfaceInfo,
00618                                    nsIVariant** aVariant)
00619 {
00620   nsresult rv;
00621 
00622   // If a variant is passed in, just return it as is.
00623   if (aTypeTag == nsXPTType::T_INTERFACE) {
00624     nsISupports* inst = (nsISupports*)aResult.val.p;
00625     nsCOMPtr<nsIVariant> instVar = do_QueryInterface(inst);
00626     if (instVar) {
00627       *aVariant = instVar;
00628       NS_ADDREF(*aVariant);
00629       return NS_OK;
00630     }
00631   }
00632 
00633   nsCOMPtr<nsIWritableVariant> var =
00634     do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
00635   if (NS_FAILED(rv)) {
00636     return rv;
00637   }
00638 
00639   switch (aTypeTag) {
00640     case nsXPTType::T_I8:
00641       var->SetAsInt8(aResult.val.i8);
00642       break;
00643     case nsXPTType::T_I16:
00644       var->SetAsInt16(aResult.val.i16);
00645       break;
00646     case nsXPTType::T_I32:
00647       var->SetAsInt32(aResult.val.i32);
00648       break;
00649     case nsXPTType::T_I64:
00650       var->SetAsInt64(aResult.val.i64);
00651       break;
00652     case nsXPTType::T_U8:
00653       var->SetAsUint8(aResult.val.u8);
00654       break;
00655     case nsXPTType::T_U16:
00656       var->SetAsUint16(aResult.val.u16);
00657       break;
00658     case nsXPTType::T_U32:
00659       var->SetAsUint32(aResult.val.u32);
00660       break;
00661     case nsXPTType::T_U64:
00662       var->SetAsUint64(aResult.val.u64);
00663       break;
00664     case nsXPTType::T_FLOAT:
00665       var->SetAsFloat(aResult.val.f);
00666       break;
00667     case nsXPTType::T_DOUBLE:
00668       var->SetAsDouble(aResult.val.d);
00669       break;
00670     case nsXPTType::T_BOOL:
00671       var->SetAsBool(aResult.val.b);
00672       break;
00673     case nsXPTType::T_CHAR:
00674       var->SetAsChar(aResult.val.c);
00675       break;
00676     case nsXPTType::T_WCHAR:
00677       var->SetAsWChar(aResult.val.wc);
00678       break;
00679     case nsXPTType::T_CHAR_STR:
00680       var->SetAsString(NS_STATIC_CAST(char*, aResult.val.p));
00681       break;
00682     case nsXPTType::T_WCHAR_STR:
00683       var->SetAsWString(NS_STATIC_CAST(PRUnichar*, aResult.val.p));
00684       break;
00685     case nsXPTType::T_DOMSTRING:
00686     case nsXPTType::T_ASTRING:
00687       var->SetAsAString(*((nsAString*)aResult.val.p));
00688       break;
00689     case nsXPTType::T_INTERFACE:
00690     {
00691       nsISupports* instance = (nsISupports*)aResult.val.p;
00692       if (instance) {
00693         nsCOMPtr<nsIPropertyBag> propBag;
00694         rv = WrapInPropertyBag(instance, aInterfaceInfo,
00695                                getter_AddRefs(propBag));
00696         if (NS_FAILED(rv)) {
00697           return rv;
00698         }
00699         var->SetAsInterface(NS_GET_IID(nsIPropertyBag), propBag);
00700         // AFAICT, there is no need to release the instance here 
00701         // because the caller who owns the object should be releasing it.
00702         // NS_RELEASE(instance); 
00703       }
00704       else {
00705         var->SetAsEmpty();
00706       }
00707 
00708       break;
00709     }
00710     default:
00711       NS_ERROR("Bad attribute type for complex type interface");
00712       rv = NS_ERROR_FAILURE;
00713   }
00714 
00715   *aVariant = var;
00716   NS_ADDREF(*aVariant);
00717 
00718   return rv;
00719 }
00720 
00721 nsresult
00722 WSPProxy::ArrayXPTCMiniVariantToVariant(uint8 aTypeTag,
00723                                         nsXPTCMiniVariant aResult,
00724                                         PRUint32 aLength,
00725                                         nsIInterfaceInfo* aInterfaceInfo,
00726                                         nsIVariant** aVariant)
00727 {
00728   nsresult rv;
00729 
00730   nsCOMPtr<nsIWritableVariant> retvar =
00731     do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
00732   if (NS_FAILED(rv)) {
00733     return rv;
00734   }
00735 
00736   if (aLength) {
00737     PRUint32 i = 0;
00738     void* array = aResult.val.p;
00739     void* entries;
00740     nsISupports** entriesSup = nsnull;
00741     const nsIID* iid = nsnull;
00742 
00743     switch (aTypeTag) {
00744       case nsXPTType::T_I8:
00745       case nsXPTType::T_I16:
00746       case nsXPTType::T_I32:
00747       case nsXPTType::T_I64:
00748       case nsXPTType::T_U8:
00749       case nsXPTType::T_U16:
00750       case nsXPTType::T_U32:
00751       case nsXPTType::T_U64:
00752       case nsXPTType::T_FLOAT:
00753       case nsXPTType::T_DOUBLE:
00754       case nsXPTType::T_BOOL:
00755       case nsXPTType::T_CHAR:
00756       case nsXPTType::T_WCHAR:
00757       case nsXPTType::T_CHAR_STR:
00758       case nsXPTType::T_WCHAR_STR:
00759         entries = array;
00760         break;
00761       case nsXPTType::T_INTERFACE:
00762       {
00763         aInterfaceInfo->GetIIDShared(&iid);
00764         if (iid->Equals(NS_GET_IID(nsIVariant))) {
00765           entries = array;
00766         }
00767         else {
00768           entriesSup = (nsISupports**)nsMemory::Alloc(aLength *
00769                                                       sizeof(nsISupports*));
00770           if (!entriesSup) {
00771             return NS_ERROR_OUT_OF_MEMORY;
00772           }
00773           const nsIID& propbagIID = NS_GET_IID(nsIPropertyBag);
00774           iid = &propbagIID;
00775           entries = (void*)entriesSup;
00776           for(i = 0; i < aLength; i++) {
00777             nsISupports* instance = *((nsISupports**)array + i);
00778             nsISupports** outptr = entriesSup + i;
00779             if (instance) {
00780               nsCOMPtr<nsIPropertyBag> propBag;
00781               rv = WrapInPropertyBag(instance, aInterfaceInfo,
00782                                      getter_AddRefs(propBag));
00783               if (NS_FAILED(rv)) {
00784                 break;
00785               }
00786               propBag->QueryInterface(NS_GET_IID(nsISupports),
00787                                       (void**)outptr);
00788             }
00789             else {
00790               *outptr = nsnull;
00791             }
00792           }
00793         }
00794         aTypeTag = nsXPTType::T_INTERFACE_IS;
00795         break;
00796       }
00797       default:
00798         NS_ERROR("Conversion of illegal array type");
00799         return NS_ERROR_FAILURE;
00800     }
00801 
00802     if (NS_SUCCEEDED(rv)) {
00803       rv = retvar->SetAsArray(aTypeTag, iid, aLength, entries);
00804     }
00805 
00806     if (entriesSup) {
00807       NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(i, entriesSup);
00808     }
00809   }
00810   else {
00811     retvar->SetAsEmpty();
00812   }
00813 
00814   if (NS_SUCCEEDED(rv)) {
00815     *aVariant = retvar;
00816     NS_ADDREF(*aVariant);
00817   }
00818 
00819   return rv;
00820 }
00821 
00822 
00823 nsresult
00824 WSPProxy::VariantToInParameter(nsIInterfaceInfo* aInterfaceInfo,
00825                                PRUint32 aMethodIndex,
00826                                const nsXPTParamInfo* aParamInfo,
00827                                nsIVariant* aVariant,
00828                                nsXPTCVariant* aXPTCVariant)
00829 {
00830   nsXPTType type;
00831   nsresult rv = aInterfaceInfo->GetTypeForParam(aMethodIndex, aParamInfo,
00832                                                 0, &type);
00833   if (NS_FAILED(rv)) {
00834     return rv;
00835   }
00836   
00837   
00838   uint8 type_tag = type.TagPart();
00839   nsCOMPtr<nsIInterfaceInfo> iinfo;
00840   if (type.IsArray()) {
00841     nsXPTType arrayType;
00842     rv = aInterfaceInfo->GetTypeForParam(aMethodIndex, aParamInfo,
00843                                          1, &arrayType);
00844     if (NS_FAILED(rv)) {
00845       return rv;
00846     }
00847 
00848     if (arrayType.IsInterfacePointer()) {
00849       rv = aInterfaceInfo->GetInfoForParam(aMethodIndex, aParamInfo,
00850                                            getter_AddRefs(iinfo));
00851       if (NS_FAILED(rv)) {
00852         return rv;
00853       }
00854     }
00855 
00856     aXPTCVariant[0].type = nsXPTType::T_U32;
00857     aXPTCVariant[1].type = nsXPTType::T_ARRAY;
00858     aXPTCVariant[1].SetValIsArray();
00859     return VariantToArrayValue(arrayType.TagPart(), aXPTCVariant, aXPTCVariant+1,
00860                                iinfo, aVariant);
00861   }
00862   // Set the param's type on the XPTCVariant because xptcinvoke's 
00863   // invoke_copy_to_stack depends on it. This fixes bug 203434.
00864   aXPTCVariant->type = type;
00865   // else
00866   if (type.IsInterfacePointer()) {
00867     rv = aInterfaceInfo->GetInfoForParam(aMethodIndex, aParamInfo, 
00868                                          getter_AddRefs(iinfo));
00869     if (NS_FAILED(rv)) {
00870       return rv;
00871     }
00872   }
00873 
00874   if (type_tag == nsXPTType::T_DOMSTRING) {
00875     // T_DOMSTRING values are expected to be stored in an nsAString
00876     // object pointed to by the nsXPTCVariant...
00877     return VariantToValue(type_tag, aXPTCVariant->val.p, iinfo, aVariant);
00878   }
00879   // else
00880 
00881   // ... but other types are expected to be stored directly in the
00882   // variant itself.
00883   return VariantToValue(type_tag, &aXPTCVariant->val, iinfo, aVariant);
00884 }
00885 
00886 nsresult
00887 WSPProxy::VariantToOutParameter(nsIInterfaceInfo* aInterfaceInfo,
00888                                 PRUint32 aMethodIndex,
00889                                 const nsXPTParamInfo* aParamInfo,
00890                                 nsIVariant* aVariant,
00891                                 nsXPTCMiniVariant* aMiniVariant)
00892 {
00893   nsXPTType type;
00894   nsresult rv = aInterfaceInfo->GetTypeForParam(aMethodIndex, aParamInfo,
00895                                                 0, &type);
00896   if (NS_FAILED(rv)) {
00897     return rv;
00898   }
00899   uint8 type_tag = type.TagPart();
00900   nsCOMPtr<nsIInterfaceInfo> iinfo;
00901   if (type.IsArray()) {
00902     nsXPTType arrayType;
00903     rv = aInterfaceInfo->GetTypeForParam(aMethodIndex, aParamInfo,
00904                                          1, &arrayType);
00905     if (NS_FAILED(rv)) {
00906       return rv;
00907     }
00908 
00909     if (arrayType.IsInterfacePointer()) {
00910       rv = aInterfaceInfo->GetInfoForParam(aMethodIndex, aParamInfo,
00911                                            getter_AddRefs(iinfo));
00912       if (NS_FAILED(rv)) {
00913         return rv;
00914       }
00915     }
00916     return VariantToArrayValue(arrayType.TagPart(), 
00917                                aMiniVariant, aMiniVariant + 1,
00918                                iinfo, aVariant);
00919   }
00920   // else
00921   if (type.IsInterfacePointer()) {
00922     rv = aInterfaceInfo->GetInfoForParam(aMethodIndex, aParamInfo,
00923                                          getter_AddRefs(iinfo));
00924     if (NS_FAILED(rv)) {
00925       return rv;
00926     }
00927   }
00928   return VariantToValue(type_tag, aMiniVariant->val.p, iinfo, aVariant);
00929 }
00930 
00931 nsresult
00932 WSPProxy::WrapInComplexType(nsIPropertyBag* aPropertyBag,
00933                             nsIInterfaceInfo* aInterfaceInfo,
00934                             nsISupports** aComplexType)
00935 {
00936   *aComplexType = nsnull;
00937   nsRefPtr<WSPPropertyBagWrapper> wrapper = new WSPPropertyBagWrapper();
00938   if (!wrapper) {
00939     return NS_ERROR_OUT_OF_MEMORY;
00940   }
00941   nsresult rv = wrapper->Init(aPropertyBag, aInterfaceInfo);
00942   if (NS_FAILED(rv)) {
00943     return rv;
00944   }
00945   wrapper->QueryInterface(NS_GET_IID(nsISupports), (void**)aComplexType);
00946   return NS_OK;
00947 }
00948 
00949 nsresult
00950 WSPProxy::VariantToValue(uint8 aTypeTag, void* aValue,
00951                          nsIInterfaceInfo* aInterfaceInfo,
00952                          nsIVariant* aProperty)
00953 {
00954   nsresult rv = NS_OK;
00955 
00956   switch(aTypeTag) {
00957     case nsXPTType::T_I8:
00958       rv = aProperty->GetAsInt8((PRUint8*)aValue);
00959       break;
00960     case nsXPTType::T_I16:
00961       rv = aProperty->GetAsInt16((PRInt16*)aValue);
00962       break;
00963     case nsXPTType::T_I32:
00964       rv = aProperty->GetAsInt32((PRInt32*)aValue);
00965       break;
00966     case nsXPTType::T_I64:
00967       rv = aProperty->GetAsInt64((PRInt64*)aValue);
00968       break;
00969     case nsXPTType::T_U8:
00970       rv = aProperty->GetAsUint8((PRUint8*)aValue);
00971       break;
00972     case nsXPTType::T_U16:
00973       rv = aProperty->GetAsUint16((PRUint16*)aValue);
00974       break;
00975     case nsXPTType::T_U32:
00976       rv = aProperty->GetAsUint32((PRUint32*)aValue);
00977       break;
00978     case nsXPTType::T_U64:
00979       rv = aProperty->GetAsUint64((PRUint64*)aValue);
00980       break;
00981     case nsXPTType::T_FLOAT:
00982       rv = aProperty->GetAsFloat((float*)aValue);
00983       break;
00984     case nsXPTType::T_DOUBLE:
00985       rv = aProperty->GetAsDouble((double*)aValue);
00986       break;
00987     case nsXPTType::T_BOOL:
00988       rv = aProperty->GetAsBool((PRBool*)aValue);
00989       break;
00990     case nsXPTType::T_CHAR:
00991       rv = aProperty->GetAsChar((char*)aValue);
00992       break;
00993     case nsXPTType::T_WCHAR:
00994       rv = aProperty->GetAsWChar((PRUnichar*)aValue);
00995       break;
00996     case nsXPTType::T_CHAR_STR:
00997       rv = aProperty->GetAsString((char**)aValue);
00998       break;
00999     case nsXPTType::T_WCHAR_STR:
01000       rv = aProperty->GetAsWString((PRUnichar**)aValue);
01001       break;
01002     case nsXPTType::T_DOMSTRING:
01003     case nsXPTType::T_ASTRING:
01004       rv = aProperty->GetAsAString(*(nsAString*)aValue);
01005       break;
01006     case nsXPTType::T_INTERFACE:
01007     {
01008       const nsIID* iid;
01009       aInterfaceInfo->GetIIDShared(&iid);
01010       PRUint16 dataType;
01011       aProperty->GetDataType(&dataType);
01012       if (dataType == nsIDataType::VTYPE_EMPTY) {
01013         *(nsISupports**)aValue = nsnull;
01014       }
01015       else if (iid->Equals(NS_GET_IID(nsIVariant))) {
01016         *(nsIVariant**)aValue = aProperty;
01017         NS_ADDREF(*(nsIVariant**)aValue);
01018       }
01019       else {
01020         nsCOMPtr<nsISupports> sup;
01021         rv = aProperty->GetAsISupports(getter_AddRefs(sup));
01022         if (NS_FAILED(rv)) {
01023           return rv;
01024         }
01025         nsCOMPtr<nsIPropertyBag> propBag = do_QueryInterface(sup, &rv);
01026         if (NS_FAILED(rv)) {
01027           return rv;
01028         }
01029         nsCOMPtr<nsISupports> wrapper;
01030         rv = WrapInComplexType(propBag, aInterfaceInfo,
01031                                getter_AddRefs(wrapper));
01032         if (NS_FAILED(rv)) {
01033           return rv;
01034         }
01035 
01036         rv = wrapper->QueryInterface(*iid, (void**)aValue);
01037       }
01038       break;
01039     }
01040     default:
01041       NS_ERROR("Bad attribute type for complex type interface");
01042       rv = NS_ERROR_FAILURE;
01043   }
01044 
01045   return rv;
01046 }
01047 
01048 nsresult
01049 WSPProxy::VariantToArrayValue(uint8 aTypeTag,
01050                               nsXPTCMiniVariant* aResultSize,
01051                               nsXPTCMiniVariant* aResultArray,
01052                               nsIInterfaceInfo* aInterfaceInfo,
01053                               nsIVariant* aProperty)
01054 {
01055   void* array;
01056   PRUint16 type;
01057   PRUint32 count;
01058 
01059   nsIID arrayIID;
01060   nsresult rv = aProperty->GetAsArray(&type, &arrayIID, &count, &array);
01061   if (NS_FAILED(rv)) {
01062     return rv;
01063   }
01064 
01065   aResultSize->val.u32 = count;
01066 
01067   switch (aTypeTag) {
01068     case nsXPTType::T_I8:
01069     case nsXPTType::T_U8:
01070     case nsXPTType::T_I16:
01071     case nsXPTType::T_U16:
01072     case nsXPTType::T_I32:
01073     case nsXPTType::T_U32:
01074     case nsXPTType::T_I64:
01075     case nsXPTType::T_U64:
01076     case nsXPTType::T_FLOAT:
01077     case nsXPTType::T_DOUBLE:
01078     case nsXPTType::T_BOOL:
01079     case nsXPTType::T_CHAR:
01080     case nsXPTType::T_WCHAR:
01081     case nsXPTType::T_CHAR_STR:
01082     case nsXPTType::T_WCHAR_STR:
01083       aResultArray->val.p = array;
01084       break;
01085     case nsXPTType::T_INTERFACE:
01086     case nsXPTType::T_INTERFACE_IS:
01087     {
01088       if (arrayIID.Equals(NS_GET_IID(nsIVariant))) {
01089         aResultArray->val.p = array;
01090       }
01091       else if (!arrayIID.Equals(NS_GET_IID(nsIPropertyBag))) {
01092         NS_ERROR("Array of complex types should be represented by property "
01093                  "bags");
01094         return NS_ERROR_FAILURE;
01095       }
01096       else {
01097         nsISupports** outptr =
01098           (nsISupports**)nsMemory::Alloc(count * sizeof(nsISupports*));
01099         if (!outptr) {
01100           return NS_ERROR_OUT_OF_MEMORY;
01101         }
01102         nsISupports** arraySup = (nsISupports**)array;
01103         const nsIID* iid;
01104         aInterfaceInfo->GetIIDShared(&iid);
01105         PRUint32 i;
01106         for (i = 0; i < count; i++) {
01107           nsCOMPtr<nsIPropertyBag> propBag(do_QueryInterface(arraySup[i]));
01108           if (!propBag) {
01109             *(outptr + i) = nsnull;
01110           }
01111           else {
01112             nsCOMPtr<nsISupports> wrapper;
01113             rv = WrapInComplexType(propBag, aInterfaceInfo,
01114                                    getter_AddRefs(wrapper));
01115             if (NS_FAILED(rv)) {
01116               NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(i, outptr);
01117               return rv;
01118             }
01119             rv = wrapper->QueryInterface(*iid, (void**)(outptr + i));
01120             if (NS_FAILED(rv)) {
01121               NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(i, outptr);
01122               return rv;
01123             }
01124           }
01125         }
01126         aResultArray->val.p = outptr;
01127       }
01128       break;
01129     }
01130     default:
01131       NS_ERROR("Conversion of illegal array type");
01132       return NS_ERROR_FAILURE;
01133   }
01134 
01135   return NS_OK;
01136 }
01137 
01138 NS_IMETHODIMP
01139 WSPProxy::GetInterfaceInfo(nsIInterfaceInfo** info)
01140 {
01141   NS_ENSURE_ARG_POINTER(info);
01142 
01143   *info = mPrimaryInterface;
01144   NS_ADDREF(*info);
01145 
01146   return NS_OK;
01147 }
01148 
01150 //
01151 // Implementation of nsIWebServiceProxy
01152 //
01154 
01155 /* readonly attribute nsIWSDLPort port; */
01156 NS_IMETHODIMP
01157 WSPProxy::GetPort(nsIWSDLPort * *aPort)
01158 {
01159   NS_ENSURE_ARG_POINTER(aPort);
01160 
01161   *aPort = mPort;
01162   NS_IF_ADDREF(*aPort);
01163 
01164   return NS_OK;
01165 }
01166 
01167 /* readonly attribute boolean isAsync; */
01168 NS_IMETHODIMP
01169 WSPProxy::GetIsAsync(PRBool *aIsAsync)
01170 {
01171   NS_ENSURE_ARG_POINTER(aIsAsync);
01172   *aIsAsync = mIsAsync;
01173   return NS_OK;
01174 }
01175 
01176 /* readonly attribute AString qualifier; */
01177 NS_IMETHODIMP
01178 WSPProxy::GetQualifier(nsAString & aQualifier)
01179 {
01180   aQualifier.Assign(mQualifier);
01181 
01182   return NS_OK;
01183 }
01184 
01185 /* readonly attribute nsISimpleEnumerator pendingCalls; */
01186 NS_IMETHODIMP
01187 WSPProxy::GetPendingCalls(nsISimpleEnumerator * *aPendingCalls)
01188 {
01189   return NS_ERROR_NOT_IMPLEMENTED;
01190 }
01191 
01192 nsresult
01193 WSPProxy::GetInterfaceName(PRBool listener, char** retval)
01194 {
01195   if (!mPrimaryInterface) {
01196     return NS_ERROR_FAILURE;
01197   }
01198 
01199   const char* rawName;
01200   nsresult rv = mPrimaryInterface->GetNameShared(&rawName);
01201   if (NS_FAILED(rv)) {
01202     return rv;
01203   }
01204 
01205   nsCAutoString name;
01206 
01207   if (listener) {
01208     if (mIsAsync) {
01209       name.Assign(rawName, strlen(rawName) - (sizeof("Async")-1) );
01210     }
01211     else {
01212       name.Assign(rawName);
01213     }
01214     name.Append("Listener");
01215   }
01216   else {
01217     name.Assign(rawName);
01218   }
01219 
01220   *retval = (char*) nsMemory::Clone(name.get(), name.Length()+1);
01221   return *retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
01222 }
01223 
01224 /* readonly attribute string primaryInterfaceName; */
01225 NS_IMETHODIMP
01226 WSPProxy::GetPrimaryInterfaceName(char * *aPrimaryInterfaceName)
01227 {
01228   return GetInterfaceName(PR_FALSE, aPrimaryInterfaceName);
01229 }
01230 
01231 /* readonly attribute string primaryAsyncListenerInterfaceName; */
01232 NS_IMETHODIMP
01233 WSPProxy::GetPrimaryAsyncListenerInterfaceName(char * *aPrimaryAsyncListenerInterfaceName)
01234 {
01235   return GetInterfaceName(PR_TRUE, aPrimaryAsyncListenerInterfaceName);
01236 }
01237 
01238 /* readonly attribute nsIScriptableInterfaces interfaces; */
01239 NS_IMETHODIMP
01240 WSPProxy::GetInterfaces(nsIScriptableInterfaces * *aInterfaces)
01241 {
01242   *aInterfaces = mInterfaces;
01243   NS_IF_ADDREF(*aInterfaces);
01244   return NS_OK;
01245 }
01246 
01248 //
01249 // Implementation of nsIClassInfo
01250 //
01252 
01253 /* void getInterfaces (out PRUint32 count, [array, size_is (count),
01254    retval] out nsIIDPtr array); */
01255 NS_IMETHODIMP
01256 WSPProxy::GetInterfaces(PRUint32 *count, nsIID * **array)
01257 {
01258   if (!mIID) {
01259     return NS_ERROR_NOT_INITIALIZED;
01260   }
01261 
01262   *count = 2;
01263   nsIID** iids = NS_STATIC_CAST(nsIID**, nsMemory::Alloc(2 * sizeof(nsIID*)));
01264   if (!iids) {
01265     return NS_ERROR_OUT_OF_MEMORY;
01266   }
01267 
01268   iids[0] = NS_STATIC_CAST(nsIID *, nsMemory::Clone(mIID, sizeof(nsIID)));
01269   if (NS_UNLIKELY(!iids[0])) {
01270     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(0, iids);
01271     return NS_ERROR_OUT_OF_MEMORY;
01272   }
01273   const nsIID& wsiid = NS_GET_IID(nsIWebServiceProxy);
01274   iids[1] = NS_STATIC_CAST(nsIID *, nsMemory::Clone(&wsiid, sizeof(nsIID)));
01275   if (NS_UNLIKELY(!iids[1])) {
01276     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(1, iids);
01277     return NS_ERROR_OUT_OF_MEMORY;
01278   }
01279 
01280   *array = iids;
01281 
01282   return NS_OK;
01283 }
01284 
01285 /* nsISupports getHelperForLanguage (in PRUint32 language); */
01286 NS_IMETHODIMP
01287 WSPProxy::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
01288 {
01289   *_retval = nsnull;
01290   return NS_OK;
01291 }
01292 
01293 /* readonly attribute string contractID; */
01294 NS_IMETHODIMP
01295 WSPProxy::GetContractID(char * *aContractID)
01296 {
01297   *aContractID = nsnull;
01298   return NS_OK;
01299 }
01300 
01301 /* readonly attribute string classDescription; */
01302 NS_IMETHODIMP
01303 WSPProxy::GetClassDescription(char * *aClassDescription)
01304 {
01305   *aClassDescription = nsnull;
01306   return NS_OK;
01307 }
01308 
01309 /* readonly attribute nsCIDPtr classID; */
01310 NS_IMETHODIMP
01311 WSPProxy::GetClassID(nsCID * *aClassID)
01312 {
01313   *aClassID = nsnull;
01314   return NS_OK;
01315 }
01316 
01317 /* readonly attribute PRUint32 implementationLanguage; */
01318 NS_IMETHODIMP
01319 WSPProxy::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
01320 {
01321   *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
01322   return NS_OK;
01323 }
01324 
01325 /* readonly attribute PRUint32 flags; */
01326 NS_IMETHODIMP
01327 WSPProxy::GetFlags(PRUint32 *aFlags)
01328 {
01329   *aFlags = nsIClassInfo::DOM_OBJECT;
01330   return NS_OK;
01331 }
01332 
01333 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
01334 NS_IMETHODIMP
01335 WSPProxy::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
01336 {
01337   return NS_ERROR_NOT_AVAILABLE;
01338 }
01339 
01340 void
01341 WSPProxy::GetListenerInterfaceInfo(nsIInterfaceInfo** aInfo)
01342 {
01343   *aInfo = mListenerInterfaceInfo;
01344   NS_IF_ADDREF(*aInfo);
01345 }
01346 
01347 void
01348 WSPProxy::CallCompleted(WSPCallContext* aContext)
01349 {
01350   mPendingCalls.RemoveObject(aContext);
01351 }