00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "TclXPCOMPrivate.h"
00036
00037
00038 nsIID nsisupportsweakreference_iid = NS_ISUPPORTSWEAKREFERENCE_IID;
00039
00045 TclXPCOMStub::TclXPCOMStub(
00046 nsIInterfaceInfo *interfaceinfo
00047 )
00048 {
00049 PRUint16 methodcount;
00050
00051 NS_PRECONDITION(interfaceinfo, "null pointer");
00052
00053 info = interfaceinfo;
00054 NS_ADDREF(info);
00055
00056 info->GetMethodCount(&methodcount);
00057
00058 if (methodcount)
00059 {
00060 bindings = (Tcl_Obj **)memmgr->Alloc(sizeof(Tcl_Obj *) * methodcount);
00061 memset(bindings, 0, sizeof(Tcl_Obj *) * methodcount);
00062 } else
00063 {
00064 bindings = NULL;
00065 }
00066 }
00067
00068
00072 TclXPCOMStub::~TclXPCOMStub(void)
00073 {
00074 PRUint16 methodcount, i;
00075
00076 info->GetMethodCount(&methodcount);
00077
00078 for (i = 0; i < methodcount; i++)
00079 {
00080 UnsetBinding(i);
00081 }
00082
00083 if (bindings)
00084 {
00085 memmgr->Free(bindings);
00086 }
00087
00088 NS_RELEASE(info);
00089 }
00090
00091
00097 void
00098 TclXPCOMStub::SetBinding(
00099 PRUint16 methodindex,
00100 Tcl_Obj *script
00101 )
00102 {
00103 NS_PRECONDITION(script, "null pointer");
00104
00105 if (bindings[methodindex])
00106 {
00107 UnsetBinding(methodindex);
00108 }
00109
00110 bindings[methodindex] = script;
00111 Tcl_IncrRefCount(script);
00112 }
00113
00114
00118 void
00119 TclXPCOMStub::UnsetBinding(
00120 PRUint16 methodindex
00121 )
00122 {
00123 if (bindings[methodindex])
00124 {
00125 Tcl_DecrRefCount(bindings[methodindex]);
00126 bindings[methodindex] = NULL;
00127 }
00128 }
00129
00130
00136 Tcl_Obj *
00137 TclXPCOMStub::GetBinding(
00138 PRUint16 methodindex
00139 )
00140 {
00141 return bindings[methodindex];
00142 }
00143
00144
00150 NS_IMETHODIMP
00151 TclXPCOMStub::GetInterfaceInfo(
00152 nsIInterfaceInfo **interfaceinfo
00153 )
00154 {
00155 NS_PRECONDITION(interfaceinfo, "null pointer");
00156
00157 NS_ADDREF(info);
00158 *interfaceinfo = info;
00159 return NS_OK;
00160 }
00161
00162
00168 NS_IMETHODIMP
00169 TclXPCOMStub::CallMethod(
00170 PRUint16 methodIndex,
00171 const nsXPTMethodInfo *info,
00172 nsXPTCMiniVariant *params
00173 )
00174 {
00175
00176 NS_PRECONDITION(info, "null pointer");
00177 NS_PRECONDITION(params, "null pointer");
00178
00179 if (!component->interp)
00180 {
00181
00182
00183 printf("Stub invocation failed cuz the interp is dead!\n");
00184 return NS_ERROR_FAILURE;
00185 }
00186
00187 if (bindings[methodIndex])
00188 {
00189
00190 NS_ASSERTION((component->thread == Tcl_GetCurrentThread()), "attempt to invoke a component from the wrong thread");
00191
00192 return TclXPCOM_CallMethod(component->interp, params, (nsISupports *)(nsXPTCStubBase *)this, this->info, methodIndex, bindings[methodIndex]);
00193 } else
00194 {
00195 return NS_ERROR_NOT_IMPLEMENTED;
00196 }
00197 }
00198
00199
00205 NS_IMETHODIMP
00206 TclXPCOMStub::QueryInterface(
00207 REFNSIID aIID,
00208 void **aInstancePtr
00209 )
00210 {
00211 int i;
00212 nsresult res;
00213 nsISupports *isupports;
00214 nsXPTCMiniVariant params[2];
00215
00216
00217
00218
00219 if (!aInstancePtr)
00220 {
00221 return NS_ERROR_NULL_POINTER;
00222 }
00223
00224 if (bindings[0] && component->interp && !component->nesting)
00225 {
00226 params[0].val.p = (void *)&aIID;
00227 params[1].val.p = aInstancePtr;
00228
00229
00230 NS_ASSERTION((component->thread == Tcl_GetCurrentThread()), "attempt to invoke a component from the wrong thread");
00231
00232 component->nesting = 1;
00233 res = TclXPCOM_CallMethod(component->interp, params, (nsISupports *)(nsXPTCStubBase *)this, this->info, 0, bindings[0]);
00234 component->nesting = 0;
00235 return res;
00236 }
00237
00238 for (i = 0; i < component->cinfo->signature.infocount; i++)
00239 {
00240 if (isInInterface(component->stubs[i]->info, (nsIID *)&aIID))
00241 {
00242 isupports = (nsISupports *)(nsXPTCStubBase *)component->stubs[i];
00243 NS_ADDREF(isupports);
00244 *aInstancePtr = isupports;
00245 return NS_OK;
00246 }
00247 }
00248
00249
00250 if (aIID.Equals(nsisupportsweakreference_iid))
00251 {
00252 isupports = NS_STATIC_CAST(nsISupportsWeakReference*, this);
00253 NS_ADDREF(isupports);
00254 *aInstancePtr = isupports;
00255 return NS_OK;
00256 }
00257
00258 *aInstancePtr = NULL;
00259 return NS_ERROR_NO_INTERFACE;
00260 }
00261
00262
00268 NS_IMETHODIMP_(nsrefcnt)
00269 TclXPCOMStub::AddRef(void)
00270 {
00271 nsrefcnt count;
00272
00273 NS_PRECONDITION(PRInt32(component->refcount) >= 0, "illegal refcnt");
00274
00275 count = PR_AtomicIncrement((PRInt32*)&component->refcount);
00276 NS_LOG_ADDREF(this, count, "TclXPCOMStub", sizeof(*this));
00277
00278 char str[128];
00279 sprintf(str, "Addrefing Component %p, Refcount: %d", component, count);
00280 NS_WARNING(str);
00281
00282 return count;
00283 }
00284
00285
00291 NS_IMETHODIMP_(nsrefcnt)
00292 TclXPCOMStub::Release(void)
00293 {
00294 int rv;
00295 nsrefcnt count;
00296 Tcl_SavedResult savedresult;
00297
00298 NS_PRECONDITION(0 != component->refcount, "dup release");
00299
00300 count = PR_AtomicDecrement((PRInt32 *)&component->refcount);
00301 NS_LOG_RELEASE(this, count, "TclXPCOMStub");
00302
00303 char str[128];
00304 sprintf(str, "Releasing Component %p, Refcount: %d", component, count);
00305 NS_WARNING(str);
00306
00307 if (0 == count) {
00308 component->refcount = 1;
00309
00310
00311
00312
00313
00314
00315 if (component->destructor && component->interp)
00316 {
00317
00318
00319 NS_ASSERTION((component->thread == Tcl_GetCurrentThread()), "attempt to invoke a component from the wrong thread");
00320 Tcl_Preserve(component->interp);
00321 Tcl_SaveResult(component->interp, &savedresult);
00322 rv = Tcl_EvalObjEx(component->interp, component->destructor, TCL_EVAL_GLOBAL);
00323 if (rv != TCL_OK)
00324 {
00325 Tcl_AddObjErrorInfo(component->interp, "\nwhile executing component destructor:\n\"", -1);
00326 Tcl_AddObjErrorInfo(component->interp, Tcl_GetString(component->destructor), -1);
00327 Tcl_AddObjErrorInfo(component->interp, "\"", -1);
00328 TclXPCOM_BackgroundError(component->interp);
00329 }
00330
00331 Tcl_RestoreResult(component->interp, &savedresult);
00332 Tcl_Release(component->interp);
00333 }
00334
00335 if (component->refcount == 1)
00336 {
00337 sprintf(str, "Destroyed Component %p", component);
00338 NS_WARNING(str);
00339
00340 FreeTclXPCOMComponent(component);
00341
00342 return 0;
00343 } else
00344 {
00345 component->refcount--;
00346 return component->refcount;
00347 }
00348 }
00349 return count;
00350 }
00351
00352