2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include <NGObjWeb/WOResourceManager.h>
23 #include <NGObjWeb/WOComponentDefinition.h>
24 #include "WOComponent+private.h"
25 #include <NGObjWeb/WORequest.h>
26 #include <NGObjWeb/WOApplication.h>
28 #import <Foundation/NSNull.h>
29 #include "_WOStringTable.h"
32 Component Discovery and Page Creation
34 All WO code uses either directly or indirectly the WOResourceManager's
35 -pageWithName:languages: method to instantiate WO components.
37 This methods works in three steps:
39 1. discovery of files associated with the component
41 2. creation of a proper WOComponentDefinition, which is some kind
42 of 'blueprint' or 'class' for components
44 3. component instantiation using the definition
46 All the instantiation/setup work is done by a component definition, the
47 resource manager is only responsible for managing those 'blueprint'
50 If you want to customize component creation, you can supply your
51 own WOComponentDefinition in a subclass of WOResourceManager by
53 - (WOComponentDefinition *)definitionForComponent:(id)_name
54 inFramework:(NSString *)_frameworkName
55 languages:(NSArray *)_languages
59 Note: this was #if !COMPILE_FOR_GSTEP_MAKE - but there is no difference
60 between Xcode and gstep-make?!
61 The only possible difference might be that .wo wrappers are directly
62 in the bundle/framework root - but this doesn't relate to Resources.
64 OK, this breaks gstep-make based template lookup which places .wo
65 wrappers in .woa/Resources/xxx.wo.
66 This is an issue because .wox are looked up in Contents/Resources
67 but .wo ones in just Resources.
69 This issue should be fixed in recent woapp-gs.make ...
71 Update: since for SOPE 4.3 we only work with gstep-make 1.10, this seems to
74 #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
75 # define RSRCDIR_CONTENTS 1
78 @implementation WOResourceManager
84 static Class UrlClass = Nil;
85 static NSString *resourcePrefix = @"";
86 static NSString *rapidTurnAroundPath = nil;
87 static NSString *suffix = nil;
88 static NSNull *null = nil;
89 static BOOL debugOn = NO;
90 static BOOL debugComponentLookup = NO;
91 static BOOL debugResourceLookup = NO;
92 static BOOL genMissingResourceLinks = NO;
95 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
96 static BOOL isInitialized = NO;
98 if (isInitialized) return;
101 null = [[NSNull null] retain];
102 UrlClass = [NSURL class];
104 defs = [NSDictionary dictionaryWithObjectsAndKeys:
105 [NSArray arrayWithObject:@"wo"],
106 @"WOComponentExtensions",
108 [ud registerDefaults:defs];
109 debugOn = [WOApplication isDebuggingEnabled];
110 debugComponentLookup = [ud boolForKey:@"WODebugComponentLookup"];
111 debugResourceLookup = [ud boolForKey:@"WODebugResourceLookup"];
112 genMissingResourceLinks = [ud boolForKey:@"WOGenerateMissingResourceLinks"];
113 rapidTurnAroundPath = [[ud stringForKey:@"WOProjectDirectory"] copy];
114 suffix = [[ud stringForKey:@"WOApplicationSuffix"] copy];
118 _pathExists(WOResourceManager *self, NSFileManager *fm, NSString *path)
122 if (self->existingPathes && (path != nil)) {
125 i = (int)NSMapGet(self->existingPathes, path);
127 doesExist = [fm fileExistsAtPath:path];
128 NSMapInsert(self->existingPathes, path, (void*)(doesExist ? 1 : 0xFF));
131 doesExist = i == 1 ? YES : NO;
134 doesExist = [fm fileExistsAtPath:path];
138 + (void)setResourcePrefix:(NSString *)_prefix {
139 [resourcePrefix autorelease];
140 resourcePrefix = [_prefix copy];
143 - (id)initWithPath:(NSString *)_path {
145 if ([_path length] == 0) {
146 NSLog(@"ERROR(%s): missing path!", __PRETTY_FUNCTION__);
147 /* this doesn't work with subclasses which do not require a path ... */
155 if ((self = [super init])) {
156 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
157 NSString *rprefix = nil;
160 self->componentDefinitions =
161 NSCreateMapTable(NSObjectMapKeyCallBacks,
162 NSObjectMapValueCallBacks,
165 NSCreateMapTable(NSObjectMapKeyCallBacks,
166 NSObjectMapValueCallBacks,
169 tmp = [_path stringByStandardizingPath];
170 if (tmp) _path = tmp;
172 self->base = [_path copy];
174 if ([WOApplication isCachingEnabled]) {
175 self->existingPathes = NSCreateMapTable(NSObjectMapKeyCallBacks,
176 NSIntMapValueCallBacks,
180 rprefix = [ud stringForKey:@"WOResourcePrefix"];
181 if (rprefix) [[self class] setResourcePrefix:rprefix];
186 return [self initWithPath:[[NGBundle mainBundle] bundlePath]];
190 if (self->existingPathes) NSFreeMapTable(self->existingPathes);
191 if (self->stringTables) NSFreeMapTable(self->stringTables);
192 if (self->componentDefinitions) NSFreeMapTable(self->componentDefinitions);
193 if (self->keyedResources) NSFreeMapTable(self->keyedResources);
194 [self->w3resources release];
195 [self->resources release];
196 [self->base release];
202 - (BOOL)isDebuggingEnabled {
208 - (NSFileManager *)fileManager {
209 static NSFileManager *fm = nil;
211 fm = [[NSFileManager defaultManager] retain];
215 - (NSString *)basePath {
219 - (NSString *)resourcesPath {
223 return self->resources;
225 fm = [self fileManager];
226 if ([self->base length] > 0) {
227 if (![fm fileExistsAtPath:self->base]) {
228 NSLog(@"WARNING(%s): Resources base path '%@' does not exist !",
229 __PRETTY_FUNCTION__, self->base);
235 if ([rapidTurnAroundPath length] > 0) {
237 In rapid turnaround mode, first check for a Resources subdir in the
238 project directory, then directly in the project dir.
239 Note: you cannot have both! Either put stuff in a Resources subdir *or*
245 tmp = [rapidTurnAroundPath stringByAppendingPathComponent:@"Resources"];
246 if (![fm fileExistsAtPath:tmp isDirectory:&isDir])
249 tmp = rapidTurnAroundPath;
251 self->resources = [tmp copy];
255 [[[self->base stringByAppendingPathComponent:@"Contents"]
256 stringByAppendingPathComponent:@"Resources"]
261 [[self->base stringByAppendingPathComponent:@"Resources"] copy];
264 if ([self->resources length] > 0) {
265 if (![fm fileExistsAtPath:self->resources]) {
266 [self debugWithFormat:
267 @"WARNING(%s): Resources path %@ does not exist !",
268 __PRETTY_FUNCTION__, self->resources];
269 [self->resources release]; self->resources = nil;
271 else if (self->existingPathes && (self->resources != nil))
272 NSMapInsert(self->existingPathes, self->resources, (void*)1);
274 return self->resources;
277 - (NSString *)resourcesPathForFramework:(NSString *)_fw {
279 return [self resourcesPath];
282 return [[_fw stringByAppendingPathComponent:@"Contents"]
283 stringByAppendingPathComponent:@"Resources"];
285 return [_fw stringByAppendingPathComponent:@"Resources"];
289 - (NSString *)webServerResourcesPath {
292 if (self->w3resources)
293 return self->w3resources;
295 #if GNUSTEP_BASE_LIBRARY && 0
297 [[self->base stringByAppendingPathComponent:@"Resources/WebServer"] copy];
300 [[self->base stringByAppendingPathComponent:@"WebServerResources"] copy];
303 fm = [self fileManager];
304 if ([self->w3resources length] == 0)
307 if (![fm fileExistsAtPath:self->w3resources]) {
308 static BOOL didLog = NO;
311 [self debugWithFormat:
312 @"WARNING(%s): WebServerResources path '%@' does not exist !",
313 __PRETTY_FUNCTION__, self->w3resources];
315 [self->w3resources release]; self->w3resources = nil;
317 else if (self->existingPathes && (self->w3resources != nil))
318 NSMapInsert(self->existingPathes, self->w3resources, (void*)1);
320 if (debugResourceLookup)
321 [self logWithFormat:@"WebServerResources: '%@'", self->w3resources];
322 return self->w3resources;
325 - (NSString *)pathForResourceNamed:(NSString *)_name
326 inFramework:(NSString *)_frameworkName
327 languages:(NSArray *)_languages
330 NSString *resource = nil;
334 if (debugResourceLookup) {
335 [self logWithFormat:@"lookup '%@' bundle=%@ languages=%@",
336 _name, _frameworkName, [_languages componentsJoinedByString:@","]];
339 fm = [self fileManager];
340 langCount = [_languages count];
342 if ((w3rp = [self webServerResourcesPath]) != nil) {
343 NSString *langPath = nil;
346 if (debugResourceLookup)
347 [self logWithFormat:@" WebServerResources: %@", w3rp];
349 // first check Language.lproj in WebServerResources
350 for (i = 0; i < langCount; i++) {
351 langPath = [_languages objectAtIndex:i];
352 langPath = [langPath stringByAppendingPathExtension:@"lproj"];
353 langPath = [w3rp stringByAppendingPathComponent:langPath];
355 if (!_pathExists(self, fm, langPath)) {
356 if (debugResourceLookup) {
358 @" no language project for '%@' in WebServerResources: %@",
359 [_languages objectAtIndex:i], langPath];
364 resource = [langPath stringByAppendingPathComponent:_name];
366 if (debugResourceLookup)
367 [self logWithFormat:@" check in WebServerResources: %@", resource];
368 if (_pathExists(self, fm, resource))
372 /* next check in WebServerResources itself */
373 resource = [w3rp stringByAppendingPathComponent:_name];
374 if (debugResourceLookup)
375 [self logWithFormat:@" check in WebServerResources-flat: %@", resource];
376 if (_pathExists(self, fm, resource))
380 if ((rp = [self resourcesPathForFramework:_frameworkName])) {
381 NSString *langPath = nil;
384 if (debugResourceLookup) [self logWithFormat:@" path %@", rp];
386 // first check Language.lproj in Resources
387 for (i = 0; i < langCount; i++) {
388 langPath = [_languages objectAtIndex:i];
389 langPath = [langPath stringByAppendingPathExtension:@"lproj"];
390 langPath = [rp stringByAppendingPathComponent:langPath];
392 if (_pathExists(self, fm, langPath)) {
393 resource = [langPath stringByAppendingPathComponent:_name];
395 if (debugResourceLookup)
396 [self logWithFormat:@" check in Resources: %@", resource];
397 if (_pathExists(self, fm, resource))
402 // next check in Resources itself
403 resource = [rp stringByAppendingPathComponent:_name];
404 if (debugResourceLookup)
405 [self logWithFormat:@" check in Resources-flat: %@", resource];
406 if (_pathExists(self, fm, resource)) {
407 if (debugResourceLookup)
408 [self logWithFormat:@" found => %@", resource];
413 /* and last check in the application directory */
414 if (_pathExists(self, fm, self->base)) {
415 resource = [self->base stringByAppendingPathComponent:_name];
416 if (_pathExists(self, fm, resource))
422 - (NSString *)pathForResourceNamed:(NSString *)_name {
424 return [self pathForResourceNamed:_name inFramework:nil languages:nil];
427 - (NSString *)pathForResourceNamed:(NSString *)_name ofType:(NSString *)_type {
428 _name = [_name stringByAppendingPathExtension:_type];
429 return [self pathForResourceNamed:_name];
434 - (NSString *)_urlForMissingResource:(NSString *)_name request:(WORequest *)_r{
437 app = [WOApplication application];
439 if (!genMissingResourceLinks)
442 return [NSString stringWithFormat:
443 @"/missingresource?name=%@&application=%@",
444 _name, app ? [app name] : [_r applicationName]];
447 - (NSString *)urlForResourceNamed:(NSString *)_name
448 inFramework:(NSString *)_frameworkName
449 languages:(NSArray *)_languages
450 request:(WORequest *)_request
453 NSMutableString *url;
454 NSString *resource = nil, *tmp;
455 NSString *path = nil, *sbase;
458 app = [WOApplication application];
460 if (_languages == nil)
461 _languages = [_request browserLanguages];
463 resource = [self pathForResourceNamed:_name
464 inFramework:_frameworkName
465 languages:_languages];
467 if ([resource rangeOfString:@"/Contents/"].length > 0) {
468 resource = [resource stringByReplacingString:@"/Contents"
473 tmp = [resource stringByStandardizingPath];
474 if (tmp != nil) resource = tmp;
477 if (resource == nil) {
478 if (debugResourceLookup)
479 [self logWithFormat:@"did not find resource (cannot build URL)"];
480 return [self _urlForMissingResource:_name request:_request];
484 tmp = [sbase commonPrefixWithString:resource options:0];
487 path = [sbase substringFromIndex:len];
488 tmp = [resource substringFromIndex:len];
489 if (([path length] > 0) && ![tmp hasPrefix:@"/"] && ![tmp hasPrefix:@"\\"])
490 path = [path stringByAppendingString:@"/"];
491 path = [path stringByAppendingString:tmp];
496 cs = [path componentsSeparatedByString:@"\\"];
497 path = [cs componentsJoinedByString:@"/"];
502 return [self _urlForMissingResource:_name request:_request];
504 url = [[NSMutableString alloc] initWithCapacity:256];
506 [url appendString:[_request adaptorPrefix]];
509 [url appendString:resourcePrefix];
510 if (![url hasSuffix:@"/"]) [url appendString:@"/"];
511 [url appendString:app ? [app name] : [_request applicationName]];
512 [url appendString:suffix];
513 if (![path hasPrefix:@"/"]) [url appendString:@"/"];
514 [url appendString:path];
518 return [path autorelease];
521 - (NSString *)urlForResourceNamed:(NSString *)_name {
523 return [self urlForResourceNamed:_name
528 - (NSString *)urlForResourceNamed:(NSString *)_name ofType:(NSString *)_type {
529 return [self urlForResourceNamed:
530 [_name stringByAppendingPathExtension:_type]];
535 - (NSString *)stringForKey:(NSString *)_key
536 inTableNamed:(NSString *)_tableName
537 withDefaultValue:(NSString *)_defaultValue
538 inFramework:(NSString *)_framework
539 languages:(NSArray *)_languages;
542 _WOStringTable *table = nil;
543 NSString *path = nil;
545 fm = [self fileManager];
547 if (_tableName == nil)
548 _tableName = @"default";
550 /* take a look whether a matching table is already loaded */
552 path = [_tableName stringByAppendingPathExtension:@"strings"];
553 path = [self pathForResourceNamed:path inFramework:_framework
554 languages:_languages];
557 if ((table = NSMapGet(self->stringTables, path)) == NULL) {
558 if ([fm fileExistsAtPath:path]) {
559 table = [_WOStringTable allocWithZone:[self zone]]; /* for gcc */
560 table = [table initWithPath:path];
561 NSMapInsert(self->stringTables, path, table);
566 return [table stringForKey:_key withDefaultValue:_defaultValue];
568 /* didn't found table in cache */
570 return _defaultValue;
573 - (NSString *)stringForKey:(NSString *)_key
574 inTableNamed:(NSString *)_tableName
575 withDefaultValue:(NSString *)_default
576 languages:(NSArray *)_languages
578 return [self stringForKey:_key inTableNamed:_tableName
579 withDefaultValue:_default
581 languages:_languages];
592 /* component definitions */
594 - (NSString *)pathToComponentNamed:(NSString *)_name
595 inFramework:(NSString *)_framework
597 /* search for component wrapper .. */
603 NSLog(@"WARNING(%s): tried to get path to component with <nil> name !",
604 __PRETTY_FUNCTION__);
609 /* scan for name.$ext resource ... */
610 e = [[[NSUserDefaults standardUserDefaults]
611 arrayForKey:@"WOComponentExtensions"]
614 while ((ext = [e nextObject])) {
618 specName = [_name stringByAppendingPathExtension:ext];
620 path = [self pathForResourceNamed:specName
621 inFramework:_framework
623 if (path) return path;
628 - (NSString *)pathToComponentNamed:(NSString *)_name
629 inFramework:(NSString *)_framework
630 languages:(NSArray *)_langs
632 return [self pathToComponentNamed:_name inFramework:_framework];
635 - (WOComponentDefinition *)_definitionForPathlessComponent:(NSString *)_name
636 languages:(NSArray *)_languages
638 /* definition factory */
639 WOComponentDefinition *cdef;
641 cdef = [[WOComponentDefinition allocWithZone:[self zone]]
647 return [cdef autorelease];
650 - (WOComponentDefinition *)_definitionWithName:(NSString *)_name
652 baseURL:(NSURL *)_baseURL
653 frameworkName:(NSString *)_fwname
655 /* definition factory */
656 static Class DefClass;
660 DefClass = [WOComponentDefinition class];
662 // TODO: is retained response intended?
663 cdef = [[DefClass alloc] initWithName:_name
665 baseURL:_baseURL frameworkName:_fwname];
668 - (WOComponentDefinition *)_definitionWithName:(NSString *)_name
669 path:(NSString *)_path
670 baseURL:(NSURL *)_baseURL
671 frameworkName:(NSString *)_fwname
675 url = ([_path length] > 0)
676 ? [[[NSURL alloc] initFileURLWithPath:_path] autorelease]
679 return [self _definitionWithName:_name url:url
680 baseURL:_baseURL frameworkName:_fwname];
683 - (WOComponentDefinition *)_cachedDefinitionForComponent:(id)_name
684 languages:(NSArray *)_languages
689 if (self->componentDefinitions == NULL)
691 if (![[WOApplication application] isCachingEnabled])
694 cacheKey = [NSArray arrayWithObjects:_name, _languages, nil];
695 cdef = NSMapGet(self->componentDefinitions, cacheKey);
699 - (WOComponentDefinition *)_cacheDefinition:(id)_cdef
700 forComponent:(id)_name
701 languages:(NSArray *)_languages
705 if (self->componentDefinitions == NULL)
707 if (![[WOApplication application] isCachingEnabled])
710 cacheKey = [NSArray arrayWithObjects:_name, _languages, nil];
711 NSMapInsert(self->componentDefinitions, cacheKey, _cdef ? _cdef : null);
716 - (NSString *)resourceNameForComponentNamed:(NSString *)_name {
717 return [_name stringByAppendingPathExtension:@"wox"];
720 - (WOComponentDefinition *)definitionForComponent:(id)_name
721 inFramework:(NSString *)_framework
722 languages:(NSArray *)_languages
725 NSFileManager *fm = nil;
726 NSEnumerator *languages = nil;
727 NSString *language = nil;
728 WOComponentDefinition *cdef = nil;
729 NSString *sname = nil;
732 BOOL doesCache, isDir;
734 app = [WOApplication application];
735 doesCache = [app isCachingEnabled];
737 /* lookup component path */
739 if ([_name isKindOfClass:UrlClass]) {
740 componentURL = _name;
741 _name = [componentURL path];
742 if (debugComponentLookup) {
743 [self debugWithFormat:@"using URL %@ for component %@",
744 componentURL, _name];
750 if (_framework == nil && _name != nil) {
754 Note: this is a bit of a hack ..., actually this method should never
755 be called without a framework and pages shouldn't be instantiated
756 without specifying their framework.
757 But for legacy reasons this needs to be done and seems to work without
758 problems. It is required for loading components from bundles.
760 if ((_framework = rapidTurnAroundPath) == nil) {
761 if ((clazz = NSClassFromString(_name)))
762 _framework = [[NSBundle bundleForClass:clazz] bundlePath];
766 if (debugComponentLookup) {
767 [self logWithFormat:@"component '%@' in framework '%@'",
771 /* look for .wox component */
773 path = [self pathForResourceNamed:
774 [self resourceNameForComponentNamed:_name]
775 inFramework:_framework
776 languages:_languages];
778 if (debugComponentLookup)
779 [self logWithFormat:@" path: '%@'", path];
781 /* look for .wo component */
783 if ([path length] == 0) {
784 path = [self pathToComponentNamed:_name
785 inFramework:_framework
786 languages:_languages];
787 if (debugComponentLookup)
788 [self logWithFormat:@" path: '%@'", path];
791 /* make URL from path */
793 componentURL = ([path length] > 0)
794 ? [[[UrlClass alloc] initFileURLWithPath:path] autorelease]
798 if (debugComponentLookup) {
799 [self logWithFormat:@" component='%@' in framework='%@': url='%@'",
800 _name, _framework, componentURL];
803 appUrl = [app baseURL];
805 /* check whether it's a 'template-less' component ... */
807 if (componentURL == nil) {
808 /* did not find component wrapper ! */
809 [app debugWithFormat:@" component '%@' has no template !", _name];
811 cdef = [self _definitionForPathlessComponent:_name languages:_languages];
815 fm = [self fileManager];
817 /* ensure that the component exists */
819 if ([componentURL isFileURL]) {
820 NSString *componentPath;
822 componentPath = [componentURL path];
824 if (![fm fileExistsAtPath:componentPath isDirectory:&isDir]) {
825 [[WOApplication application]
827 @"%s: did not find component '%@' at path '%@' !",
829 _name, componentPath];
833 /* if the component spec is a directory (eg a .wo), scan inside for stuff */
836 languages = [_languages objectEnumerator];
838 while ((language = [languages nextObject])) {
839 NSString *compoundKey = nil;
840 NSString *languagePath = nil;
841 BOOL isDirectory = NO;
843 if (sname == nil) sname = [_name stringByAppendingString:@"\t"];
844 compoundKey = [sname stringByAppendingString:language];
847 cdef = NSMapGet(self->componentDefinitions, compoundKey);
849 if (cdef == (id)null)
850 /* resource does not exist */
854 if (cdef) return cdef; // found definition in cache
857 /* take a look into the file system */
858 languagePath = [language stringByAppendingPathExtension:@"lproj"];
860 [componentPath stringByAppendingPathComponent:languagePath];
862 if ([fm fileExistsAtPath:languagePath isDirectory:&isDirectory]) {
863 NSString *baseUrl = nil;
866 NSLog(@"WARNING(%s): language entry %@ is not a directory !",
867 __PRETTY_FUNCTION__, languagePath);
868 if (doesCache && (compoundKey != nil)) {
869 // register null in cache, so that we know it's non-existent
870 NSMapInsert(self->componentDefinitions, compoundKey, null);
875 baseUrl = [NSString stringWithFormat:@"%@/%@.lproj/%@.wo",
876 [appUrl absoluteString], language, _name];
878 /* found appropriate language project */
879 cdef = [self _definitionWithName:_name
881 baseURL:[NSURL URLWithString:baseUrl]
884 NSLog(@"WARNING(%s): could not load component definition of "
885 @"'%@' from language project: %@",
886 __PRETTY_FUNCTION__, _name, languagePath);
887 if (doesCache && (compoundKey != nil)) {
888 // register null in cache, so that we know it's non-existent
889 NSMapInsert(self->componentDefinitions, compoundKey, null);
894 if (doesCache && (compoundKey != nil)) {
896 NSMapInsert(self->componentDefinitions, compoundKey, cdef);
900 // don't register in cache
901 cdef = [cdef autorelease];
908 // register null in cache, so that we know it's non-existent
909 NSMapInsert(self->componentDefinitions, compoundKey, null);
919 cdef = NSMapGet(self->componentDefinitions, componentURL);
921 if (cdef == (id)null)
922 /* resource does not exist */
926 if (cdef) return cdef; // found definition in cache
929 /* take a look into the file system */
931 NSString *baseUrl = nil;
933 baseUrl = [NSString stringWithFormat:@"%@/%@",
934 [appUrl absoluteString], [_name lastPathComponent]];
936 cdef = [self _definitionWithName:_name
938 baseURL:[NSURL URLWithString:baseUrl]
941 NSLog(@"WARNING(%s): could not load component definition of '%@' from "
942 @"component wrapper: '%@'",
943 __PRETTY_FUNCTION__, _name, componentURL);
945 /* register null in cache, so that we know it's non-existent */
946 NSMapInsert(self->componentDefinitions, componentURL, null);
952 /* register in cache */
953 NSMapInsert(self->componentDefinitions, componentURL, cdef);
957 /* don't register in cache, does not cache */
958 cdef = [cdef autorelease];
963 /* did not find component */
966 - (WOComponentDefinition *)definitionForComponent:(id)_name
967 languages:(NSArray *)_langs
969 return [self definitionForComponent:_name inFramework:nil languages:_langs];
972 - (WOComponentDefinition *)__definitionForComponent:(id)_name
973 languages:(NSArray *)_languages
975 WOComponentDefinition *cdef;
977 /* look into cache */
979 cdef = [self _cachedDefinitionForComponent:_name languages:_languages];
981 if (cdef == (id)null)
982 /* component does not exist */
985 if ([cdef respondsToSelector:@selector(touch)])
990 /* not cached, create a definition */
992 cdef = [self definitionForComponent:_name languages:_languages];
994 /* cache created definition */
996 return [self _cacheDefinition:cdef forComponent:_name languages:_languages];
999 - (WOElement *)templateWithName:(NSString *)_name
1000 languages:(NSArray *)_languages
1002 WOComponentDefinition *cdef;
1004 cdef = [self __definitionForComponent:_name languages:_languages];
1005 if (cdef == nil) return nil;
1007 return (WOElement *)[cdef template];
1010 - (WOComponent *)pageWithName:(NSString *)_name
1011 languages:(NSArray *)_languages
1014 TODO: this appears to be deprecated since the WOComponent initializer
1015 is now -initWithContext: and we have no context here ...
1017 NSAutoreleasePool *pool = nil;
1018 WOComponentDefinition *cdef = nil;
1019 WOComponent *component = nil;
1021 pool = [[NSAutoreleasePool alloc] init];
1023 cdef = [self __definitionForComponent:_name languages:_languages];
1026 [cdef instantiateWithResourceManager:self languages:_languages];
1027 component = [component retain];
1032 return [component autorelease];
1037 - (NSString *)description {
1038 return [NSString stringWithFormat:@"<%@[0x%08X]: path=%@>",
1039 [self class], self, self->base];
1045 - (void)setData:(NSData *)_data
1046 forKey:(NSString *)_key
1047 mimeType:(NSString *)_type
1048 session:(WOSession *)_session
1050 if ((_key == nil) || (_data == nil))
1053 _type = @"application/octet-stream";
1057 if (self->keyedResources == NULL) {
1058 self->keyedResources = NSCreateMapTable(NSObjectMapKeyCallBacks,
1059 NSObjectMapValueCallBacks,
1063 NSMapInsert(self->keyedResources,
1065 [NSDictionary dictionaryWithObjectsAndKeys:
1074 - (id)_dataForKey:(NSString *)_key sessionID:(NSString *)_sid {
1079 if (self->keyedResources)
1080 tmp = NSMapGet(self->keyedResources, _key);
1084 tmp = [[tmp retain] autorelease];
1091 - (void)removeDataForKey:(NSString *)_key session:(WOSession *)_session {
1094 if (self->keyedResources)
1095 NSMapRemove(self->keyedResources, _key);
1100 - (void)flushDataCache {
1103 if (self->keyedResources) {
1104 NSFreeMapTable(self->keyedResources);
1105 self->keyedResources = NULL;
1111 @end /* WOResourceManager */