Back to index

lightning-sunbird  0.9+nobinonly
xptiprivate.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Mike McCabe <mccabe@netscape.com>
00024  *   John Bandhauer <jband@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or 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 /* Library-private header for Interface Info system. */
00041 
00042 #ifndef xptiprivate_h___
00043 #define xptiprivate_h___
00044 
00045 #include "nscore.h"
00046 #include "nsISupports.h"
00047 
00048 // this after nsISupports, to pick up IID
00049 // so that xpt stuff doesn't try to define it itself...
00050 #include "xpt_struct.h"
00051 #include "xpt_xdr.h"
00052 
00053 #include "nsIInterfaceInfo.h"
00054 #include "nsIInterfaceInfoManager.h"
00055 #include "xptinfo.h"
00056 #include "nsIXPTLoader.h"
00057 
00058 #include "nsIServiceManager.h"
00059 #include "nsILocalFile.h"
00060 #include "nsIDirectoryService.h"
00061 #include "nsDirectoryServiceDefs.h"
00062 #include "nsAppDirectoryServiceDefs.h"
00063 #include "nsIWeakReference.h"
00064 
00065 #include "nsCRT.h"
00066 #include "nsMemory.h"
00067 
00068 #include "nsISupportsArray.h"
00069 #include "nsSupportsArray.h"
00070 #include "nsInt64.h"
00071 
00072 #include "nsQuickSort.h"
00073 
00074 #include "nsXPIDLString.h"
00075 
00076 #include "nsIInputStream.h"
00077 
00078 #include "nsAutoLock.h"
00079 
00080 #include "pldhash.h"
00081 #include "plstr.h"
00082 #include "prprf.h"
00083 #include "prio.h"
00084 #include "prtime.h"
00085 #include "prenv.h"
00086 
00087 #include <stdio.h>
00088 #include <stdarg.h>
00089 
00090 /***************************************************************************/
00091 
00092 #if 0 && defined(DEBUG_jband)
00093 #define LOG_RESOLVE(x) printf x
00094 #define LOG_LOAD(x)    printf x
00095 #define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
00096 #else
00097 #define LOG_RESOLVE(x) ((void)0)
00098 #define LOG_LOAD(x)    ((void)0)
00099 #define LOG_AUTOREG(x) xptiInterfaceInfoManager::WriteToLog x
00100 #endif
00101 
00102 #if 1 && defined(DEBUG_jband)
00103 #define SHOW_INFO_COUNT_STATS
00104 #endif
00105 
00106 /***************************************************************************/
00107 
00108 class xptiFile;
00109 class xptiInterfaceInfo;
00110 class xptiInterfaceInfoManager;
00111 class xptiInterfaceEntry;
00112 class xptiInterfaceGuts;
00113 class xptiTypelibGuts;
00114 class xptiWorkingSet;
00115 
00116 /***************************************************************************/
00117 
00118 class xptiTypelib
00119 {
00120 public:
00121     // No ctors or dtors so that we can be in a union in xptiInterfaceInfo.
00122     // Allow automatic shallow copies.
00123 
00124     uint16 GetFileIndex()    const {return mFileIndex;}
00125     uint16 GetZipItemIndex() const {return mZipItemIndex;}
00126 
00127     enum {NOT_ZIP = 0xffff};
00128 
00129     PRBool IsZip() const {return mZipItemIndex != NOT_ZIP;}
00130 
00131     void Init(uint16 aFileIndex, uint16 aZipItemIndex = NOT_ZIP)
00132         {mFileIndex = aFileIndex; mZipItemIndex = aZipItemIndex;}
00133 
00134     PRBool Equals(const xptiTypelib& r) const
00135         {return mFileIndex == r.mFileIndex && 
00136                 mZipItemIndex == r.mZipItemIndex;}
00137 
00138 private:
00139     uint16 mFileIndex;
00140     uint16 mZipItemIndex;
00141 };
00142 
00143 /***************************************************************************/
00144 
00145 // No virtuals.
00146 // These are always constructed in the struct arena using placement new.
00147 // dtor need not be called.
00148 
00149 class xptiTypelibGuts
00150 {
00151 public:
00152     static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
00153                                     xptiWorkingSet* aWorkingSet);
00154 
00155     XPTHeader*          GetHeader()           {return mHeader;}
00156     PRUint16            GetEntryCount() const {return mHeader->num_interfaces;}
00157     
00158     void                SetEntryAt(PRUint16 i, xptiInterfaceEntry* ptr)
00159     {
00160         NS_ASSERTION(mHeader,"bad state!");
00161         NS_ASSERTION(i < GetEntryCount(),"bad param!");
00162         mEntryArray[i] = ptr;
00163     }        
00164 
00165     xptiInterfaceEntry* GetEntryAt(PRUint16 i) const
00166     {
00167         NS_ASSERTION(mHeader,"bad state!");
00168         NS_ASSERTION(i < GetEntryCount(),"bad param!");
00169         return mEntryArray[i];
00170     }        
00171 
00172 private:
00173     xptiTypelibGuts(); // not implemented
00174     xptiTypelibGuts(XPTHeader* aHeader);
00175     ~xptiTypelibGuts() {}
00176     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
00177 
00178 private:
00179     XPTHeader*           mHeader;        // hold pointer into arena
00180     xptiInterfaceEntry*  mEntryArray[1]; // Always last. Sized to fit.
00181 };
00182 
00183 /***************************************************************************/
00184 
00185 class xptiFile
00186 {
00187 public:
00188     const nsInt64&          GetSize()      const {return mSize;}
00189     const nsInt64&          GetDate()      const {return mDate;}
00190     const char*             GetName()      const {return mName;}
00191     const PRUint32          GetDirectory() const {return mDirectory;}
00192           xptiTypelibGuts*  GetGuts()            {return mGuts;}
00193 
00194     xptiFile();
00195 
00196     xptiFile(const nsInt64&  aSize,
00197              const nsInt64&  aDate,
00198              PRUint32        aDirectory,
00199              const char*     aName,
00200              xptiWorkingSet* aWorkingSet);
00201 
00202     xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
00203 
00204     ~xptiFile();
00205 
00206     PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
00207 
00208     PRBool Equals(const xptiFile& r) const
00209     {
00210         return  mDirectory == r.mDirectory &&
00211                 mSize == r.mSize &&
00212                 mDate == r.mDate &&
00213                 0 == PL_strcmp(mName, r.mName);
00214     }
00215 
00216     xptiFile(const xptiFile& r) {CopyFields(r);}
00217     xptiFile& operator= (const xptiFile& r)
00218     {
00219         if(this != &r)
00220             CopyFields(r);
00221         return *this;
00222     }
00223 
00224 private:
00225     void CopyFields(const xptiFile& r)
00226     {
00227 #ifdef DEBUG
00228         // If 'this' has a workingset then it better match that of the assigner. 
00229         NS_ASSERTION(!mDEBUG_WorkingSet || 
00230                      mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
00231                      "illegal xptiFile assignment");
00232         mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
00233 #endif
00234 
00235         mSize      = r.mSize;
00236         mDate      = r.mDate;
00237         mName      = r.mName;
00238         mDirectory = r.mDirectory;
00239         mGuts      = r.mGuts;
00240     }
00241 
00242 private:
00243 #ifdef DEBUG
00244     xptiWorkingSet*  mDEBUG_WorkingSet;
00245 #endif
00246     nsInt64          mSize;
00247     nsInt64          mDate;
00248     const char*      mName; // hold pointer into arena from initializer
00249     xptiTypelibGuts* mGuts; // hold pointer into arena
00250     PRUint32         mDirectory;
00251 };
00252 
00253 /***************************************************************************/
00254 
00255 class xptiZipItem
00256 {
00257 public:
00258     const char*             GetName() const {return mName;}
00259           xptiTypelibGuts*  GetGuts()       {return mGuts;}
00260 
00261     xptiZipItem();
00262 
00263     xptiZipItem(const char*     aName,
00264                 xptiWorkingSet* aWorkingSet);
00265 
00266     xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
00267 
00268     ~xptiZipItem();
00269 
00270     PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
00271 
00272     PRBool Equals(const xptiZipItem& r) const
00273     {
00274         return 0 == PL_strcmp(mName, r.mName);
00275     }
00276 
00277     xptiZipItem(const xptiZipItem& r) {CopyFields(r);}
00278     xptiZipItem& operator= (const xptiZipItem& r)
00279     {
00280         if(this != &r)
00281             CopyFields(r);
00282         return *this;
00283     }
00284 
00285 private:
00286     void CopyFields(const xptiZipItem& r)
00287     {
00288 #ifdef DEBUG
00289         // If 'this' has a workingset then it better match that of the assigner. 
00290         NS_ASSERTION(!mDEBUG_WorkingSet || 
00291                      mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
00292                      "illegal xptiFile assignment");
00293         mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
00294 #endif
00295 
00296         mName = r.mName;
00297         mGuts = r.mGuts;
00298     }
00299 
00300 private:
00301 #ifdef DEBUG
00302     xptiWorkingSet*  mDEBUG_WorkingSet;
00303 #endif
00304     const char*      mName; // hold pointer into arena from initializer
00305     xptiTypelibGuts* mGuts; // hold pointer into arena
00306 };
00307 
00308 /***************************************************************************/
00309 
00310 class xptiWorkingSet
00311 {
00312 public:
00313     xptiWorkingSet(); // not implmented
00314     xptiWorkingSet(nsISupportsArray* aDirectories);
00315     ~xptiWorkingSet();
00316     
00317     PRBool IsValid() const;
00318 
00319     void InvalidateInterfaceInfos();
00320     void ClearHashTables();
00321     void ClearFiles();
00322     void ClearZipItems();
00323 
00324     // utility methods...
00325 
00326     xptiTypelibGuts* GetTypelibGuts(const xptiTypelib& typelib)
00327     { 
00328         return typelib.IsZip() ?
00329             GetZipItemAt(typelib.GetZipItemIndex()).GetGuts() :
00330             GetFileAt(typelib.GetFileIndex()).GetGuts();
00331     }
00332     
00333     enum {NOT_FOUND = 0xffffffff};
00334 
00335     // FileArray stuff...
00336 
00337     PRUint32  GetFileCount() const {return mFileCount;}
00338     PRUint32  GetFileFreeSpace()
00339         {return mFileArray ? mMaxFileCount - mFileCount : 0;} 
00340     
00341     PRUint32 FindFile(PRUint32 dir, const char* name);
00342 
00343     PRUint32 GetTypelibDirectoryIndex(const xptiTypelib& typelib)
00344     {
00345         return GetFileAt(typelib.GetFileIndex()).GetDirectory();
00346     }
00347 
00348     const char* GetTypelibFileName(const xptiTypelib& typelib)
00349     {
00350         return GetFileAt(typelib.GetFileIndex()).GetName();
00351     }
00352 
00353     xptiFile& GetFileAt(PRUint32 i) const 
00354     {
00355         NS_ASSERTION(mFileArray, "bad state!");
00356         NS_ASSERTION(i < mFileCount, "bad param!");
00357         return mFileArray[i];
00358     }
00359 
00360     void SetFileAt(PRUint32 i, const xptiFile& r)
00361     { 
00362         NS_ASSERTION(mFileArray, "bad state!");
00363         NS_ASSERTION(i < mFileCount, "bad param!");
00364         mFileArray[i] = r;
00365     }
00366 
00367     void AppendFile(const xptiFile& r)
00368     { 
00369         NS_ASSERTION(mFileArray, "bad state!");
00370         NS_ASSERTION(mFileCount < mMaxFileCount, "bad param!");
00371         mFileArray[mFileCount++] = r;
00372     }
00373 
00374     PRBool NewFileArray(PRUint32 count);
00375     PRBool ExtendFileArray(PRUint32 count);
00376 
00377     // ZipItemArray stuff...
00378 
00379     PRUint32  GetZipItemCount() const {return mZipItemCount;}
00380     PRUint32  GetZipItemFreeSpace()
00381         {return mZipItemArray ? mMaxZipItemCount - mZipItemCount : 0;} 
00382 
00383     PRUint32 FindZipItemWithName(const char* name);
00384 
00385     xptiZipItem& GetZipItemAt(PRUint32 i) const 
00386     {
00387         NS_ASSERTION(mZipItemArray, "bad state!");
00388         NS_ASSERTION(i < mZipItemCount, "bad param!");
00389         return mZipItemArray[i];
00390     }
00391 
00392     void SetZipItemAt(PRUint32 i, const xptiZipItem& r)
00393     { 
00394         NS_ASSERTION(mZipItemArray, "bad state!");
00395         NS_ASSERTION(i < mZipItemCount, "bad param!");
00396         mZipItemArray[i] = r;
00397     }
00398 
00399     void AppendZipItem(const xptiZipItem& r)
00400     { 
00401         NS_ASSERTION(mZipItemArray, "bad state!");
00402         NS_ASSERTION(mZipItemCount < mMaxZipItemCount, "bad param!");
00403         mZipItemArray[mZipItemCount++] = r;
00404     }
00405 
00406     PRBool NewZipItemArray(PRUint32 count);
00407     PRBool ExtendZipItemArray(PRUint32 count);
00408 
00409     // Directory stuff...
00410 
00411     PRUint32 GetDirectoryCount();
00412     nsresult GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir);
00413     nsresult GetDirectoryAt(PRUint32 i, nsILocalFile** dir);
00414     PRBool   FindDirectory(nsILocalFile* dir, PRUint32* index);
00415     PRBool   FindDirectoryOfFile(nsILocalFile* file, PRUint32* index);
00416     PRBool   DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc);
00417 
00418     // Arena stuff...
00419 
00420     XPTArena*  GetStringArena() {return mStringArena;}
00421     XPTArena*  GetStructArena() {return mStructArena;}
00422 
00423 
00424 private:
00425     PRUint32        mFileCount;
00426     PRUint32        mMaxFileCount;
00427     xptiFile*       mFileArray;         // using new[] and delete[]
00428 
00429     PRUint32        mZipItemCount;
00430     PRUint32        mMaxZipItemCount;
00431     xptiZipItem*    mZipItemArray;      // using new[] and delete[]
00432 
00433     XPTArena*       mStringArena;
00434     XPTArena*       mStructArena;
00435 
00436     nsCOMPtr<nsISupportsArray> mDirectories;
00437 
00438 public:
00439     // XXX make these private with accessors
00440     PLDHashTable*   mNameTable;
00441     PLDHashTable*   mIIDTable;
00442     PRUint32*       mFileMergeOffsetMap;    // always in an arena
00443     PRUint32*       mZipItemMergeOffsetMap; // always in an arena
00444 };
00445 
00446 /***************************************************************************/
00447 
00448 class xptiInterfaceGuts
00449 {
00450 public:
00451     uint16                      mMethodBaseIndex;
00452     uint16                      mConstantBaseIndex;
00453     xptiInterfaceEntry*         mParent;
00454     XPTInterfaceDescriptor*     mDescriptor;
00455     xptiTypelib                 mTypelib;
00456     xptiWorkingSet*             mWorkingSet;
00457 
00458     static xptiInterfaceGuts* NewGuts(XPTInterfaceDescriptor* aDescriptor,
00459                                       const xptiTypelib&      aTypelib,
00460                                       xptiWorkingSet*         aWorkingSet)
00461     {
00462         void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
00463                                  sizeof(xptiInterfaceGuts));
00464         if(!place)
00465             return nsnull;
00466         return new(place) xptiInterfaceGuts(aDescriptor, aTypelib, aWorkingSet);
00467     }
00468 
00469 private:
00470     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
00471     xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
00472                       const xptiTypelib&      aTypelib,
00473                       xptiWorkingSet*         aWorkingSet)
00474         :   mMethodBaseIndex(0),
00475             mConstantBaseIndex(0),
00476             mParent(nsnull),
00477             mDescriptor(aDescriptor),
00478             mTypelib(aTypelib),
00479             mWorkingSet(aWorkingSet) {}
00480 
00481     ~xptiInterfaceGuts() {}
00482 };
00483 
00484 /***************************************************************************/
00485 
00486 // This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value 
00487 // and a set of bitflags in one 8bit value. See below.
00488 
00489 class xptiInfoFlags
00490 {
00491     enum {STATE_MASK = 3};
00492 public:
00493     xptiInfoFlags(uint8 n) : mData(n) {}
00494     xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
00495 
00496     static uint8 GetStateMask()
00497         {return uint8(STATE_MASK);}
00498     
00499     void Clear()
00500         {mData = 0;}
00501 
00502     uint8 GetData() const
00503         {return mData;}
00504 
00505     uint8 GetState() const 
00506         {return mData & GetStateMask();}
00507 
00508     void SetState(uint8 state) 
00509         {mData &= ~GetStateMask(); mData |= state;}                                   
00510 
00511     void SetFlagBit(uint8 flag, PRBool on) 
00512         {if(on)
00513             mData |= ~GetStateMask() & flag;
00514          else
00515             mData &= GetStateMask() | ~flag;}
00516 
00517     PRBool GetFlagBit(uint8 flag) const 
00518         {return (mData & flag) ? PR_TRUE : PR_FALSE;}
00519 
00520 private:
00521     uint8 mData;    
00522 };
00523 
00524 /****************************************************/
00525 
00526 // No virtual methods.
00527 // We always create in the struct arena and construct using "placement new".
00528 // No members need dtor calls.
00529 
00530 class xptiInterfaceEntry
00531 {
00532 public:
00533     static xptiInterfaceEntry* NewEntry(const char* name,
00534                                         int nameLength,
00535                                         const nsID& iid,
00536                                         const xptiTypelib& typelib,
00537                                         xptiWorkingSet* aWorkingSet);
00538 
00539     static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
00540                                         const xptiTypelib& typelib,
00541                                         xptiWorkingSet* aWorkingSet);
00542 
00543     enum {
00544         NOT_RESOLVED          = 0,
00545         PARTIALLY_RESOLVED    = 1,
00546         FULLY_RESOLVED        = 2,
00547         RESOLVE_FAILED        = 3
00548     };
00549     
00550     // Additional bit flags...
00551     enum {SCRIPTABLE = 4};
00552 
00553     uint8 GetResolveState() const {return mFlags.GetState();}
00554     
00555     PRBool IsFullyResolved() const 
00556         {return GetResolveState() == (uint8) FULLY_RESOLVED;}
00557 
00558     PRBool HasInterfaceRecord() const
00559         {int s = (int) GetResolveState(); 
00560          return (s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface;}
00561 
00562     const xptiTypelib&  GetTypelibRecord() const
00563         {return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
00564 
00565     xptiInterfaceGuts*  GetInterfaceGuts() const
00566         {return HasInterfaceRecord() ? mInterface : nsnull;}
00567 
00568 #ifdef DEBUG
00569     PRBool DEBUG_ScriptableFlagIsValid() const
00570         {int s = (int) GetResolveState(); 
00571          if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
00572             {
00573                 if(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags))
00574                     return GetScriptableFlag();
00575                 return !GetScriptableFlag();
00576             }
00577          return PR_TRUE;
00578         }
00579 #endif
00580 
00581     void   SetScriptableFlag(PRBool on)
00582                 {mFlags.SetFlagBit(uint8(SCRIPTABLE),on);}
00583     PRBool GetScriptableFlag() const
00584                 {return mFlags.GetFlagBit(uint8(SCRIPTABLE));}
00585 
00586     const nsID* GetTheIID()  const {return &mIID;}
00587     const char* GetTheName() const {return mName;}
00588 
00589     PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
00590         {return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
00591 
00592     PRBool PartiallyResolveLocked(XPTInterfaceDescriptor*  aDescriptor,
00593                                   xptiWorkingSet*          aWorkingSet);
00594 
00595     nsresult GetInterfaceInfo(xptiInterfaceInfo** info);
00596     PRBool   InterfaceInfoEquals(const xptiInterfaceInfo* info) const 
00597         {return info == mInfo;}
00598     
00599     void     LockedInvalidateInterfaceInfo();
00600     void     LockedInterfaceInfoDeathNotification() {mInfo = nsnull;}
00601 
00603     // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
00604 
00605     nsresult GetName(char * *aName);
00606     nsresult GetIID(nsIID * *aIID);
00607     nsresult IsScriptable(PRBool *_retval);
00608     // Except this one.
00609     //nsresult GetParent(nsIInterfaceInfo * *aParent);
00610     nsresult GetMethodCount(PRUint16 *aMethodCount);
00611     nsresult GetConstantCount(PRUint16 *aConstantCount);
00612     nsresult GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info);
00613     nsresult GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info);
00614     nsresult GetConstant(PRUint16 index, const nsXPTConstant * *constant);
00615     nsresult GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
00616     nsresult GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
00617     nsresult GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval);
00618     nsresult GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
00619     nsresult GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
00620     nsresult GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
00621     nsresult IsIID(const nsIID * IID, PRBool *_retval);
00622     nsresult GetNameShared(const char **name);
00623     nsresult GetIIDShared(const nsIID * *iid);
00624     nsresult IsFunction(PRBool *_retval);
00625     nsresult HasAncestor(const nsIID * iid, PRBool *_retval);
00626     nsresult GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid);
00627 
00629 
00630 private:
00631     xptiInterfaceEntry();   // not implemented
00632 
00633     xptiInterfaceEntry(const char* name,
00634                        size_t nameLength,
00635                        const nsID& iid,
00636                        const xptiTypelib& typelib);
00637 
00638     xptiInterfaceEntry(const xptiInterfaceEntry& r,
00639                        size_t nameLength,
00640                        const xptiTypelib& typelib);
00641     ~xptiInterfaceEntry();
00642 
00643     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
00644 
00645     void SetResolvedState(int state) 
00646         {mFlags.SetState(uint8(state));}
00647 
00648     PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
00649 
00650     // We only call these "*Locked" variants after locking. This is done to 
00651     // allow reentrace as files are loaded and various interfaces resolved 
00652     // without having to worry about the locked state.
00653 
00654     PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
00655         {return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
00656     PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
00657 
00658     // private helpers
00659 
00660     nsresult GetEntryForParam(PRUint16 methodIndex, 
00661                               const nsXPTParamInfo * param,
00662                               xptiInterfaceEntry** entry);
00663 
00664     nsresult GetTypeInArray(const nsXPTParamInfo* param,
00665                             uint16 dimension,
00666                             const XPTTypeDescriptor** type);
00667 
00668 private:
00669     nsID                    mIID;
00670     union {
00671         xptiTypelib         mTypelib;     // Valid only until resolved.
00672         xptiInterfaceGuts*  mInterface;   // Valid only after resolved.
00673     };
00674     xptiInterfaceInfo*      mInfo;        // May come and go.
00675     xptiInfoFlags           mFlags;
00676     char                    mName[1];     // Always last. Sized to fit.
00677 };
00678 
00679 struct xptiHashEntry : public PLDHashEntryHdr
00680 {
00681     xptiInterfaceEntry* value;    
00682 };
00683 
00684 /****************************************************/
00685 
00686 class xptiInterfaceInfo : public nsIInterfaceInfo
00687 {
00688 public:
00689     NS_DECL_ISUPPORTS
00690 
00691     // Use delegation to implement (most!) of nsIInterfaceInfo.
00692     NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
00693     NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
00694     NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
00695     // Except this one.
00696     NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) 
00697     {
00698         if(!EnsureResolved() || !EnsureParent())
00699             return NS_ERROR_UNEXPECTED;
00700         NS_IF_ADDREF(*aParent = mParent);
00701         return NS_OK;
00702     }
00703     NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
00704     NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
00705     NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
00706     NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
00707     NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); }
00708     NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
00709     NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
00710     NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
00711     NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
00712     NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetLengthIsArgNumberForParam(methodIndex, param, dimension, _retval); }
00713     NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
00714     NS_IMETHOD IsIID(const nsIID * IID, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
00715     NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
00716     NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
00717     NS_IMETHOD IsFunction(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
00718     NS_IMETHOD HasAncestor(const nsIID * iid, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
00719     NS_IMETHOD GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
00720 
00721 public:
00722     xptiInterfaceInfo(xptiInterfaceEntry* entry);
00723 
00724     void Invalidate() 
00725         {NS_IF_RELEASE(mParent); mEntry = nsnull;}
00726 
00727 #ifdef DEBUG
00728     static void DEBUG_ShutdownNotification();
00729 #endif
00730 
00731 private:
00732 
00733     ~xptiInterfaceInfo();
00734 
00735     // Note that mParent might still end up as nsnull if we don't have one.
00736     PRBool EnsureParent(xptiWorkingSet* aWorkingSet = nsnull)
00737     {
00738         NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
00739         return mParent || !mEntry->GetInterfaceGuts()->mParent || BuildParent();
00740     }
00741     
00742     PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
00743     {
00744         return mEntry && mEntry->EnsureResolved(aWorkingSet);
00745     }
00746 
00747     PRBool BuildParent()
00748     {
00749         NS_ASSERTION(mEntry && 
00750                      mEntry->IsFullyResolved() && 
00751                      !mParent &&
00752                      mEntry->GetInterfaceGuts()->mParent,
00753                     "bad BuildParent call");
00754         return NS_SUCCEEDED(mEntry->GetInterfaceGuts()->mParent->
00755                                         GetInterfaceInfo(&mParent));
00756     }
00757 
00758     xptiInterfaceInfo();  // not implemented
00759 
00760 private:
00761     xptiInterfaceEntry* mEntry;
00762     xptiInterfaceInfo*  mParent;
00763 };
00764 
00765 /***************************************************************************/
00766 
00767 class xptiManifest
00768 {
00769 public:
00770     static PRBool Read(xptiInterfaceInfoManager* aMgr,
00771                        xptiWorkingSet*           aWorkingSet);
00772 
00773     static PRBool Write(xptiInterfaceInfoManager* aMgr,
00774                         xptiWorkingSet*           aWorkingSet);
00775 
00776     static PRBool Delete(xptiInterfaceInfoManager* aMgr);
00777 
00778 private:
00779     xptiManifest(); // no implementation
00780 };
00781 
00782 /***************************************************************************/
00783 
00784 class xptiZipLoaderSink : public nsIXPTLoaderSink
00785 {
00786 public:
00787     xptiZipLoaderSink(xptiInterfaceInfoManager* aMgr,
00788                       xptiWorkingSet* aWorkingSet) :
00789         mManager(aMgr),
00790         mWorkingSet(aWorkingSet) {}
00791     
00792     NS_DECL_ISUPPORTS
00793     NS_DECL_NSIXPTLOADERSINK
00794     
00795 private:
00796     ~xptiZipLoaderSink() {}
00797 
00798     xptiInterfaceInfoManager* mManager;
00799     xptiWorkingSet* mWorkingSet;
00800 
00801 };
00802 
00803 class xptiZipLoader
00804 {
00805 public:
00806     xptiZipLoader();  // not implemented
00807 
00808     static XPTHeader*
00809     ReadXPTFileFromInputStream(nsIInputStream *stream,
00810                                xptiWorkingSet* aWorkingSet);
00811 
00812 };
00813 
00814 
00815 /***************************************************************************/
00816 
00817 class xptiFileType
00818 {
00819 public:
00820     enum Type {UNKNOWN = -1, XPT = 0, ZIP = 1 };
00821 
00822     static Type GetType(const char* name);
00823 
00824     static PRBool IsUnknown(const char* name)
00825         {return GetType(name) == UNKNOWN;}
00826 
00827     static PRBool IsXPT(const char* name)
00828         {return GetType(name) == XPT;}
00829 
00830     static PRBool IsZip(const char* name)
00831         {return GetType(name) == ZIP;}
00832 private:
00833     xptiFileType(); // no implementation
00834 };
00835 
00836 /***************************************************************************/
00837 
00838 // We use this is as a fancy way to open a logfile to be used within the scope
00839 // of some given function where it is instantiated.
00840  
00841 class xptiAutoLog
00842 {
00843 public:    
00844     xptiAutoLog();  // not implemented
00845     xptiAutoLog(xptiInterfaceInfoManager* mgr,
00846                 nsILocalFile* logfile, PRBool append);
00847     ~xptiAutoLog();
00848 private:
00849     void WriteTimestamp(PRFileDesc* fd, const char* msg);
00850 
00851     xptiInterfaceInfoManager* mMgr;
00852     PRFileDesc* mOldFileDesc;
00853 #ifdef DEBUG
00854     PRFileDesc* m_DEBUG_FileDesc;
00855 #endif
00856 };
00857 
00858 /***************************************************************************/
00859 
00860 class xptiInterfaceInfoManager 
00861     : public nsIInterfaceInfoSuperManager
00862 {
00863     NS_DECL_ISUPPORTS
00864     NS_DECL_NSIINTERFACEINFOMANAGER
00865     NS_DECL_NSIINTERFACEINFOSUPERMANAGER
00866 
00867     // helper
00868     PRBool 
00869     FoundZipEntry(const char* entryName,
00870                   int index,
00871                   XPTHeader* header,
00872                   xptiWorkingSet* aWorkingSet);
00873 
00874 public:
00875     static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
00876     static void FreeInterfaceInfoManager();
00877 
00878     xptiWorkingSet*  GetWorkingSet() {return &mWorkingSet;}
00879     PRFileDesc*      GetOpenLogFile() {return mOpenLogFile;}
00880     PRFileDesc*      SetOpenLogFile(PRFileDesc* fd) 
00881         {PRFileDesc* temp = mOpenLogFile; mOpenLogFile = fd; return temp;}
00882 
00883     PRBool LoadFile(const xptiTypelib& aTypelibRecord,
00884                     xptiWorkingSet* aWorkingSet = nsnull);
00885 
00886     PRBool GetApplicationDir(nsILocalFile** aDir);
00887     PRBool GetCloneOfManifestLocation(nsILocalFile** aDir);
00888 
00889     void   GetSearchPath(nsISupportsArray** aSearchPath)
00890         {NS_ADDREF(*aSearchPath = mSearchPath);}
00891 
00892     static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull) 
00893         {if(!self && !(self = GetInterfaceInfoManagerNoAddRef())) 
00894             return nsnull;
00895          return self->mResolveLock;}
00896 
00897     static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull) 
00898         {if(!self && !(self = GetInterfaceInfoManagerNoAddRef())) 
00899             return nsnull;
00900          return self->mAutoRegLock;}
00901 
00902     static PRMonitor* GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull) 
00903         {if(!self && !(self = GetInterfaceInfoManagerNoAddRef())) 
00904             return nsnull;
00905          return self->mInfoMonitor;}
00906 
00907     static void WriteToLog(const char *fmt, ...);
00908 
00909 private:
00910     ~xptiInterfaceInfoManager();
00911     xptiInterfaceInfoManager(); // not implmented
00912     xptiInterfaceInfoManager(nsISupportsArray* aSearchPath);
00913 
00914     enum AutoRegMode {
00915         NO_FILES_CHANGED = 0,
00916         FILES_ADDED_ONLY,
00917         FULL_VALIDATION_REQUIRED
00918     };
00919 
00920     PRBool IsValid();
00921 
00922     PRBool BuildFileList(nsISupportsArray* aSearchPath,
00923                          nsISupportsArray** aFileList);
00924 
00925     nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aSearchPath,
00926                                          nsISupportsArray* aFileList,
00927                                          xptiWorkingSet* aWorkingSet);
00928 
00929     XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet* aWorkingSet);
00930     
00931     AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
00932                                          nsISupportsArray* aFileList,
00933                                          xptiWorkingSet* aWorkingSet);
00934 
00935     PRBool AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
00936                                        nsISupportsArray* aFileList,
00937                                        xptiWorkingSet* aWorkingSet);
00938 
00939     PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
00940                                              nsISupportsArray* aFileList,
00941                                              xptiWorkingSet* aWorkingSet);
00942 
00943     PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
00944                                   XPTInterfaceDirectoryEntry* iface,
00945                                   const xptiTypelib& typelibRecord,
00946                                   xptiInterfaceEntry** entryAdded);
00947 
00948     PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
00949                             xptiWorkingSet* aSrcWorkingSet);
00950 
00951     void   LogStats(); 
00952 
00953     PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
00954     PRBool DEBUG_DumpFileArray(nsILocalFile** aFileArray, PRUint32 count);
00955     PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet);
00956 
00957     static PRBool BuildFileSearchPath(nsISupportsArray** aPath);
00958 
00959 private:
00960     xptiWorkingSet               mWorkingSet;
00961     nsCOMPtr<nsILocalFile>       mStatsLogFile;
00962     nsCOMPtr<nsILocalFile>       mAutoRegLogFile;
00963     PRFileDesc*                  mOpenLogFile;
00964     PRLock*                      mResolveLock;
00965     PRLock*                      mAutoRegLock;
00966     PRMonitor*                   mInfoMonitor;
00967     PRLock*                      mAdditionalManagersLock;
00968     nsSupportsArray              mAdditionalManagers;
00969     nsCOMPtr<nsISupportsArray>   mSearchPath;
00970 };
00971 
00972 /***************************************************************************/
00973 // utilities...
00974 
00975 nsresult xptiCloneLocalFile(nsILocalFile*  aLocalFile,
00976                             nsILocalFile** aCloneLocalFile);
00977 
00978 nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
00979                                      nsILocalFile** aLocalFile);
00980 
00981 #endif /* xptiprivate_h___ */