]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WODirectActionRequestHandler.m
bumbed versions to 4.5
[sope] / sope-appserver / NGObjWeb / WODirectActionRequestHandler.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include "WODirectActionRequestHandler.h"
23 #include "WORequestHandler+private.h"
24 #include "WOContext+private.h"
25 #include <NGObjWeb/WOApplication.h>
26 #include <NGObjWeb/WOComponent.h>
27 #include <NGObjWeb/WODirectAction.h>
28 #include <NGObjWeb/WORequest.h>
29 #include <NGObjWeb/WOResponse.h>
30 #include <NGObjWeb/WOSession.h>
31 #include <NGObjWeb/WOSessionStore.h>
32 #include <NGObjWeb/WOStatisticsStore.h>
33 #include "common.h"
34
35 #if APPLE_RUNTIME || NeXT_RUNTIME
36 #  include <objc/objc-class.h>
37 #endif
38
39 static BOOL  perflog = NO;
40 static Class NSDateClass = Nil;
41
42 //#define USE_POOLS 1
43
44 @implementation WODirectActionRequestHandler
45
46 + (int)version {
47   return [super version] + 0 /* 2 */;
48 }
49 + (void)initialize {
50   NSAssert2([super version] == 2,
51             @"invalid superclass (%@) version %i !",
52             NSStringFromClass([self superclass]), [super version]);
53
54   NSDateClass = [NSDate class];
55   perflog = [[NSUserDefaults standardUserDefaults]
56                              boolForKey:@"WOProfileDirectActionRequestHandler"];
57 }
58
59 - (NSString *)loggingPrefix {
60   return @"[da-handler]";
61 }
62
63 /*
64   The request handler part of a direct action URI looks like this:
65
66     [actionClass/]actionName[?key=value&key=value&...]
67 */
68
69 - (BOOL)isComponentClass:(Class)_clazz {
70   if (_clazz == Nil) 
71     return NO;
72   while ((_clazz = _clazz->super_class)) {
73     if (_clazz == [WOComponent    class]) return YES;
74     if (_clazz == [WODirectAction class]) return NO;
75     if (_clazz == [NSObject       class]) return NO;
76   }
77   return NO;
78 }
79
80 - (id)instantiateObjectForActionClass:(Class)actionClass
81   inContext:(WOContext *)context
82   application:(WOApplication *)app
83 {
84   WOComponent *component;
85   
86   if (actionClass == Nil)
87     return nil;
88   if (![self isComponentClass:actionClass]) {
89     /* create direct action object */
90     id actionObject;
91     
92     if (![actionClass instancesRespondToSelector:
93                         @selector(initWithContext:)]) {
94       [self logWithFormat:@"tried to use class '%@' as a direct-action class",
95               NSStringFromClass(actionClass)];
96       return nil;
97     }
98     
99     actionObject =
100       [(WODirectAction *)[actionClass alloc] initWithContext:context];
101     actionObject = [actionObject autorelease];
102     return actionObject;
103   }
104   
105   /* special initialization for WOComponents used as direct actions */
106     
107   component = [app pageWithName:NSStringFromClass(actionClass)
108                    inContext:context];
109   [context setPage:(id)component];
110   
111   /* TODO: why was that commented out? */
112   if ([component shouldTakeValuesFromRequest:[context request]
113                  inContext:context])
114     [app takeValuesFromRequest:[context request] inContext:context];
115   
116   return component;
117 }
118
119 - (WOResponse *)handleRequest:(WORequest *)_request
120   inContext:(WOContext *)context
121   session:(WOSession *)session
122   application:(WOApplication *)app
123 {
124 #if USE_POOLS
125   NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
126 #endif
127   NSString      *actionClassName;
128   NSString      *actionName;
129   WOResponse    *response;
130   NSArray       *handlerPath;
131   Class         actionClass = Nil;
132   WODirectAction      *actionObject = nil;
133   id<WOActionResults> result = nil;
134   
135   *(&result) = nil;
136   *(&response)        = nil;
137   *(&actionClassName) = nil;
138   *(&actionName)      = nil;
139   *(&handlerPath)     = nil;
140   
141   /* process path */
142   
143   handlerPath = [_request requestHandlerPathArray];
144
145 #if DEBUG_DIRECT_ACTION
146   [self debugWithFormat:@"path=%@ array=%@",
147           [_request requestHandlerPath], handlerPath];
148 #endif
149
150   switch ([handlerPath count]) {
151     case 0:
152       actionClassName = @"DirectAction";
153       actionName      = @"default";
154       break;
155     case 1:
156       actionClassName = @"DirectAction";
157       actionName      = [handlerPath objectAtIndex:0];
158       break;
159     case 2:
160       actionClassName = [handlerPath objectAtIndex:0];
161       actionName      = [handlerPath objectAtIndex:1];
162       break;
163
164     default:
165       actionClassName = [handlerPath objectAtIndex:0];
166       actionName      = [handlerPath objectAtIndex:1];
167 #if 0
168       NSLog(@"invalid direction action URL: %@",
169               [_request requestHandlerPath]);
170 #endif
171       break;
172   }
173
174   if ([actionName length] == 0)
175     actionName = @"default";
176
177   if ((*(&actionClass) = NSClassFromString(actionClassName)) == Nil) {
178     [self logWithFormat:@"ERROR: did not find direct action class %@",
179             actionClassName];
180     actionClass = [WODirectAction class];
181   }
182   
183 #if DEBUG_DIRECT_ACTION
184   [self debugWithFormat:
185           @"[direct action request handler] class=%@ action=%@ ..",
186           actionClassName, actionName];
187 #endif
188   
189   /* process request */
190   
191   actionObject = [self instantiateObjectForActionClass:actionClass
192                        inContext:context
193                        application:app];
194   
195   if (actionObject == nil) {
196     [self logWithFormat:
197             @"ERROR: could not create direct action object of class %@",
198             actionClassName];
199     actionObject = nil;
200   }
201   else {
202     static Class WOComponentClass = Nil;
203     
204     if (WOComponentClass == Nil)
205       WOComponentClass = [WOComponent class];
206     
207     result = [(id)[actionObject performActionNamed:actionName] retain];
208     
209     if (result == nil) result = [[context page] retain];
210     
211     if ([(id)result isKindOfClass:WOComponentClass]) {
212       [(id)result _awakeWithContext:context];
213       [context setPage:(WOComponent *)result];
214       
215       response = [self generateResponseForComponent:(WOComponent *)result
216                        inContext:context
217                        application:app];
218       
219       if ([context hasSession]) {
220         if ([context savePageRequired])
221           [[context session] savePage:(WOComponent *)result];
222       }
223       
224       response = [response retain];
225     }
226     else {
227       /* generate response */
228       response = [[result generateResponse] retain];
229     }
230               
231     [context sleepComponents];
232     
233     [(id)result release]; result = nil;
234     
235     /* check whether a session was created */
236     if ((session == nil) && [context hasSession]) {
237       session = [[[context session] retain] autorelease];
238       [session lock];
239     }
240     
241 #if USE_POOLS
242     session = [session retain];
243     [pool2 release]; pool2 = nil;
244     session = [session autorelease];
245 #endif
246     response = [response autorelease];
247   }
248   
249   return response;
250 }
251
252 @end /* WODirectActionRequestHandler */