Back to index

lightning-sunbird  0.9+nobinonly
wspcomplextypewrapper.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 
00042 // xtpcall includes
00043 #include "xptcall.h"
00044 #include "xptinfo.h"
00045 
00046 // xpcom includes
00047 #include "nsIServiceManager.h"
00048 #include "nsIProperty.h"
00049 #include "nsIVariant.h"
00050 
00051 class WSPComplexTypeProperty : public nsIProperty
00052 {
00053 public:
00054   WSPComplexTypeProperty(const nsAString& aName, nsIVariant* aValue);
00055   virtual ~WSPComplexTypeProperty()
00056   {
00057   }
00058 
00059   NS_DECL_ISUPPORTS
00060   NS_DECL_NSIPROPERTY
00061 
00062 protected:
00063   nsString mName;
00064   nsCOMPtr<nsIVariant> mValue;
00065 };
00066 
00067 WSPComplexTypeProperty::WSPComplexTypeProperty(const nsAString& aName,
00068                                                nsIVariant* aValue)
00069   : mName(aName), mValue(aValue)
00070 {
00071   NS_ASSERTION(mValue, "Null value!");
00072 }
00073 
00074 NS_IMPL_ISUPPORTS1(WSPComplexTypeProperty, nsIProperty)
00075 
00076 /* readonly attribute AString name; */
00077 NS_IMETHODIMP 
00078 WSPComplexTypeProperty::GetName(nsAString & aName)
00079 {
00080   aName.Assign(mName);
00081   return NS_OK;
00082 }
00083 
00084 /* readonly attribute nsIVariant value; */
00085 NS_IMETHODIMP 
00086 WSPComplexTypeProperty::GetValue(nsIVariant * *aValue)
00087 {
00088   NS_ADDREF(*aValue = mValue);
00089   return NS_OK;
00090 }
00091 
00092 
00093 class WSPComplexTypeEnumerator : public nsISimpleEnumerator {
00094 public:
00095   WSPComplexTypeEnumerator(WSPComplexTypeWrapper* aWrapper,
00096                            nsIInterfaceInfo* aInterfaceInfo);
00097   virtual ~WSPComplexTypeEnumerator();
00098 
00099   NS_DECL_ISUPPORTS
00100   NS_DECL_NSISIMPLEENUMERATOR
00101 
00102 protected:
00103   WSPComplexTypeWrapper* mWrapper;
00104   nsCOMPtr<nsIInterfaceInfo> mInterfaceInfo;
00105   PRUint16 mIndex;
00106   PRUint16 mCount;
00107 };
00108 
00109 WSPComplexTypeEnumerator::WSPComplexTypeEnumerator(WSPComplexTypeWrapper* aWrapper, nsIInterfaceInfo* aInterfaceInfo) 
00110   : mInterfaceInfo(aInterfaceInfo), mIndex(3)
00111 {
00112   mWrapper = aWrapper;
00113   NS_ADDREF(mWrapper);
00114   if (mInterfaceInfo) {
00115     mInterfaceInfo->GetMethodCount(&mCount);
00116   }
00117 }
00118 
00119 WSPComplexTypeEnumerator::~WSPComplexTypeEnumerator()
00120 {
00121   NS_RELEASE(mWrapper);
00122 }
00123 
00124 NS_IMPL_ISUPPORTS1(WSPComplexTypeEnumerator, nsISimpleEnumerator)
00125 
00126 /* boolean hasMoreElements (); */
00127 NS_IMETHODIMP 
00128 WSPComplexTypeEnumerator::HasMoreElements(PRBool *_retval)
00129 {
00130   NS_ENSURE_ARG_POINTER(_retval);
00131   *_retval = mIndex < mCount;
00132   return NS_OK;
00133 }
00134 
00135 /* nsISupports getNext (); */
00136 NS_IMETHODIMP 
00137 WSPComplexTypeEnumerator::GetNext(nsISupports **_retval)
00138 {
00139   NS_ENSURE_ARG_POINTER(_retval);
00140 
00141   if (mIndex >= mCount) {
00142     NS_ERROR("Bad nsISimpleEnumerator caller!");
00143     return NS_ERROR_FAILURE;
00144   }
00145 
00146   const nsXPTMethodInfo* methodInfo;
00147   nsresult rv = mInterfaceInfo->GetMethodInfo(mIndex, &methodInfo);
00148   if (NS_FAILED(rv)) {
00149     return rv;
00150   }
00151   
00152   nsCOMPtr<nsIVariant> var;
00153   rv =  mWrapper->GetPropertyValue(mIndex++, methodInfo, getter_AddRefs(var));
00154   if (NS_FAILED(rv)) {
00155     return rv;
00156   }
00157 
00158   nsAutoString propName;
00159   rv = WSPFactory::C2XML(nsDependentCString(methodInfo->GetName()), propName);
00160   if (NS_FAILED(rv)) {
00161     return rv;
00162   }
00163 
00164   WSPComplexTypeProperty* prop = new WSPComplexTypeProperty(propName, var);
00165   if (!prop) {
00166     return NS_ERROR_OUT_OF_MEMORY;
00167   }
00168 
00169   *_retval = prop;
00170   NS_ADDREF(*_retval);
00171 
00172   return NS_OK;
00173 }
00174 
00175 
00176 WSPComplexTypeWrapper::WSPComplexTypeWrapper()
00177 {
00178 }
00179 
00180 WSPComplexTypeWrapper::~WSPComplexTypeWrapper()
00181 {
00182 }
00183 
00184 nsresult
00185 WSPComplexTypeWrapper::Init(nsISupports* aComplexTypeInstance,
00186                             nsIInterfaceInfo* aInterfaceInfo)
00187 {
00188   mComplexTypeInstance = aComplexTypeInstance;
00189   mInterfaceInfo = aInterfaceInfo;
00190   return NS_OK;
00191 }
00192 
00193 NS_METHOD
00194 WSPComplexTypeWrapper::Create(nsISupports* outer, const nsIID& aIID, 
00195                               void* *aInstancePtr)
00196 {
00197   NS_ENSURE_ARG_POINTER(aInstancePtr);
00198   NS_ENSURE_NO_AGGREGATION(outer);
00199 
00200   WSPComplexTypeWrapper* wrapper = new WSPComplexTypeWrapper();
00201   if (!wrapper) {
00202     return NS_ERROR_OUT_OF_MEMORY;
00203   }
00204 
00205   NS_ADDREF(wrapper);
00206   nsresult rv = wrapper->QueryInterface(aIID, aInstancePtr);
00207   NS_RELEASE(wrapper);
00208   return rv;
00209 }
00210 
00211 NS_IMPL_ISUPPORTS2_CI(WSPComplexTypeWrapper, 
00212                       nsIWebServiceComplexTypeWrapper,
00213                       nsIPropertyBag)
00214 
00215 /* readonly attribute nsISimpleEnumerator enumerator; */
00216 NS_IMETHODIMP 
00217 WSPComplexTypeWrapper::GetEnumerator(nsISimpleEnumerator * *aEnumerator)
00218 {
00219   WSPComplexTypeEnumerator* enumerator =
00220     new WSPComplexTypeEnumerator(this, mInterfaceInfo);
00221   if (!enumerator) {
00222     return NS_ERROR_OUT_OF_MEMORY;
00223   }
00224 
00225   *aEnumerator = enumerator;
00226   NS_ADDREF(*aEnumerator);
00227   return NS_OK;
00228 }
00229 
00230 /* nsIVariant getProperty (in AString name); */
00231 NS_IMETHODIMP 
00232 WSPComplexTypeWrapper::GetProperty(const nsAString & name,
00233                                    nsIVariant **_retval)
00234 {
00235   NS_ENSURE_ARG_POINTER(_retval);
00236 
00237   nsCAutoString methodName;
00238   WSPFactory::XML2C(name, methodName);
00239 
00240   const nsXPTMethodInfo* methodInfo;
00241   PRUint16 methodIndex;
00242   nsresult rv = mInterfaceInfo->GetMethodInfoForName(methodName.get(),
00243                                                      &methodIndex,
00244                                                      &methodInfo);
00245   if (NS_FAILED(rv)) {
00246     return rv;
00247   }
00248 
00249   return GetPropertyValue(methodIndex, methodInfo, _retval);
00250 }
00251 
00252 nsresult
00253 WSPComplexTypeWrapper::GetPropertyValue(PRUint32 aMethodIndex,
00254                                         const nsXPTMethodInfo* aMethodInfo,
00255                                         nsIVariant** _retval)
00256 {
00257   nsresult rv;
00258   nsAutoString outstr;
00259   PRUint32 numParams;
00260   nsXPTCVariant var[2];
00261   uint8 type_tag;
00262   nsXPTType arrayType;
00263   nsCOMPtr<nsIInterfaceInfo> iinfo;
00264 
00265   var[0].ClearFlags();
00266   var[1].ClearFlags();
00267 
00268   // There are two possibilities here: a getter or a
00269   // method that returns array and array size out parameters.
00270   if (aMethodInfo->IsGetter()) {
00271     // If it's a getter make sure that it takes just a single (out) param
00272     if (aMethodInfo->GetParamCount() != 1) {
00273       return NS_ERROR_FAILURE;
00274     }
00275   
00276     const nsXPTParamInfo& paramInfo = aMethodInfo->GetParam(0);
00277     const nsXPTType& type = paramInfo.GetType();
00278     type_tag = type.TagPart();
00279     
00280     numParams = 1;
00281     var[0].type = type_tag;
00282     if (paramInfo.IsOut()) {
00283       var[0].SetPtrIsData();
00284       var[0].ptr = &var[0].val;
00285     }
00286     else if (paramInfo.IsDipper() && type.IsPointer() && 
00287              (type_tag == nsXPTType::T_DOMSTRING)) {
00288       var[0].val.p = &outstr;
00289     }
00290     else {
00291       NS_ERROR("Unexpected parameter type for getter");
00292       return NS_ERROR_FAILURE;
00293     }
00294 
00295     if (type_tag == nsXPTType::T_INTERFACE) {
00296       rv = mInterfaceInfo->GetInfoForParam(aMethodIndex, &paramInfo, 
00297                                            getter_AddRefs(iinfo));
00298       if (NS_FAILED(rv)) {
00299         return rv;
00300       }
00301     }
00302   }
00303   // If it isn't a getter, then it has to be an array
00304   // getter method
00305   else {
00306     // It must take two parameters for this to work
00307     if (aMethodInfo->GetParamCount() != 2) {
00308       return NS_ERROR_FAILURE;
00309     }
00310 
00311     numParams = 2;
00312 
00313     // The first parameter must be "out PRUint32"
00314     const nsXPTParamInfo& paramInfo1 = aMethodInfo->GetParam(0);
00315     const nsXPTType& type1 = paramInfo1.GetType();
00316     if (!paramInfo1.IsOut() || (type1.TagPart() != nsXPTType::T_U32)) {
00317       NS_ERROR("Unexpected parameter type for getter");
00318       return NS_ERROR_FAILURE;
00319     }
00320     
00321     var[0].type = nsXPTType::T_U32;
00322     var[0].SetPtrIsData();
00323     var[0].ptr = &var[0].val;
00324     
00325     // The second parameter must be "[array] out"
00326     const nsXPTParamInfo& paramInfo2 = aMethodInfo->GetParam(1);
00327     const nsXPTType& type2 = paramInfo2.GetType();
00328     type_tag = type2.TagPart();
00329     if (!paramInfo2.IsOut() || !type2.IsArray()) {
00330       NS_ERROR("Unexpected parameter type for getter");
00331       return NS_ERROR_FAILURE;
00332     }
00333 
00334     var[1].type = type_tag;
00335     var[1].SetPtrIsData();
00336     var[1].ptr = &var[1].val;
00337 
00338     rv = mInterfaceInfo->GetTypeForParam(aMethodIndex, &paramInfo2, 1,
00339                                          &arrayType);
00340     if (NS_FAILED(rv)) {
00341       return rv;
00342     }
00343     
00344     if (arrayType.IsInterfacePointer()) {
00345       rv = mInterfaceInfo->GetInfoForParam(aMethodIndex, &paramInfo2, 
00346                                            getter_AddRefs(iinfo));
00347       if (NS_FAILED(rv)) {
00348         return rv;
00349       }
00350     }
00351   }
00352 
00353   rv = XPTC_InvokeByIndex(mComplexTypeInstance, aMethodIndex,
00354                           numParams, var);
00355 
00356   if (NS_FAILED(rv)) {
00357     return rv;
00358   }
00359 
00360   if (type_tag == nsXPTType::T_ARRAY) {
00361     rv = WSPProxy::ArrayXPTCMiniVariantToVariant(arrayType.TagPart(), var[1], 
00362                                                  var[0].val.u32, iinfo, 
00363                                                  _retval);
00364   }
00365   else {
00366     rv = WSPProxy::XPTCMiniVariantToVariant(type_tag, var[0], iinfo, _retval);
00367   }
00368 
00369   return rv;
00370 }