From ddc7cbacf97fb7b2f836b71eb9861230f11de24a Mon Sep 17 00:00:00 2001 From: helge Date: Wed, 14 Sep 2005 16:10:17 +0000 Subject: [PATCH] improved Tiger support in bundle manager git-svn-id: http://svn.opengroupware.org/SOPE/trunk@1106 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-core/NGExtensions/ChangeLog | 5 + sope-core/NGExtensions/NGBundleManager.m | 161 ++++++++++++++++++----- sope-core/NGExtensions/Version | 2 +- 3 files changed, 131 insertions(+), 37 deletions(-) diff --git a/sope-core/NGExtensions/ChangeLog b/sope-core/NGExtensions/ChangeLog index b871e4f5..d2ff66c8 100644 --- a/sope-core/NGExtensions/ChangeLog +++ b/sope-core/NGExtensions/ChangeLog @@ -1,3 +1,8 @@ +2005-09-14 Helge Hess + + * NGBundleManager.m: avoid an autorelease call in class lookup, added + some lookup hacks for Tiger Foundation (v4.5.174) + 2005-08-26 Helge Hess * added common.h files to support PCH compilation of subprojects (just diff --git a/sope-core/NGExtensions/NGBundleManager.m b/sope-core/NGExtensions/NGBundleManager.m index 23463b00..5d006c7f 100644 --- a/sope-core/NGExtensions/NGBundleManager.m +++ b/sope-core/NGExtensions/NGBundleManager.m @@ -49,8 +49,10 @@ //OBJC_EXPORT void objc_setClassHandler(int (*)(const char *)); static BOOL debugClassHook = NO; +static BOOL hookDoLookup = YES; static int _getClassHook(const char *className) { + // Cocoa variant if (className == NULL) return 0; if (debugClassHook) @@ -59,18 +61,21 @@ static int _getClassHook(const char *className) { if (objc_lookUpClass(className)) return 1; - { + if (hookDoLookup) { static NGBundleManager *manager = nil; NSBundle *bundle; + NSString *cns; if (debugClassHook) - NSLog(@"%s: look for class %s", __PRETTY_FUNCTION__, className); + printf("%s: look for class %s\n", __PRETTY_FUNCTION__, className); if (manager == nil) manager = [NGBundleManager defaultBundleManager]; - bundle = [manager bundleForClassNamed: - [NSString stringWithCString:className]]; - if (bundle) { + cns = [[NSString alloc] initWithCString:className]; + bundle = [manager bundleForClassNamed:cns]; + [cns release]; cns = nil; + + if (bundle != nil) { if (debugClassHook) { NSLog(@"%s: found bundle %@", __PRETTY_FUNCTION__, [bundle bundlePath]); @@ -126,7 +131,7 @@ static Class _classLoadHook(const char *_name) { manager = [NGBundleManager defaultBundleManager]; bundle = [manager bundleForClassNamed:[NSString stringWithCString:_name]]; - if (bundle) { + if (bundle != nil) { #if 0 NSLog(@"%s: found bundle %@", __PRETTY_FUNCTION__, [bundle bundlePath]); #endif @@ -248,9 +253,7 @@ static NSString *NGEnvVarPathSeparator = @":"; objc_setClassHandler(_getClassHook); } } -#endif - -#if GNU_RUNTIME +#elif GNU_RUNTIME if (_objc_lookup_class != _classLoadHook) { oldClassLoadHook = _objc_lookup_class; _objc_lookup_class = _classLoadHook; @@ -377,9 +380,9 @@ static NSString *NGEnvVarPathSeparator = @":"; - (void)_registerLoadedBundles { NSEnumerator *currentBundles; NSBundle *loadedBundle; - + currentBundles = [[NSBundle allBundles] objectEnumerator]; - while ((loadedBundle = [currentBundles nextObject])) + while ((loadedBundle = [currentBundles nextObject]) != nil) [self registerBundle:loadedBundle classes:nil categories:nil]; } @@ -468,16 +471,35 @@ static NSString *NGEnvVarPathSeparator = @":"; NSEnumerator *e; id v; - //NSLog(@"NGBundleManager: register loaded bundle %@", [_bundle bundlePath]); - +#if NeXT_RUNTIME || APPLE_RUNTIME + v = [_bundle bundlePath]; + if ([v hasSuffix:@"Libraries"] || [v hasSuffix:@"Tools"]) { + if (debugOn) + fprintf(stderr, "INVALID BUNDLE: %s\n", [[_bundle bundlePath] cString]); + return; + } +#endif + +#if 0 + NSLog(@"NGBundleManager: register loaded bundle %@", [_bundle bundlePath]); +#endif + e = [_classes objectEnumerator]; - while ((v = [e nextObject])) { + while ((v = [e nextObject]) != nil) { +#if NeXT_RUNTIME || APPLE_RUNTIME + hookDoLookup = NO; +#endif + NSMapInsert(self->classToBundle, NSClassFromString(v), _bundle); NSMapInsert(self->classNameToBundle, v, _bundle); + +#if NeXT_RUNTIME || APPLE_RUNTIME + hookDoLookup = YES; +#endif } - + e = [_categories objectEnumerator]; - while ((v = [e nextObject])) + while ((v = [e nextObject]) != nil) NSMapInsert(self->categoryNameToBundle, v, _bundle); } @@ -529,14 +551,38 @@ static NSString *NGEnvVarPathSeparator = @":"; - (NSBundle *)bundleForClass:(Class)aClass { /* this method never loads a dynamic bundle (since the class is set up) */ NSBundle *bundle; - + + if (aClass == Nil) + return nil; + bundle = NSMapGet(self->classToBundle, aClass); #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY - if (bundle == nil){ + if (bundle == nil) { + NSString *p; + bundle = [NSBundle bundleForClass:aClass]; if (bundle == [NSBundle mainBundle]) bundle = nil; + else { + p = [bundle bundlePath]; + if ([p hasSuffix:@"Libraries"]) { + if (debugOn) { + fprintf(stderr, "%s: Dylib bundle: 0x%08X: %s\n", + __PRETTY_FUNCTION__, + (unsigned int )bundle, [[bundle bundlePath] cString]); + } + bundle = nil; + } + else if ([p hasSuffix:@"Tools"]) { + if (debugOn) { + fprintf(stderr, "%s: Tool bundle: 0x%08X: %s\n", + __PRETTY_FUNCTION__, + (unsigned int )bundle, [[bundle bundlePath] cString]); + } + bundle = nil; + } + } } #endif if (bundle == nil) { @@ -617,13 +663,13 @@ static NSString *NGEnvVarPathSeparator = @":"; - (NSBundle *)bundleForClassNamed:(NSString *)_className { NSString *path = nil; NSBundle *bundle = nil; - + if (_className == nil) return nil; /* first check in table */ - if ((bundle = NSMapGet(self->classNameToBundle, _className))) + if ((bundle = NSMapGet(self->classNameToBundle, _className)) != nil) return bundle; #if GNU_RUNTIME @@ -633,26 +679,47 @@ static NSString *NGEnvVarPathSeparator = @":"; void *loadCallback; Class clazz; - loadCallback = _objc_lookup_class; _objc_lookup_class = NULL; clazz = NSClassFromString(_className); _objc_lookup_class = loadCallback; - if (clazz) { + if (clazz != Nil) { /* the class is already loaded */ bundle = [self bundleForClass:clazz]; NSMapInsert(self->classNameToBundle, _className, bundle); return bundle; } } +#elif NeXT_RUNTIME || APPLE_RUNTIME + { + Class clazz; + + hookDoLookup = NO; // THREAD + clazz = NSClassFromString(_className); + hookDoLookup = YES; + + if (clazz != Nil) { + /* the class is already loaded */ +#if 0 + printf("found class in runtime: %s\n", [_className cString]); +#endif + bundle = [self bundleForClass:clazz]; + NSMapInsert(self->classNameToBundle, _className, bundle); + return bundle; + } +#if 0 + else + printf("did NOT find class in runtime: %s\n", [_className cString]); +#endif + } #endif path = [self pathForBundleProvidingResource:_className ofType:@"classes" resourceSelector:_selectClassByVersion context:NULL /* version */]; - if (path) { + if (path != nil) { path = [path stringByResolvingSymlinksInPath]; NSAssert(path, @"couldn't resolve symlinks in path .."); } @@ -660,7 +727,7 @@ static NSString *NGEnvVarPathSeparator = @":"; if (path == nil) return nil; - if ((bundle = [self bundleWithPath:path])) + if ((bundle = [self bundleWithPath:path]) != nil) NSMapInsert(self->classNameToBundle, _className, bundle); return bundle; @@ -732,9 +799,15 @@ static NSString *NGEnvVarPathSeparator = @":"; [self debugWithFormat: @"no bundle handler, lookup principal class of bundle: %@", _bundle]; - if ((handler = [_bundle principalClass]) == nil) + if ((handler = [_bundle principalClass]) == nil) { /* use NGBundle class as default bundle handler */ +#if !(NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY) + [self warnWithFormat:@"bundle has no principal class: %@", _bundle]; +#endif handler = [NGBundle class]; + } + else + [self debugWithFormat:@" => %@", handler]; } return handler; @@ -779,6 +852,16 @@ static NSString *NGEnvVarPathSeparator = @":"; return nil; } + // TODO: do we need to check the runtime for already loaded classes? + // Yes, I think so. But avoid recursions +#if 0 +#if APPLE_Foundation_LIBRARY || COCOA_Foundation_LIBRARY + // TODO: HACK, see above. w/o this, we get issues. + if ([className hasPrefix:@"NS"]) + return nil; +#endif +#endif + if ((bundle = [self bundleForClassNamed:className]) == nil) { #if 0 // class might be already loaded NSLog(@"ERROR: did not find class %@ required by bundle %@.", @@ -786,6 +869,9 @@ static NSString *NGEnvVarPathSeparator = @":"; #endif } + if (debugOn) + NSLog(@"CLASS %@ => BUNDLE %@", className, bundle); + return bundle; } - (NSArray *)_locateBundlesForClassInfos:(NSEnumerator *)_classInfos { @@ -793,7 +879,7 @@ static NSString *NGEnvVarPathSeparator = @":"; NSDictionary *i; requiredBundles = [NSMutableArray arrayWithCapacity:16]; - while ((i = [_classInfos nextObject])) { + while ((i = [_classInfos nextObject]) != nil) { NSBundle *bundle; if ((bundle = [self _locateBundleForClassInfo:i]) == nil) @@ -806,7 +892,7 @@ static NSString *NGEnvVarPathSeparator = @":"; - (BOOL)_preLoadBundle:(NSBundle *)_bundle info:(NSDictionary *)_bundleInfo { /* TODO: split up this huge method */ - NSDictionary *requires = nil; + NSDictionary *requires; NSMutableArray *requiredBundles = nil; NSBundle *requiredBundle = nil; @@ -824,7 +910,7 @@ static NSString *NGEnvVarPathSeparator = @":"; /* locate required bundles */ e = [[requires objectForKey:@"bundles"] objectEnumerator]; - while ((i = [e nextObject])) { + while ((i = [e nextObject]) != nil) { NSString *bundleName; if (![i respondsToSelector:@selector(objectForKey:)]) { @@ -857,18 +943,19 @@ static NSString *NGEnvVarPathSeparator = @":"; NSLog(@"ERROR: error in bundle-info.plist of bundle %@", _bundle); } } - + /* load located bundles */ { NSEnumerator *e; e = [requiredBundles objectEnumerator]; - while ((requiredBundle = [e nextObject])) { + while ((requiredBundle = [e nextObject]) != nil) { Class bundleMaster; if ((bundleMaster = [self loadBundle:requiredBundle]) == Nil) { NSLog(@"ERROR: could not load bundle %@ (%@) required by bundle %@.", - [requiredBundle bundlePath], requiredBundle, [_bundle bundlePath]); + [requiredBundle bundlePath], requiredBundle, + [_bundle bundlePath]); continue; } } @@ -880,23 +967,25 @@ static NSString *NGEnvVarPathSeparator = @":"; NSArray *reqClasses; reqClasses = [requires objectForKey:@"classes"]; + bundles = [self _locateBundlesForClassInfos:[reqClasses objectEnumerator]]; if (requiredBundles == nil) requiredBundles = [NSMutableArray arrayWithCapacity:16]; [requiredBundles addObjectsFromArray:bundles]; } - + /* load located bundles */ { NSEnumerator *e; e = [requiredBundles objectEnumerator]; - while ((requiredBundle = [e nextObject])) { + while ((requiredBundle = [e nextObject]) != nil) { Class bundleMaster; if ((bundleMaster = [self loadBundle:requiredBundle]) == Nil) { NSLog(@"ERROR: could not load bundle %@ (%@) required by bundle %@.", - [requiredBundle bundlePath], requiredBundle, [_bundle bundlePath]); + [requiredBundle bundlePath], requiredBundle, + [_bundle bundlePath]); continue; } } @@ -908,7 +997,7 @@ static NSString *NGEnvVarPathSeparator = @":"; NSDictionary *i; e = [[requires objectForKey:@"classes"] objectEnumerator]; - while ((i = [e nextObject])) { + while ((i = [e nextObject]) != nil) { NSString *className; Class clazz; @@ -1377,7 +1466,7 @@ static BOOL _doesInfoMatch(NSArray *keys, NSDictionary *dict, NSDictionary *info /* check whether an appropriate bundle is contained in 'path' */ dir = [[fm directoryContentsAtPath:path] objectEnumerator]; - while ((tmp = [dir nextObject])) { + while ((tmp = [dir nextObject]) != nil) { NSDictionary *bundleInfo = nil; NSString *infoPath; diff --git a/sope-core/NGExtensions/Version b/sope-core/NGExtensions/Version index 2a3637f2..00285053 100644 --- a/sope-core/NGExtensions/Version +++ b/sope-core/NGExtensions/Version @@ -1,6 +1,6 @@ # version -SUBMINOR_VERSION:=173 +SUBMINOR_VERSION:=174 # v4.3.115 requires libFoundation v1.0.59 # v4.2.72 requires libEOControl v4.2.39 -- 2.39.5