weakref = new nsJavaXPTCStubWeakRef(env, java_obj, stub);
weakref = new nsJavaXPTCStubWeakRef(java_obj, stub);
SetupParams(JNIEnv *env, const jobject aParam, PRUint8 aType, PRBool aIsOut,            const nsID& aIID, PRUint8 aArrayType, PRUint32 aArraySize,            PRBool aIsArrayElement, PRUint32 aIndex, nsXPTCVariant &aVariant){  nsresult rv = NS_OK;  switch (aType)  {    case nsXPTType::T_I8:    {      LOG(("byte\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.i8 = env->CallByteMethod(aParam, byteValueMID);      } else { // 'inout' & 'array'        jbyte value;        if (aParam) {          env->GetByteArrayRegion((jbyteArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.i8 = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          NS_STATIC_CAST(PRInt8*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_I16:    case nsXPTType::T_U8:   // C++ unsigned octet <=> Java short    {      LOG(("short\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.i16 = env->CallShortMethod(aParam, shortValueMID);      } else { // 'inout' & 'array'        jshort value;        if (aParam) {          env->GetShortArrayRegion((jshortArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.i16 = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          if (aType == nsXPTType::T_I16)            NS_STATIC_CAST(PRInt16*, aVariant.val.p)[aIndex] = value;          else            NS_STATIC_CAST(PRUint8*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_I32:    case nsXPTType::T_U16:  // C++ unsigned short <=> Java int    {      LOG(("int\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.i32 = env->CallIntMethod(aParam, intValueMID);      } else { // 'inout' & 'array'        jint value;        if (aParam) {          env->GetIntArrayRegion((jintArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.i32 = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          if (aType == nsXPTType::T_I32)            NS_STATIC_CAST(PRInt32*, aVariant.val.p)[aIndex] = value;          else            NS_STATIC_CAST(PRUint16*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_I64:    case nsXPTType::T_U32:  // C++ unsigned int <=> Java long    {      LOG(("long\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.i64 = env->CallLongMethod(aParam, longValueMID);      } else { // 'inout' & 'array'        jlong value;        if (aParam) {          env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.i64 = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          if (aType == nsXPTType::T_I64)            NS_STATIC_CAST(PRInt64*, aVariant.val.p)[aIndex] = value;          else            NS_STATIC_CAST(PRUint32*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_FLOAT:    {      LOG(("float\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.f = env->CallFloatMethod(aParam, floatValueMID);      } else { // 'inout' & 'array'        jfloat value;        if (aParam) {          env->GetFloatArrayRegion((jfloatArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.f = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          NS_STATIC_CAST(float*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    // XXX how do we handle unsigned 64-bit value?    case nsXPTType::T_U64:  // C++ unsigned long <=> Java double    case nsXPTType::T_DOUBLE:    {      LOG(("double\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        jdouble value = env->CallDoubleMethod(aParam, doubleValueMID);        if (aType == nsXPTType::T_DOUBLE)          aVariant.val.d = value;        else          aVariant.val.u64 = NS_STATIC_CAST(PRUint64, value);      } else { // 'inout' & 'array'        jdouble value;        if (aParam) {          env->GetDoubleArrayRegion((jdoubleArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            if (aType == nsXPTType::T_DOUBLE)              aVariant.val.d = value;            else              aVariant.val.u64 = NS_STATIC_CAST(PRUint64, value);            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          if (aType == nsXPTType::T_DOUBLE)            NS_STATIC_CAST(double*, aVariant.val.p)[aIndex] = value;          else            NS_STATIC_CAST(PRUint64*, aVariant.val.p)[aIndex] =                                                NS_STATIC_CAST(PRUint64, value);        }      }      break;    }    case nsXPTType::T_BOOL:    {      LOG(("boolean\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.b = env->CallBooleanMethod(aParam, booleanValueMID);      } else { // 'inout' & 'array'        jboolean value;        if (aParam) {          env->GetBooleanArrayRegion((jbooleanArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.b = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          NS_STATIC_CAST(PRBool*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_CHAR:    {      LOG(("char\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.c = env->CallCharMethod(aParam, charValueMID);      } else { // 'inout' & 'array'        jchar value;        if (aParam) {          env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.c = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          NS_STATIC_CAST(char*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_WCHAR:    {      LOG(("char\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.wc = env->CallCharMethod(aParam, charValueMID);      } else { // 'inout' & 'array'        jchar value;        if (aParam) {          env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.wc = value;            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          NS_STATIC_CAST(PRUnichar*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_CHAR_STR:    case nsXPTType::T_WCHAR_STR:    {      LOG(("String\n"));      jstring data = nsnull;      if (!aIsOut && !aIsArrayElement) {  // 'in'        data = (jstring) aParam;      } else if (aParam) {  // 'inout' & 'array'        data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,                                                    aIndex);      }      void* buf = nsnull;      if (data) {        jsize uniLength = env->GetStringLength(data);        if (uniLength > 0) {          if (aType == nsXPTType::T_CHAR_STR) {            jsize utf8Length = env->GetStringUTFLength(data);            buf = nsMemory::Alloc((utf8Length + 1) * sizeof(char));            if (!buf) {              rv = NS_ERROR_OUT_OF_MEMORY;              break;            }            char* char_str = NS_STATIC_CAST(char*, buf);            env->GetStringUTFRegion(data, 0, uniLength, char_str);            char_str[utf8Length] = '\0';          } else {  // if T_WCHAR_STR            buf = nsMemory::Alloc((uniLength + 1) * sizeof(jchar));            if (!buf) {              rv = NS_ERROR_OUT_OF_MEMORY;              break;            }            jchar* jchar_str = NS_STATIC_CAST(jchar*, buf);            env->GetStringRegion(data, 0, uniLength, jchar_str);            jchar_str[uniLength] = '\0';          }        } else {          // create empty string          buf = nsMemory::Alloc(2);          if (!buf) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }          ((jchar*)buf)[0] = '\0';        }      }      if (!aIsArrayElement) { // 'in' & 'inout'        aVariant.val.p = buf;        if (aIsOut) { // 'inout'          aVariant.ptr = &aVariant.val;          aVariant.SetPtrIsData();        }      } else {  // 'array'        if (aType == nsXPTType::T_CHAR_STR) {          char* str = NS_STATIC_CAST(char*, buf);          NS_STATIC_CAST(char**, aVariant.val.p)[aIndex] = str;        } else {          PRUnichar* str = NS_STATIC_CAST(PRUnichar*, buf);          NS_STATIC_CAST(PRUnichar**, aVariant.val.p)[aIndex] = str;        }      }      break;    }    case nsXPTType::T_IID:    {      LOG(("String(IID)\n"));      jstring data = nsnull;      if (!aIsOut && !aIsArrayElement) {  // 'in'        data = (jstring) aParam;      } else if (aParam) {  // 'inout' & 'array'        data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,                                                    aIndex);      }      nsID* iid = new nsID;      if (!iid) {        rv = NS_ERROR_OUT_OF_MEMORY;        break;      }      if (data) {        // extract IID string from Java string        const char* str = env->GetStringUTFChars(data, nsnull);        if (!str) {          rv = NS_ERROR_OUT_OF_MEMORY;          break;        }        // parse string into IID object        iid->Parse(str);        env->ReleaseStringUTFChars(data, str);      } else {        *iid = nullID;      }      if (!aIsArrayElement) { // 'in' & 'inout'        aVariant.val.p = iid;        if (aIsOut) { // 'inout'          aVariant.ptr = &aVariant.val;          aVariant.SetPtrIsData();        }      } else {  // 'array'        NS_STATIC_CAST(nsID**, aVariant.val.p)[aIndex] = iid;      }      break;    }    case nsXPTType::T_INTERFACE:    case nsXPTType::T_INTERFACE_IS:    {      LOG(("nsISupports\n"));      jobject java_obj = nsnull;      if (!aIsOut && !aIsArrayElement) {  // 'in'        java_obj = (jobject) aParam;      } else if (aParam) {  // 'inout' & 'array'        java_obj = (jobject) env->GetObjectArrayElement((jobjectArray) aParam,                                                        aIndex);      }      nsISupports* xpcom_obj;      if (java_obj) {        // If the requested interface is nsIWeakReference, then we look for or        // create a stub for the nsISupports interface.  Then we create a weak        // reference from that stub.        PRBool isWeakRef;        nsID iid;        if (aIID.Equals(NS_GET_IID(nsIWeakReference))) {          isWeakRef = PR_TRUE;          iid = NS_GET_IID(nsISupports);        } else {          isWeakRef = PR_FALSE;          iid = aIID;        }        PRBool isXPTCStub;        rv = GetNewOrUsedXPCOMObject(env, java_obj, iid, &xpcom_obj,                                     &isXPTCStub);        if (NS_FAILED(rv))          break;        // If the function expects a weak reference, then we need to        // create it here.        if (isWeakRef) {          if (isXPTCStub) {            nsJavaXPTCStub* stub = NS_STATIC_CAST(nsJavaXPTCStub*,                                                 NS_STATIC_CAST(nsXPTCStubBase*,                                                                xpcom_obj));            nsJavaXPTCStubWeakRef* weakref;            weakref = new nsJavaXPTCStubWeakRef(env, java_obj, stub);            if (!weakref) {              rv = NS_ERROR_OUT_OF_MEMORY;              break;            }            NS_RELEASE(xpcom_obj);            xpcom_obj = weakref;            NS_ADDREF(xpcom_obj);          } else { // if is native XPCOM object            nsCOMPtr<nsISupportsWeakReference> supportsweak =                                                   do_QueryInterface(xpcom_obj);            if (supportsweak) {              nsWeakPtr weakref;              supportsweak->GetWeakReference(getter_AddRefs(weakref));              NS_RELEASE(xpcom_obj);              xpcom_obj = weakref;              NS_ADDREF(xpcom_obj);            } else {              xpcom_obj = nsnull;            }          }        }      } else {        xpcom_obj = nsnull;      }      if (!aIsArrayElement) { // 'in' & 'inout'        aVariant.val.p = xpcom_obj;        aVariant.SetValIsInterface();        if (aIsOut) { // 'inout'          aVariant.ptr = &aVariant.val;          aVariant.SetPtrIsData();        }      } else {  // 'array'        NS_STATIC_CAST(nsISupports**, aVariant.val.p)[aIndex] = xpcom_obj;      }      break;    }    case nsXPTType::T_ASTRING:    case nsXPTType::T_DOMSTRING:    {      LOG(("String\n"));      jstring data = nsnull;      if (!aIsOut && !aIsArrayElement) {  // 'in'        data = (jstring) aParam;      } else if (aParam) {  // 'inout' & 'array'        data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,                                                    aIndex);      }      nsAString* str;      if (data) {        str = jstring_to_nsAString(env, data);        if (!str) {          rv = NS_ERROR_OUT_OF_MEMORY;          break;        }      } else {        str = nsnull;      }      if (!aIsArrayElement) { // 'in' & 'inout'        aVariant.val.p = str;        aVariant.SetValIsDOMString();        if (aIsOut) { // 'inout'          aVariant.ptr = &aVariant.val;          aVariant.SetPtrIsData();        }      } else {  // 'array'        NS_STATIC_CAST(nsAString**, aVariant.val.p)[aIndex] = str;      }      break;    }    case nsXPTType::T_UTF8STRING:    case nsXPTType::T_CSTRING:    {      LOG(("StringUTF\n"));      jstring data = nsnull;      if (!aIsOut && !aIsArrayElement) {  // 'in'        data = (jstring) aParam;      } else if (aParam) {  // 'inout' & 'array'        data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,                                                    aIndex);      }      nsACString* str;      if (data) {        str = jstring_to_nsACString(env, data);        if (!str) {          rv = NS_ERROR_OUT_OF_MEMORY;          break;        }      } else {        str = nsnull;      }      if (!aIsArrayElement) { // 'in' & 'inout'        aVariant.val.p = str;        if (aType == nsXPTType::T_CSTRING) {          aVariant.SetValIsCString();        } else {          aVariant.SetValIsUTF8String();        }        if (aIsOut) { // 'inout'          aVariant.ptr = &aVariant.val;          aVariant.SetPtrIsData();        }      } else {  // 'array'        NS_STATIC_CAST(nsACString**, aVariant.val.p)[aIndex] = str;      }      break;    }    // handle "void *" as an "int" in Java    case nsXPTType::T_VOID:    {      LOG(("int (void*)\n"));      if (!aIsOut && !aIsArrayElement) {  // 'in'        aVariant.val.p = (void*) env->CallIntMethod(aParam, intValueMID);      } else { // 'inout' & 'array'        jint value;        if (aParam) {          env->GetIntArrayRegion((jintArray) aParam, aIndex, 1, &value);        }        if (aIsOut) { // 'inout'          if (aParam) {            aVariant.val.p = NS_REINTERPRET_CAST(void*, value);            aVariant.ptr = &aVariant.val;          } else {            aVariant.ptr = nsnull;          }          aVariant.SetPtrIsData();        } else {  // 'array'          NS_STATIC_CAST(PRUint32*, aVariant.val.p)[aIndex] = value;        }      }      break;    }    case nsXPTType::T_ARRAY:    {      jobject sourceArray = nsnull;      if (!aIsOut) {  // 'in'        sourceArray = aParam;      } else if (aParam) {  // 'inout'        jobjectArray array = NS_STATIC_CAST(jobjectArray, aParam);        sourceArray = env->GetObjectArrayElement(array, 0);      }      if (sourceArray) {        rv = CreateNativeArray(aArrayType, aArraySize, &aVariant.val.p);        for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {          rv = SetupParams(env, sourceArray, aArrayType, PR_FALSE, aIID, 0, 0,                           PR_TRUE, i, aVariant);        }      }      if (aIsOut) { // 'inout'        aVariant.ptr = &aVariant.val.p;        aVariant.SetPtrIsData();      }      break;    }    default:      NS_WARNING("unexpected parameter type");      return NS_ERROR_UNEXPECTED;  }  return rv;}