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 #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
72 # define RSRCDIR_CONTENTS 1
75 @implementation WOResourceManager
81 static Class UrlClass = Nil;
82 static NSString *resourcePrefix = @"";
83 static NSString *rapidTurnAroundPath = nil;
84 static NSNull *null = nil;
85 static BOOL debugOn = NO;
86 static BOOL debugComponentLookup = NO;
87 static BOOL debugResourceLookup = NO;
88 static BOOL genMissingResourceLinks = NO;
91 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
92 static BOOL isInitialized = NO;
94 if (isInitialized) return;
97 null = [[NSNull null] retain];
98 UrlClass = [NSURL class];
100 defs = [NSDictionary dictionaryWithObjectsAndKeys:
101 [NSArray arrayWithObject:@"wo"],
102 @"WOComponentExtensions",
104 [ud registerDefaults:defs];
105 debugOn = [WOApplication isDebuggingEnabled];
106 debugComponentLookup = [ud boolForKey:@"WODebugComponentLookup"];
107 debugResourceLookup = [ud boolForKey:@"WODebugResourceLookup"];
108 genMissingResourceLinks = [ud boolForKey:@"WOGenerateMissingResourceLinks"];
109 rapidTurnAroundPath = [[ud stringForKey:@"WOProjectDirectory"] copy];
113 _pathExists(WOResourceManager *self, NSFileManager *fm, NSString *path)
117 if (self->existingPathes && (path != nil)) {
120 i = (int)NSMapGet(self->existingPathes, path);
122 doesExist = [fm fileExistsAtPath:path];
123 NSMapInsert(self->existingPathes, path, (void*)(doesExist ? 1 : 0xFF));
126 doesExist = i == 1 ? YES : NO;
129 doesExist = [fm fileExistsAtPath:path];
133 + (void)setResourcePrefix:(NSString *)_prefix {
134 [resourcePrefix autorelease];
135 resourcePrefix = [_prefix copy];
138 - (id)initWithPath:(NSString *)_path {
140 if ([_path length] == 0) {
141 NSLog(@"ERROR(%s): missing path!", __PRETTY_FUNCTION__);
142 /* this doesn't work with subclasses which do not require a path ... */
150 if ((self = [super init])) {
151 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
152 NSString *rprefix = nil;
155 self->componentDefinitions =
156 NSCreateMapTable(NSObjectMapKeyCallBacks,
157 NSObjectMapValueCallBacks,
160 NSCreateMapTable(NSObjectMapKeyCallBacks,
161 NSObjectMapValueCallBacks,
164 tmp = [_path stringByStandardizingPath];
165 if (tmp) _path = tmp;
167 self->base = [_path copy];
169 if ([WOApplication isCachingEnabled]) {
170 self->existingPathes = NSCreateMapTable(NSObjectMapKeyCallBacks,
171 NSIntMapValueCallBacks,
175 rprefix = [ud stringForKey:@"WOResourcePrefix"];
176 if (rprefix) [[self class] setResourcePrefix:rprefix];
181 return [self initWithPath:[[NGBundle mainBundle] bundlePath]];
185 if (self->existingPathes) NSFreeMapTable(self->existingPathes);
186 if (self->stringTables) NSFreeMapTable(self->stringTables);
187 if (self->componentDefinitions) NSFreeMapTable(self->componentDefinitions);
188 if (self->keyedResources) NSFreeMapTable(self->keyedResources);
189 [self->w3resources release];
190 [self->resources release];
191 [self->base release];
197 - (BOOL)isDebuggingEnabled {
203 - (NSFileManager *)fileManager {
204 static NSFileManager *fm = nil;
206 fm = [[NSFileManager defaultManager] retain];
210 - (NSString *)basePath {
214 - (NSString *)resourcesPath {
218 return self->resources;
220 fm = [self fileManager];
221 if ([self->base length] > 0) {
222 if (![fm fileExistsAtPath:self->base]) {
223 NSLog(@"WARNING(%s): Resources base path '%@' does not exist !",
224 __PRETTY_FUNCTION__, self->base);
230 if ([rapidTurnAroundPath length] > 0) {
232 In rapid turnaround mode, first check for a Resources subdir in the
233 project directory, then directly in the project dir.
234 Note: you cannot have both! Either put stuff in a Resources subdir *or*
240 tmp = [rapidTurnAroundPath stringByAppendingPathComponent:@"Resources"];
241 if (![fm fileExistsAtPath:tmp isDirectory:&isDir])
244 tmp = rapidTurnAroundPath;
246 self->resources = [tmp copy];
250 [[[self->base stringByAppendingPathComponent:@"Contents"]
251 stringByAppendingPathComponent:@"Resources"]
256 [[self->base stringByAppendingPathComponent:@"Resources"] copy];
259 if ([self->resources length] > 0) {
260 if (![fm fileExistsAtPath:self->resources]) {
261 [self debugWithFormat:
262 @"WARNING(%s): Resources path %@ does not exist !",
263 __PRETTY_FUNCTION__, self->resources];
264 [self->resources release]; self->resources = nil;
266 else if (self->existingPathes && (self->resources != nil))
267 NSMapInsert(self->existingPathes, self->resources, (void*)1);
269 return self->resources;
272 - (NSString *)resourcesPathForFramework:(NSString *)_fw {
274 return [self resourcesPath];
277 return [[_fw stringByAppendingPathComponent:@"Contents"]
278 stringByAppendingPathComponent:@"Resources"];
280 return [_fw stringByAppendingPathComponent:@"Resources"];
284 - (NSString *)webServerResourcesPath {
287 if (self->w3resources)
288 return self->w3resources;
290 #if GNUSTEP_BASE_LIBRARY && 0
292 [[self->base stringByAppendingPathComponent:@"Resources/WebServer"] copy];
295 [[self->base stringByAppendingPathComponent:@"WebServerResources"] copy];
298 fm = [self fileManager];
299 if ([self->w3resources length] == 0)
302 if (![fm fileExistsAtPath:self->w3resources]) {
303 static BOOL didLog = NO;
306 [self debugWithFormat:
307 @"WARNING(%s): WebServerResources path '%@' does not exist !",
308 __PRETTY_FUNCTION__, self->w3resources];
310 [self->w3resources release]; self->w3resources = nil;
312 else if (self->existingPathes && (self->w3resources != nil))
313 NSMapInsert(self->existingPathes, self->w3resources, (void*)1);
315 if (debugResourceLookup)
316 [self logWithFormat:@"WebServerResources: '%@'", self->w3resources];
317 return self->w3resources;
320 - (NSString *)pathForResourceNamed:(NSString *)_name
321 inFramework:(NSString *)_frameworkName
322 languages:(NSArray *)_languages
325 NSString *resource = nil;
329 if (debugResourceLookup) {
330 [self logWithFormat:@"lookup '%@' bundle=%@ languages=%@",
331 _name, _frameworkName, [_languages componentsJoinedByString:@","]];
334 fm = [self fileManager];
335 langCount = [_languages count];
337 if ((w3rp = [self webServerResourcesPath])) {
338 NSString *langPath = nil;
341 // first check Language.lproj in WebServerResources
342 for (i = 0; i < langCount; i++) {
343 langPath = [_languages objectAtIndex:i];
344 langPath = [langPath stringByAppendingPathExtension:@"lproj"];
345 langPath = [w3rp stringByAppendingPathComponent:langPath];
347 if (!_pathExists(self, fm, langPath)) {
348 if (debugResourceLookup) {
350 @" no language project for '%@' in WebServerResources: %@",
351 [_languages objectAtIndex:i],resource];
356 resource = [langPath stringByAppendingPathComponent:_name];
358 if (debugResourceLookup)
359 [self logWithFormat:@" check in WebServerResources: %@", resource];
360 if (_pathExists(self, fm, resource))
364 /* next check in WebServerResources itself */
365 resource = [w3rp stringByAppendingPathComponent:_name];
366 if (debugResourceLookup)
367 [self logWithFormat:@" check in WebServerResources-flat: %@", resource];
368 if (_pathExists(self, fm, resource))
372 if ((rp = [self resourcesPathForFramework:_frameworkName])) {
373 NSString *langPath = nil;
376 if (debugResourceLookup) [self logWithFormat:@" path %@", rp];
378 // first check Language.lproj in Resources
379 for (i = 0; i < langCount; i++) {
380 langPath = [_languages objectAtIndex:i];
381 langPath = [langPath stringByAppendingPathExtension:@"lproj"];
382 langPath = [rp stringByAppendingPathComponent:langPath];
384 if (_pathExists(self, fm, langPath)) {
385 resource = [langPath stringByAppendingPathComponent:_name];
387 if (debugResourceLookup)
388 [self logWithFormat:@" check in Resources: %@", resource];
389 if (_pathExists(self, fm, resource))
394 // next check in Resources itself
395 resource = [rp stringByAppendingPathComponent:_name];
396 if (debugResourceLookup)
397 [self logWithFormat:@" check in Resources-flat: %@", resource];
398 if (_pathExists(self, fm, resource))
402 /* and last check in the application directory */
403 if (_pathExists(self, fm, self->base)) {
404 resource = [self->base stringByAppendingPathComponent:_name];
405 if (_pathExists(self, fm, resource))
411 - (NSString *)pathForResourceNamed:(NSString *)_name {
413 return [self pathForResourceNamed:_name inFramework:nil languages:nil];
416 - (NSString *)pathForResourceNamed:(NSString *)_name ofType:(NSString *)_type {
417 _name = [_name stringByAppendingPathExtension:_type];
418 return [self pathForResourceNamed:_name];
423 - (NSString *)urlForResourceNamed:(NSString *)_name
424 inFramework:(NSString *)_frameworkName
425 languages:(NSArray *)_languages
426 request:(WORequest *)_request
429 NSString *resource = nil, *tmp;
431 app = [WOApplication application];
433 if (_languages == nil)
434 _languages = [_request browserLanguages];
436 resource = [self pathForResourceNamed:_name
437 inFramework:_frameworkName
438 languages:_languages];
440 if ([resource rangeOfString:@"/Contents/"].length > 0) {
441 resource = [resource stringByReplacingString:@"/Contents"
446 tmp = [resource stringByStandardizingPath];
447 if (tmp) resource = tmp;
451 NSString *path = nil, *sbase;
455 tmp = [sbase commonPrefixWithString:resource options:0];
458 path = [sbase substringFromIndex:len];
459 tmp = [resource substringFromIndex:len];
460 if (([path length] > 0) && ![tmp hasPrefix:@"/"] && ![tmp hasPrefix:@"\\"])
461 path = [path stringByAppendingString:@"/"];
462 path = [path stringByAppendingString:tmp];
467 cs = [path componentsSeparatedByString:@"\\"];
468 path = [cs componentsJoinedByString:@"/"];
473 static NSString *suffix = nil;
474 NSMutableString *url = nil;
477 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
478 suffix = [ud stringForKey:@"WOApplicationSuffix"];
481 url = [[NSMutableString alloc] initWithCapacity:256];
483 [url appendString:[_request adaptorPrefix]];
486 [url appendString:resourcePrefix];
487 if (![url hasSuffix:@"/"]) [url appendString:@"/"];
488 [url appendString:app ? [app name] : [_request applicationName]];
489 [url appendString:suffix];
490 if (![path hasPrefix:@"/"]) [url appendString:@"/"];
491 [url appendString:path];
496 return [path autorelease];
500 if (genMissingResourceLinks) {
501 return [NSString stringWithFormat:
502 @"/missingresource?name=%@&application=%@",
503 _name, app ? [app name] : [_request applicationName]];
508 - (NSString *)urlForResourceNamed:(NSString *)_name {
510 return [self urlForResourceNamed:_name
515 - (NSString *)urlForResourceNamed:(NSString *)_name ofType:(NSString *)_type {
516 return [self urlForResourceNamed:
517 [_name stringByAppendingPathExtension:_type]];
522 - (NSString *)stringForKey:(NSString *)_key
523 inTableNamed:(NSString *)_tableName
524 withDefaultValue:(NSString *)_defaultValue
525 inFramework:(NSString *)_framework
526 languages:(NSArray *)_languages;
529 _WOStringTable *table = nil;
530 NSString *path = nil;
532 fm = [self fileManager];
534 if (_tableName == nil)
535 _tableName = @"default";
537 /* take a look whether a matching table is already loaded */
539 path = [_tableName stringByAppendingPathExtension:@"strings"];
540 path = [self pathForResourceNamed:path inFramework:_framework
541 languages:_languages];
544 if ((table = NSMapGet(self->stringTables, path)) == NULL) {
545 if ([fm fileExistsAtPath:path]) {
546 table = [_WOStringTable allocWithZone:[self zone]]; /* for gcc */
547 table = [table initWithPath:path];
548 NSMapInsert(self->stringTables, path, table);
553 return [table stringForKey:_key withDefaultValue:_defaultValue];
555 /* didn't found table in cache */
557 return _defaultValue;
560 - (NSString *)stringForKey:(NSString *)_key
561 inTableNamed:(NSString *)_tableName
562 withDefaultValue:(NSString *)_default
563 languages:(NSArray *)_languages
565 return [self stringForKey:_key inTableNamed:_tableName
566 withDefaultValue:_default
568 languages:_languages];
579 /* component definitions */
581 - (NSString *)pathToComponentNamed:(NSString *)_name
582 inFramework:(NSString *)_framework
584 /* search for component wrapper .. */
590 NSLog(@"WARNING(%s): tried to get path to component with <nil> name !",
591 __PRETTY_FUNCTION__);
596 /* scan for name.$ext resource ... */
597 e = [[[NSUserDefaults standardUserDefaults]
598 arrayForKey:@"WOComponentExtensions"]
601 while ((ext = [e nextObject])) {
605 specName = [_name stringByAppendingPathExtension:ext];
607 path = [self pathForResourceNamed:specName
608 inFramework:_framework
610 if (path) return path;
615 - (NSString *)pathToComponentNamed:(NSString *)_name
616 inFramework:(NSString *)_framework
617 languages:(NSArray *)_langs
619 return [self pathToComponentNamed:_name inFramework:_framework];
622 - (WOComponentDefinition *)_definitionForPathlessComponent:(NSString *)_name
623 languages:(NSArray *)_languages
625 /* definition factory */
626 WOComponentDefinition *cdef;
628 cdef = [[WOComponentDefinition allocWithZone:[self zone]]
634 return [cdef autorelease];
637 - (WOComponentDefinition *)_definitionWithName:(NSString *)_name
639 baseURL:(NSURL *)_baseURL
640 frameworkName:(NSString *)_fwname
642 /* definition factory */
643 static Class DefClass;
647 DefClass = [WOComponentDefinition class];
649 // TODO: is retained response intended?
650 cdef = [[DefClass alloc] initWithName:_name
652 baseURL:_baseURL frameworkName:_fwname];
655 - (WOComponentDefinition *)_definitionWithName:(NSString *)_name
656 path:(NSString *)_path
657 baseURL:(NSURL *)_baseURL
658 frameworkName:(NSString *)_fwname
662 url = ([_path length] > 0)
663 ? [[[NSURL alloc] initFileURLWithPath:_path] autorelease]
666 return [self _definitionWithName:_name url:url
667 baseURL:_baseURL frameworkName:_fwname];
670 - (WOComponentDefinition *)_cachedDefinitionForComponent:(id)_name
671 languages:(NSArray *)_languages
676 if (self->componentDefinitions == NULL)
678 if (![[WOApplication application] isCachingEnabled])
681 cacheKey = [NSArray arrayWithObjects:_name, _languages, nil];
682 cdef = NSMapGet(self->componentDefinitions, cacheKey);
686 - (WOComponentDefinition *)_cacheDefinition:(id)_cdef
687 forComponent:(id)_name
688 languages:(NSArray *)_languages
692 if (self->componentDefinitions == NULL)
694 if (![[WOApplication application] isCachingEnabled])
697 cacheKey = [NSArray arrayWithObjects:_name, _languages, nil];
698 NSMapInsert(self->componentDefinitions, cacheKey, _cdef ? _cdef : null);
703 - (NSString *)resourceNameForComponentNamed:(NSString *)_name {
704 return [_name stringByAppendingPathExtension:@"wox"];
707 - (WOComponentDefinition *)definitionForComponent:(id)_name
708 inFramework:(NSString *)_framework
709 languages:(NSArray *)_languages
712 NSFileManager *fm = nil;
713 NSEnumerator *languages = nil;
714 NSString *language = nil;
715 WOComponentDefinition *cdef = nil;
716 NSString *sname = nil;
719 BOOL doesCache, isDir;
721 app = [WOApplication application];
722 doesCache = [app isCachingEnabled];
724 /* lookup component path */
726 if ([_name isKindOfClass:UrlClass]) {
727 componentURL = _name;
728 _name = [componentURL path];
729 if (debugComponentLookup) {
730 [self debugWithFormat:@"using URL %@ for component %@",
731 componentURL, _name];
737 if (_framework == nil && _name != nil) {
741 Note: this is a bit of a hack ..., actually this method should never
742 be called without a framework and pages shouldn't be instantiated
743 without specifying their framework.
744 But for legacy reasons this needs to be done and seems to work without
745 problems. It is required for loading components from bundles.
747 if ((_framework = rapidTurnAroundPath) == nil) {
748 if ((clazz = NSClassFromString(_name)))
749 _framework = [[NSBundle bundleForClass:clazz] bundlePath];
753 if (debugComponentLookup) {
754 [self logWithFormat:@"component '%@' in framework '%@'",
758 /* look for .wox component */
760 path = [self pathForResourceNamed:
761 [self resourceNameForComponentNamed:_name]
762 inFramework:_framework
763 languages:_languages];
765 if (debugComponentLookup)
766 [self logWithFormat:@" path: '%@'", path];
768 /* look for .wo component */
770 if ([path length] == 0) {
771 path = [self pathToComponentNamed:_name
772 inFramework:_framework
773 languages:_languages];
774 if (debugComponentLookup)
775 [self logWithFormat:@" path: '%@'", path];
778 /* make URL from path */
780 componentURL = ([path length] > 0)
781 ? [[[UrlClass alloc] initFileURLWithPath:path] autorelease]
785 if (debugComponentLookup) {
786 [self logWithFormat:@" component='%@' in framework='%@': url='%@'",
787 _name, _framework, componentURL];
790 appUrl = [app baseURL];
792 /* check whether it's a 'template-less' component ... */
794 if (componentURL == nil) {
795 /* did not find component wrapper ! */
796 [app debugWithFormat:@" component '%@' has no template !", _name];
798 cdef = [self _definitionForPathlessComponent:_name languages:_languages];
802 fm = [self fileManager];
804 /* ensure that the component exists */
806 if ([componentURL isFileURL]) {
807 NSString *componentPath;
809 componentPath = [componentURL path];
811 if (![fm fileExistsAtPath:componentPath isDirectory:&isDir]) {
812 [[WOApplication application]
814 @"%s: did not find component '%@' at path '%@' !",
816 _name, componentPath];
820 /* if the component spec is a directory (eg a .wo), scan inside for stuff */
823 languages = [_languages objectEnumerator];
825 while ((language = [languages nextObject])) {
826 NSString *compoundKey = nil;
827 NSString *languagePath = nil;
828 BOOL isDirectory = NO;
830 if (sname == nil) sname = [_name stringByAppendingString:@"\t"];
831 compoundKey = [sname stringByAppendingString:language];
834 cdef = NSMapGet(self->componentDefinitions, compoundKey);
836 if (cdef == (id)null)
837 /* resource does not exist */
841 if (cdef) return cdef; // found definition in cache
844 /* take a look into the file system */
845 languagePath = [language stringByAppendingPathExtension:@"lproj"];
847 [componentPath stringByAppendingPathComponent:languagePath];
849 if ([fm fileExistsAtPath:languagePath isDirectory:&isDirectory]) {
850 NSString *baseUrl = nil;
853 NSLog(@"WARNING(%s): language entry %@ is not a directory !",
854 __PRETTY_FUNCTION__, languagePath);
855 if (doesCache && (compoundKey != nil)) {
856 // register null in cache, so that we know it's non-existent
857 NSMapInsert(self->componentDefinitions, compoundKey, null);
862 baseUrl = [NSString stringWithFormat:@"%@/%@.lproj/%@.wo",
863 [appUrl absoluteString], language, _name];
865 /* found appropriate language project */
866 cdef = [self _definitionWithName:_name
868 baseURL:[NSURL URLWithString:baseUrl]
871 NSLog(@"WARNING(%s): could not load component definition of "
872 @"'%@' from language project: %@",
873 __PRETTY_FUNCTION__, _name, languagePath);
874 if (doesCache && (compoundKey != nil)) {
875 // register null in cache, so that we know it's non-existent
876 NSMapInsert(self->componentDefinitions, compoundKey, null);
881 if (doesCache && (compoundKey != nil)) {
883 NSMapInsert(self->componentDefinitions, compoundKey, cdef);
887 // don't register in cache
888 cdef = [cdef autorelease];
895 // register null in cache, so that we know it's non-existent
896 NSMapInsert(self->componentDefinitions, compoundKey, null);
906 cdef = NSMapGet(self->componentDefinitions, componentURL);
908 if (cdef == (id)null)
909 /* resource does not exist */
913 if (cdef) return cdef; // found definition in cache
916 /* take a look into the file system */
918 NSString *baseUrl = nil;
920 baseUrl = [NSString stringWithFormat:@"%@/%@",
921 [appUrl absoluteString], [_name lastPathComponent]];
923 cdef = [self _definitionWithName:_name
925 baseURL:[NSURL URLWithString:baseUrl]
928 NSLog(@"WARNING(%s): could not load component definition of '%@' from "
929 @"component wrapper: '%@'",
930 __PRETTY_FUNCTION__, _name, componentURL);
932 /* register null in cache, so that we know it's non-existent */
933 NSMapInsert(self->componentDefinitions, componentURL, null);
939 /* register in cache */
940 NSMapInsert(self->componentDefinitions, componentURL, cdef);
944 /* don't register in cache, does not cache */
945 cdef = [cdef autorelease];
950 /* did not find component */
953 - (WOComponentDefinition *)definitionForComponent:(id)_name
954 languages:(NSArray *)_langs
956 return [self definitionForComponent:_name inFramework:nil languages:_langs];
959 - (WOComponentDefinition *)__definitionForComponent:(id)_name
960 languages:(NSArray *)_languages
962 WOComponentDefinition *cdef;
964 /* look into cache */
966 cdef = [self _cachedDefinitionForComponent:_name languages:_languages];
968 if (cdef == (id)null)
969 /* component does not exist */
972 if ([cdef respondsToSelector:@selector(touch)])
977 /* not cached, create a definition */
979 cdef = [self definitionForComponent:_name languages:_languages];
981 /* cache created definition */
983 return [self _cacheDefinition:cdef forComponent:_name languages:_languages];
986 - (WOElement *)templateWithName:(NSString *)_name
987 languages:(NSArray *)_languages
989 WOComponentDefinition *cdef;
991 cdef = [self __definitionForComponent:_name languages:_languages];
992 if (cdef == nil) return nil;
994 return (WOElement *)[cdef template];
997 - (WOComponent *)pageWithName:(NSString *)_name
998 languages:(NSArray *)_languages
1001 TODO: this appears to be deprecated since the WOComponent initializer
1002 is now -initWithContext: and we have no context here ...
1004 NSAutoreleasePool *pool = nil;
1005 WOComponentDefinition *cdef = nil;
1006 WOComponent *component = nil;
1008 pool = [[NSAutoreleasePool alloc] init];
1010 cdef = [self __definitionForComponent:_name languages:_languages];
1013 [cdef instantiateWithResourceManager:self languages:_languages];
1014 component = [component retain];
1019 return [component autorelease];
1024 - (NSString *)description {
1025 return [NSString stringWithFormat:@"<%@[0x%08X]: path=%@>",
1026 [self class], self, self->base];
1030 @end /* WOResourceManager */
1032 @implementation WOResourceManager(KeyedData)
1034 - (void)setData:(NSData *)_data
1035 forKey:(NSString *)_key
1036 mimeType:(NSString *)_type
1037 session:(WOSession *)_session
1039 if ((_key == nil) || (_data == nil))
1042 _type = @"application/octet-stream";
1046 if (self->keyedResources == NULL) {
1047 self->keyedResources = NSCreateMapTable(NSObjectMapKeyCallBacks,
1048 NSObjectMapValueCallBacks,
1052 NSMapInsert(self->keyedResources,
1054 [NSDictionary dictionaryWithObjectsAndKeys:
1063 - (id)_dataForKey:(NSString *)_key sessionID:(NSString *)_sid {
1068 if (self->keyedResources)
1069 tmp = NSMapGet(self->keyedResources, _key);
1073 tmp = [[tmp retain] autorelease];
1080 - (void)removeDataForKey:(NSString *)_key session:(WOSession *)_session {
1083 if (self->keyedResources)
1084 NSMapRemove(self->keyedResources, _key);
1089 - (void)flushDataCache {
1092 if (self->keyedResources) {
1093 NSFreeMapTable(self->keyedResources);
1094 self->keyedResources = NULL;
1100 @end /* WOResourceManager(KeyedData) */
1102 @implementation WOResourceManager(JavaScript)
1104 - (id)_jsfunc_pathForResourceNamed:(NSArray *)_args {
1105 unsigned argc = [_args count];
1107 return [self pathForResourceNamed:
1108 argc > 0 ? [_args objectAtIndex:0] : nil
1109 inFramework:argc > 1 ? [_args objectAtIndex:1] : nil
1110 languages:argc > 2 ? [_args objectAtIndex:2] : nil];
1113 - (id)_jsfunc_loadPropertyListNamed:(NSArray *)_args {
1116 if ((s = [self _jsfunc_pathForResourceNamed:_args]) == nil)
1119 if ((s = [NSString stringWithContentsOfFile:s]) == nil)
1122 return [s propertyList];
1125 @end /* WOResourceManager(JavaScript) */