home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ODNewObj.cpp
-
- Contains: Abstract wrapper for instantiating objects by class-name
-
- Owned by: Jens Alfke
-
- Copyright: © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <8> 8/13/96 DM 1377223: instantiating parts in shell
- plugins
- <7> 7/2/96 TJ Only load fragments of the current arc.
- <6> 6/27/96 TJ T10003 Load editors of type oded also.
- <5> 6/27/96 jpa 1361886: Return error string
- <4> 6/21/96 jpa T10002: Don't check app heap space if
- NewPtr override exists.
- <3> 1/23/96 VL 1170098: Put back the CFM loading code
- removed in the last checkin. The code was
- used for debugging and getting CFM errors.
- <2> 1/16/96 VL 1170098: Removed code for GetSharedLibrary.
-
- To Do:
- */
-
-
- #ifndef _ODMEMORY_
- #include "ODMemory.h"
- #endif
-
- #ifndef _BARRAY_
- #include <BArray.h>
- #endif
-
- #ifndef SOM_ODBinding_xh
- #include <ODBindng.xh>
- #endif
-
- #ifndef _BNDNSUTL_
- #include "BndNSUtl.h"
- #endif
-
- #ifndef _ODNEWOBJ_
- #include "ODNewObj.h"
- #endif
-
- #ifndef _PLFMDEF_
- #include "PlfmDef.h"
- #endif
-
- #ifndef _MEMMGR_
- #include <MemMgr.h>
- #endif
-
- #ifndef _EXCEPT_
- #include "Except.h"
- #endif
-
- #ifndef _ODDEBUG_
- #include "ODDebug.h"
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef _PASCLSTR_
- #include <PasclStr.h>
- #endif
-
- #ifndef _UTILERRS_
- #include "UtilErrs.h"
- #endif
-
- #ifndef __SOM__
- #include <som.xh>
- #endif
-
- #ifndef SOM_SOMClassMgr_xh
- #include <somcm.xh>
- #endif
-
- #ifndef _ISOSTR_
- #include "ISOStr.h"
- #endif
-
- #ifdef _PLATFORM_MACINTOSH_
-
- #ifndef __STRINGS__
- #include <strings.h>
- #endif
-
- #include <CodeFragments.h>
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #define LOAD_UNDER_ASSUMED_NAME 1
- /* SOM requires that the library name (in the 'cfrg') be of the form "Module::ClassName".
- This obviously won't match the library's SYM file name. This causes problems for source
- level debuggers; they can't associate the two and you end up not being able to debug
- the library.
- To work around this, we give the library two names (two 'cfrg' entries), the second of
- which is just the classname. Then if the SYM file name matches the classname, we can first
- load the library by the classname, which will signal the debugger that it can link the
- library up with the similarly-named SYM file.
- Got that?? Off we go!!
- */
- #endif
-
- #ifndef _ODDEBUG_
- #include "ODDebug.h"
- #endif
-
-
- const ODSize kMinAppFreeSpace = 48 * 1024; // Only if we can't override NewPtr
- const ODSize kMinAppContigSpace = 8 * 1024;
-
- const unsigned char kMemoryLibName[] = "\pMemory Manager",
- kMemoryOverrideOnName[] = "\pMMOverridePlatform",
- kMemoryOverrideOffName[]= "\pMMEndOverridePlatform";
-
- extern "C" {
- typedef void (*MemoryOverrideProcPtr)( MMBoolean ptrs, MMBoolean handles );
- }
-
- static somTD_SOMError *gOld_SOMError;
-
-
- static ODBoolean TryToOverrideNewPtr( ODBoolean onoff );
-
-
- extern "C" {
- static void
- Temp_GetClass_SOMError( int error, corbastring filename, int linenum );
- }
-
-
- static void
- Temp_GetClass_SOMError( int error, corbastring filename, int linenum )
- {
- int severity = error % 10;
- if( severity == SOM_Fatal ) {
- WARN("Fatal SOM err %d caught during GetClass; throwing...",error);
- THROW(error);
- } else if( gOld_SOMError )
- gOld_SOMError(error,filename,linenum);
- }
-
-
- static SOMClass*
- GetClass( const char *className, Str255 errorString = kODNULL )
- {
- char libname[64];
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma options align=mac68k
- #endif
-
- struct FragDesc {
- ResType codeType;
- long ignore[5];
- long offsetToFrag;
- long lengthOfFrag;
- long moreIgnore[2];
- short recordLength;
- Str63 name;
- };
-
- struct CFRGResource {
- long ignore[7];
- long numFrags;
- struct FragDesc firstDesc;
- };
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma options align=reset
- #endif
-
- #if LOAD_UNDER_ASSUMED_NAME
- // First grab everything after the last colon in className:
- const char *lastcolon = strrchr(className,':');
- if (lastcolon == nil) {
- // Hack to load Bento:
- if( strcmp(className,"ODFileContainer")==0 ||
- strcmp(className,"ODMemContainer")==0 ||
- strcmp(className,"ODEmbeddedContainer")==0 )
- strcpy(libname, "OpenDoc Bento");
- else
- strcpy(libname, className);
- }
- else {
- strncpy(libname,lastcolon+1,sizeof(libname)-1);
- libname[sizeof(libname)-1] = '\0';
- }
- #else
- strcpy(libname,className);
- #endif /*LOAD_UNDER_ASSUMED_NAME*/
-
- if( errorString ) errorString[0] = '\0';
-
- c2pstr(libname);
-
- CFragConnectionID connID;
- Ptr mainAddr;
- Str255 errName;
- ODBoolean unloadLib = kODFalse;
-
- // Either override NewPtr or at least make sure there's memory available:
- ODBoolean override = TryToOverrideNewPtr(kODTrue);
- if( !override )
- ODRequireFreeSpace(kMinAppFreeSpace,kMinAppContigSpace,kODTrue);
-
- // First see if the library is already loaded:
- OSErr err = GetSharedLibrary((StringPtr)libname, kCurrentCFragArch,
- kFindCFrag, &connID,&mainAddr,errName);
-
- if( err == fragLibNotFound || err==fragLibConnErr )
- {
- // Nope, need to load it:
- ODByteArray ba = CreateEmptyByteArrayStruct(sizeof(ODFileSpec));
- ODVolatile(ba);
- TRY
- Environment* ev = somGetGlobalEnvironment();
- ODFileSpec* fsspecPtr = kODNULL;
- if (GetgBinding()->GetODFileSpecFromEditor(ev,ODISOStrFromCStr(className),&ba))
- {
- fsspecPtr = (ODFileSpec*)((&ba)->_buffer);
- short refNum = HOpenResFile( fsspecPtr->vRefNum, fsspecPtr->parID,
- fsspecPtr->name, fsRdPerm );
- short saveRefNum = CurResFile();
- WASSERT(ResError()==noErr);
- if (refNum != -1)
- {
- UseResFile( refNum );
- struct CFRGResource** cfrgHandle =
- (struct CFRGResource**)Get1Resource( 'cfrg', 0 );
- if ( cfrgHandle )
- {
- long entryCount = (*cfrgHandle)->numFrags;
- struct FragDesc* oneEntryPtr = &(*cfrgHandle)->firstDesc;
- while ( entryCount-- )
- {
- if ( oneEntryPtr->codeType == kCurrentCFragArch &&
- EqualPascalStrings((StringPtr)libname,oneEntryPtr->name))
- {
- err = GetDiskFragment(fsspecPtr, oneEntryPtr->offsetToFrag,
- oneEntryPtr->lengthOfFrag,NULL,
- kLoadCFrag, &connID,&mainAddr,errName);
- break;
- }
- else
- oneEntryPtr = (FragDesc*)(oneEntryPtr->recordLength
- + (char*)oneEntryPtr);
-
- }
- }
- }
- CloseResFile( refNum );
- UseResFile( saveRefNum );
- }
- else
- err = GetSharedLibrary((StringPtr)libname, kCurrentCFragArch,
- kLoadCFrag, &connID, &mainAddr, errName);
-
- DisposeByteArrayStruct(ba);
- CATCH_ALL
- DisposeByteArrayStruct(ba);
- RERAISE;
- ENDTRY
- if( err==noErr && !override && !ODHaveFreeSpace(kMinAppFreeSpace,
- kMinAppContigSpace,kODTrue) ) {
- CloseConnection(&connID);
- err = fragNoMem;
- #if ODDebug
- CopyPascalString(errName,"\pOD free space too low");
- #endif
- }
- else
- unloadLib = kODTrue;
- }
-
- if( override )
- TryToOverrideNewPtr(kODFalse); // turn off override
-
- if( err ) {
- if( errorString )
- CopyPascalString(errorString,errName);
- p2cstr(errName);
- WARN("Can't load lib '%s'; error %hd, '%s'",
- p2cstr((StringPtr)libname),err,errName);
- THROW(err,(char*)errName);
- }
-
- /* Now try to load the class. Install a temporary error handler that
- converts a fatal SOM error into a THROW, in case SOM runs out of
- memory. */
- SOMClass *c;
- gOld_SOMError = SOMError;
- SOMError = &Temp_GetClass_SOMError;
- TRY{
- long majorVersion = 0;
- long minorVersion = 0;
- somId id = somIdFromString((corbastring)className);
- c = somGetDynamicClassReference(id,majorVersion,minorVersion, kODNULL);
- SOMFree(id);
- if (unloadLib)
- {
- unloadLib = kODFalse;
- CloseConnection(&connID);
- }
- }CATCH_ALL{
- if (unloadLib)
- CloseConnection(&connID);
- SOMError = gOld_SOMError;
- RERAISE;
- }ENDTRY
- SOMError = gOld_SOMError;
-
-
- if( !c )
- THROW(kODErrCantLoadSOMClass);
- return c;
- }
-
-
- SOMObject*
- ODNewObject( const char *className, Str255 errorString )
- {
- SOMClass *cls = GetClass(className,errorString);
- THROW_IF_NULL (cls); // would have thrown anyway...
- SOMObject* obj = cls->somNew();
- somReleaseClassReference(cls); // must release class reference
- THROW_IF_NULL (obj); // similar to new ODObject, must throw if nil
- return obj;
- }
-
-
- ODBoolean
- ODClassExists( const char *className )
- {
- /* This function will now propagate errors if the library _does_ exist
- but just couldn't be loaded due to e.g. insufficient memory or missing
- imports. This allows for better error display to the user since otherwise
- the error would be eaten and replaced with a simple Boolean return value. */
-
- ODBoolean result = kODTrue;
- TRY
- SOMClass *cls = GetClass(className);
- somReleaseClassReference ( cls );
- CATCH_ALL
- if( ErrorCode()==kODErrCantLoadSOMClass || ErrorCode()==fragLibNotFound )
- result = kODFalse;
- else
- RERAISE;
- ENDTRY
- return result;
- }
-
-
- static ODBoolean
- TryToOverrideNewPtr( ODBoolean onoff )
- {
- Str255 errName;
- CFragConnectionID connID;
- Ptr mainAddr;
- OSErr err = GetSharedLibrary(kMemoryLibName, kCurrentCFragArch,
- kLoadCFrag, &connID,&mainAddr,errName);
- if( err ) {
- WARN("Couldn't find Memory Mgr?? %d, %s", err,p2cstr(errName));
- return kODFalse;
- }
-
- MemoryOverrideProcPtr proc;
- CFragSymbolClass type;
- err= FindSymbol(connID, onoff ?kMemoryOverrideOnName :kMemoryOverrideOffName, (Ptr*)&proc, &type);
- if( err ) {
- WASSERT(err==fragSymbolNotFound);
- return kODFalse;
- }
-
- (*proc)(true,false); // Call proc
- return kODTrue;
- }
-