]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WODirectActionRequestHandler.m
bumped Xcode projects to version 4.7. Added a new Xcode project for the STXSaxDriver.
[sope] / sope-appserver / NGObjWeb / WODirectActionRequestHandler.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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  usePool = NO;
40 static BOOL  perflog = NO;
41 static BOOL  debugOn = NO;
42 static Class NSDateClass = Nil;
43
44 @implementation WODirectActionRequestHandler
45
46 + (int)version {
47   return [super version] + 0 /* 2 */;
48 }
49 + (void)initialize {
50   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
51   
52   NSAssert2([super version] == 2,
53             @"invalid superclass (%@) version %i !",
54             NSStringFromClass([self superclass]), [super version]);
55
56   NSDateClass = [NSDate class];
57   perflog = [ud boolForKey:@"WOProfileDirectActionRequestHandler"];
58 }
59
60 - (NSString *)loggingPrefix {
61   return @"[da-handler]";
62 }
63
64 /*
65   The request handler part of a direct action URI looks like this:
66   
67     [actionClass/]actionName[?key=value&key=value&...]
68 */
69
70 - (BOOL)isComponentClass:(Class)_clazz {
71   if (_clazz == Nil) 
72     return NO;
73   while ((_clazz = _clazz->super_class) != Nil) {
74     if (_clazz == [WOComponent    class]) return YES;
75     if (_clazz == [WODirectAction class]) return NO;
76     if (_clazz == [NSObject       class]) return NO;
77   }
78   return NO;
79 }
80
81 - (id)instantiateObjectForActionClass:(Class)actionClass
82   inContext:(WOContext *)context
83   application:(WOApplication *)app
84 {
85   WOComponent *component;
86   
87   if (actionClass == Nil)
88     return nil;
89   
90   if (![self isComponentClass:actionClass]) {
91     /* create direct action object */
92     id actionObject;
93     
94     if (![actionClass instancesRespondToSelector:
95                         @selector(initWithContext:)]) {
96       [self logWithFormat:@"tried to use class '%@' as a direct-action class",
97               NSStringFromClass(actionClass)];
98       return nil;
99     }
100     
101     actionObject =
102       [(WODirectAction *)[actionClass alloc] initWithContext:context];
103     actionObject = [actionObject autorelease];
104     return actionObject;
105   }
106   
107   /* special initialization for WOComponents used as direct actions */
108     
109   component = [app pageWithName:NSStringFromClass(actionClass)
110                    inContext:context];
111   [context setPage:(id)component];
112   
113   if ([component shouldTakeValuesFromRequest:[context request]
114                  inContext:context])
115     [app takeValuesFromRequest:[context request] inContext:context];
116   
117   return component;
118 }
119
120 - (WOResponse *)handleRequest:(WORequest *)_request
121   inContext:(WOContext *)context
122   session:(WOSession *)session
123   application:(WOApplication *)app
124 {
125   NSAutoreleasePool   *pool2;
126   NSString            *actionClassName;
127   NSString            *actionName;
128   WOResponse          *response;
129   NSArray             *handlerPath;
130   Class               actionClass = Nil;
131   WODirectAction      *actionObject = nil;
132   id<WOActionResults> result = nil;
133
134   pool2 = usePool ? [[NSAutoreleasePool alloc] init] : nil;
135   
136   *(&result) = nil;
137   *(&response)        = nil;
138   *(&actionClassName) = nil;
139   *(&actionName)      = nil;
140   *(&handlerPath)     = nil;
141   
142   /* process path */
143   
144   handlerPath = [_request requestHandlerPathArray];
145
146   if (debugOn) {
147     [self debugWithFormat:@"path=%@ array=%@",
148           [_request requestHandlerPath], handlerPath];
149   }
150   
151   // TODO: fix OGo bug #1028
152   switch ([handlerPath count]) {
153     case 0:
154       actionClassName = @"DirectAction";
155       actionName      = @"default";
156       break;
157     case 1:
158       actionClassName = @"DirectAction";
159       actionName      = [handlerPath objectAtIndex:0];
160       break;
161     case 2:
162       actionClassName = [handlerPath objectAtIndex:0];
163       actionName      = [handlerPath objectAtIndex:1];
164       break;
165
166     default:
167       actionClassName = [handlerPath objectAtIndex:0];
168       actionName      = [handlerPath objectAtIndex:1];
169       // TODO: set path info in ctx?
170       if (debugOn) {
171         [self logWithFormat:@"invalid direction action URL: %@",
172                 [_request requestHandlerPath]];
173       }
174       break;
175   }
176
177   if ([actionName length] == 0)
178     actionName = @"default";
179
180   if ((*(&actionClass) = NSClassFromString(actionClassName)) == Nil) {
181     [self errorWithFormat:@"did not find direct action class %@",
182             actionClassName];
183     actionClass = [WODirectAction class];
184   }
185   
186   if (debugOn) {
187     [self debugWithFormat:
188             @"[direct action request handler] class=%@ action=%@ ..",
189             actionClassName, actionName];
190   }
191   
192   /* process request */
193   
194   actionObject = [self instantiateObjectForActionClass:actionClass
195                        inContext:context
196                        application:app];
197   
198   if (actionObject == nil) {
199     [self errorWithFormat:
200             @"could not create direct action object of class %@",
201             actionClassName];
202     actionObject = nil;
203   }
204   else {
205     static Class WOComponentClass = Nil;
206     
207     if (WOComponentClass == Nil)
208       WOComponentClass = [WOComponent class];
209     
210     result = [(id)[actionObject performActionNamed:actionName] retain];
211     
212     if (result == nil) result = [[context page] retain];
213     
214     if ([(id)result isKindOfClass:WOComponentClass]) {
215       [(id)result _awakeWithContext:context];
216       [context setPage:(WOComponent *)result];
217       
218       response = [self generateResponseForComponent:(WOComponent *)result
219                        inContext:context
220                        application:app];
221       
222       if ([context hasSession]) {
223         if ([context savePageRequired])
224           [[context session] savePage:(WOComponent *)result];
225       }
226       
227       response = [response retain];
228     }
229     else {
230       /* generate response */
231       response = [[result generateResponse] retain];
232     }
233               
234     [context sleepComponents];
235     
236     [(id)result release]; result = nil;
237     
238     /* check whether a session was created */
239     if ((session == nil) && [context hasSession]) {
240       session = [[[context session] retain] autorelease];
241       [session lock];
242     }
243     
244     if (usePool) {
245       session = [session retain];
246       [pool2 release]; pool2 = nil;
247       session = [session autorelease];
248     }
249     response = [response autorelease];
250   }
251   
252   return response;
253 }
254
255 @end /* WODirectActionRequestHandler */