Main Page   Compound List   File List   Compound Members   File Members  

TclXPCOMComponent.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * The contents of this file are subject to the Mozilla Public License Version
00004  * 1.1 (the "License"); you may not use this file except in compliance with
00005  * the License. You may obtain a copy of the License at
00006  * http://www.mozilla.org/MPL/
00007  *
00008  * Software distributed under the License is distributed on an "AS IS" basis,
00009  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00010  * for the specific language governing rights and limitations under the
00011  * License.
00012  *
00013  * The Original Code is TclXPCOM.
00014  * 
00015  * The Initial Developer of the Original Code is Mark Follett.
00016  * Portions created by Mark Follett are Copyright (C) 2001-2002
00017  * Mark Follett.  All Rights Reserved.
00018  * 
00019  * Contributor(s):
00020  *     Mark Follett <mef123@myrealbox.com> (Original Author)
00021  *
00022  * Alternatively, the contents of this file may be used under the terms of
00023  * either the GNU General Public License Version 2 or later (the "GPL"), or
00024  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00025  * in which case the provisions of the GPL or the LGPL are applicable instead
00026  * of those above. If you wish to allow use of your version of this file only
00027  * under the terms of either the GPL or the LGPL, and not to allow others to
00028  * use your version of this file under the terms of the MPL, indicate your
00029  * decision by deleting the provisions above and replace them with the notice
00030  * and other provisions required by the GPL or the LGPL. If you do not delete
00031  * the provisions above, a recipient may use your version of this file under
00032  * the terms of any one of the MPL, the GPL or the LGPL.
00033  */
00034 
00040 #include "TclXPCOMPrivate.h"
00041 
00042 
00048 void
00049 InterpDeletedCallback(
00050     ClientData  clientData,
00051     Tcl_Interp *interp     
00052 )
00053 {
00054     NS_PRECONDITION(clientData, "null pointer");
00055     NS_PRECONDITION(interp, "null pointer");
00056 
00057     char str[128];
00058     sprintf(str, "Interpreter for Component %p has been killed", clientData);
00059     NS_WARNING(str);
00060     
00061     ((TclXPCOMComponent *)clientData)->interp = NULL;
00062 }
00063 
00064 
00070 TclXPCOMComponent *
00071 NewTclXPCOMComponent(
00072     Tcl_Interp   *interp, 
00073     Tcl_ThreadId  thread, 
00074     ClassInfo    *cinfo   
00075 )
00076 {
00077     int i;
00078     TclXPCOMComponent *component;
00079 
00080     NS_PRECONDITION(interp, "null pointer");
00081     // no precondition on thread
00082     NS_PRECONDITION(cinfo, "null pointer");
00083 
00084     component = (TclXPCOMComponent *)memmgr->Alloc(sizeof(TclXPCOMComponent));
00085 
00086     component->stubs = (TclXPCOMStub **)memmgr->Alloc(sizeof(TclXPCOMStub *) * cinfo->signature.infocount);
00087 
00088     for (i = 0; i < cinfo->signature.infocount; i++)
00089     {
00090         component->stubs[i] = new TclXPCOMStub(cinfo->signature.infolist[i]);
00091     }
00092 
00093     component->refcount   = 0;
00094     component->interp     = interp;
00095     component->thread     = thread;
00096     component->cinfo      = cinfo;
00097     component->destructor = NULL;
00098     component->nesting    = 0;
00099 
00100     for (i = 0; i < cinfo->signature.infocount; i++)
00101     {
00102         component->stubs[i]->component = component;
00103     }
00104 
00105     Tcl_CallWhenDeleted(interp, InterpDeletedCallback, (ClientData)component);
00106 
00107     return component;
00108 }
00109 
00110 
00114 void
00115 UnsetDestructorBinding(
00116     TclXPCOMComponent *component 
00117 )
00118 {
00119     NS_PRECONDITION(component, "null pointer");
00120 
00121     if (component->destructor)
00122     {
00123         Tcl_DecrRefCount(component->destructor);
00124         component->destructor = NULL;
00125     }
00126 }
00127 
00128 
00133 void
00134 SetDestructorBinding(
00135     TclXPCOMComponent *component,
00136     Tcl_Obj           *script    
00137 )
00138 {
00139     NS_PRECONDITION(component, "null pointer");
00140     NS_PRECONDITION(script, "null pointer");
00141 
00142     if (component->destructor)
00143     {
00144         UnsetDestructorBinding(component);
00145     }
00146 
00147     component->destructor = script;
00148     Tcl_IncrRefCount(component->destructor);
00149 }
00150 
00151 
00155 void
00156 FreeTclXPCOMComponent(
00157     TclXPCOMComponent *component 
00158 )
00159 {
00160     int i;
00161 
00162     NS_PRECONDITION(component, "null pointer");
00163 
00164     if (component->interp)
00165     {
00166         Tcl_DontCallWhenDeleted(component->interp, InterpDeletedCallback, (ClientData)component);
00167     }
00168 
00169     UnsetDestructorBinding(component);
00170 
00171     for (i = 0; i < component->cinfo->signature.infocount; i++)
00172     {
00173         delete component->stubs[i];
00174     }
00175 
00176     memmgr->Free(component->stubs);
00177 }
00178 
00179 
00189 int
00190 BindScript(
00191     Tcl_Interp        *interp,    
00192     TclXPCOMComponent *component, 
00193     Tcl_Obj           *identifier,
00194     Tcl_Obj           *script,    
00195     int                flags      
00196 )
00197 {
00198     int rv;
00199     int i;
00200     int length;
00201 
00202     int index;
00203     PRUint16 identifiercount;
00204     PRUint16 methodindex, getterindex, setterindex;
00205 
00206     nsIInterfaceInfo *info;
00207     IdentifierInfo       *idinfo;
00208     ClassIdentifierInfo  *identifiers;
00209 
00210     NS_PRECONDITION(interp, "null pointer");
00211     NS_PRECONDITION(component, "null pointer");
00212     NS_PRECONDITION(identifier, "null pointer");
00213     NS_PRECONDITION(script, "null pointer");
00214     NS_PRECONDITION(!(flags & ~(FORCE_HIDDEN | FORCE_NOTXPCOM | FORCE_NOTSCRIPTABLE)), "invalid flags");
00215 
00216     if (strlen(Tcl_GetString(identifier)) == 0)
00217     {
00218         if (component->destructor)
00219         {
00220             Tcl_ResetResult(interp);
00221             Tcl_AppendResult(interp, "destructor is already bound", NULL);
00222             return TCL_ERROR;
00223         }
00224 
00225         SetDestructorBinding(component, script);
00226         return TCL_OK;
00227     }
00228 
00229     rv = Tcl_ListObjLength(interp, script, &length);
00230     if (rv != TCL_OK)
00231     {
00232         Tcl_ResetResult(interp);
00233         Tcl_AppendResult(interp, "binding \"", Tcl_GetString(script), "\" is not a valid list", NULL);
00234         return TCL_ERROR;
00235     }
00236 
00237     identifiercount = component->cinfo->attributecount + component->cinfo->methodcount;
00238     if (identifiercount)
00239     {
00240         identifiers = (ClassIdentifierInfo *)memmgr->Alloc(sizeof(ClassIdentifierInfo) * identifiercount + sizeof(char *));
00241         memcpy(&identifiers[0], &component->cinfo->attributes[0], sizeof(ClassIdentifierInfo) * component->cinfo->attributecount);
00242         memcpy(&identifiers[component->cinfo->attributecount], &component->cinfo->methods[0], sizeof(ClassIdentifierInfo) * component->cinfo->methodcount);
00243         identifiers[identifiercount].idinfo.name = NULL;
00244 
00245         rv = Tcl_GetIndexFromObjStruct(interp, identifier, (char **)&identifiers[0].idinfo.name, sizeof(ClassIdentifierInfo), "method or attribute", 0, &index);
00246 
00247         if (rv == TCL_OK)
00248         {
00249             idinfo = &identifiers[index].idinfo;
00250             info = identifiers[index].info;
00251             rv = TclXPCOM_CheckInterfaceIsReflectable(interp, info, flags);
00252         }
00253 
00254         if (rv == TCL_OK)
00255         {
00256             if ((idinfo->type & INTERFACEINFO_METHOD)
00257                 || (idinfo->type & INTERFACEINFO_GETTER))
00258             {
00259                 methodindex = idinfo->indices.methodindex;
00260                 getterindex = idinfo->indices.attributeindices.getterindex;
00261                 rv = TclXPCOM_CheckMethodIsReflectable(interp, info, methodindex, flags);
00262             }
00263         }
00264 
00265         if (rv == TCL_OK)
00266         {
00267             if (idinfo->type & INTERFACEINFO_SETTER)
00268             {
00269                 setterindex = idinfo->indices.attributeindices.setterindex;
00270                 rv = TclXPCOM_CheckMethodIsReflectable(interp, info, setterindex, flags);
00271             }
00272         }
00273 
00274         if (rv == TCL_OK)
00275         {
00276             if (idinfo->type & INTERFACEINFO_METHOD)
00277             {
00278                 for (i = 0; i < component->cinfo->signature.infocount; i++)
00279                 {
00280                     if (IsInInterface(info, component->cinfo->signature.infolist[i]))
00281                     {
00282                         component->stubs[i]->SetBinding(methodindex, script);
00283                     }
00284                 }
00285             } else
00286             {
00287                 for (i = 0; i < component->cinfo->signature.infocount; i++)
00288                 {
00289                     if (IsInInterface(info, component->cinfo->signature.infolist[i]))
00290                     {
00291                         if (idinfo->type & INTERFACEINFO_GETTER)
00292                         {
00293                             component->stubs[i]->SetBinding(getterindex, script);
00294                         }
00295 
00296                         if (idinfo->type & INTERFACEINFO_SETTER)
00297                         {
00298                             component->stubs[i]->SetBinding(setterindex, script);
00299                         }
00300                     }
00301                 }
00302             }
00303         }
00304 
00305         memmgr->Free(identifiers);
00306         return rv;
00307     } else
00308     {
00309         Tcl_AppendResult(interp, "no methods or attributes in class", NULL);
00310         return TCL_ERROR;
00311     }
00312 }
00313 

Generated on Fri Jun 14 23:25:50 2002 for TclXPCOM by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002