From 39c130d0f5f8c70e3dc6144641a644ad6d1ced6c Mon Sep 17 00:00:00 2001 From: Dave Wetzel Date: Tue, 22 Jun 2010 05:02:29 +0000 Subject: [PATCH] * GSWExtensions/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswd * GSWExtensions/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswd * GSWExtensions/GNUmakefile * GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswd * GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.gswd use exclamation.png. exclamation.svg is not displayed inline in mozilla due to a bug in mozilla. * GSWExtensions/WebServerResources/exclamation.png * GSWExtensions/WebServerResources/exclamation.svg new file * GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html * GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.html better web design * GSWeb/GSWApplication.m -path get path from _resourceManager _resetCache do not call _clearCache, maybe we should trash the _componentDefinitionCache? _finishInitializingSession: make empty, still seems to work +_applicationClass don not use _applicationGSWBundle * GSWeb/GSWResourceManager.h * GSWeb/GSWResourceManager.m major redesign with WO 4.5 docs in mind. * GSWeb/GSWImageButton.m refactor resourceManager code * GSWeb/GSWeb.h remove GSWBundle class * Testing/DynamicElements added Image test. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@30806 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 33 + Examples/WebBookStore1/GNUmakefile | 2 +- GSWExtensions/GNUmakefile | 3 +- .../GSWExceptionPage.gswd | 8 + .../GSWExceptionPage.html | 177 +- .../GSWPageRestorationErrorPage.gswd | 8 +- .../GSWSessionCreationErrorPage.gswd | 8 +- .../GSWSessionRestorationErrorPage.gswd | 8 +- .../GSWSessionRestorationErrorPage.html | 51 +- .../WebServerResources/exclamation.png | Bin 0 -> 4148 bytes .../WebServerResources/exclamation.svg | 35 + GSWeb/GSWActionRequestHandler.m | 6 - GSWeb/GSWActiveImage.m | 35 +- GSWeb/GSWApplication.m | 140 +- GSWeb/GSWBundle.h | 120 +- GSWeb/GSWBundle.m | 1005 +---------- GSWeb/GSWComponent.h | 62 +- GSWeb/GSWComponent.m | 184 +- GSWeb/GSWComponentDefinition.h | 11 +- GSWeb/GSWComponentDefinition.m | 260 +-- GSWeb/GSWContext.m | 2 +- GSWeb/GSWDynamicURLString.m | 18 +- GSWeb/GSWHTTPIO.m | 29 +- GSWeb/GSWImage.m | 162 +- GSWeb/GSWImageButton.m | 32 +- GSWeb/GSWResourceManager.h | 134 +- GSWeb/GSWResourceManager.m | 1547 ++++------------- GSWeb/GSWResourceRequestHandler.h | 4 - GSWeb/GSWResourceRequestHandler.m | 144 +- GSWeb/GSWResponse.m | 12 +- GSWeb/GSWeb.h | 3 +- GSWeb/Resources/MIME.plist | 1 + Testing/DynamicElements/GNUmakefile | 7 +- Testing/DynamicElements/ImagePage.h | 39 + Testing/DynamicElements/ImagePage.m | 38 + .../ImagePage.wo/ImagePage.html | 14 + .../ImagePage.wo/ImagePage.wod | 11 + .../ImagePage.wo/ImagePage.woo | 1 + .../Resources/Info-DynamicElements.plist | 5 + .../WebServerResources/testpic.jpg | Bin 0 -> 38220 bytes 40 files changed, 1306 insertions(+), 3053 deletions(-) create mode 100644 GSWExtensions/WebServerResources/exclamation.png create mode 100644 GSWExtensions/WebServerResources/exclamation.svg create mode 100644 Testing/DynamicElements/ImagePage.h create mode 100644 Testing/DynamicElements/ImagePage.m create mode 100644 Testing/DynamicElements/ImagePage.wo/ImagePage.html create mode 100644 Testing/DynamicElements/ImagePage.wo/ImagePage.wod create mode 100644 Testing/DynamicElements/ImagePage.wo/ImagePage.woo create mode 100644 Testing/DynamicElements/WebServerResources/testpic.jpg diff --git a/ChangeLog b/ChangeLog index eadc477..c792e2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2010-06-21 David Wetzel + * GSWExtensions/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswd + * GSWExtensions/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswd + * GSWExtensions/GNUmakefile + * GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswd + * GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.gswd + use exclamation.png. exclamation.svg is not displayed inline in mozilla + due to a bug in mozilla. + * GSWExtensions/WebServerResources/exclamation.png + * GSWExtensions/WebServerResources/exclamation.svg + new file + * GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html + * GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.html + better web design + * GSWeb/GSWApplication.m + -path + get path from _resourceManager + _resetCache + do not call _clearCache, maybe we should trash the _componentDefinitionCache? + _finishInitializingSession: + make empty, still seems to work + +_applicationClass + don not use _applicationGSWBundle + * GSWeb/GSWResourceManager.h + * GSWeb/GSWResourceManager.m + major redesign with WO 4.5 docs in mind. + * GSWeb/GSWImageButton.m + refactor resourceManager code + * GSWeb/GSWeb.h + remove GSWBundle class + * Testing/DynamicElements + added Image test. + 2010-06-18 David Wetzel * GSWeb/GSWContext.m - computeQueryDictionaryWithPath:queryDictionary:otherQueryDictionary diff --git a/Examples/WebBookStore1/GNUmakefile b/Examples/WebBookStore1/GNUmakefile index ad1a4db..6f747b4 100644 --- a/Examples/WebBookStore1/GNUmakefile +++ b/Examples/WebBookStore1/GNUmakefile @@ -27,7 +27,7 @@ include $(GNUSTEP_MAKEFILES)/Auxiliary/gsweb.make GSWAPP_NAME=WebBookStore1 WebBookStore1_HAS_GSWCOMPONENTS=YES -WebBookStore1_PRINCIPAL_CLASS=WebBookStore1 +WebBookStore1_PRINCIPAL_CLASS=Application WebBookStore1_GSWAPP_INFO_PLIST=Resources/Info-WebBookStore1.plist # The Objective-C source files to be compiled diff --git a/GSWExtensions/GNUmakefile b/GSWExtensions/GNUmakefile index 13c6a40..27abd80 100644 --- a/GSWExtensions/GNUmakefile +++ b/GSWExtensions/GNUmakefile @@ -124,7 +124,8 @@ appOff.png \ appOn.png \ back.png \ dir.png \ -exclamation.mng \ +exclamation.png \ +exclamation.svg \ eye.png \ lft-OSarw.png \ rt-OSarw.png \ diff --git a/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.gswd b/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.gswd index 1ae24ec..c2eeb5b 100644 --- a/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.gswd +++ b/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.gswd @@ -1,3 +1,11 @@ +ExclamationImage: GSWImage +{ + filename = "exclamation.png"; + framework = "WOExtensions"; + height="50"; + width="60"; + alt="exclamation sign" +} ApplicationNameString: GSWString { diff --git a/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.html b/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.html index 7fdb2a6..df1be7b 100644 --- a/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.html +++ b/GSWExtensions/GSWExceptionPage.gswc/GSWExceptionPage.html @@ -1,86 +1,95 @@ - - - GNUstepWeb Error - - - - - - - - - - - -
-

[!] An error occured in application .

-

<< Re-enter

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + GNUstepWeb Error + + + + +
+ +

An error occured in application .

+

Re-enter to continue.

+ +
- Application: - - -
- Reference: - - -
- Error: - - -
- Reason: - - -
-
-
-
- User Info Dictionary: -
- : - - -
+ + + + + + + + + + + + + + + - - - - -
+ Application: + + +
+ Reference: + + +
+ Error: + + +
+ Reason: + + +
- -
- - Exception has no userInfo dictionary -
-
-

Powered by GNUstep Web

- + + + + +
+ User Info Dictionary: + + + + + + + : + + + + + + + + + + + + + Exception has no userInfo dictionary + + + + + +

Powered by GNUstep Web

+ + + diff --git a/GSWExtensions/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswd b/GSWExtensions/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswd index e5f2740..dd296aa 100644 --- a/GSWExtensions/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswd +++ b/GSWExtensions/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswd @@ -1,8 +1,10 @@ ExclamationImage: GSWImage { - filename = "exclamation.mng"; - framework = "GSWExtensions"; - border = 0; + filename = "exclamation.png"; + framework = "WOExtensions"; + height="50"; + width="60"; + alt="exclamation sign" } ApplicationNameString: GSWString diff --git a/GSWExtensions/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswd b/GSWExtensions/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswd index 259a571..6b100c3 100644 --- a/GSWExtensions/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswd +++ b/GSWExtensions/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswd @@ -1,9 +1,11 @@ ExclamationImage: GSWImage { - filename = "exclamation.mng"; - framework = "GSWExtensions"; - border = 0; + filename = "exclamation.png"; + framework = "WOExtensions"; + height="50"; + width="60"; + alt="exclamation sign" } ApplicationNameString: GSWString diff --git a/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswd b/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswd index 60647f6..fb181f7 100644 --- a/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswd +++ b/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswd @@ -1,8 +1,10 @@ ExclamationImage: GSWImage { - filename = "exclamation.mng"; - framework = "GSWExtensions"; - border = 0; + filename = "exclamation.png"; + framework = "WOExtensions"; + height="50"; + width="60"; + alt="exclamation sign" } ApplicationNameString: GSWString diff --git a/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html b/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html index 187bfb6..3688ee7 100644 --- a/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html +++ b/GSWExtensions/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html @@ -1,24 +1,29 @@ - - - Missing Session Error - - - - - - - - - -
-
- Re-enter
- - - -
- Your session has timed out. -
- - + + + + + + + Missing Session Error + + + +
+ +

Your session has timed out.

+

Re-enter to continue.

+

Powered by GNUstep Web

+
+ diff --git a/GSWExtensions/WebServerResources/exclamation.png b/GSWExtensions/WebServerResources/exclamation.png new file mode 100644 index 0000000000000000000000000000000000000000..9f57b8b9037c401efdf5445d7e296f51e41f298f GIT binary patch literal 4148 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GSWeb/GSWActionRequestHandler.m b/GSWeb/GSWActionRequestHandler.m index 813e6de..f380473 100644 --- a/GSWeb/GSWActionRequestHandler.m +++ b/GSWeb/GSWActionRequestHandler.m @@ -333,13 +333,7 @@ RCS_ID("$Id$") if (actionClass) { - GSWResourceManager* resourceManager=nil; - GSWDeployedBundle* appBundle=nil; id actionResult=nil; - - resourceManager=[application resourceManager]; - appBundle=[resourceManager _appProjectBundle]; - [resourceManager _allFrameworkProjectBundles];//So what ? NS_DURING { diff --git a/GSWeb/GSWActiveImage.m b/GSWeb/GSWActiveImage.m index fb52fde..259a70c 100644 --- a/GSWeb/GSWActiveImage.m +++ b/GSWeb/GSWActiveImage.m @@ -389,27 +389,22 @@ static NSString * static_tempQueryKey = nil; GSWAssociation* actionAssociation=nil; NSArray* regions=nil; if (_file) + { + id imageMapFileNameValue=[_file valueInComponent:component]; + NSString* imageMapFilePath; + GSWResourceManager* resourceManager=[[GSWApplication application]resourceManager]; + NSArray* languages=[aContext languages]; + imageMapFilePath=[resourceManager pathForResourceNamed:imageMapFileNameValue + inFramework:nil + languages:languages]; + + if (imageMapFilePath) + regions=[GSWGeometricRegion geometricRegionsWithFile:imageMapFilePath]; + else { - id imageMapFileNameValue=[_file valueInComponent:component]; - NSString* imageMapFilePath=[GSWContext_component(aContext) - pathForResourceNamed:imageMapFileNameValue - ofType:nil]; - if (!imageMapFilePath) - { - GSWResourceManager* resourceManager=[[GSWApplication application]resourceManager]; - NSArray* languages=[aContext languages]; - imageMapFilePath=[resourceManager pathForResourceNamed:imageMapFileNameValue - inFramework:nil - languages:languages]; - - }; - if (imageMapFilePath) - regions=[GSWGeometricRegion geometricRegionsWithFile:imageMapFilePath]; - else - { - //NSDebugMLLog0(@"gswdync",@"GSWActiveImage No image Map."); - }; - } + //NSDebugMLLog0(@"gswdync",@"GSWActiveImage No image Map."); + }; + } else if (!WOStrictFlag && _imageMapString) { id imageMapValue=[_imageMapString valueInComponent:component]; diff --git a/GSWeb/GSWApplication.m b/GSWeb/GSWApplication.m index efc31b8..070d168 100644 --- a/GSWeb/GSWApplication.m +++ b/GSWeb/GSWApplication.m @@ -332,8 +332,9 @@ int GSWApplicationMain(NSString* applicationClassName, { [self _setupForMonitoring]; }; - [[GSWResourceManager _applicationGSWBundle] initializeObject:self - fromArchiveNamed:@"Application"]; + // ?? + // [[GSWResourceManager _applicationGSWBundle] initializeObject:self + // fromArchiveNamed:@"Application"]; [self setPrintsHTMLParserDiagnostics:NO]; if ([[self class] recordingPath]) @@ -658,7 +659,7 @@ int GSWApplicationMain(NSString* applicationClassName, { NSString* path=nil; - path=[[GSWResourceManager _applicationGSWBundle] path]; + path=[[_resourceManager _appProjectBundle] path]; return path; }; @@ -852,15 +853,17 @@ int GSWApplicationMain(NSString* applicationClassName, [self lock]; NS_DURING { - anEnum=[_componentDefinitionCache objectEnumerator]; - while ((definition = [anEnum nextObject])) - { - if (((NSString*)definition != GSNotFoundMarker) && (![definition isCachingEnabled])) - [definition _clearCache]; - } + // we should probably clear the _componentDefinitionCache? -- dw + +// anEnum=[_componentDefinitionCache objectEnumerator]; +// while ((definition = [anEnum nextObject])) +// { +// if (((NSString*)definition != GSNotFoundMarker) && (![definition isCachingEnabled])) +// [definition _clearCache]; +// } if (![self isCachingEnabled]) { - [[GSWResourceManager _applicationGSWBundle] clearCache]; + [_resourceManager flushDataCache]; } } NS_HANDLER @@ -1331,27 +1334,9 @@ int GSWApplicationMain(NSString* applicationClassName, //-------------------------------------------------------------------- -(void)_finishInitializingSession:(GSWSession*)aSession -{ - //OK - - [self lock]; - NS_DURING - { - [[GSWResourceManager _applicationGSWBundle] initializeObject:aSession - fromArchiveNamed:@"Session"]; - } - NS_HANDLER - { - localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, - @"In initializeObject:fromArchiveNamed:"); - //TODO - [self unlock]; - [localException raise]; - }; - NS_ENDHANDLER; - [self unlock]; - -}; +{ + //Does nothing on WO 5 +} //-------------------------------------------------------------------- -(GSWSession*)_initializeSessionInContext:(GSWContext*)aContext @@ -1714,64 +1699,16 @@ to another instance **/ //-------------------------------------------------------------------- -(Class)_sessionClass { - //OK Class sessionClass=nil; - sessionClass=[[GSWResourceManager _applicationGSWBundle] scriptedClassWithName:GSWClassName_Session - superclassName:GSWClassName_Session]; +// sessionClass=[[_resourceManager _appProjectBundle] scriptedClassWithName:GSWClassName_Session +// superclassName:GSWClassName_Session]; + if (!sessionClass) sessionClass=NSClassFromString(GSWClassName_Session); - -/* - - //Search Compiled Class "Session" (subclass of GSWsession) - gswsessionClass=NSClassFromString(); - sessionClass=NSClassFromString(GSWClassName_Session); - - //If not found, search for library "Session" in application .gswa directory - if (!_sessionClass) - { - NSString* sessionPath=[self pathForResourceNamed:@"session" - ofType:nil]; - Class _principalClass=[self libraryClassWithPath:sessionPath]; - NSDebugMLLog(@"application",@"_principalClass=%@",_principalClass); - if (_principalClass) - { - _sessionClass=NSClassFromString(GSWClassName_Session); - NSDebugMLLog(@"application",@"sessionClass=%@",_sessionClass); - }; - }; - - //If not found, search for scripted "Session" in application .gswa directory - if (!sessionClass) - { - //TODO - }; - - //If not found, search for scripted "Session" in a session.gsws file - if (!sessionClass) - { - //TODO - }; - - if (!sessionClass) - { - sessionClass=_gswsessionClass; - } - else - { - if (!ClassIsKindOfClass(_sessionClass,_gswsessionClass)) - { - //TODO exception - NSDebugMLLog(@"application", - @"session class is not a kind of GSWSession"); - } - }; - NSDebugMLLog(@"application",@"_sessionClass:%@",_sessionClass); -*/ return sessionClass; -}; +} //-------------------------------------------------------------------- //NDFN @@ -2265,7 +2202,7 @@ to another instance **/ [noteCenter postNotificationName:@"ApplicationWillDispatchRequestNotification" object:aRequest]; - + requestHandler = [self handlerForRequest:aRequest]; if (!requestHandler) @@ -2488,11 +2425,11 @@ to another instance **/ NS_DURING { errorPage=[self pageWithName:pageName - inContext:context]; - + inContext:context]; + if (anException) - [errorPage takeValue:anException - forKey:@"exception"]; + [errorPage setValue:anException + forKey:@"exception"]; } NS_HANDLER { @@ -3504,13 +3441,30 @@ to another instance **/ //-------------------------------------------------------------------- +(Class)_applicationClass { + NSBundle * mainBundle = [NSBundle mainBundle]; + NSString * className = [[mainBundle infoDictionary] objectForKey:@"NSPrincipalClass"]; + Class potentialAppClass = NULL; - [[GSWResourceManager _applicationGSWBundle] - scriptedClassWithName:GSWClassName_Application//TODO - superclassName:GSWClassName_Application]; //retirune nil //TODO + if (className) { + potentialAppClass = NSClassFromString(className); + + if ((potentialAppClass) && GSObjCIsKindOf(potentialAppClass,[GSWApplication class])) + { + return potentialAppClass; + } + } - return NSClassFromString(globalApplicationClassName); -}; + potentialAppClass = NSClassFromString(@"Application"); + + if ((potentialAppClass) && GSObjCIsKindOf(potentialAppClass,[GSWApplication class])) + { + return potentialAppClass; + } + + + NSLog(@"You should consider creating your own WOApplication subclass."); + return NSClassFromString(@"WOApplication"); +} //-------------------------------------------------------------------- +(Class)_compiledApplicationClass diff --git a/GSWeb/GSWBundle.h b/GSWeb/GSWBundle.h index faf9afd..1d23e68 100644 --- a/GSWeb/GSWBundle.h +++ b/GSWeb/GSWBundle.h @@ -4,7 +4,8 @@ Written by: Manuel Guesdon Date: Mar 1999 - + Written by: David Wetzel + $Revision$ $Date$ @@ -33,116 +34,19 @@ #define _GSWBundle_h__ -//==================================================================== -@interface GSWBundle : NSObject -{ - NSString* _path; - NSString* _baseURL; - NSString* _frameworkName; - NSMutableDictionary* _archiveCache; - NSMutableDictionary* _apiCache;//NDFN - NSMutableDictionary* _encodingCache; - NSMutableDictionary* _templateParserTypeCache;//NDFN - NSMutableDictionary* _pathCache; - NSMutableDictionary* _urlCache; - NSMutableDictionary* _stringsTableCache; - NSMutableDictionary* _stringsTableArrayCache; //NDFN - NSMutableDictionary* _templateCache; - NSMutableDictionary* _classCache; - NSRecursiveLock* _selfLock; -#ifndef NDEBUG - int _selfLockn; -#endif -}; - --(NSString*)baseURL; --(NSString*)path; --(NSString*)frameworkName; --(NSString*)description; --(void)dealloc; --(id)initWithPath:(NSString*)aPath - baseURL:(NSString*)aBaseURL - inFrameworkNamed:(NSString*)aFrameworkName; --(id)initWithPath:(NSString*)aPath - baseURL:(NSString*)aBaseURL; --(void)unlock; --(void)lock; - -// CHECKME: do we need this for WO 4.5? -- dw - --(void)clearCache; -//-(void)loadCache; - -//-(id)lockedResourceNamed:(NSString*)aName -// ofType:(NSString*)aType -// withLanguages:(NSArray*)languages -// usingCache:(NSMutableDictionary*)cache -// relativePath:(NSString**)relativePath -// absolutePath:(NSString**)absolutePath; +@interface NSBundle (WOResourceManagement) -(void)initializeObject:(id)anObject - fromArchiveNamed:(NSString*)aName; - --(void)initializeObject:(id)anObject - fromArchive:(NSDictionary*)archive; - --(Class)scriptedClassWithName:(NSString*)aName - superclassName:(NSString*)superclassName; - --(Class)lockedScriptedClassWithName:(NSString*)aName - pathName:(NSString*)pathName - superclassName:(NSString*)superclassName; - --(NSString*)lockedScriptedClassPathWithName:(NSString*)aName; - -//-(Class)compiledClassWithName:(NSString*)aName -// superclassName:(NSString*)superclassName; - --(GSWElement*)templateNamed:(NSString*)aName - languages:(NSArray*)languages; - - --(GSWElement*)lockedTemplateNamed:(NSString*)aName - languages:(NSArray*)languages; - - -//-(NSString*)stringForKey:(NSString*)key_ -// inTableNamed:(NSString*)aName -// withDefaultValue:(NSString*)defaultValue -// languages:(NSArray*)languages; -// - -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)aName - withLanguages:(NSArray*)languages; - -//NDFN -//-(NSArray*)stringsTableArrayNamed:(NSString*)aName -// withLanguages:(NSArray*)languages; - -//-(NSString*)urlForResourceNamed:(NSString*)aName -// ofType:(NSString*)aType -// languages:(NSArray*)languages -// request:(GSWRequest*)aRequest; -// - --(NSString*)pathForResourceNamed:(NSString*)aName - ofType:(NSString*)aType - languages:(NSArray*)languages; - - --(NSStringEncoding)encodingForResourcesNamed:(NSString*)aName; --(GSWTemplateParserType)templateParserTypeForResourcesNamed:(NSString*)aName;//NDFN - --(NSDictionary*)archiveNamed:(NSString*)aName; --(NSDictionary*)apiNamed:(NSString*)aName;//NDFN - --(NSDictionary*)lockedArchiveNamed:(NSString*)aName; --(NSDictionary*)lockedApiNamed:(NSString*)aName;//NDFN - -//-(id)scriptedClassNameFromClassName:(NSString*)aName; -//-(id)scriptPathNameFromScriptedClassName:(NSString*)aName; + fromArchive:(NSDictionary*)anArchive; @end +@interface GSWBundleUnarchiverDelegate : NSObject +{ + id _object; +} +- (id) unarchiver:(NSKeyedUnarchiver*)unarchiver objectForReference:(NSString*)keyPath; +- (id) initWithObject:(id)object; +@end + #endif //_GSWBundle_h__ diff --git a/GSWeb/GSWBundle.m b/GSWeb/GSWBundle.m index c0945b4..a660ad4 100644 --- a/GSWeb/GSWBundle.m +++ b/GSWeb/GSWBundle.m @@ -40,312 +40,16 @@ RCS_ID("$Id$") #include "WOKeyValueUnarchiver.h" #include -//==================================================================== -@interface GSWBundleUnarchiverDelegate : NSObject -{ - id _object; -} -- (id) unarchiver:(NSKeyedUnarchiver*)unarchiver objectForReference:(NSString*)keyPath; -- (id) initWithObject:(id)object; -@end - -//==================================================================== -@implementation GSWBundleUnarchiverDelegate - -//-------------------------------------------------------------------- -- (void) dealloc -{ - [super dealloc]; -} - -//-------------------------------------------------------------------- -- (id) unarchiver:(NSKeyedUnarchiver*)unarchiver objectForReference:(NSString*)keyPath -{ - return [_object valueForKeyPath:keyPath]; -} - -//-------------------------------------------------------------------- -- (id) initWithObject:(id)object -{ - if ((self=[super init])) - { - _object=object; - } - return self; -} - -@end -//#endif // HAVE_GDL2 - -@implementation GSWBundle - -//-------------------------------------------------------------------- --(id)initWithPath:(NSString*)aPath - baseURL:(NSString*)aBaseURL -{ - return [self initWithPath:aPath - baseURL:aBaseURL - inFrameworkNamed:nil]; -} - -//-------------------------------------------------------------------- --(id)initWithPath:(NSString*)aPath - baseURL:(NSString*)aBaseURL - inFrameworkNamed:(NSString*)aFrameworkName -{ - if ((self=[super init])) - { - ASSIGN(_path,[aPath stringGoodPath]); - ASSIGN(_baseURL,aBaseURL); - ASSIGN(_frameworkName,aFrameworkName); - _archiveCache=[NSMutableDictionary new]; - _apiCache=[NSMutableDictionary new]; - _encodingCache=[NSMutableDictionary new]; - _templateParserTypeCache=[NSMutableDictionary new]; - _pathCache=[NSMutableDictionary new]; - _urlCache=[NSMutableDictionary new]; - _stringsTableCache=[NSMutableDictionary new]; - _stringsTableArrayCache=[NSMutableDictionary new]; - _templateCache=[NSMutableDictionary new]; - _classCache=[NSMutableDictionary new]; - _selfLock=[NSRecursiveLock new]; - } - return self; -} - -//-------------------------------------------------------------------- --(void)dealloc -{ - DESTROY(_path); - DESTROY(_baseURL); - DESTROY(_archiveCache); - DESTROY(_apiCache); - DESTROY(_encodingCache); - DESTROY(_templateParserTypeCache); - DESTROY(_pathCache); - DESTROY(_urlCache); - DESTROY(_stringsTableCache); - DESTROY(_stringsTableArrayCache); - DESTROY(_templateCache); - DESTROY(_classCache); - DESTROY(_selfLock); - - [super dealloc]; -} - -//-------------------------------------------------------------------- --(NSString*)baseURL -{ - return _baseURL; -} - -//-------------------------------------------------------------------- --(NSString*)path -{ - return _path; -} - -//-------------------------------------------------------------------- --(NSString*)frameworkName -{ - return _frameworkName; -} - -//-------------------------------------------------------------------- --(NSString*)description -{ - NSString* descr=nil; - - descr=[NSString stringWithFormat:@"<%s %p - ", - object_getClassName(self), - (void*)self]; - - descr=[descr stringByAppendingFormat:@"path:[%@] ", - _path]; - - descr=[descr stringByAppendingFormat:@"baseURL:[%@] frameworkName:[%@]>", - _baseURL, - _frameworkName]; - - return descr; -} - -//-------------------------------------------------------------------- --(void)unlock -{ - LoggedUnlock(_selfLock); -#ifndef NDEBUG - _selfLockn--; -#endif -} - -//-------------------------------------------------------------------- --(void)lock -{ - LoggedLockBeforeDate(_selfLock,GSW_LOCK_LIMIT); -#ifndef NDEBUG - _selfLockn++; -#endif -} -//-------------------------------------------------------------------- --(void)clearCache -{ - [self lock]; - NS_DURING - { - DESTROY(_archiveCache); - DESTROY(_apiCache); - DESTROY(_encodingCache); - DESTROY(_templateParserTypeCache); - DESTROY(_pathCache); - DESTROY(_urlCache); - DESTROY(_stringsTableCache); - DESTROY(_stringsTableArrayCache); - DESTROY(_templateCache); - DESTROY(_classCache); - - _archiveCache=[NSMutableDictionary new]; - _apiCache=[NSMutableDictionary new]; - _encodingCache=[NSMutableDictionary new]; - _templateParserTypeCache=[NSMutableDictionary new]; - _pathCache=[NSMutableDictionary new]; - _urlCache=[NSMutableDictionary new]; - _stringsTableCache=[NSMutableDictionary new]; - _stringsTableArrayCache=[NSMutableDictionary new]; - _templateCache=[NSMutableDictionary new]; - _classCache=[NSMutableDictionary new]; - - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; -} +@implementation NSBundle (WOResourceManagement) -//-------------------------------------------------------------------- --(void)loadCache -{ - [self notImplemented: _cmd]; //TODOFN -} - - -// returned relativePath won't have "/" prefix - --(id)lockedResourceNamed:(NSString*)aName - ofType:(NSString*)aType - withLanguages:(NSArray*)someLanguages - usingCache:(NSMutableDictionary*)aCache - relativePath:(NSString**)aRelativePath - absolutePath:(NSString**)anAbsolutePath -{ - int languageIndex=0; - NSString* relativePath=nil; - NSString* absolutePath=nil; - NSString* fileName=nil; - NSString* language=nil; - id resource=nil; - NSString* path=nil; - NSFileManager* fileManager=nil; - int languagesNb=0; - BOOL exists=NO; - - languagesNb=[someLanguages count]; - - fileManager=[NSFileManager defaultManager]; - NSAssert(fileManager,@"No fileManager"); - - fileName=[aName stringByAppendingPathExtension:aType]; - - for(languageIndex=0;!resource && !path && languageIndex<=languagesNb;languageIndex++) - { - language=nil; - if (languageIndex==languagesNb) - relativePath=fileName; - else - { - language=[someLanguages objectAtIndex:languageIndex]; - // format like: language.languageSuffix/fileName - relativePath=[language stringByAppendingPathExtension:GSLanguageSuffix]; - relativePath=[relativePath stringByAppendingPathComponent:fileName]; - } - - absolutePath=[_path stringByAppendingPathComponent:relativePath]; - - if ([[GSWApplication application] isCachingEnabled]) - resource=[aCache objectForKey:relativePath]; - - if (resource==GSNotFoundMarker) - { - resource=nil; - absolutePath=nil; - relativePath=nil; - } - else if (!resource) - { - exists=[fileManager fileExistsAtPath:absolutePath]; - - if (!exists) - { - if ([[GSWApplication application] isCachingEnabled]) - [aCache setObject:GSNotFoundMarker - forKey:relativePath]; - relativePath=nil; - absolutePath=nil; - } - } - } - - if (aRelativePath) { - if ([relativePath length]>0) { - *aRelativePath = relativePath; - } else { - *aRelativePath = nil; - } - } - if (anAbsolutePath) { - if ([absolutePath length]>0) { - *anAbsolutePath = absolutePath; - } else { - *anAbsolutePath = nil; - } - } - - return resource; -} - -//-------------------------------------------------------------------- --(void)initializeObject:(id)anObject - fromArchiveNamed:(NSString*)aName -{ - //OK - NSDictionary* archive=nil; - - //call application _isDynamicLoadingEnabled - //call -- isTerminating - //call -- isCachingEnabled - //call -- isPageRefreshOnBacktrackEnabled//0 - archive=[self archiveNamed:aName]; - //Verify - - if (archive) - [self initializeObject:anObject - fromArchive:archive]; -} - -//-------------------------------------------------------------------- -(void)initializeObject:(id)anObject fromArchive:(NSDictionary*)anArchive { - SYNCHRONIZED(self) { NSDictionary * variableDefinitions = nil; WOKeyValueUnarchiver * unarchiver; - + unarchiver = [[WOKeyValueUnarchiver alloc] initWithDictionary: anArchive]; AUTORELEASE(unarchiver); @@ -363,690 +67,35 @@ RCS_ID("$Id$") while ((varName = [keyEnumer nextObject])) { varValue = [variableDefinitions objectForKey:varName]; - + [anObject setValue:varValue forKey:varName]; } } - - } END_SYNCHRONIZED; -} - -//-------------------------------------------------------------------- --(Class)scriptedClassWithName:(NSString*)aName - superclassName:(NSString*)aSuperclassName -{ - //OK - Class aClass=nil; - NSString* pathName=nil; - - [self lock]; - NS_DURING - { - pathName=[self lockedScriptedClassPathWithName:aName]; - //Verify - if (pathName) - { - aClass=[self lockedScriptedClassWithName:aName - pathName:pathName - superclassName:aSuperclassName]; - } - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return aClass; -} - -//-------------------------------------------------------------------- --(Class)lockedScriptedClassWithName:(NSString*)aName - pathName:(NSString*)aPathName - superclassName:(NSString*)aSuperclassName -{ - [self notImplemented: _cmd]; //TODOFN - return nil; -} - -//-------------------------------------------------------------------- --(NSString*)lockedScriptedClassPathWithName:(NSString*)aName -{ - NSString* path=nil; - id script=nil; - script=[self lockedResourceNamed:aName - ofType:GSWScriptSuffix[GSWebNamingConv] - withLanguages:nil - usingCache:_classCache - relativePath:NULL - absolutePath:&path]; - if (!script && !path) - script=[self lockedResourceNamed:aName - ofType:GSWScriptSuffix[GSWebNamingConvInversed] - withLanguages:nil - usingCache:_classCache - relativePath:NULL - absolutePath:&path]; - return path; -} - -//-------------------------------------------------------------------- --(Class)compiledClassWithName:(NSString*)aName - superclassName:(NSString*)aSuperclassName -{ - [self notImplemented: _cmd]; //TODOFN - return nil; -} - -//-------------------------------------------------------------------- --(GSWElement*)templateNamed:(NSString*)aName - languages:(NSArray*)someLanguages -{ - GSWElement* template=nil; - - [self lock]; - NS_DURING - { - template=[self lockedTemplateNamed:aName - languages:someLanguages]; - } - NS_HANDLER - { - //TODO - [self unlock]; - localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, - @"In lockedTemplateNamed"); - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return template; -} - -//-------------------------------------------------------------------- --(GSWElement*)lockedTemplateNamed:(NSString*)aName - languages:(NSArray*)someLanguages -{ - //OK - GSWElement* template=nil; - NSString* relativeTemplatePath=nil; - NSString* absoluteTemplatePath=nil; - - template=[self lockedResourceNamed:aName - ofType:GSWComponentTemplateSuffix - withLanguages:someLanguages - usingCache:_templateCache - relativePath:&relativeTemplatePath - absolutePath:&absoluteTemplatePath]; - - if (!template) - { - if (!relativeTemplatePath) - { -// NSDebugMLLog(@"errors",@"No template named:%@ for languages:%@", -// aName, -// someLanguages); - } - else - { - GSWTemplateParserType templateParserType=[self templateParserTypeForResourcesNamed:aName]; - NSStringEncoding encoding=[self encodingForResourcesNamed:aName]; - NSString* pageDefString=nil; - NSString* htmlString=[NSString stringWithContentsOfFile:absoluteTemplatePath - encoding:encoding]; - //NSString* htmlString=[NSString stringWithContentsOfFile:absoluteTemplatePath]; - - if (!htmlString) - { -// NSDebugMLLog(@"errors",@"No html file for template named:%@ for languages:%@", -// aName, -// someLanguages); - } - else - { - NSString* absoluteDefinitionPath=nil; - pageDefString=[self lockedResourceNamed:aName - ofType:GSWComponentDeclarationsSuffix[GSWebNamingConv] - withLanguages:someLanguages - usingCache:nil - relativePath:NULL - absolutePath:&absoluteDefinitionPath]; - - if (!pageDefString && !absoluteDefinitionPath) - { - pageDefString=[self lockedResourceNamed:aName - ofType:GSWComponentDeclarationsSuffix[GSWebNamingConvInversed] - withLanguages:someLanguages - usingCache:nil - relativePath:NULL - absolutePath:&absoluteDefinitionPath]; - } - - if (absoluteDefinitionPath) - { - //TODO use encoding ! - //pageDefString=[NSString stringWithContentsOfFile:absoluteDefinitionPath]; - pageDefString = [NSString stringWithContentsOfFile:absoluteDefinitionPath - encoding:encoding]; - - } -#ifndef NDEBUG - NS_DURING -#endif - { - template=[GSWTemplateParser templateNamed:aName - inFrameworkNamed:[self frameworkName] - withParserType:templateParserType - parserClassName:nil - withString:htmlString - encoding:encoding - fromPath:absoluteTemplatePath - declarationsString:pageDefString - languages:someLanguages - declarationsPath:absoluteDefinitionPath]; - } -#ifndef NDEBUG - NS_HANDLER - { - localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, - @"In template Parsing"); - [localException raise]; - } - NS_ENDHANDLER; -#endif - } - if ([[GSWApplication application] isCachingEnabled]) - { - if (template) - { - [_templateCache setObject:template - forKey:relativeTemplatePath]; - } - else - { - [_templateCache setObject:GSNotFoundMarker - forKey:relativeTemplatePath]; - } - } - } - } - - return template; -} - -//-------------------------------------------------------------------- --(NSString*)stringForKey:(NSString*)aKey - inTableNamed:(NSString*)aName - withDefaultValue:(NSString*)defaultValue - languages:(NSArray*)someLanguages -{ - NSDictionary* stringsTable=nil; - NSString* string=nil; - - stringsTable=[self stringsTableNamed:aName - withLanguages:someLanguages]; - if (stringsTable) - string=[stringsTable objectForKey:aKey]; - if (!string) - string=defaultValue; - - return string; -} - -//-------------------------------------------------------------------- -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)aName - withLanguages:(NSArray*)someLanguages -{ - NSDictionary* stringsTable=nil; - - [self lock]; - NS_DURING - { - NSString* relativePath=nil; - NSString* absolutePath=nil; - - stringsTable=[self lockedResourceNamed:aName - ofType:GSWStringTableSuffix - withLanguages:someLanguages - usingCache:_stringsTableCache - relativePath:&relativePath - absolutePath:&absolutePath]; - if (!stringsTable) - { - if (absolutePath) - { - //TODO use encoding ?? - NSString* stringsTableContent = [NSString stringWithContentsOfFile:absolutePath]; - NS_DURING - { - stringsTable = [stringsTableContent propertyListFromStringsFileFormat]; - } - NS_HANDLER - { -// LOGSeriousError(@"Failed to parse strings file %@ - %@", -// absolutePath, localException); - stringsTable = nil; - } - NS_ENDHANDLER - if ([[GSWApplication application] isCachingEnabled]) - { - if (stringsTable) - [_stringsTableCache setObject:stringsTable - forKey:relativePath]; - else - [_stringsTableCache setObject:GSNotFoundMarker - forKey:relativePath]; - } - } - } - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return stringsTable; -} - -//-------------------------------------------------------------------- -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)aName - withLanguages:(NSArray*)someLanguages -{ - NSArray* stringsTableArray=nil; - - [self lock]; - NS_DURING - { - NSString* relativePath=nil; - NSString* absolutePath=nil; - - stringsTableArray=[self lockedResourceNamed:aName - ofType:GSWStringTableArraySuffix - withLanguages:someLanguages - usingCache:_stringsTableArrayCache - relativePath:&relativePath - absolutePath:&absolutePath]; - if (!stringsTableArray) - { - if (absolutePath) - { - //TODO use encoding ?? - stringsTableArray=[NSArray arrayWithContentsOfFile:absolutePath]; - if (!stringsTableArray) - { -// LOGSeriousError(@"Bad stringTableArray \n%@\n from file %@", -// [NSString stringWithContentsOfFile:absolutePath], -// absolutePath); - } - if ([[GSWApplication application] isCachingEnabled]) - { - if (stringsTableArray) - [_stringsTableArrayCache setObject:stringsTableArray - forKey:relativePath]; - else - [_stringsTableArrayCache setObject:GSNotFoundMarker - forKey:relativePath]; - } - } - } - } - NS_HANDLER - { - localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, - @"During stringsTableArrayNamed:withLanguages:"); - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return stringsTableArray; -} - -//-------------------------------------------------------------------- --(NSString*)urlForResourceNamed:(NSString*)aName - ofType:(NSString*)aType - languages:(NSArray*)someLanguages - request:(GSWRequest*)aRequest -{ - BOOL isUsingWebServer=NO; - NSString* url=nil; - - isUsingWebServer=[aRequest _isUsingWebServer]; - [self lock]; - NS_DURING - { - NSString* relativePath=nil; - NSString* absolutePath=nil; - NSString* baseURL=nil; - - // baseURL have / prefix, relativePath don't - baseURL=[self lockedResourceNamed:aName - ofType:aType - withLanguages:someLanguages - usingCache:_urlCache - relativePath:&relativePath - absolutePath:&absolutePath]; - if (!baseURL) - { - if (relativePath) - { - baseURL=[relativePath stringByAppendingString:@"/"]; - if ([[GSWApplication application] isCachingEnabled]) - { - [_pathCache setObject:baseURL - forKey:relativePath]; - } - } - } - if (baseURL) - { - if (isUsingWebServer) - { - url=[_baseURL stringByAppendingString:baseURL]; - } - else - { - NSString* completePath=[_path stringByAppendingString:baseURL]; - url=(NSString*)[aRequest _urlWithRequestHandlerKey:GSWResourceRequestHandlerKey[GSWebNamingConv] - path:nil - queryString:[NSString stringWithFormat:@"%@=%@", - GSWKey_Data[GSWebNamingConv], - completePath]];//TODO Escape - } - } - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return url; -} - -//-------------------------------------------------------------------- --(NSString*)pathForResourceNamed:(NSString*)aName - ofType:(NSString*)aType - languages:(NSArray*)someLanguages -{ - NSString* absolutePath=nil; - - [self lock]; - NS_DURING - { - NSString* path=nil; - NSString* relativePath=nil; - - path=[self lockedResourceNamed:aName - ofType:aType - withLanguages:someLanguages - usingCache:_stringsTableCache - relativePath:&relativePath - absolutePath:&absolutePath]; - if (path) - absolutePath=path; - else if (absolutePath - &&[[GSWApplication application] isCachingEnabled]) - { - [_pathCache setObject:absolutePath - forKey:relativePath]; - } - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return absolutePath; -} - -//-------------------------------------------------------------------- --(NSStringEncoding)encodingForResourcesNamed:(NSString*)aName -{ - NSDictionary* archive=nil; - NSStringEncoding encoding=[GSWMessage defaultEncoding]; // safer, because we may not have a .woo file - id encodingObject=nil; - - [self lock]; - NS_DURING - { - encodingObject=[_encodingCache objectForKey:aName]; - if (!encodingObject) - { - archive=[self archiveNamed:aName]; - if (archive) - { - //NSLog(@"archive is '%@'", archive); - encodingObject=[archive objectForKey:@"encoding"]; - if (encodingObject) - { - //NSLog(@"encodingObject is '%@'", encodingObject); - //encodingObject is 'NSISOLatin1StringEncoding' - //not very cool to make a int into a string and some time later a string.. - - encoding = [GSMimeDocument encodingFromCharset:encodingObject]; - - if ((encoding == 0)) { - [NSException raise: NSInvalidArgumentException - format: @"Resource named %@ -- unknown encoding '%@'", aName, encodingObject]; - } - - encodingObject=GSWIntToNSString(encoding); - [_encodingCache setObject:encodingObject - forKey:aName]; - } - } - } - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return encoding; -} - -//-------------------------------------------------------------------- --(GSWTemplateParserType)templateParserTypeForResourcesNamed:(NSString*)aName -{ - NSDictionary* archive=nil; - GSWTemplateParserType templateParserType=GSWTemplateParserType_Default; - id templateParserTypeObject=nil; - - [self lock]; - NS_DURING - { - templateParserTypeObject=[_templateParserTypeCache objectForKey:aName]; - if (!templateParserTypeObject) - { - archive=[self archiveNamed:aName]; - if (archive) - { - templateParserTypeObject=[archive objectForKey:@"templateParserType"]; - if (templateParserTypeObject) - { - templateParserTypeObject=GSWIntNumber([GSWTemplateParser templateParserTypeFromString:templateParserTypeObject]); - [_templateParserTypeCache setObject:templateParserTypeObject - forKey:aName]; - } - } - } - if (templateParserTypeObject) - templateParserType=[templateParserTypeObject intValue]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return templateParserType; -} - -//-------------------------------------------------------------------- --(NSDictionary*)archiveNamed:(NSString*)aName -{ - //OK - NSDictionary* archive=nil; - - [self lock]; - NS_DURING - { - archive=[self lockedArchiveNamed:aName]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return archive; -} - -//-------------------------------------------------------------------- --(NSDictionary*)lockedArchiveNamed:(NSString*)aName -{ - //OK - NSDictionary* archive=nil; - NSString* relativePath=nil; - NSString* absolutePath=nil; - - archive=[self lockedResourceNamed:aName - ofType:GSWArchiveSuffix[GSWebNamingConv] - withLanguages:nil - usingCache:_archiveCache - relativePath:&relativePath - absolutePath:&absolutePath]; - - if (!archive && !absolutePath) - { - archive=[self lockedResourceNamed:aName - ofType:GSWArchiveSuffix[GSWebNamingConvInversed] - withLanguages:nil - usingCache:_archiveCache - relativePath:&relativePath - absolutePath:&absolutePath]; - } - if (!archive) - { - if (absolutePath) - { - archive=[NSDictionary dictionaryWithContentsOfFile:absolutePath]; - if ([[GSWApplication application] isCachingEnabled]) - { - if (archive) - [_archiveCache setObject:archive - forKey:relativePath]; - else - [_archiveCache setObject:GSNotFoundMarker - forKey:relativePath]; - } - } - } - - return archive; -} - -//-------------------------------------------------------------------- --(NSDictionary*)apiNamed:(NSString*)aName -{ - //OK - NSDictionary* api=nil; - - [self lock]; - NS_DURING - { - api=[self lockedApiNamed:aName]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - - return api; -} - -//-------------------------------------------------------------------- --(NSDictionary*)lockedApiNamed:(NSString*)aName -{ - //OK - NSDictionary* api=nil; - NSString* relativePath=nil; - NSString* absolutePath=nil; - - api=[self lockedResourceNamed:aName - ofType:GSWAPISuffix - withLanguages:nil - usingCache:_apiCache - relativePath:&relativePath - absolutePath:&absolutePath]; - if (!api) - { - if (absolutePath) - { - api=[NSDictionary dictionaryWithContentsOfFile:absolutePath]; - if ([[GSWApplication application] isCachingEnabled]) - { - if (api) - [_apiCache setObject:api - forKey:relativePath]; - else - [_apiCache setObject:GSNotFoundMarker - forKey:relativePath]; - } - } - } - - return api; -} - - -//-------------------------------------------------------------------- --(id)scriptedClassNameFromClassName:(NSString*)aName -{ - [self notImplemented: _cmd]; //TODOFN - return nil; -} - -//-------------------------------------------------------------------- --(id)scriptPathNameFromScriptedClassName:(NSString*)aName -{ - [self notImplemented: _cmd]; //TODOFN - return nil; +} + +@end + + +@implementation GSWBundleUnarchiverDelegate + +- (void) dealloc +{ + [super dealloc]; +} + +- (id) unarchiver:(NSKeyedUnarchiver*)unarchiver objectForReference:(NSString*)keyPath +{ + return [_object valueForKeyPath:keyPath]; +} + +- (id) initWithObject:(id)object +{ + if ((self=[super init])) + { + _object=object; + } + return self; } @end diff --git a/GSWeb/GSWComponent.h b/GSWeb/GSWComponent.h index 8defa46..8b06c09 100644 --- a/GSWeb/GSWComponent.h +++ b/GSWeb/GSWComponent.h @@ -105,7 +105,7 @@ -(GSWElement*)_childTemplate; -(GSWElement*) template; -(GSWComponentDefinition*)_componentDefinition; --(NSString*)_templateName; +-(NSString*)_templateName GS_ATTRIB_DEPRECATED; -(NSString*)declarationName; -(BOOL)_isPage; -(void)_setIsPage:(BOOL)isPage; @@ -225,58 +225,32 @@ Call this method before using a component which was cached in a variable. //+(id)validateValue:(id*)valuePtr // forKey:(id)key; --(NSString*)stringForKey:(NSString*)key - inTableNamed:(NSString*)aName - withDefaultValue:(NSString*)defaultValue; -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)aName; - -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)aName; - -(NSString*)urlForResourceNamed:(NSString*)aName - ofType:(NSString*)extension; --(NSString*)_urlForResourceNamed:(NSString*)aName - ofType:(NSString*)extension; + ofType:(NSString*)extension GS_ATTRIB_DEPRECATED; + +/* + Deprecated in WO 4.0. + Use GSWResourceManager’s implementation of + pathForResourceNamed:inFramework:languages: + instead. + */ -(NSString*)pathForResourceNamed:(NSString*)aName - ofType:(NSString*)extension; -//NDFN --(NSString*)pathForComponentResourceNamed:(NSString*)aName - ofType:(NSString*)type; - - -//NDFN --(NSString*)stringForKey:(id)key - inTableNamed:(NSString*)aName - withDefaultValue:(NSString*)defaultValue - inFramework:(NSString*)frameworkName; - -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)aName - inFramework:(NSString*)frameworkName; - -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)aName - inFramework:(NSString*)frameworkName; - -//NDFN --(NSString*)urlForResourceNamed:(NSString*)aName - ofType:(NSString*)extension - inFramework:(NSString*)frameworkName; - -//NDFN --(NSString*)pathForResourceNamed:(NSString*)aName - ofType:(NSString*)extension - inFramework:(NSString*)frameworkName; - + ofType:(NSString*)extension GS_ATTRIB_DEPRECATED; +(GSWElement*)templateWithHTMLString:(NSString*)htmlString declarationString:(NSString*)declarationString languages:(NSArray*)languages; +/* + Deprecated in WO 4.0. + Use + templateWithHTMLString:declarationString:languages: + instead. + */ + +(GSWElement*)templateWithHTMLString:(NSString *)htmlString - declarationString:(NSString*)declarationString;//old + declarationString:(NSString*)declarationString GS_ATTRIB_DEPRECATED; - (GSWResponse*)generateResponse; diff --git a/GSWeb/GSWComponent.m b/GSWeb/GSWComponent.m index a499046..e475f9e 100644 --- a/GSWeb/GSWComponent.m +++ b/GSWeb/GSWComponent.m @@ -1453,185 +1453,47 @@ Call this method before using a component which was cached in a variable. return value; } -//-------------------------------------------------------------------- -// stringForKey:inTableNamed:withDefaultValue: - --(NSString*)stringForKey:(NSString*)key - inTableNamed:(NSString*)tableName - withDefaultValue:(NSString*)defaultValue -{ - //OK - NSString* string=nil; - - string=[GSWApp stringForKey:key - inTableNamed:tableName - withDefaultValue:defaultValue - inFramework:[self frameworkName] - languages:[self languages]]; - return string; -} - -//-------------------------------------------------------------------- -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)aName -{ - //OK - NSDictionary* stringsTable=nil; - - stringsTable=[GSWApp stringsTableNamed:aName - inFramework:[self frameworkName] - languages:[self languages]]; - return stringsTable; -} - -//-------------------------------------------------------------------- -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)aName -{ - //OK - NSArray* stringsTableArray=nil; - - stringsTableArray=[GSWApp stringsTableArrayNamed:aName - inFramework:[self frameworkName] - languages:[self languages]]; - - return stringsTableArray; -} - - //-------------------------------------------------------------------- // urlForResourceNamed:ofType: -(NSString*)urlForResourceNamed:(NSString*)aName ofType:(NSString*)type { - //TODO - NSString* url=nil; - NSString* name; + NSString* url = nil; - if ((type != nil)) { - name = [NSString stringWithFormat:@"%@.%@",aName,type]; - } else { - name = aName; - } + GSOnceMLog(@"%s is depricated in WO 4.0. Use GSWResourceManager’s implementation of " + @"urlForResourceNamed:inFramework:languages:request: " + @"instead.", + __PRETTY_FUNCTION__); - url=[GSWApp urlForResourceNamed:name - inFramework:[self frameworkName] - languages:[self languages] - request:nil];//TODO + url=[[GSWApp resourceManager] urlForResourceNamed:aName + ofType:type + inFramework:nil + languages:[self languages] + request:nil]; return url; } //-------------------------------------------------------------------- --(NSString*)_urlForResourceNamed:(NSString*)aName - ofType:(NSString*)type -{ - [self notImplemented: _cmd]; //TODOFN - return nil; -} - -//-------------------------------------------------------------------- -// pathForResourceNamed:ofType: -// Normally: local search. Here we do a resourceManager serahc. -(NSString*)pathForResourceNamed:(NSString*)aName ofType:(NSString*)type { NSString* path=nil; + + GSOnceMLog(@"%s is depricated in WO 4.0. Use GSWResourceManager’s implementation of " + @"pathForResourceNamed:inFramework:languages: " + @"instead.", + __PRETTY_FUNCTION__); - path=[GSWApp pathForResourceNamed:aName - ofType:type - inFramework:[self frameworkName] - languages:[self languages]]; - + path=[[GSWApp resourceManager] pathForResourceNamed:aName + ofType:type + inFramework:nil + languages:[self languages]]; + return path; } -//-------------------------------------------------------------------- -//NDFN --(NSString*)pathForComponentResourceNamed:(NSString*)aName - ofType:(NSString*)type_ -{ - NSString* path=nil; - NSArray* languages=nil; - GSWComponentDefinition* aComponentDefinition=nil; - - languages=[self languages]; - aComponentDefinition=[self _componentDefinition]; - if (aComponentDefinition) - path=[aComponentDefinition pathForResourceNamed:aName - ofType:type_ - languages:languages]; - return path; -} - -//-------------------------------------------------------------------- -//NDFN --(NSString*)stringForKey:(id)key - inTableNamed:(NSString*)aName - withDefaultValue:(NSString*)defaultValue - inFramework:(NSString*)aFrameworkName -{ - return [GSWApp stringForKey:key - inTableNamed:aName - withDefaultValue:defaultValue - inFramework:aFrameworkName - languages:[self languages]]; -} - -//-------------------------------------------------------------------- -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)aName - inFramework:(NSString*)aFrameworkName -{ - return [GSWApp stringsTableNamed:aName - inFramework:aFrameworkName - languages:[self languages]]; -} - -//-------------------------------------------------------------------- -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)aName - inFramework:(NSString*)aFrameworkName -{ - return [GSWApp stringsTableArrayNamed:aName - inFramework:aFrameworkName - languages:[self languages]]; -} - -//-------------------------------------------------------------------- -//NDFN --(NSString*)urlForResourceNamed:(NSString*)aName - ofType:(NSString*)extension - inFramework:(NSString*)aFrameworkName; -{ - - NSString * name; - - if ((extension != nil)) { - name = [NSString stringWithFormat:@"%@.%@",aName,extension]; - } else { - name = aName; - } - - return [GSWApp urlForResourceNamed:name - inFramework:aFrameworkName - languages:[self languages] - request:nil];//TODO -} - -//-------------------------------------------------------------------- -//NDFN --(NSString*)pathForResourceNamed:(NSString*)aName - ofType:(NSString*)extension - inFramework:(NSString*)aFrameworkName -{ - return [GSWApp pathForResourceNamed:aName - ofType:(NSString*)extension - inFramework:aFrameworkName - languages:[self languages]]; -} - //-------------------------------------------------------------------- // templateWithHTMLString:declarationString:languages @@ -1651,10 +1513,14 @@ Call this method before using a component which was cached in a variable. //-------------------------------------------------------------------- // templateWithHTMLString:declarationString: -//old +(GSWElement*)templateWithHTMLString:(NSString*)htmlString declarationString:(NSString*)pageDefString { + GSOnceMLog(@"%s is depricated in WO 4.0. Use " + @"templateWithHTMLString:declarationString:languages:" + @"instead.", + __PRETTY_FUNCTION__); + return [self templateWithHTMLString:htmlString declarationString:pageDefString languages:nil]; diff --git a/GSWeb/GSWComponentDefinition.h b/GSWeb/GSWComponentDefinition.h index e0916ad..dbe434a 100644 --- a/GSWeb/GSWComponentDefinition.h +++ b/GSWeb/GSWComponentDefinition.h @@ -33,7 +33,6 @@ #define _GSWComponentDefinition_h__ @class GSWElement; -@class GSWBundle; @class GSWComponent; @class GSWContext; @class GSWComponentReference; @@ -58,14 +57,15 @@ NSDictionary * _archive; NSStringEncoding _encoding; BOOL _isStateless; - GSWBundle * _bundle; GSWComponent * _sharedInstance; NSMutableArray * _instancePool; BOOL _lockInstancePool; BOOL _hasBeenAccessed; BOOL _hasContextConstructor; NSLock * _instancePoolLock; -}; + NSDate * _wooReadDate; + NSDate * _htmlReadDate; +} -(id)initWithName:(NSString*)aName path:(NSString*)aPath @@ -94,6 +94,11 @@ - (GSWElement *) template; +/* + * returns the contents of the .wod + */ +- (NSDictionary *) archive; + -(NSString*)pathForResourceNamed:(NSString*)aName ofType:(NSString*)aType languages:(NSArray*)languages; diff --git a/GSWeb/GSWComponentDefinition.m b/GSWeb/GSWComponentDefinition.m index 6cad9b3..78a9d4e 100644 --- a/GSWeb/GSWComponentDefinition.m +++ b/GSWeb/GSWComponentDefinition.m @@ -30,6 +30,7 @@ #include "GSWeb.h" #include +#include //==================================================================== @@ -80,6 +81,8 @@ static GSWContext * TheTemporaryContext; ASSIGN(_url, baseURL); ASSIGN(_frameworkName, aFrameworkName); DESTROY(_language); + DESTROY(_wooReadDate); + DESTROY(_htmlReadDate); _hasBeenAccessed = NO; _hasContextConstructor = NO; _isStateless = NO; @@ -88,10 +91,7 @@ static GSWContext * TheTemporaryContext; _lockInstancePool = [GSWApp isConcurrentRequestHandlingEnabled]; if ((_name != nil) && (_frameworkName != nil)) { - NSBundle * nsbundle = [NSBundle bundleForClass:NSClassFromString(_className)]; - if (nsbundle != nil) { - _componentClass = NSClassFromString(_className); - } + _componentClass = NSClassFromString(_className); } myBasePath = [aPath stringByAppendingPathComponent: aName]; ASSIGN(_htmlPath,[myBasePath stringByAppendingPathExtension:@"html"]); @@ -116,25 +116,10 @@ static GSWContext * TheTemporaryContext; // __PRETTY_FUNCTION__, _name]; // } _archive = nil; - _encoding = NSUTF8StringEncoding; + _encoding = 0; // to test for real value later _template = nil; [self setCachingEnabled:[[GSWApp class] isCachingEnabled]]; _isAwake = NO; - if (_frameworkName == nil) { - _bundle=[[GSWBundle alloc] initWithPath:aPath - baseURL:baseURL - inFrameworkNamed: nil]; - } else { - _bundle=[[GSWBundle alloc] initWithPath:aPath - baseURL:baseURL - inFrameworkNamed: _frameworkName]; - if (_bundle == nil) - { - [NSException raise:NSInvalidArgumentException - format:@"%s: No framework named '%@'", - __PRETTY_FUNCTION__, _frameworkName]; - } - } _instancePoolLock = [[NSLock alloc] init]; @@ -156,10 +141,13 @@ static GSWContext * TheTemporaryContext; DESTROY(_wodPath); DESTROY(_wooPath); DESTROY(_archive); - DESTROY(_bundle); DESTROY(_sharedInstance); DESTROY(_instancePool); + DESTROY(_wooReadDate); + DESTROY(_htmlReadDate); + + [super dealloc]; }; @@ -232,11 +220,10 @@ static GSWContext * TheTemporaryContext; -(NSString*)description { //TODO - return [NSString stringWithFormat:@"<%s %p - name:[%@] bundle:[%@] frameworkName=[%@] componentClass=[%@] isCachingEnabled=[%s] isAwake=[%s]>", + return [NSString stringWithFormat:@"<%s %p - name:[%@] frameworkName=[%@] componentClass=[%@] isCachingEnabled=[%s] isAwake=[%s]>", object_getClassName(self), (void*)self, _name, - _bundle, _frameworkName, _componentClass, _caching ? "YES" : "NO", @@ -279,37 +266,8 @@ static GSWContext * TheTemporaryContext; //-------------------------------------------------------------------- -(void)_clearCache { - //OK - [_bundle clearCache]; } -//-------------------------------------------------------------------- --(GSWElement*)templateWithName:(NSString*)aName - languages:(NSArray*)languages -{ - GSWElement* element=nil; - - element=[_bundle templateNamed:aName - languages:languages]; - - return element; -}; - -//-------------------------------------------------------------------- --(NSString*)pathForResourceNamed:(NSString*)aName - ofType:(NSString*)aType - languages:(NSArray*)languages -{ - NSString* path=nil; - - path=[_bundle pathForResourceNamed:aName - ofType:aType - languages:languages]; - - return path; -}; - - // CHECKME -(GSWComponent*) _componentInstanceInContext:(GSWContext*) aContext @@ -475,24 +433,9 @@ static GSWContext * TheTemporaryContext; { BOOL createClassesOk=NO; NSString* superClassName=nil; - if (!WOStrictFlag) - { - // Search component archive for a superclass (superClassName keyword) - NSDictionary* archive=[_bundle archiveNamed:_name]; - superClassName=[archive objectForKey:@"superClassName"]; - if (superClassName) - { - if (!NSClassFromString(superClassName)) - { - ExceptionRaise(NSGenericException,@"Superclass %@ of component %@ doesn't exist", - superClassName, - _name); - }; - }; - }; // If we haven't found a superclass, use GSWComponent as the superclass if (!superClassName) - superClassName=@"GSWComponent"; + superClassName=@"WOComponent"; // Create class createClassesOk=[GSWApplication createUnknownComponentClasses:[NSArray arrayWithObject:_name] superClassName:superClassName]; @@ -518,27 +461,18 @@ static GSWContext * TheTemporaryContext; return componentReference; }; -//-------------------------------------------------------------------- -//NDFN --(NSDictionary*)componentAPI -{ - NSDictionary* componentAPI=nil; - componentAPI=[_bundle apiNamed:_name]; - - return componentAPI; -}; - //-------------------------------------------------------------------- -(void) finishInitializingComponent:(GSWComponent*)component { - NSDictionary* archive=nil; - - archive = [_bundle archiveNamed:_name]; + NSDictionary * archive=nil; + NSBundle * bundle = [NSBundle bundleForClass:NSClassFromString(_className)]; + + archive = [self archive]; if (archive) { - [_bundle initializeObject:component - fromArchive:archive]; + [bundle initializeObject:component + fromArchive:archive]; } } @@ -579,33 +513,161 @@ static GSWContext * TheTemporaryContext; [self notImplemented: _cmd]; //TODOFN }; -- (GSWElement *) template +/* + * returns the contents of the .woo + */ +- (NSDictionary *) archive { - BOOL htmlChangedOnDisk = NO; - BOOL wodChangedOnDisk = NO; - BOOL doCache = [self isCachingEnabled]; - - if (doCache == NO) { - htmlChangedOnDisk = YES; // todo compare last chage date with load date - if (_htmlPath != nil && !htmlChangedOnDisk) { - wodChangedOnDisk = YES; // todo compare last chage date with load date + if ((_caching) && (_archive)) { + // nothing to waste time with. + return _archive; + } else { + NSFileManager * defaultManager = [NSFileManager defaultManager]; + NSDictionary * attributes; + NSDate * modDate; + + attributes = [defaultManager attributesOfItemAtPath:_wooPath error:NULL]; + modDate = [attributes fileModificationDate]; + + + // file not found. + if (!modDate) { + modDate = [NSDate date]; + ASSIGN(_wooReadDate, modDate); + ASSIGN(_archive, [NSDictionary dictionary]); + return _archive; + } + + if ((!_wooReadDate) || (([modDate compare:_wooReadDate] == NSOrderedDescending))) { + ASSIGN(_wooReadDate, [NSDate date]); + ASSIGN(_archive, [NSDictionary dictionaryWithContentsOfFile:_wooPath]); } } - if (_htmlPath != nil && (_template == nil || htmlChangedOnDisk || wodChangedOnDisk)) { + return _archive; +} + + +-(NSStringEncoding) encoding +{ + NSDictionary * archive = nil; + NSString * encodingName = nil; + + if ((_encoding == 0)) { + + _encoding = [GSWMessage defaultEncoding]; // safer, because we may not have a .woo file + + archive = [self archive]; + if (archive) + { + encodingName = [archive objectForKey:@"encoding"]; + if (encodingName) + { + _encoding = [GSMimeDocument encodingFromCharset:encodingName]; + + if ((_encoding == 0)) { + [NSException raise: NSInvalidArgumentException + format: @"%s %@ -- unknown encoding '%@'",__PRETTY_FUNCTION__, _wooPath, encodingName]; + } + + } + } + } + + return _encoding; +} + +- (GSWElement *) _lockedTemplate +{ + //OK + GSWElement* template=nil; + NSStringEncoding encoding = [self encoding]; + + NSString* pageDefString=nil; + NSString* htmlString = [NSString stringWithContentsOfFile:_htmlPath + encoding:encoding]; + + if (!htmlString) + { + [NSException raise:NSInvalidArgumentException + format:@"%s: No HTML file found at '%@'", + __PRETTY_FUNCTION__, _htmlPath]; + } + + pageDefString = [NSString stringWithContentsOfFile:_wodPath + encoding:encoding]; + + if (!pageDefString) { + [NSException raise:NSInvalidArgumentException + format:@"%s: No WOD file found at '%@'", + __PRETTY_FUNCTION__, _wodPath]; + } + NS_DURING + { + template=[GSWTemplateParser templateNamed:_name + inFrameworkNamed:nil + withParserType:GSWTemplateParserType_Default + parserClassName:nil + withString:htmlString + encoding:encoding + fromPath:nil + declarationsString:pageDefString + languages:nil + declarationsPath:nil]; + } + NS_HANDLER + { + localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, + @"In template Parsing"); + [localException raise]; + } + NS_ENDHANDLER; + + return template; +} + +- (GSWElement *) template +{ + BOOL htmlChangedOnDisk = NO; + + // _htmlReadDate + if (_caching == NO) { + htmlChangedOnDisk = YES; + } else { + NSFileManager * defaultManager = [NSFileManager defaultManager]; + NSDictionary * attributes; + NSDate * modDate; + + attributes = [defaultManager attributesOfItemAtPath:_wooPath error:NULL]; + modDate = [attributes fileModificationDate]; + + if ((!_htmlReadDate) || (([modDate compare:_htmlReadDate] == NSOrderedDescending))) { + htmlChangedOnDisk = YES; + } else { + attributes = [defaultManager attributesOfItemAtPath:_wodPath error:NULL]; + modDate = [attributes fileModificationDate]; + + if (([modDate compare:_htmlReadDate] == NSOrderedDescending)) { + htmlChangedOnDisk = YES; + } + } + } + + if (_htmlPath != nil && (_template == nil || htmlChangedOnDisk)) { + ASSIGN(_htmlReadDate, [NSDate date]); + NS_DURING [TemplateLock lock]; DESTROY(_template); - - _template = RETAIN([_bundle templateNamed: _name - languages:nil]); // _language? array? + + _template = RETAIN([self _lockedTemplate]); [TemplateLock unlock]; - NS_HANDLER + NS_HANDLER DESTROY(_template); [TemplateLock unlock]; [localException raise]; - NS_ENDHANDLER - + NS_ENDHANDLER + } return _template; } diff --git a/GSWeb/GSWContext.m b/GSWeb/GSWContext.m index a33d3fe..427e8e6 100644 --- a/GSWeb/GSWContext.m +++ b/GSWeb/GSWContext.m @@ -1519,7 +1519,7 @@ GSWEB_EXPORT BOOL GSWContext_isSenderIDSearchOver(GSWContext* aContext) } if ((queryDictionary != nil) && ([queryDictionary count] > 0)) { - aQueryString = [queryDictionary encodeAsCGIFormValuesEscpaeAmpersand:escapeQueryDict]; + aQueryString = [queryDictionary encodeAsCGIFormValuesEscapeAmpersand:escapeQueryDict]; } url = [self _urlWithRequestHandlerKey:[[GSWApp class] directActionRequestHandlerKey] diff --git a/GSWeb/GSWDynamicURLString.m b/GSWeb/GSWDynamicURLString.m index 7dac6da..2698e11 100644 --- a/GSWeb/GSWDynamicURLString.m +++ b/GSWeb/GSWDynamicURLString.m @@ -460,6 +460,7 @@ static SEL appendStringSel = NULL; int tmpIndex=0; NSRange protocolEndRange; NSRange queryStringStartRange=[Left rangeOfString:@"?"]; + if (queryStringStartRange.length>0) { if (queryStringStartRange.location+1<[Left length]) @@ -527,8 +528,9 @@ static SEL appendStringSel = NULL; ASSIGN(_host,[Left substringToIndex:hostEndRangeSlash.location]); //NSDebugMLLog(@"low",@"host [%@]",_host); if (hostEndRangeSlash.location+hostEndRangeSlash.length<[Left length]) + { Left=[Left substringFromIndex:hostEndRangeSlash.location+hostEndRangeSlash.length-1];//Keep the '/' - else + } else Left=nil; //NSDebugMLLog(@"low",@"Left [%@]",Left); } @@ -638,13 +640,13 @@ static SEL appendStringSel = NULL; }; }; }; - //NSDebugMLLog(@"low",@"url=%@",_url); - //NSDebugMLLog(@"low",@"prefix=%@",_prefix); - //NSDebugMLLog(@"low",@"applicationName=%@",_applicationName); - //NSDebugMLLog(@"low",@"applicationNumberString=%@",_applicationNumberString); - //NSDebugMLLog(@"low",@"requestHandlerKey=%@",_requestHandlerKey); - //NSDebugMLLog(@"low",@"queryString=%@",_queryString); - //NSDebugMLLog(@"low",@"requestHandlerPath=%@",_requestHandlerPath); + // NSLog(@"%s %d _url:'%@'",__PRETTY_FUNCTION__, __LINE__, _url); + // NSLog(@"%s %d _prefix:'%@'",__PRETTY_FUNCTION__, __LINE__, _prefix); + // NSLog(@"%s %d _applicationName:'%@'",__PRETTY_FUNCTION__, __LINE__, _applicationName); + // NSLog(@"%s %d _applicationNumberString:'%@'",__PRETTY_FUNCTION__, __LINE__, _applicationNumberString); + // NSLog(@"%s %d _requestHandlerKey:'%@'",__PRETTY_FUNCTION__, __LINE__, _requestHandlerKey); + // NSLog(@"%s %d _queryString:'%@'",__PRETTY_FUNCTION__, __LINE__, _queryString); + // NSLog(@"%s %d _requestHandlerPath:'%@'",__PRETTY_FUNCTION__, __LINE__, _requestHandlerPath); }; /* diff --git a/GSWeb/GSWHTTPIO.m b/GSWeb/GSWHTTPIO.m index 2776c41..6cbfb2f 100644 --- a/GSWeb/GSWHTTPIO.m +++ b/GSWeb/GSWHTTPIO.m @@ -169,7 +169,7 @@ void _unpackHeaderLineAddToDict(NSString *line, NSMutableDictionary* headers) //PRIVATE -void _appendMessageHeaders(GSWMessage * message,NSMutableString * headers) +void _appendMessageHeaders(GSWResponse * message,NSMutableString * headers) { NSMutableDictionary * headerDict = [message headers]; NSArray * keyArray = nil; @@ -209,14 +209,17 @@ void _appendMessageHeaders(GSWMessage * message,NSMutableString * headers) } //PRIVATE -void _sendMessage(GSWMessage * message, NSFileHandle* fh, NSString * httpVersion, GSWRequest * request, NSMutableString * headers) +void _sendMessage(GSWResponse * message, NSFileHandle* fh, NSString * httpVersion, GSWRequest * request, NSMutableString * headers) { int contentLength = 0; BOOL keepAlive = NO; BOOL requestIsHead = NO; - + NSString * eTagString = nil; + NSString * ifNoneMatchValue; + if (message) { contentLength = [message _contentLength]; + eTagString = [message headerForKey:@"ETag"]; } if (request) { @@ -225,10 +228,19 @@ void _sendMessage(GSWMessage * message, NSFileHandle* fh, NSString * httpVersion keepAlive = [connectionValue isEqualToString:KEEP_ALIVE]; } requestIsHead = [[request method] isEqualToString:HEAD]; + ifNoneMatchValue = [request headerForKey:@"if-none-match"]; } + if ([ifNoneMatchValue isEqualToString:eTagString]) { + // return 304 Not Modified + [message setStatus:304]; + } + + [headers appendString:GSWIntToNSString([message status])]; + [headers appendString:URIResponseString]; + _appendMessageHeaders(message,headers); - + if ([httpVersion isEqualToString:HTTP11]) { // bug #24006 keep-alive is not implemented. // I am uable to reproduce the need for double clicking on links/forms, @@ -239,7 +251,7 @@ void _sendMessage(GSWMessage * message, NSFileHandle* fh, NSString * httpVersion [headers appendString:@"connection: keep-alive\r\n"]; } } - + if ((contentLength > 0) || _alwaysAppendContentLength) { [headers appendString:CONTENT_LENGTHCOLON]; [headers appendString:[NSString stringWithFormat:@"%d\r\n", contentLength]]; @@ -249,7 +261,8 @@ void _sendMessage(GSWMessage * message, NSFileHandle* fh, NSString * httpVersion [fh writeData: [headers dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:YES]]; - if ((requestIsHead == NO) && (contentLength > 0)) { + if (((requestIsHead == NO) && (contentLength > 0)) && + ([message status] != 304)) { [fh writeData: [message content]]; } } @@ -401,7 +414,7 @@ void _sendMessage(GSWMessage * message, NSFileHandle* fh, NSString * httpVersion method: [requestArray objectAtIndex:0] length: contentLength]; } - + request = [[GSWRequest alloc] initWithMethod:method uri:[requestArray objectAtIndex:1] httpVersion:[requestArray objectAtIndex:2] @@ -430,8 +443,6 @@ void _sendMessage(GSWMessage * message, NSFileHandle* fh, NSString * httpVersion [bufferStr appendString:httpVersion]; [bufferStr appendString:SPACE]; - [bufferStr appendString:GSWIntToNSString([response status])]; - [bufferStr appendString:URIResponseString]; _sendMessage(response, fh, httpVersion, request, bufferStr); diff --git a/GSWeb/GSWImage.m b/GSWeb/GSWImage.m index 3672608..4023793 100644 --- a/GSWeb/GSWImage.m +++ b/GSWeb/GSWImage.m @@ -110,109 +110,99 @@ RCS_ID("$Id$") NSString *fileNameValue; NSString *frameworkName = nil; NSString *resourceURL; - + resourcemanager = [GSWApp resourceManager]; component = GSWContext_component(context); fileNameValue = [filename valueInComponent:component]; - frameworkName - = [GSWHTMLDynamicElement _frameworkNameForAssociation: framework - inComponent: component]; - + frameworkName = [framework valueInComponent:component]; + resourceURL = [context _urlForResourceNamed: fileNameValue - inFramework: frameworkName]; - + inFramework: frameworkName]; + if (resourceURL != nil) + { + NSString *widthStr = nil; + NSString *heightStr = nil; + BOOL calculateWidth = NO; + BOOL calculateHeight = NO; + + if (width != nil) { - NSString *widthStr = nil; - NSString *heightStr = nil; - BOOL calculateWidth = NO; - BOOL calculateHeight = NO; - - if (width != nil || height != nil) - { - if (width != nil) - { - id widthValue; - widthValue = [width valueInComponent:component]; - if (widthValue) - { - widthStr = NSStringWithObject(widthValue); - } - calculateWidth = (widthStr == nil || [widthStr isEqual:@"*"]); - } - if (height != nil) - { - id heightValue; - heightValue = [height valueInComponent:component]; - if (heightValue) - { - heightStr = NSStringWithObject(heightValue); - } - calculateHeight = (heightStr == nil || [heightStr isEqual:@"*"]); - } - } - else - { - calculateWidth = YES; - calculateHeight = YES; - - GSOnceMLog(@"%@: No height or width information provided for '%@'. If possible, this information should be provided for best performance.", - NSStringFromClass([self class]), fileNameValue); - } - - if (calculateWidth || calculateHeight) - { - GSWImageInfo * imageinfo; - - imageinfo = [resourcemanager _imageInfoForUrl: resourceURL - fileName: fileNameValue - framework: frameworkName - languages: [context languages]]; - if (imageinfo != nil) + id widthValue; + widthValue = [width valueInComponent:component]; + if (widthValue) + { + widthStr = NSStringWithObject(widthValue); + } + calculateWidth = (widthStr == nil || [widthStr isEqual:@"*"]); + } + if (height != nil) + { + id heightValue; + heightValue = [height valueInComponent:component]; + if (heightValue) + { + heightStr = NSStringWithObject(heightValue); + } + calculateHeight = (heightStr == nil || [heightStr isEqual:@"*"]); + } + + if (calculateWidth || calculateHeight) + { + GSWImageInfo * imageinfo; + + GSOnceMLog(@"%@: No height or width information provided for '%@'. If possible, this information should be provided for best performance.", + NSStringFromClass([self class]), fileNameValue); + + imageinfo = [resourcemanager _imageInfoForUrl: resourceURL + fileName: fileNameValue + framework: frameworkName + languages: [context languages]]; + if (imageinfo != nil) { if (calculateWidth) - { - widthStr = [imageinfo widthString]; - } + { + widthStr = [imageinfo widthString]; + } if (calculateHeight) - { - heightStr = [imageinfo heightString]; - } + { + heightStr = [imageinfo heightString]; + } } - else + else { NSLog(@"%@: Could not get height/width information for image at '%@' '%@' '%@'", NSStringFromClass([self class]), resourceURL, - fileNameValue, frameworkName); + fileNameValue, frameworkName); } - } - - [response _appendTagAttribute: @"src" - value: resourceURL - escapingHTMLAttributeValue: NO]; - - if (widthStr != nil) - { - [response _appendTagAttribute: @"width" - value: widthStr - escapingHTMLAttributeValue: NO]; - } - if (heightStr != nil) - { - [response _appendTagAttribute: @"height" - value: heightStr - escapingHTMLAttributeValue: NO]; - } } - else + + [response _appendTagAttribute: @"src" + value: resourceURL + escapingHTMLAttributeValue: NO]; + + if (widthStr != nil) { - NSString *message - = [resourcemanager errorMessageUrlForResourceNamed: fileNameValue - inFramework: frameworkName]; - [response _appendTagAttribute:@"src" - value: message - escapingHTMLAttributeValue:NO]; + [response _appendTagAttribute: @"width" + value: widthStr + escapingHTMLAttributeValue: NO]; } + if (heightStr != nil) + { + [response _appendTagAttribute: @"height" + value: heightStr + escapingHTMLAttributeValue: NO]; + } + } + else + { + NSString *message + = [resourcemanager errorMessageUrlForResourceNamed: fileNameValue + inFramework: frameworkName]; + [response _appendTagAttribute:@"src" + value: message + escapingHTMLAttributeValue:NO]; + } } // used from GSWActiveImage diff --git a/GSWeb/GSWImageButton.m b/GSWeb/GSWImageButton.m index b5bc234..2c731ae 100644 --- a/GSWeb/GSWImageButton.m +++ b/GSWeb/GSWImageButton.m @@ -462,26 +462,20 @@ RCS_ID("$Id$") GSWAssociation* actionAssociation=nil; NSArray* regions=nil; if (_imageMapFileName) + { + id imageMapFileNameValue=[_imageMapFileName valueInComponent:component]; + NSString* imageMapFilePath; + + imageMapFilePath=[[GSWApp resourceManager] pathForResourceNamed:imageMapFileNameValue + inFramework:nil + languages:[aContext languages]]; + if (imageMapFilePath) + regions=[GSWGeometricRegion geometricRegionsWithFile:imageMapFilePath]; + else { - id imageMapFileNameValue=[_imageMapFileName valueInComponent:component]; - NSString* imageMapFilePath=[component - pathForResourceNamed:imageMapFileNameValue - ofType:nil]; - if (!imageMapFilePath) - { - GSWResourceManager* resourceManager=[[GSWApplication application]resourceManager]; - NSArray* languages=[aContext languages]; - imageMapFilePath=[resourceManager pathForResourceNamed:imageMapFileNameValue - inFramework:nil - languages:languages]; - }; - if (imageMapFilePath) - regions=[GSWGeometricRegion geometricRegionsWithFile:imageMapFilePath]; - else - { - //NSDebugMLLog0(@"gswdync",@"GSWActiveImage No image Map."); - }; - } + //NSDebugMLLog0(@"gswdync",@"GSWActiveImage No image Map."); + }; + } else if (!WOStrictFlag && _imageMapString) { id imageMapValue=[_imageMapString valueInComponent:component]; diff --git a/GSWeb/GSWResourceManager.h b/GSWeb/GSWResourceManager.h index f0736b3..340dde0 100644 --- a/GSWeb/GSWResourceManager.h +++ b/GSWeb/GSWResourceManager.h @@ -57,128 +57,35 @@ GSWEB_EXPORT NSDictionary* globalMime; }; -(NSString*)description; --(void)_initFrameworkProjectBundles; //-(NSString*)frameworkNameForPath:(NSString*)path_; -(NSString*)pathForResourceNamed:(NSString*)name inFramework:(NSString*)frameworkName languages:(NSArray*)languages; + -(NSString*)urlForResourceNamed:(NSString*)name inFramework:(NSString*)frameworkName languages:(NSArray*)languages request:(GSWRequest*)request; --(NSString*)stringForKey:(NSString*)key_ + +/* + * Return value: string from tableName using key to look it up. + * first searches the tableName.strings file in the locale + * subdirectories. languages specifies the search order. + */ + +-(NSString*)stringForKey:(NSString*)key inTableNamed:(NSString*)tableName - withDefaultValue:(NSString*)defaultValue_ + withDefaultValue:(NSString*)defaultValue inFramework:(NSString*)frameworkName languages:(NSArray*)languages; -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)tableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages - foundLanguage:(NSString**)foundLanguagePtr; - -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)tableName - inFramework:(NSString*)frameworkName - languages:(NSArray*)languages; - -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)tableName - inFramework:(NSString*)frameworkName - languages:(NSArray*)languages; - -(void)lock; -(void)unlock; --(NSString*)lockedStringForKey:(NSString*)key - inTableNamed:(NSString*)tableName - inFramework:(NSString*)framework - languages:(NSArray*)languages; - -//NDFN --(NSDictionary*)lockedStringsTableNamed:(NSString*)aTableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages - foundLanguage:(NSString**)foundLanguagePtr; - - -//NDFN --(NSString*)lockedStringForKey:(NSString*)aKey - inTableNamed:(NSString*)aTableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages - foundLanguage:(NSString**)foundLanguagePtr; - -//NDFN --(NSDictionary*)lockedStringsTableNamed:(NSString*)tableName - inFramework:(NSString*)framework - languages:(NSArray*)languages; - -//NDFN --(NSArray*)lockedStringsTableArrayNamed:(NSString*)aTableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages - foundLanguage:(NSString**)foundLanguagePtr; - -//NDFN --(NSArray*)lockedStringsTableArrayNamed:(NSString*)tableName - inFramework:(NSString*)framework - languages:(NSArray*)languages; - --(NSString*)lockedCachedStringForKey:(NSString*)key - inTableNamed:(NSString*)tableName - inFramework:(NSString*)frameworkName - language:(NSString*)language; - --(NSDictionary*)lockedCachedStringsTableWithName:(NSString*)tableName - inFramework:(NSString*)frameworkName - language:(NSString*)language; - -//NDFN --(NSArray*)lockedCachedStringsTableArrayWithName:(NSString*)tableName - inFramework:(NSString*)frameworkName - language:(NSString*)language; - --(NSDictionary*)lockedStringsTableWithName:(NSString*)tableName - inFramework:(NSString*)frameworkName - language:(NSString*)language; - -//NDFN --(NSArray*)lockedStringsTableArrayWithName:(NSString*)tableName - inFramework:(NSString*)frameworkName - language:(NSString*)language; - --(NSString*)lockedUrlForResourceNamed:(NSString*)name - inFramework:(NSString*)frameworkName - languages:(NSArray*)languages_ - request:(GSWRequest*)request; - --(NSString*)lockedCachedURLForResourceNamed:(NSString*)name - inFramework:(NSString*)frameworkName - languages:(NSArray*)languages; - --(NSString*)lockedPathForResourceNamed:(NSString*)name - inFramework:(NSString*)frameworkName - languages:(NSArray*)languages; - -/** GSWeb specific -Returns the bundle for framework named aFrameworkName or application -bundle if none is found -**/ --(GSWDeployedBundle*)cachedBundleForFrameworkNamed:(NSString*)aFrameworkName; - -/** Returns the bundle for framework named aFrameworkName or application -bundle if none is found -**/ --(GSWDeployedBundle*)lockedCachedBundleForFrameworkNamed:(NSString*)name; - -(void)flushDataCache; --(void)setURLValuedElementData:(GSWURLValuedElementData*)data; - -(void)setData:(NSData*)data forKey:(NSString*)key mimeType:(NSString*)type @@ -190,29 +97,32 @@ bundle if none is found -(NSString*)pathForResourceNamed:(NSString*)name inFramework:(NSString*)frameworkName language:(NSString*)language; --(NSString*)lockedPathForResourceNamed:(NSString*)name - inFramework:(NSString*)frameworkName - language:(NSString*)language; + -(GSWDeployedBundle*)_appProjectBundle; --(NSArray*)_allFrameworkProjectBundles; --(void)lockedRemoveDataForKey:(NSString*)key; -(BOOL)_doesRequireJavaVirualMachine; -(NSString*)_absolutePathForJavaClassPath:(NSString*)path; -(GSWURLValuedElementData*)_cachedDataForKey:(NSString*)key; --(void)lockedCacheData:(GSWURLValuedElementData*)data; -(NSString*)contentTypeForResourcePath:(NSString*)path; -(NSArray*)_frameworkClassPaths; +/* Deprecated in WO 4.0. + * Use urlForResourceNamed:inFramework:languages:request: instead. + */ + -(NSString*)urlForResourceNamed:(NSString*)name - inFramework:(NSString*)frameworkName; + inFramework:(NSString*)frameworkName GS_ATTRIB_DEPRECATED; + +/* Deprecated in WO 4.0. + * Use pathForResourceNamed:inFramework:languages: instead. + */ + -(NSString*)pathForResourceNamed:(NSString*)name - inFramework:(NSString*)frameworkName; + inFramework:(NSString*)frameworkName GS_ATTRIB_DEPRECATED; +(NSString*)GSLanguageFromISOLanguage:(NSString*)ISOLanguage; //NDFN +(NSArray*)GSLanguagesFromISOLanguages:(NSArray*)ISOlanguages; //NDFN +(NSString*)ISOLanguageFromGSLanguage:(NSString*)GSLanguage; //NDFN +(NSArray*)ISOLanguagesFromGSLanguages:(NSArray*)GSlanguages; //NDFN -+(GSWBundle*)_applicationGSWBundle; - (NSString*) errorMessageUrlForResourceNamed:(NSString *) resourceName inFramework:(NSString *) frameworkName; diff --git a/GSWeb/GSWResourceManager.m b/GSWeb/GSWResourceManager.m index 0d466d9..f513f28 100644 --- a/GSWeb/GSWResourceManager.m +++ b/GSWeb/GSWResourceManager.m @@ -42,7 +42,6 @@ static NSString * emptyStr=@""; //==================================================================== @implementation GSWResourceManager -GSWBundle* globalAppGSWBundle=nil; GSWProjectBundle* globalAppProjectBundle=nil; NSDictionary* globalMime=nil; NSString* globalMimePListPathName=nil; @@ -50,6 +49,7 @@ NSDictionary* localGS2ISOLanguages=nil; NSDictionary* localISO2GSLanguages=nil; NSString* globalLanguagesPListPathName=nil; NSString* localNotFoundMarker=@"NOTFOUND"; +NSMutableDictionary *globalPathCache = nil; //-------------------------------------------------------------------- +(void)initialize { @@ -73,11 +73,91 @@ NSString* localNotFoundMarker=@"NOTFOUND"; }; }; +-(void) _loadMimeTypes +{ + NSBundle* resourceManagerBundle = [NSBundle bundleForClass: [self class]]; + + globalMimePListPathName=[resourceManagerBundle pathForResource:@"MIME" + ofType:@"plist"]; + + NSAssert(globalMimePListPathName,@"No resource MIME.plist"); + { + NSDictionary* tmpMimeTypes=nil; + NSMutableDictionary* mimeTypes=(NSMutableDictionary*)[NSMutableDictionary dictionary]; + tmpMimeTypes=[NSDictionary dictionaryWithContentsOfFile:globalMimePListPathName]; + + if (tmpMimeTypes) + { + NSEnumerator* enumerator = [tmpMimeTypes keyEnumerator]; + id key=nil; + id value=nil; + while ((key = [enumerator nextObject])) + { + value=[tmpMimeTypes objectForKey:key]; + NSAssert(value,@"No value"); + value=[value lowercaseString]; + key=[key lowercaseString]; + NSAssert(key,@"No key"); + [mimeTypes setObject:value + forKey:key]; + }; + // NSDebugMLLog(@"resmanager",@"mimeTypes=%@",mimeTypes); + }; + ASSIGN(globalMime,[NSDictionary dictionaryWithDictionary:mimeTypes]); + } +} + +- (void) _loadLanguages +{ + NSBundle* resourceManagerBundle = [NSBundle bundleForClass: [self class]]; + globalLanguagesPListPathName=[resourceManagerBundle pathForResource:@"languages" + ofType:@"plist"]; + if (!globalLanguagesPListPathName) + globalLanguagesPListPathName=[[NSBundle bundleForClass: [self class]] + pathForResource:@"languages" + ofType:@"plist"]; + + NSAssert(globalLanguagesPListPathName,@"No resource languages.plist"); + { + NSDictionary* tmpLanguages=nil; + NSMutableDictionary* ISO2GS=(NSMutableDictionary*)[NSMutableDictionary dictionary]; + NSMutableDictionary* GS2ISO=(NSMutableDictionary*)[NSMutableDictionary dictionary]; + tmpLanguages=[NSDictionary dictionaryWithContentsOfFile:globalLanguagesPListPathName]; + if (tmpLanguages) + { + NSEnumerator* enumerator = [tmpLanguages keyEnumerator]; + id iso=nil; + id gs=nil; + while ((iso = [enumerator nextObject])) + { + gs=[tmpLanguages objectForKey:iso]; + NSAssert(gs,@"No gs"); + [ISO2GS setObject:gs + forKey:[iso lowercaseString]]; + if ([iso length]==2)//No xx-xx + { + [GS2ISO setObject:iso + forKey:[gs lowercaseString]]; + }; + }; + }; + ASSIGN(localISO2GSLanguages,[NSDictionary dictionaryWithDictionary:ISO2GS]); + ASSIGN(localGS2ISOLanguages,[NSDictionary dictionaryWithDictionary:GS2ISO]); + } +} + //-------------------------------------------------------------------- -(id)init { if ((self=[super init])) { + if (!globalMime) { + [self _loadMimeTypes]; + [self _loadLanguages]; + } + if (!globalPathCache) { + globalPathCache = [NSMutableDictionary new]; + } //TODO NSBundle* mainBundle=[NSBundle mainBundle]; NSArray* allFrameworks=[NSBundle allFrameworks]; int i=0; @@ -102,7 +182,7 @@ NSString* localNotFoundMarker=@"NOTFOUND"; _urlValuedElementsData=[NSMutableDictionary new]; _stringsTablesByFrameworkByLanguageByName=[NSMutableDictionary new]; _stringsTableArraysByFrameworkByLanguageByName=[NSMutableDictionary new]; - [self _initFrameworkProjectBundles]; +// [self _initFrameworkProjectBundles]; // _frameworkPathsToFrameworksNames=[NSMutableDictionary new]; allFrameworks=[NSBundle allFrameworks]; @@ -174,224 +254,144 @@ NSString* localNotFoundMarker=@"NOTFOUND"; }; //-------------------------------------------------------------------- --(void)_initFrameworkProjectBundles -{ - //OK - NSArray* allFrameworks=nil; - int i=0; - int allFrameworksCount=0; - NSBundle* bundle=nil; - NSString* frameworkName=nil; - - allFrameworks=[NSBundle allFrameworks]; - - allFrameworksCount=[allFrameworks count]; - - for(i=0;i> /WOExtensions/wr/back.png + // /Users/dave/dev/gsweb/trunk/Testing/DynamicElements/DynamicElements.gswa/Contents/Resources/WebServer/testpic.jpg + // ->> /wr/testpic.jpg + + NSString * newPath = nil; + + NSRange range = [oldPath rangeOfString:@"Resources/WebServer" + options:NSBackwardsSearch]; + + if ((range.location == NSNotFound)) { + if (([oldPath hasSuffix:@".wo"] == NO)) { + return nil; + } + } else { + newPath = [oldPath substringFromIndex: range.location+range.length]; + } + + if (!frameworkName) { + return newPath; + } + + return [NSString stringWithFormat:@"/%@/wr%@",frameworkName, newPath]; + +} + +/* + Returns the URL for a resource name. + The URL returned is of the following form: + /WebObjects/MyApp.woa/0/wr/English.lproj/name + /WebObjects/MyApp.woa/0/wr/testpic.jpg + /WebObjects/MyApp.woa/0/wr/MyFramework/wr/English.lproj/name + */ + -(NSString*)urlForResourceNamed:(NSString*)name inFramework:(NSString*)aFrameworkName languages:(NSArray*)languages request:(GSWRequest*)request { - //OK NSString* url=nil; + NSString* path=nil; + + if ((languages) && ([languages count])) { + NSEnumerator * langEnumer = [languages objectEnumerator]; + NSString * currentLang; + + while (((currentLang = [langEnumer nextObject])) && (!path)) { + path = [self pathForResourceNamed:name + inFramework:aFrameworkName + language:currentLang]; + + } + } else { + // no languages + + path = [self pathForResourceNamed:name + inFramework:aFrameworkName + language:nil]; + + } - [self lock]; - NS_DURING - { - url=[self lockedUrlForResourceNamed:name - inFramework:aFrameworkName - languages:languages - request:request]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; + if (!path) { + return nil; + } + + path = [self _cleanPath:path frameworkName:aFrameworkName]; + + url = [NSString stringWithFormat:@"%@/%@.woa/0/wr%@", [GSWApplication applicationBaseURL], + [GSWApp name], path]; + return url; -}; +} -//-------------------------------------------------------------------- +/* + * Return value: string from tableName using key to look it up. + * first searches the tableName.strings file in the locale + * subdirectories. languages specifies the search order. + */ -(NSString*)stringForKey:(NSString*)key inTableNamed:(NSString*)tableName withDefaultValue:(NSString*)defaultValue inFramework:(NSString*)framework languages:(NSArray*)languages { - NSString* string=nil; - [self lock]; - NS_DURING - { - string=[self lockedStringForKey:key - inTableNamed:tableName - inFramework:framework - languages:languages]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - if (!string) - string=defaultValue; - return string; -}; - -//-------------------------------------------------------------------- -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)tableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages - foundLanguage:(NSString**)foundLanguagePtr -{ - NSDictionary* stringsTable=nil; - [self lock]; - NS_DURING - { - stringsTable=[self lockedStringsTableNamed:tableName - inFramework:aFrameworkName - languages:languages - foundLanguage:foundLanguagePtr]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - return stringsTable; -}; - -//-------------------------------------------------------------------- -//NDFN --(NSDictionary*)stringsTableNamed:(NSString*)tableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages; -{ - return [self stringsTableNamed:tableName - inFramework:aFrameworkName - languages:languages - foundLanguage:NULL]; -}; - -//-------------------------------------------------------------------- -//NDFN --(NSArray*)stringsTableArrayNamed:(NSString*)tableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages -{ - NSArray* stringsTableArray=nil; - - [self lock]; - NS_DURING - { - stringsTableArray=[self lockedStringsTableArrayNamed:tableName - inFramework:aFrameworkName - languages:languages]; - } - NS_HANDLER - { - //TODO - [self unlock]; - [localException raise]; - } - NS_ENDHANDLER; - [self unlock]; - return stringsTableArray; + NSLog(@"I am working on this -- dw"); +// NSString* string=nil; +// [self lock]; +// NS_DURING +// { +// string=[self lockedStringForKey:key +// inTableNamed:tableName +// inFramework:framework +// languages:languages]; +// } +// NS_HANDLER +// { +// //TODO +// [self unlock]; +// [localException raise]; +// } +// NS_ENDHANDLER; +// [self unlock]; +// if (!string) +// string=defaultValue; +// return string; + return nil; }; //-------------------------------------------------------------------- @@ -412,723 +412,31 @@ NSString* localNotFoundMarker=@"NOTFOUND"; #endif }; -//-------------------------------------------------------------------- --(NSString*)lockedStringForKey:(NSString*)aKey - inTableNamed:(NSString*)aTableName - inFramework:(NSString*)aFrameworkName - languages:(NSArray*)languages - foundLanguage:(NSString**)foundLanguagePtr -{ - //OK - NSString* string=nil; - NSString* language=nil; - int i=0; - int count=0; - int iFramework=0; - NSArray* frameworks=nil; - NSString* frameworkName=nil; - int frameworksCount=0; - - if (!WOStrictFlag && [aFrameworkName isEqualToString:GSWFramework_all]) - { - frameworks=[_frameworkProjectBundlesCache allKeys]; - frameworks=[frameworks arrayByAddingObject:emptyStr]; - } - count=[languages count]; - frameworksCount=[frameworks count]; - - for(i=0;!string && i<=count;i++) - { - if (i0) { + NSString * eTagString = [NSString stringWithFormat:@"%lx", + (unsigned long) [_contentData hash]]; + + [self setHeader:eTagString + forKey:@"ETag"]; + } + // Now we see if we can gzip the content // it does not make sense to compress data less than 150 bytes. if ((dataLength > 150) && ([self _browserSupportsCompression:[aContext request]])) diff --git a/GSWeb/GSWeb.h b/GSWeb/GSWeb.h index 0104f52..952af99 100644 --- a/GSWeb/GSWeb.h +++ b/GSWeb/GSWeb.h @@ -99,7 +99,7 @@ @class GSWStatisticsStore; @class GSWRequestHandler; @class GSWComponentDefinition; -@class GSWBundle; +//@class GSWBundle; @class GSWMultiKeyDictionary; @class GSWCookie; @class GSWElementID; @@ -122,7 +122,6 @@ @class GSWDeclaration; @class GSWDeclarationParser; @class GSWDynamicGroup; -@class GSWBundle; @class GSWSessionTimeOutManager; @class GSWServerSessionStore; @class GSWDeployedBundle; diff --git a/GSWeb/Resources/MIME.plist b/GSWeb/Resources/MIME.plist index bf66d46..992207b 100644 --- a/GSWeb/Resources/MIME.plist +++ b/GSWeb/Resources/MIME.plist @@ -12,6 +12,7 @@ "tif" = "image/tiff"; "tiff" = "image/tiff"; "jpeg" = "image/jpeg"; + "svg" = "image/svg+xml"; // Audio types "au" = "audio/basic"; diff --git a/Testing/DynamicElements/GNUmakefile b/Testing/DynamicElements/GNUmakefile index 725286e..76bd48a 100644 --- a/Testing/DynamicElements/GNUmakefile +++ b/Testing/DynamicElements/GNUmakefile @@ -34,6 +34,7 @@ DynamicElements_GSWAPP_INFO_PLIST=Resources/Info-DynamicElements.plist DynamicElements_RESOURCE_FILES = \ Resources/Info-DynamicElements.plist \ +DynamicElements_WEBSERVER_RESOURCE_FILES = testpic.jpg # The Objective-C source files to be compiled DynamicElements_OBJC_FILES = \ @@ -53,7 +54,8 @@ PopUpButton2Page.m \ TextField1Page.m \ CheckBox1Page.m \ CheckBox2Page.m \ -RadioButton1Page.m +RadioButton1Page.m \ +ImagePage.m DynamicElements_COMPONENTS = \ Main.wo \ @@ -69,7 +71,8 @@ PopUpButton2Page.wo \ TextField1Page.wo \ CheckBox1Page.wo \ CheckBox2Page.wo \ -RadioButton1Page.wo +RadioButton1Page.wo \ +ImagePage.wo -include Makefile.preamble diff --git a/Testing/DynamicElements/ImagePage.h b/Testing/DynamicElements/ImagePage.h new file mode 100644 index 0000000..135bd7a --- /dev/null +++ b/Testing/DynamicElements/ImagePage.h @@ -0,0 +1,39 @@ +/** ImagePage.h - GSWeb Testing: Class GSWImage + + Copyright (C) 2010 Free Software Foundation, Inc. + + Written by: David Wetzel + + $Revision: 15261 $ + $Date: 2002-12-06 06:28:27 -0800 (Fr, 06 Dez 2002) $ + $Id: CheckBox2Page.h 15261 2002-12-06 14:28:27Z mguesdon $ + + This file is part of the GNUstep Web Library. + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **/ + + +#ifndef _ImagePage_h__ +#define _ImagePage_h__ + +@interface ImagePage: BasePage +{ +} +@end + +#endif //_ImagePage_h__ diff --git a/Testing/DynamicElements/ImagePage.m b/Testing/DynamicElements/ImagePage.m new file mode 100644 index 0000000..f3e994b --- /dev/null +++ b/Testing/DynamicElements/ImagePage.m @@ -0,0 +1,38 @@ +/** ImagePage.m - GSWeb Testing: Class GSWImage + + Copyright (C) 2010 Free Software Foundation, Inc. + + Written by: David Wetzel + + $Revision: 30689 $ + $Date: 2010-06-11 18:18:12 -0700 (Fr, 11 Jun 2010) $ + $Id: CheckBox2Page.m 30689 2010-06-12 01:18:12Z dwetzel $ + + This file is part of the GNUstep Web Library. + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **/ + +#include +#include "BasePage.h" +#include "ImagePage.h" + + +@implementation ImagePage + +@end + diff --git a/Testing/DynamicElements/ImagePage.wo/ImagePage.html b/Testing/DynamicElements/ImagePage.wo/ImagePage.html new file mode 100644 index 0000000..f2d4ada --- /dev/null +++ b/Testing/DynamicElements/ImagePage.wo/ImagePage.html @@ -0,0 +1,14 @@ + + + + + GSW Image Test + + +

GSWImage Test 1 (Web server resources)

+
+ +
+ + + diff --git a/Testing/DynamicElements/ImagePage.wo/ImagePage.wod b/Testing/DynamicElements/ImagePage.wo/ImagePage.wod new file mode 100644 index 0000000..09f4b0a --- /dev/null +++ b/Testing/DynamicElements/ImagePage.wo/ImagePage.wod @@ -0,0 +1,11 @@ +MainPageLink: WOHyperlink +{ + pageName = "Main"; + string = "Main Page"; +} + +TestImage: WOImage +{ + filename = "testpic.jpg"; + alt = "test"; +} diff --git a/Testing/DynamicElements/ImagePage.wo/ImagePage.woo b/Testing/DynamicElements/ImagePage.wo/ImagePage.woo new file mode 100644 index 0000000..9037d67 --- /dev/null +++ b/Testing/DynamicElements/ImagePage.wo/ImagePage.woo @@ -0,0 +1 @@ +{"WebObjects Release" = "WebObjects 5.0"; encoding = NSUTF8StringEncoding; } diff --git a/Testing/DynamicElements/Resources/Info-DynamicElements.plist b/Testing/DynamicElements/Resources/Info-DynamicElements.plist index be9fa53..6bc213c 100644 --- a/Testing/DynamicElements/Resources/Info-DynamicElements.plist +++ b/Testing/DynamicElements/Resources/Info-DynamicElements.plist @@ -78,6 +78,11 @@ pageName = "RadioButton1Page"; label = "RadioButton 1"; comment = "GSWRadioButton Test 1"; + }, + { + pageName = "ImagePage"; + label = "Image"; + comment = "GSWImage Test"; } ); RadioButtonList = { diff --git a/Testing/DynamicElements/WebServerResources/testpic.jpg b/Testing/DynamicElements/WebServerResources/testpic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..95f23f81d435f604771921309813ea76b8a0b2bb GIT binary patch literal 38220 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 literal 0 HcmV?d00001