]> err.no Git - sope/blobdiff - sope-appserver/NGObjWeb/WOApplication.m
major improvements in resource/template lookup with SoProduct's
[sope] / sope-appserver / NGObjWeb / WOApplication.m
index 64dc6924300e5476924928780730fb0043b6af65..61bca098e6b568ff7d5e1c764de345286f7b91f2 100644 (file)
@@ -1,24 +1,23 @@
 /*
-  Copyright (C) 2000-2004 SKYRIX Software AG
+  Copyright (C) 2000-2005 SKYRIX Software AG
 
-  This file is part of OpenGroupware.org.
+  This file is part of SOPE.
 
-  OGo is free software; you can redistribute it and/or modify it under
+  SOPE is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version.
 
-  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+  SOPE 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 Lesser General Public
   License for more details.
 
   You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
+  License along with SOPE; see the file COPYING.  If not, write to the
   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.
 */
-// $Id: WOApplication.m 1 2004-08-20 10:08:27Z znek $
 
 #include <NGObjWeb/WOApplication.h>
 #include "WOContext+private.h"
 #include <time.h>
 
 @interface WOApplication(PrivateMethods)
++ (id)logger;
 - (id)_loadComponentDefinitionWithName:(NSString *)_name
   language:(NSArray *)_langs;
 - (NSDictionary *)memoryStatistics;
 @end
 
 static NSRecursiveLock *classLock = nil;
-static BOOL  perflog     = NO;
+static NGLogger *perfLogger       = nil;
 static Class NSDateClass = Nil;
 static Class WOTemplateClass = Nil;
 static BOOL  debugOn     = NO;
@@ -57,6 +57,12 @@ static NSString *rapidTurnAroundPath = nil;
 
 @implementation WOApplication
 
+#if 1
+static NSString *defaultCompRqHandlerClassName = @"OWViewRequestHandler";
+#else
+static NSString *defaultCompRqHandlerClassName = @"WOComponentRequestHandler";
+#endif
+
 + (int)version {
   return [super version] + 5 /* v6 */;
 }
@@ -69,25 +75,30 @@ static NSString *rapidTurnAroundPath = nil;
   c = [(id<NSObject>)clazz performSelector:@selector(defaultSNSConnection)];
 
   if (c == nil) {
-    NSLog(@"could not connect SNS, exiting ..");
+    [[self logger] fatalWithFormat:@"could not connect SNS, exiting .."];
     exit(20);
   }
   
-  NSLog(@"SNS enabled");
+  [[self logger] logWithFormat:@"SNS enabled"];
 }
 
 + (void)_initializeWOApp {
   static BOOL isInitialized = NO;
   NSAutoreleasePool *pool;
   NSUserDefaults    *ud;
-  
+  NGLoggerManager   *lm;
+
   if (isInitialized) return;
 
   isInitialized = YES;
 
   pool = [[NSAutoreleasePool alloc] init];
   debugOn = [WOApplication isDebuggingEnabled];
-  
+  if (!debugOn)
+    [[self logger] setLogLevel:NGLogLevelInfo];
+  else
+    NSLog(@"Note: WOApplication debugging is enabled.");
+
   if (classLock == nil) classLock = [[NSRecursiveLock alloc] init];
   ud = [NSUserDefaults standardUserDefaults];
   
@@ -96,14 +107,16 @@ static NSString *rapidTurnAroundPath = nil;
   if ([ud boolForKey:@"WOContactSNS"])
     [self _setupSNS];
   else
-    NSLog(@"SNS support disabled.");
+    [[self logger] logWithFormat:@"SNS support disabled."];
   
   NSDateClass = [NSDate class];
   WOTemplateClass = [WOTemplate class];
 
-  perflog               = [ud boolForKey:@"WOProfileApplication"];
   rapidTurnAroundPath   = [[ud stringForKey:@"WOProjectDirectory"] copy];
 
+  lm         = [NGLoggerManager defaultLoggerManager];
+  perfLogger = [lm loggerForDefaultKey:@"WOProfileApplication"];
+
   [pool release];
 }
 
@@ -168,14 +181,28 @@ static NSString *rapidTurnAroundPath = nil;
     result = [result stringByAppendingPathComponent:wrapperName];
     if (![fm fileExistsAtPath:result]) {
       /* lookup in process-path */
-      NSString *ppath;
+      NSProcessInfo *pi;
+      NSDictionary  *env;
+      NSString      *ppath;
+      BOOL isFlattened;
       
-      ppath = [[[NSProcessInfo processInfo] arguments] objectAtIndex:0];
+      pi  = [NSProcessInfo processInfo];
+      env = [pi environment];
+      if ([env objectForKey:@"GNUSTEP_SYSTEM_ROOT"] != nil) {
+       isFlattened = [[[env objectForKey:@"GNUSTEP_FLATTENED"]
+                             lowercaseString] isEqualToString:@"yes"];
+      }
+      else /* default to flattened if no GNUstep runtime is set */
+       isFlattened = YES;
+      
+      ppath = [[pi arguments] objectAtIndex:0];
       ppath = [ppath stringByDeletingLastPathComponent]; // del exe-name
-      ppath = [ppath stringByDeletingLastPathComponent]; // lib-combo
-      ppath = [ppath stringByDeletingLastPathComponent]; // os
-      ppath = [ppath stringByDeletingLastPathComponent]; // cpu
-
+      
+      if (!isFlattened) {
+       ppath = [ppath stringByDeletingLastPathComponent]; // lib-combo
+       ppath = [ppath stringByDeletingLastPathComponent]; // os
+       ppath = [ppath stringByDeletingLastPathComponent]; // cpu
+      }
       if ([ppath hasSuffix:suffix])
         result = ppath;
     }
@@ -208,7 +235,9 @@ static NSString *rapidTurnAroundPath = nil;
   e    = [keys objectEnumerator];
   while((key = [e nextObject]) != nil) {
     if ([key hasPrefix:@"WO"] || [key isEqualToString:@"NSProjectSearchPath"])
-      NSLog(@"%@ = %@", key, [[ud objectForKey:key] description]);
+      [self logWithFormat:@"[default]: %@ = %@",
+        key,
+        [[ud objectForKey:key] description]];
   }
 }
 
@@ -242,12 +271,13 @@ static NSString *rapidTurnAroundPath = nil;
     self->requestHandlerRegistry =
       NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 8);
     
-    rk = [WOApplication componentRequestHandlerKey];
-#if 1
-    rh = [[NSClassFromString(@"OWViewRequestHandler") alloc] init];
-#else
-    rh = [[NSClassFromString(@"WOComponentRequestHandler") alloc] init];
-#endif
+    if ((rk = [WOApplication componentRequestHandlerKey]) == nil) {
+      [self logWithFormat:
+             @"WARNING: no component request handler key is specified, "
+             @"this probably means that share/ngobjweb/Defaults.plist "
+             @"could not get loaded (permissions?)"];
+    }
+    rh = [[NSClassFromString(defaultCompRqHandlerClassName) alloc] init];
     if ([rk length] > 0 && (rh != nil))
       [self registerRequestHandler:rh forKey:rk];
     [rh release]; rh = nil;
@@ -339,13 +369,12 @@ static NSString *rapidTurnAroundPath = nil;
 }
 - (NSString *)path {
   static BOOL missingPath = NO;
-  if (missingPath) return nil;
+  if (missingPath)
+    return nil;
+  
   if (self->path == nil) {
     if ((self->path = [[self _lookupAppPath] copy]) == nil) {
-      if (debugOn) {
-       [self debugWithFormat:
-               @"WARNING: could not find wrapper of application !"];
-      }
+      [self debugWithFormat:@"could not find wrapper of application !"];
       missingPath = YES;
       return nil;
     }
@@ -388,12 +417,12 @@ static NSString *rapidTurnAroundPath = nil;
   NSDictionary *td;
   
   if ((t = [NSThread currentThread]) == nil) {
-    [self logWithFormat:@"ERROR: missing current thread !!!"];
+    [self errorWithFormat:@"missing current thread !!!"];
     return nil;
   }
   if ((td = [t threadDictionary]) == nil) {
-    [self logWithFormat:
-            @"ERROR: missing current thread's dictionary (thread=%@) !!!",
+    [self errorWithFormat:
+            @"missing current thread's dictionary (thread=%@) !!!",
             t];
     return nil;
   }
@@ -492,18 +521,18 @@ static NSString *rapidTurnAroundPath = nil;
   if (_request == nil) return nil;
   
   /* first look into form values */
-  if ((sessionId = [_request formValueForKey:WORequestValueSessionID])) {
+  if ((sessionId = [_request formValueForKey:WORequestValueSessionID])!=nil) {
     if ([sessionId length] > 0)
       return sessionId;
   }
   
   /* now look into the cookies */
-  if ((sessionId = [_request cookieValueForKey:[self name]])) {
+  if ((sessionId = [_request cookieValueForKey:[self name]]) != nil) {
     if ([sessionId respondsToSelector:@selector(objectEnumerator)]) {
       NSEnumerator *e;
       
       e = [(id)sessionId objectEnumerator];
-      while ((sessionId = [e nextObject])) {
+      while ((sessionId = [e nextObject]) != nil) {
         if ([sessionId length] > 0 && ![sessionId isEqual:@"nil"])
           return sessionId;
       }
@@ -534,7 +563,7 @@ static NSString *rapidTurnAroundPath = nil;
 - (WOSession *)createSessionForRequest:(WORequest *)_request {
   if ([self respondsToSelector:@selector(createSession)]) {
     /* call deprecated method */
-    NSLog(@"WARNING: calling deprecated -createSession ..");
+    [self warnWithFormat:@"calling deprecated -createSession .."];
     return [self createSession];
   }
   else {
@@ -556,7 +585,7 @@ static NSString *rapidTurnAroundPath = nil;
 
   if ([self respondsToSelector:@selector(restoreSession)]) {
     /* call deprecated method */
-    NSLog(@"WARNING: calling deprecated -restoreSession ..");
+    [self warnWithFormat:@"calling deprecated -restoreSession .."];
     return [self restoreSession];
   }
   
@@ -564,7 +593,7 @@ static NSString *rapidTurnAroundPath = nil;
     WOSessionStore *store;
     
     if ((store = [self sessionStore]) == nil) {
-      [self logWithFormat:@"missing session store ..."];
+      [self errorWithFormat:@"missing session store ..."];
     }
     else {
       session = [store restoreSessionWithID:_sid request:[_ctx request]];
@@ -593,7 +622,7 @@ static NSString *rapidTurnAroundPath = nil;
       if ([sid respondsToSelector:@selector(objectEnumerator)]) {
         NSEnumerator *e;
         
-        [self logWithFormat:@"got multiple session IDs !"];
+        [self errorWithFormat:@"got multiple session IDs !"];
         
         e = [sid objectEnumerator];
         while ((_sid = [e nextObject])) {
@@ -603,7 +632,7 @@ static NSString *rapidTurnAroundPath = nil;
           if ((session = [self restoreSessionWithID:_sid inContext:_ctx]))
             return session;
           
-          //NSLog(@"WARNING: did not find session for sid %@", _sid);
+          //[self warnWithFormat:@"did not find session for sid %@", _sid);
         }
       }
     }
@@ -613,12 +642,12 @@ static NSString *rapidTurnAroundPath = nil;
 - (void)saveSessionForContext:(WOContext *)_ctx {
   NSTimeInterval startSave = 0.0;
 
-  if (perflog)
+  if (perfLogger)
     startSave = [[NSDateClass date] timeIntervalSince1970];
   
   if ([self respondsToSelector:@selector(saveSession:)]) {
     /* call deprecated method */
-    NSLog(@"WARNING: calling deprecated -saveSession: ..");
+    [self warnWithFormat:@"calling deprecated -saveSession: .."];
     [self saveSession:[_ctx session]];
     return;
   }
@@ -629,17 +658,17 @@ static NSString *rapidTurnAroundPath = nil;
     
     sn = [_ctx session];
 
-    if (perflog)
+    if (perfLogger)
       startSnSleep = [[NSDateClass date] timeIntervalSince1970];
     
     /* put session to sleep */
     [sn _sleepWithContext:_ctx];
     
-    if (perflog) {
+    if (perfLogger) {
       NSTimeInterval rt;
       rt = [[NSDateClass date] timeIntervalSince1970] - startSnSleep;
-      NSLog(@"  [woapp]: session -sleep took %4.3fs.",
-            rt < 0.0 ? -1.0 : rt);
+      [perfLogger logWithFormat:@"[woapp]: session -sleep took %4.3fs.",
+                                    rt < 0.0 ? -1.0 : rt];
     }
     
     if ([sn isTerminating]) {
@@ -649,25 +678,25 @@ static NSString *rapidTurnAroundPath = nil;
                              object:sn];
     }
     
-    if (perflog)
+    if (perfLogger)
       startStore = [[NSDateClass date] timeIntervalSince1970];
     
     [[self sessionStore] saveSessionForContext:_ctx];
     
-    if (perflog) {
+    if (perfLogger) {
       NSTimeInterval rt;
       rt = [[NSDateClass date] timeIntervalSince1970] - startStore;
-      NSLog(@"  [woapp]: storing sn in store took %4.3fs.",
-            rt < 0.0 ? -1.0 : rt);
+      [perfLogger logWithFormat:@"[woapp]: storing sn in store took %4.3fs.",
+                                    rt < 0.0 ? -1.0 : rt];
     }
   }
   END_SYNCHRONIZED;
 
-  if (perflog) {
+  if (perfLogger) {
     NSTimeInterval rt;
     rt = [[NSDateClass date] timeIntervalSince1970] - startSave;
-    NSLog(@"[woapp]: saveSessionForContext took %4.3fs.",
-          rt < 0.0 ? -1.0 : rt);
+    [perfLogger logWithFormat:@"[woapp]: saveSessionForContext took %4.3fs.",
+                                  rt < 0.0 ? -1.0 : rt];
   }
 }
 
@@ -735,11 +764,11 @@ static NSString *rapidTurnAroundPath = nil;
 #endif
   
   if ([self respondsToSelector:@selector(handleSessionCreationError)]) {
-    NSLog(@"WARNING: called deprecated -handleSessionCreationError method");
+    [self warnWithFormat:@"called deprecated -handleSessionCreationError method"];
     return [self handleSessionCreationError];
   }
   
-  [self logWithFormat:@"could not create session for context %@", _ctx];
+  [self errorWithFormat:@"could not create session for context %@", _ctx];
   
   [response setStatus:200];
   [response appendContentString:@"<h4>Session Creation Error</h4>\n<pre>"];
@@ -765,12 +794,12 @@ static NSString *rapidTurnAroundPath = nil;
 
 - (WOResponse *)handleSessionRestorationErrorInContext:(WOContext *)_ctx {
   if ([self respondsToSelector:@selector(handleSessionRestorationError)]) {
-    NSLog(@"WARNING: calling deprecated -handleSessionRestorationError "
-         @"method");
+    [self warnWithFormat:@"calling deprecated "
+                            @"-handleSessionRestorationError method"];
     return [self handleSessionRestorationError];
   }
   
-  [self logWithFormat:@"could not restore session for context %@", _ctx];
+  [self errorWithFormat:@"could not restore session for context %@", _ctx];
   return nil;
 }
 
@@ -789,23 +818,38 @@ static NSString *rapidTurnAroundPath = nil;
 
 /* resources */
 
+- (void)_setupDefaultResourceManager {
+  NSUserDefaults *ud;
+  Class    rmClass;
+  NSString *p;
+  
+  ud = [NSUserDefaults standardUserDefaults];
+  p  = [ud stringForKey:@"WODefaultResourceManager"];
+  rmClass = ([p length] == 0)
+    ? [WOResourceManager class]
+    : NSClassFromString(p);
+  
+  if (rmClass == Nil) {
+    [self errorWithFormat:
+            @"failed to locate class of resource manager: '%@'", p];
+    return;
+  }
+  
+  if ([rmClass instancesRespondToSelector:@selector(initWithPath:)])
+    self->resourceManager = [[rmClass alloc] init];
+  else {
+    self->resourceManager = 
+      [(WOResourceManager *)[rmClass alloc] initWithPath:[self path]];
+  }
+}
+
 - (void)setResourceManager:(WOResourceManager *)_manager {
   ASSIGN(self->resourceManager, _manager);
 }
 - (WOResourceManager *)resourceManager {
-  if (self->resourceManager == nil) {
-    NSString *p;
-
-#if 0 && DEBUG
-    if ([(p = [self path]) length] > 0)
-      [self logWithFormat:@"setup WOResourceManager at path '%@' ...", p];
-#else
-    p = [self path];
-#endif
-    
-    self->resourceManager = 
-      [(WOResourceManager *)[WOResourceManager alloc] initWithPath:p];
-  }
+  if (self->resourceManager == nil)
+    [self _setupDefaultResourceManager];
+  
   return self->resourceManager;
 }
 
@@ -921,11 +965,11 @@ static NSString *rapidTurnAroundPath = nil;
   Class     dynamicElementClass = NSClassFromString(_name);
 
   if (dynamicElementClass == Nil) {
-    NSLog(@"WARNING: did not find dynamic element class %@ !", _name);
+    [self warnWithFormat:@"did not find dynamic element class %@ !", _name];
     return nil;
   }
   if (![dynamicElementClass isDynamicElement]) {
-    NSLog(@"WARNING: class %@ is not a dynamic element class !", _name);
+    [self warnWithFormat:@"class %@ is not a dynamic element class !", _name];
     return nil;
   }
   
@@ -1002,17 +1046,15 @@ static NSString *rapidTurnAroundPath = nil;
   start = [self memoryStatistics];
 #endif
   
-  pool = [[NSAutoreleasePool alloc] init];
+  pool      = [[NSAutoreleasePool alloc] init];
   
-  languages = [_ctx hasSession]
-    ? [(WOSession *)[_ctx session] languages]
-    : [[_ctx request] browserLanguages];
+  languages = [_ctx resourceLookupLanguages];
 
   if ((rm = [[_ctx component] resourceManager]) == nil)
     rm = [self resourceManager];
   
-  page = [rm pageWithName:(_name ? _name : @"Main")
-             languages:languages];
+  page      = [rm pageWithName:(_name != nil ? _name : @"Main")
+                  languages:languages];
   [page ensureAwakeInContext:_ctx];
   
   page = [page retain];
@@ -1028,7 +1070,8 @@ static NSString *rapidTurnAroundPath = nil;
              [[start objectForKey:@"VmSize"] intValue];
     lib    = [[stop objectForKey:@"VmLib"] intValue] -
              [[start objectForKey:@"VmLib"] intValue];
-    NSLog(@"loaded component %@; rss=%i vm=%i lib=%i.", _name, rss,vmsize,lib);
+    [self debugWithFormat:@"loaded component %@; rss=%i vm=%i lib=%i.",
+            _name, rss,vmsize,lib];
   }
 #endif
   
@@ -1043,7 +1086,7 @@ static NSString *rapidTurnAroundPath = nil;
   if ((rm = [self resourceManager]) == nil)
     return nil;
   
-  return [rm pageWithName:_name ? _name : @"Main"
+  return [rm pageWithName:(_name != nil) ? _name : @"Main"
              languages:[_req browserLanguages]];
 }
 
@@ -1057,7 +1100,7 @@ static NSString *rapidTurnAroundPath = nil;
 }
 
 - (WOResponse *)handlePageRestorationErrorInContext:(WOContext *)_ctx {
-  [self logWithFormat:
+  [self errorWithFormat:
           @"could not restore page for context-id %@\n  in context %@",
           [_ctx currentElementID], _ctx];
   
@@ -1078,7 +1121,7 @@ static NSString *rapidTurnAroundPath = nil;
   WOResponse *r  = nil;
   
   if ([self respondsToSelector:@selector(handleException:)]) {
-    NSLog(@"WARNING: calling deprecated -handleException method !");
+    [self warnWithFormat:@"calling deprecated -handleException method !"];
     return [self handleException:_exc];
   }
   
@@ -1091,19 +1134,21 @@ static NSString *rapidTurnAroundPath = nil;
        ? 1 : 0;
     }
     if (doCore) {
-      [self logWithFormat:@"%@: caught (ctx=%@):\n  %@.",
-           self, _ctx, _exc];
+      [self fatalWithFormat:@"%@: caught (ctx=%@):\n  %@.",
+              self, _ctx, _exc];
       abort();
     }
   }
 #endif
   
   if (_ctx == nil) {
-    [self logWithFormat:@"%@: caught (without context):\n  %@.", self, _exc];
+    [self fatalWithFormat:@"%@: caught (without context):\n  %@.",
+            self, _exc];
     [self terminate];
   }
   else if (rq == nil) {
-    [self logWithFormat:@"%@: caught (without request):\n  %@.", self, _exc];
+    [self fatalWithFormat:@"%@: caught (without request):\n  %@.",
+            self, _exc];
     [self terminate];
   }
   else {
@@ -1121,7 +1166,7 @@ static NSString *rapidTurnAroundPath = nil;
     NSString *str = nil;
     NSString *bt  = nil;
     
-    [self logWithFormat:@"%@: caught:\n  %@\nin context:\n  %@.",
+    [self errorWithFormat:@"%@: caught:\n  %@\nin context:\n  %@.",
             self, _exc, _ctx];
 
 #if LIB_FOUNDATION_LIBRARY
@@ -1130,7 +1175,7 @@ static NSString *rapidTurnAroundPath = nil;
 #endif
     
     if ((r = [WOResponse responseWithRequest:rq]) == nil)
-      [self logWithFormat:@"could not create response !"];
+      [self errorWithFormat:@"could not create response !"];
     
     [r setHeader:@"text/html" forKey:@"content-type"];
     [r setHeader:@"no-cache" forKey:@"cache-control"];
@@ -1205,7 +1250,7 @@ static NSString *rapidTurnAroundPath = nil;
 
 #if !LIB_FOUNDATION_LIBRARY
 - (id)valueForUndefinedKey:(NSString *)_key {
-  [self logWithFormat:@"WARNING: tried to access undefined KVC key: '%@'",
+  [self warnWithFormat:@"tried to access undefined KVC key: '%@'",
          _key];
   return nil;
 }