Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#include "NGBundleManager.h"
#include "common.h"
+#include <NGExtensions/NSObject+Logs.h>
+#include <NGExtensions/NSNull+misc.h>
#import <Foundation/NSFileManager.h>
#import <EOControl/EOQualifier.h>
#include <ctype.h>
# include <NGExtensions/NGPropertyListParser.h>
#endif
+#if LIB_FOUNDATION_LIBRARY
+@interface NSBundle(UsedPrivates)
++ (BOOL)isFlattenedDirLayout;
+@end
+#endif
+
#if NeXT_RUNTIME || APPLE_RUNTIME
#include <objc/objc-runtime.h>
bundle = [manager bundleForClassNamed:[NSString stringWithCString:_name]];
if (bundle) {
- //NSLog(@"%s: found bundle %@", __PRETTY_FUNCTION__, [bundle bundlePath]);
+#if 0
+ NSLog(@"%s: found bundle %@", __PRETTY_FUNCTION__, [bundle bundlePath]);
+#endif
if ([manager loadBundle:bundle]) {
Class clazz;
static NGBundleManager *defaultManager = nil;
static BOOL debugOn = NO;
+#if defined(__MINGW32__)
+static NSString *NGEnvVarPathSeparator = @";";
+#else
+static NSString *NGEnvVarPathSeparator = @":";
+#endif
+
+ (void)initialize {
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
return defaultManager;
}
-- (void)_setupBundleSearchPathes {
- NSProcessInfo *pi;
- NSUserDefaults *ud;
- id paths;
- NSString *path;
+/* setup bundle search path */
- pi = [NSProcessInfo processInfo];
+- (void)_addMainBundlePathToPathArray:(NSMutableArray *)_paths {
+ NSProcessInfo *pi;
+ NSString *path;
- /* setup bundle search path */
-
- self->bundleSearchPaths = [[NSMutableArray alloc] init];
-
- // first add main-bundle path
+ pi = [NSProcessInfo processInfo];
+ path = [[pi arguments] objectAtIndex:0];
+ path = [path stringByDeletingLastPathComponent];
- path = [[[pi arguments] objectAtIndex:0] stringByDeletingLastPathComponent];
if ([path isEqual:@""])
- path = @".";
+ path = @".";
#if WITH_GNUSTEP
else {
- /* The path is the complete path to the executable, including the
- processor, the OS and the library combo. Strip these directories
- from the main bundle's path. */
- path = [[[path stringByDeletingLastPathComponent]
- stringByDeletingLastPathComponent]
- stringByDeletingLastPathComponent];
+ // TODO: to be correct this would need to read the bundle-info
+ // NSExecutable?!
+ /*
+ The path is the complete path to the executable, including the
+ processor, the OS and the library combo. Strip these directories
+ from the main bundle's path.
+ */
+#if LIB_FOUNDATION_LIBRARY
+ if (![NSBundle isFlattenedDirLayout])
+#endif
+ path = [[[path stringByDeletingLastPathComponent]
+ stringByDeletingLastPathComponent]
+ stringByDeletingLastPathComponent];
}
#endif
- [self->bundleSearchPaths addObject:path];
-
- // look into NGBundlePath default
-
+ [_paths addObject:path];
+}
+
+- (void)_addBundlePathDefaultToPathArray:(NSMutableArray *)_paths {
+ NSUserDefaults *ud;
+ id paths;
+
if ((ud = [NSUserDefaults standardUserDefaults]) == nil) {
// got this with gstep-base during the port, apparently it happens
// if the bundle manager is created inside the setup process of
abort();
#endif
}
-
- paths = [ud arrayForKey:@"NGBundlePath"];
- if (paths == nil) {
- paths = [ud stringForKey:@"NGBundlePath"];
- if (paths) {
-#if defined(__MINGW32__)
- paths = [paths componentsSeparatedByString:@";"];
-#else
- paths = [paths componentsSeparatedByString:@":"];
-#endif
- }
+
+ if ((paths = [ud arrayForKey:@"NGBundlePath"]) == nil) {
+ if ((paths = [ud stringForKey:@"NGBundlePath"]) != nil)
+ paths = [paths componentsSeparatedByString:NGEnvVarPathSeparator];
}
- if (paths)
- [self->bundleSearchPaths addObjectsFromArray:paths];
- else
+ if (paths != nil)
+ [_paths addObjectsFromArray:paths];
+ else if (debugOn)
NSLog(@"Note: NGBundlePath default is not configured.");
+}
- // look into environment
-
+- (void)_addEnvironmentPathToPathArray:(NSMutableArray *)_paths {
+ NSProcessInfo *pi;
+ id paths;
+
+ pi = [NSProcessInfo processInfo];
paths = [[pi environment] objectForKey:@"NGBundlePath"];
- if (paths) {
-#if defined(__MINGW32__)
- paths = [paths componentsSeparatedByString:@";"];
-#else
- paths = [paths componentsSeparatedByString:@":"];
-#endif
- }
- if (paths) [self->bundleSearchPaths addObjectsFromArray:paths];
+ if (paths)
+ paths = [paths componentsSeparatedByString:NGEnvVarPathSeparator];
+ if (paths) [_paths addObjectsFromArray:paths];
+}
- /* add standard bundle paths */
- {
+- (void)_addGNUstepPathsToPathArray:(NSMutableArray *)_paths {
#if !GNUSTEP
#else
- // TODO: whats that supposed to do?
- // TODO: replace with proper path locator function!
- NSDictionary *env;
- NSString *p;
+ // TODO: whats that supposed to do?
+ // TODO: replace with proper path locator function!
+ NSDictionary *env;
+ NSString *p;
+ unsigned i, count;
+ id tmp;
+
+ env = [[NSProcessInfo processInfo] environment];
+
+ if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
+ tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
+ tmp = [tmp componentsSeparatedByString:@":"];
+
+ for (i = 0, count = [tmp count]; i < count; i++) {
+ p = [tmp objectAtIndex:i];
+ p = [p stringByAppendingPathComponent:@"Library"];
+ p = [p stringByAppendingPathComponent:@"Bundles"];
+ if ([self->bundleSearchPaths containsObject:p]) continue;
- env = [[NSProcessInfo processInfo] environment];
- p = [[[env objectForKey:@"GNUSTEP_USER_ROOT"]
- stringByAppendingPathComponent:@"Library"]
- stringByAppendingPathComponent:@"Bundles"];
if (p) [self->bundleSearchPaths addObject:p];
- p = [[[env objectForKey:@"GNUSTEP_LOCAL_ROOT"]
- stringByAppendingPathComponent:@"Library"]
- stringByAppendingPathComponent:@"Bundles"];
- if (p) [self->bundleSearchPaths addObject:p];
- p = [[[env objectForKey:@"GNUSTEP_NETWORK_ROOT"]
- stringByAppendingPathComponent:@"Library"]
- stringByAppendingPathComponent:@"Bundles"];
- if (p) [self->bundleSearchPaths addObject:p];
- p = [[[env objectForKey:@"GNUSTEP_SYSTEM_ROOT"]
- stringByAppendingPathComponent:@"Library"]
- stringByAppendingPathComponent:@"Bundles"];
- if (p) [self->bundleSearchPaths addObject:p];
-#endif
}
+#endif
+}
+
+- (void)_setupBundleSearchPathes {
+ NSProcessInfo *pi;
+
+ pi = [NSProcessInfo processInfo];
+
+ /* setup bundle search path */
+
+ self->bundleSearchPaths = [[NSMutableArray alloc] initWithCapacity:16];
+
+ [self _addMainBundlePathToPathArray:self->bundleSearchPaths];
+ [self _addBundlePathDefaultToPathArray:self->bundleSearchPaths];
+ [self _addEnvironmentPathToPathArray:self->bundleSearchPaths];
+ [self _addGNUstepPathsToPathArray:self->bundleSearchPaths];
#if DEBUG && NeXT_Foundation_LIBRARY && 0
NSLog(@"%s: bundle search pathes:\n%@", __PRETTY_FUNCTION__,
[super dealloc];
}
+/* accessors */
+
+- (void)setBundleSearchPaths:(NSArray *)_paths {
+ ASSIGNCOPY(self->bundleSearchPaths, _paths);
+}
+- (NSArray *)bundleSearchPaths {
+ return self->bundleSearchPaths;
+}
+
/* registering bundles */
- (void)registerBundle:(NSBundle *)_bundle
*/
#if !LIB_FOUNDATION_LIBRARY && !GNUSTEP_BASE_LIBRARY
-# warning incorrect behaviour if NGExtensions is dynamically loaded !
+ // Note: incorrect behaviour if NGExtensions is dynamically loaded !
// TODO: can we do anything about this? Can we detect the situation and
// print a log instead of the compile warning?
+ // Note: the above refers to the situation when a framework is implicitly
+ // loaded by loading a bundle (the framework is not linked against
+ // the main tool)
#endif
bundle = [NSBundle mainBundle];
NSMapInsert(self->classToBundle, aClass, bundle);
bn = [_name stringByAppendingPathExtension:_type];
bundle = NSMapGet(self->nameToBundle, bn);
- if (bundle == nil)
- bundle = [self bundleWithPath:[self pathForBundleWithName:_name type:_type]];
-
+ if (![bundle isNotNull]) {
+ bundle = [self bundleWithPath:
+ [self pathForBundleWithName:_name type:_type]];
+ }
+
+ if (![bundle isNotNull]) /* NSNull is used to signal missing bundles */
+ return nil;
+
if (![[bundle bundleType] isEqualToString:_type])
- bundle = nil;
-
+ return nil;
+
+ /* bundle matches */
return bundle;
}
- (NSBundle *)bundleWithName:(NSString *)_name {
return nil;
}
-// initialization
+/* initialization */
- (NSString *)makeBundleInfoPath:(NSString *)_path {
#if (NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) && !defined(GSWARN)
- (id)_initializeLoadedBundle:(NSBundle *)_bundle
info:(NSDictionary *)_bundleInfo
{
- id handler = nil;
+ id handler;
/* check whether a handler was specified */
-
- if ((handler = [_bundleInfo objectForKey:@"bundleHandler"])) {
+
+ if ((handler = [_bundleInfo objectForKey:@"bundleHandler"]) != nil) {
+ [self debugWithFormat:@"lookup bundle handler %@ of bundle: %@",
+ handler, _bundle];
+
if ((handler = NSClassFromString(handler)) == nil) {
NSLog(@"ERROR: did not find handler class %@ of bundle %@.",
[_bundleInfo objectForKey:@"bundleHandler"], [_bundle bundlePath]);
handler = [_bundle principalClass];
}
-
+
handler = [handler alloc];
if ([handler respondsToSelector:@selector(initForBundle:bundleManager:)])
}
}
else {
+ [self debugWithFormat:
+ @"no bundle handler, lookup principal class of bundle: %@",
+ _bundle];
if ((handler = [_bundle principalClass]) == nil)
/* use NGBundle class as default bundle handler */
handler = [NGBundle class];
NSFileManager *fm;
NSEnumerator *e;
NSString *path;
+
+ if (debugOn) {
+ NSLog(@"BM LOOKUP pathes (%d bundles loaded): %@ / %@",
+ NSCountMapTable(self->loadedBundles), _resourceName, _type);
+ }
fm = [NSFileManager defaultManager];
result = [NSMutableArray arrayWithCapacity:64];
+ // TODO: look in loaded bundles
+
+ /* check physical pathes */
+
e = [self->bundleSearchPaths objectEnumerator];
- while ((path = [e nextObject])) {
- BOOL isDir = NO;
+ while ((path = [e nextObject]) != nil) {
+ NSEnumerator *dir;
+ BOOL isDir = NO;
+ NSString *tmp, *bundleDirPath;
+ id info = nil;
- if ([fm fileExistsAtPath:path isDirectory:&isDir]) {
- NSString *tmp;
- id info = nil;
- if (!isDir) continue;
-
- /* check whether an appropriate bundle is contained in 'path' */
- {
- NSEnumerator *dir;
-
- dir = [[fm directoryContentsAtPath:path] objectEnumerator];
- while ((tmp = [dir nextObject])) {
- NSDictionary *bundleInfo = nil;
- NSEnumerator *providedResources = nil;
- NSString *infoPath;
- id info;
+ if (![fm fileExistsAtPath:path isDirectory:&isDir])
+ continue;
+
+ if (!isDir) continue;
+
+ /* check whether an appropriate bundle is contained in 'path' */
+
+ dir = [[fm directoryContentsAtPath:path] objectEnumerator];
+ while ((bundleDirPath = [dir nextObject]) != nil) {
+ NSDictionary *bundleInfo = nil;
+ NSEnumerator *providedResources = nil;
+ NSString *infoPath;
+ id info;
- tmp = [path stringByAppendingPathComponent:tmp];
- infoPath = [self makeBundleInfoPath:tmp];
-
- if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) {
- if (![fm fileExistsAtPath:infoPath])
- continue;
-
- bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath];
- }
-
- providedResources =
- [[(NSDictionary *)[bundleInfo objectForKey:@"provides"]
- objectForKey:_type]
- objectEnumerator];
- if (providedResources == nil) continue;
+ bundleDirPath = [path stringByAppendingPathComponent:bundleDirPath];
+ infoPath = [self makeBundleInfoPath:bundleDirPath];
+
+ // TODO: can we use _doesBundleInfo:path:providedResource:... ?
+ if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath))==nil) {
+ if (![fm fileExistsAtPath:infoPath])
+ continue;
- // scan provide array
- while ((info = [providedResources nextObject])) {
- NSString *name;
+ bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath];
+ }
+
+ providedResources =
+ [[(NSDictionary *)[bundleInfo objectForKey:@"provides"]
+ objectForKey:_type]
+ objectEnumerator];
+ if (providedResources == nil) continue;
+
+ /* scan 'provides' array */
+ while ((info = [providedResources nextObject])) {
+ NSString *name;
- name = [[(NSDictionary *)info objectForKey:@"name"] stringValue];
- if (name == nil) continue;
-
- if (_resourceName) {
- if (![name isEqualToString:_resourceName])
- continue;
- }
- if (_selector) {
- if (!_selector(name, _type, tmp, info, self, _context))
- continue;
- }
-
- [result addObject:tmp];
- break;
- }
- }
+ name = [[(NSDictionary *)info objectForKey:@"name"] stringValue];
+ if (name == nil) continue;
+
+ if (_resourceName != nil) {
+ if (![name isEqualToString:_resourceName])
+ continue;
+ }
+ if (_selector != NULL) {
+ if (!_selector(name, _type, bundleDirPath, info, self, _context))
+ continue;
+ }
+
+ [result addObject:bundleDirPath];
+ break;
}
+ }
+
+ /* check for direct match (NGBundlePath element is a bundle) */
+
+ tmp = [self makeBundleInfoPath:path];
- /* check for direct match */
+ if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) {
+ if ([fm fileExistsAtPath:tmp])
+ info = [self _loadBundleInfoAtExistingPath:tmp];
+ }
+
+ [self _processInfoForProvidedResources:info ofType:_type path:path
+ resourceName:_resourceName resourceSelector:_selector
+ context:_context
+ andAddToResultArray:result];
+ }
+
+ if ([result count] == 0) {
+ [self logWithFormat:
+ @"Note(%s): method does not search in loaded bundles for "
+ @"resources of type '%@'",
+ __PRETTY_FUNCTION__, _type];
+ }
+
+ return [[result copy] autorelease];
+}
- tmp = [self makeBundleInfoPath:path];
+- (BOOL)_doesBundleInfo:(NSDictionary *)_bundleInfo path:(NSString *)_path
+ provideResource:(id)_resourceName ofType:(NSString *)_type
+ rnKeys:(NSArray *)_rnKeys
+ resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context
+{
+ NSEnumerator *providedResources;
+ NSDictionary *info;
+
+ providedResources =
+ [[(NSDictionary *)[_bundleInfo objectForKey:@"provides"]
+ objectForKey:_type] objectEnumerator];
+ if (providedResources == nil) return NO;
+
+ /* scan provide array */
+ while ((info = [providedResources nextObject])) {
+ if (_rnKeys != nil) {
+ if (!_doesInfoMatch(_rnKeys, _resourceName, info))
+ continue;
+ }
+ else {
+ NSString *name;
- if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) {
- if ([fm fileExistsAtPath:tmp])
- info = [self _loadBundleInfoAtExistingPath:tmp];
- }
-
- [self _processInfoForProvidedResources:info ofType:_type path:path
- resourceName:_resourceName resourceSelector:_selector
- context:_context
- andAddToResultArray:result];
+ name = [[(NSDictionary *)info objectForKey:@"name"] stringValue];
+ if (name == nil) continue;
+ if (![name isEqualToString:_resourceName]) continue;
+ }
+
+ if (_selector != NULL) {
+ if (!_selector(_resourceName, _type, _path, info, self, _context))
+ continue;
}
+
+ /* all conditions applied (found) */
+ return YES;
}
- return [[result copy] autorelease];
+ return NO;
+}
+
+- (NSString *)pathOfLoadedBundleProvidingResource:(id)_resourceName
+ ofType:(NSString *)_type
+ resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context
+{
+ NSMapEnumerator menum;
+ NSString *path;
+ NSDictionary *bundleInfo;
+ NSArray *rnKeys;
+
+ rnKeys = ([_resourceName respondsToSelector:@selector(objectForKey:)])
+ ? [_resourceName allKeys]
+ : nil;
+
+ menum = NSEnumerateMapTable(self->pathToBundleInfo);
+ while (NSNextMapEnumeratorPair(&menum, (void *)&path, (void *)&bundleInfo)) {
+ if (debugOn) {
+ NSLog(@"check loaded bundle for resource %@: %@", _resourceName,
+ path);
+ }
+
+ if ([self _doesBundleInfo:bundleInfo path:path
+ provideResource:_resourceName ofType:_type rnKeys:rnKeys
+ resourceSelector:_selector context:_context])
+ /* strip bundle-info.plist name */
+ return [path stringByDeletingLastPathComponent];
+ }
+
+ return nil;
}
- (NSString *)pathForBundleProvidingResource:(id)_resourceName
resourceSelector:(NGBundleResourceSelector)_selector
context:(void *)_context
{
- NSFileManager *fm = [NSFileManager defaultManager];
+ /* main path lookup method */
+ // TODO: this method seriously needs some refactoring
+ NSFileManager *fm;
NSEnumerator *e;
NSString *path;
NSArray *rnKeys = nil;
int rnKeyCount = 0;
-
+
+ if (debugOn) {
+ NSLog(@"BM LOOKUP path (%d bundles loaded): %@ / %@",
+ NSCountMapTable(self->loadedBundles), _resourceName, _type);
+ }
+
+ /* look in loaded bundles */
+
+ path = [self pathOfLoadedBundleProvidingResource:_resourceName ofType:_type
+ resourceSelector:_selector context:_context];
+ if (path != nil) return path;
+
+ /* look in filesystem */
+
if ([_resourceName respondsToSelector:@selector(objectForKey:)]) {
rnKeys = [_resourceName allKeys];
rnKeyCount = [rnKeys count];
}
+ fm = [NSFileManager defaultManager];
e = [self->bundleSearchPaths objectEnumerator];
- while ((path = [e nextObject])) {
- BOOL isDir = NO;
+ while ((path = [e nextObject]) != nil) {
+ NSEnumerator *dir;
+ BOOL isDir = NO;
+ NSString *tmp;
+ id info = nil;
- if ([fm fileExistsAtPath:path isDirectory:&isDir]) {
- NSString *tmp;
- id info = nil;
+ if (![fm fileExistsAtPath:path isDirectory:&isDir])
+ continue;
+
+ if (!isDir) continue;
+
+ /* check whether an appropriate bundle is contained in 'path' */
+
+ dir = [[fm directoryContentsAtPath:path] objectEnumerator];
+ while ((tmp = [dir nextObject])) {
+ NSDictionary *bundleInfo = nil;
+ NSString *infoPath;
- if (!isDir) continue;
+ tmp = [path stringByAppendingPathComponent:tmp];
+ infoPath = [self makeBundleInfoPath:tmp];
- /* check whether an appropriate bundle is contained in 'path' */
- {
- NSEnumerator *dir;
-
- dir = [[fm directoryContentsAtPath:path] objectEnumerator];
- while ((tmp = [dir nextObject])) {
- NSDictionary *bundleInfo = nil;
- NSEnumerator *providedResources = nil;
- NSString *infoPath;
- id info;
-
- tmp = [path stringByAppendingPathComponent:tmp];
- infoPath = [self makeBundleInfoPath:tmp];
-
- if (debugOn)
- NSLog(@"check path path=%@ info=%@", tmp, infoPath);
+ if (debugOn)
+ NSLog(@"check path path=%@ info=%@", tmp, infoPath);
- if ((bundleInfo=NSMapGet(self->pathToBundleInfo, infoPath)) == nil) {
- if (![fm fileExistsAtPath:infoPath])
- continue;
+ if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) {
+ if (![fm fileExistsAtPath:infoPath])
+ continue;
- bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath];
- }
- if (debugOn) {
- NSLog(@"found info for path=%@ info=%@: %@",
- tmp, infoPath, bundleInfo);
- }
-
- providedResources =
- [[(NSDictionary *)[bundleInfo objectForKey:@"provides"]
- objectForKey:_type]
- objectEnumerator];
- if (providedResources == nil) continue;
-
- // scan provide array
- while ((info = [providedResources nextObject])) {
- if (rnKeys) {
- if (!_doesInfoMatch(rnKeys, _resourceName, info))
- continue;
- }
- else {
- NSString *name;
-
- name = [[(NSDictionary *)info objectForKey:@"name"] stringValue];
- if (name == nil) continue;
- if (![name isEqualToString:_resourceName]) continue;
- }
-
- if (_selector) {
- if (!_selector(_resourceName, _type, tmp, info, self, _context))
- continue;
- }
- /* all conditions applied */
- return tmp;
- }
- }
+ bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath];
}
-
- /* check for direct match */
+ if (debugOn)
+ NSLog(@"found info for path=%@ info=%@: %@", tmp,infoPath,bundleInfo);
- tmp = [self makeBundleInfoPath:path];
+ if ([self _doesBundleInfo:bundleInfo path:tmp
+ provideResource:_resourceName ofType:_type rnKeys:rnKeys
+ resourceSelector:_selector context:_context])
+ return tmp;
+ }
+
+ /* check for direct match */
+
+ tmp = [self makeBundleInfoPath:path];
- if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) {
+ if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) {
if ([fm fileExistsAtPath:tmp])
info = [self _loadBundleInfoAtExistingPath:tmp];
else if (debugOn) {
NSLog(@"WARNING(%s): did not find direct path '%@'",
__PRETTY_FUNCTION__, tmp);
}
- }
+ }
- if (info) {
+ if (info != nil) {
// direct match (a bundle was specified in the path)
NSEnumerator *providedResources;
NSDictionary *provides;
/* all conditions applied */
return tmp;
}
- }
}
}
return nil;
}
-- (NSBundle *)bundleProvidingResource:(id)_resourceName
- ofType:(NSString *)_resourceType
-{
+- (NSBundle *)bundleProvidingResource:(id)_name ofType:(NSString *)_type {
NSString *bp;
- bp = [self pathForBundleProvidingResource:_resourceName
- ofType:_resourceType
+ if (debugOn) NSLog(@"BM LOOKUP: %@ / %@", _name, _type);
+
+ bp = [self pathForBundleProvidingResource:_name
+ ofType:_type
resourceSelector:NULL context:nil];
if ([bp length] == 0) {
#if (NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) && HEAVY_DEBUG
NSLog(@"%s: found no resource '%@' of type '%@' ...",
__PRETTY_FUNCTION__, _resourceName, _resourceType);
#endif
+ if (debugOn) NSLog(@" did not find: %@ / %@", _name, _type);
return nil;
}
+ if (debugOn) NSLog(@" FOUND: %@", bp);
return [self bundleWithPath:bp];
}
objectForKey:_resourceType];
}
+- (void)_addRegisteredProvidedResourcesOfType:(NSString *)_type
+ toSet:(NSMutableSet *)_result
+{
+ NSMapEnumerator menum;
+ NSString *path;
+ NSDictionary *bundleInfo;
+
+ menum = NSEnumerateMapTable(self->pathToBundleInfo);
+ while (NSNextMapEnumeratorPair(&menum, (void *)&path, (void *)&bundleInfo)) {
+ NSArray *providedResources;
+
+ if (debugOn)
+ NSLog(@"check loaded bundle for resource types %@: %@", _type, path);
+
+ providedResources =
+ [(NSDictionary *)[bundleInfo objectForKey:@"provides"]
+ objectForKey:_type];
+ if (providedResources == nil) continue;
+
+ [_result addObjectsFromArray:providedResources];
+ }
+}
+
- (NSArray *)providedResourcesOfType:(NSString *)_resourceType {
NSMutableSet *result = nil;
NSFileManager *fm = [NSFileManager defaultManager];
result = [NSMutableSet setWithCapacity:128];
+ /* scan loaded bundles */
+
+ [self _addRegisteredProvidedResourcesOfType:_resourceType toSet:result];
+
+ /* scan all bundle search paths */
+
e = [self->bundleSearchPaths objectEnumerator];
while ((path = [e nextObject])) {
- BOOL isDir = NO;
+ NSEnumerator *dir;
+ BOOL isDir = NO;
+ NSString *tmp;
+ id info = nil;
- if ([fm fileExistsAtPath:path isDirectory:&isDir]) {
- NSString *tmp;
- id info = nil;
- if (!isDir) continue;
+ if (![fm fileExistsAtPath:path isDirectory:&isDir])
+ continue;
+ if (!isDir) continue;
- /* check whether an appropriate bundle is contained in 'path' */
- {
- NSEnumerator *dir;
+ /* check whether an appropriate bundle is contained in 'path' */
- dir = [[fm directoryContentsAtPath:path] objectEnumerator];
- while ((tmp = [dir nextObject])) {
- NSDictionary *bundleInfo = nil;
- NSArray *providedResources = nil;
- NSString *infoPath;
+ dir = [[fm directoryContentsAtPath:path] objectEnumerator];
+ while ((tmp = [dir nextObject])) {
+ NSDictionary *bundleInfo = nil;
+ NSArray *providedResources = nil;
+ NSString *infoPath;
- tmp = [path stringByAppendingPathComponent:tmp];
- infoPath = [self makeBundleInfoPath:tmp];
-
- //NSLog(@" info path: %@", tmp);
-
- if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) {
- if (![fm fileExistsAtPath:infoPath])
- continue;
-
- bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath];
- }
+ tmp = [path stringByAppendingPathComponent:tmp];
+ infoPath = [self makeBundleInfoPath:tmp];
+
+#if 0
+ NSLog(@" info path: %@", tmp);
+#endif
- providedResources =
- [(NSDictionary *)[bundleInfo objectForKey:@"provides"]
- objectForKey:_resourceType];
- if (providedResources == nil) continue;
+ if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) {
+ if (![fm fileExistsAtPath:infoPath])
+ continue;
- [result addObjectsFromArray:providedResources];
- }
+ bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath];
}
- /* check for direct match */
+ providedResources =
+ [(NSDictionary *)[bundleInfo objectForKey:@"provides"]
+ objectForKey:_resourceType];
+ if (providedResources == nil) continue;
+
+ [result addObjectsFromArray:providedResources];
+ }
+
+ /* check for direct match */
- tmp = [self makeBundleInfoPath:path];
+ tmp = [self makeBundleInfoPath:path];
- if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) {
- if ([fm fileExistsAtPath:tmp])
- info = [self _loadBundleInfoAtExistingPath:tmp];
- }
+ if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) {
+ if ([fm fileExistsAtPath:tmp])
+ info = [self _loadBundleInfoAtExistingPath:tmp];
+ }
- if (info) {
- // direct match (a bundle was specified in the path)
- NSArray *providedResources;
- NSDictionary *provides;
+ if (info != nil) {
+ // direct match (a bundle was specified in the path)
+ NSArray *providedResources;
+ NSDictionary *provides;
- provides = [(NSDictionary *)info objectForKey:@"provides"];
- providedResources = [provides objectForKey:_resourceType];
- info = nil;
- if (providedResources == nil) continue;
+ provides = [(NSDictionary *)info objectForKey:@"provides"];
+ providedResources = [provides objectForKey:_resourceType];
+ info = nil;
+ if (providedResources == nil) continue;
- [result addObjectsFromArray:providedResources];
- }
+ [result addObjectsFromArray:providedResources];
}
}
return [result allObjects];
return [[bundles copy] autorelease];
}
-// notifications
+/* notifications */
- (void)_bundleDidLoadNotifcation:(NSNotification *)_notification {
NSDictionary *ui = [_notification userInfo];
categories:[ui objectForKey:@"NSLoadedCategories"]];
}
+/* debugging */
+
+- (BOOL)isDebuggingEnabled {
+ return debugOn;
+}
+
@end /* NGBundleManager */
@implementation NSBundle(BundleManagerSupport)
- (NSString *)description {
char buffer[1024];
-
+
sprintf (buffer,
"<%s %p fullPath: %s infoDictionary: %p loaded=%s>",
(char*)object_get_class_name(self),