]> err.no Git - sope/blob - sope-appserver/NGObjWeb/OWViewRequestHandler.m
minor improvement to WOHttpAdaptor, bumped framework revisions
[sope] / sope-appserver / NGObjWeb / OWViewRequestHandler.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 <NGObjWeb/OWViewRequestHandler.h>
23 #include "WORequestHandler+private.h"
24 #include "WOContext+private.h"
25 #include "WOComponent+private.h"
26 #include "WOApplication+private.h"
27 #include <NGObjWeb/WOComponent.h>
28 #include <NGObjWeb/WORequest.h>
29 #include <NGObjWeb/WOResponse.h>
30 #include <NGObjWeb/WOSessionStore.h>
31 #include <NGObjWeb/WOSession.h>
32 #include "common.h"
33
34 NSString *OWAppDidRefuseSessionName = @"OWAppDidRefuseSession";
35 static BOOL perflog = NO;
36
37 //#define USE_POOLS 1
38
39 #if USE_POOLS
40 #  warning extensive pools are enabled ...
41 #endif
42
43 @implementation OWViewRequestHandler
44
45 + (int)version {
46   return [super version] + 0 /* 2 */;
47 }
48 + (void)initialize {
49   NSAssert2([super version] == 2,
50             @"invalid superclass (%@) version %i !",
51             NSStringFromClass([self superclass]), [super version]);
52   
53   perflog = [[NSUserDefaults standardUserDefaults]
54                              boolForKey:@"OWViewRequestHandlerProfile"];
55 }
56
57 - (NSString *)loggingPrefix {
58   return @"[ow-handler]";
59 }
60
61 - (id)init {
62   //NSLog(@"DEPRECATED: OWViewRequestHandler is being allocated ...");
63   return [super init];
64 }
65
66 - (WOResponse *)runTransactionWithContext:(WOContext *)_ctx {
67   WOApplication *app      = nil;
68   WOSession     *sn       = nil;
69   WOResponse    *response = nil;
70   id<NSObject,WOActionResults> result;
71   
72   app = [_ctx application];
73   sn  = [_ctx session];
74   NSAssert(_ctx != nil, @"no context available");
75   NSAssert(sn   != nil, @"no session available");
76   NSAssert(app  != nil, @"no application available in context");
77
78   /* take request values */
79
80   [app takeValuesFromRequest:[_ctx request] inContext:_ctx];
81
82   /* invoke action */
83     
84   result = [app invokeActionForRequest:[_ctx request] inContext:_ctx];
85     
86   /* check whether there is an page set at all ! */
87
88   if ([_ctx page] == nil) {
89     /* no page is set yet, load Main .. */
90     WOComponent *mainPage;
91
92     if ((mainPage = [app pageWithName:nil inContext:_ctx])) {
93       [_ctx setPage:mainPage];
94       [mainPage _awakeWithContext:_ctx];
95     }
96   }
97   
98   /* make response */
99   
100   if ((result == nil) || [result isKindOfClass:[WOComponent class]]) {
101     /* determine the response page */
102       
103     if (result == nil) {
104       /* make the request page the response page */
105       if ((result = [_ctx page]) == nil) {
106         /* no request page (probably the first request) */
107         result = [app pageWithName:nil inContext:_ctx];
108         [(id)result _awakeWithContext:_ctx];
109         [_ctx setPage:(WOComponent *)result];
110       }
111     }
112
113     response = [self generateResponseForComponent:(WOComponent *)result
114                      inContext:_ctx
115                      application:app];
116       
117     /* save page in session */
118       
119     if ([_ctx savePageRequired]) {
120       [sn savePage:[_ctx page]];
121 #if DEBUG && 0
122       [self logWithFormat:@"saved page ..."];
123 #endif
124     }
125 #if DEBUG && 0
126     else {
127       [self logWithFormat:@"no save page required ..."];
128     }
129 #endif
130   }
131   else {
132     /* generate response from WOActionResult */
133     if ([result respondsToSelector:@selector(generateResponse)]) {
134       [app debugWithFormat:@"generating response for result .."];
135       response = [result generateResponse];
136     }
137     else {
138       [app logWithFormat:
139              @"action result (class=%@) doesn't conform to "
140              @"WOActionResult protocol !",
141              NSStringFromClass([result class])];
142         
143       response = [[WOResponse alloc] init];
144       [response setStatus:200];
145       [response appendContentString:@"<pre>"];
146       [response appendContentHTMLString:
147                   @"ERROR:\n"
148                   @"Result of action doesn't conform to WOActionResult "
149                   @"protocol:\n---\n"
150                   @"Content-Class: "];
151       [response appendContentHTMLString:
152                    [NSStringFromClass([result class]) description]];
153       [response appendContentHTMLString:@"\nContent:\n"];
154       [response appendContentHTMLString:[result description]];
155       [response appendContentString:@"</pre>\n"];
156       AUTORELEASE(response);
157     }
158   }
159     
160   [_ctx sleepComponents];
161     
162   return response;
163 }
164
165 - (NSString *)sessionIDFromRequest:(WORequest *)_request
166   application:(WOApplication *)_app
167 {
168   NSString *sessionId = nil;
169   id tmp;
170   
171   if ((tmp = [_request formValueForKey:WORequestValueSenderID]) == nil) {
172     if ([[_request requestHandlerPath] length] > 0) {
173       /* traditional style URLs */
174       NSArray *spath;
175       
176       spath = [_request requestHandlerPathArray];
177       if ([spath count] > 0)
178         sessionId = [spath objectAtIndex:0];
179     }
180   }
181   
182   if ([sessionId length] == 0)
183     sessionId = [_app sessionIDFromRequest:_request];
184   
185   return sessionId;
186 }
187
188 - (BOOL)autocreateSessionForRequest:(WORequest *)_request {
189   /* autocreate a session if none was restored */
190   return YES;
191 }
192 - (BOOL)requiresSessionForRequest:(WORequest *)_request {
193   /* _ensure_ that a session is available */
194   return YES;
195 }
196
197 - (WOResponse *)handleRequest:(WORequest *)_request
198   inContext:(WOContext *)context
199   session:(WOSession *)session
200   application:(WOApplication *)app
201 {
202   NSString       *requestContextID;
203   WOResponse     *response;
204   WOComponent    *requestComponent;
205   NSString       *cid;
206   NSTimeInterval startRunTx = 0.0;
207   id tmp;
208
209   *(&requestContextID) = nil;
210   *(&response)         = nil;
211   *(&requestComponent) = nil;
212   
213   NSAssert(session, @"no session given !");
214
215   /*
216     parse handler path (URL)
217       
218     The format is:
219       session/context-id.element-id
220       
221     or
222       pageName?_i=context-id.element-id&wosid=session&_c=context-id
223   */
224   
225   if ((tmp = [_request formValueForKey:WORequestValueSenderID])) {
226     /* new query-para style URL */
227     [context setRequestSenderID:tmp];
228     
229     if ((tmp = [_request formValueForKey:WORequestValueContextID]))
230       requestContextID = tmp;
231     else
232       requestContextID = [context currentElementID];
233   }
234   else if ([[_request requestHandlerPath] length] > 0) {
235     /* traditional style URLs */
236     NSArray *spath;
237     
238     spath = [_request requestHandlerPathArray];
239       
240     if ([spath count] > 1) {
241       [context setRequestSenderID:[spath objectAtIndex:1]];
242       requestContextID = [context currentElementID];
243     }
244     // at idx 0 => sessionId
245   }
246   
247   /* determine request component */
248
249   if ([[self sessionIDFromRequest:_request application:app]
250              isEqualToString:[session sessionID]])
251     cid = [context currentElementID];
252   else
253     /* the session is different, was autocreated ... */
254     cid = nil;
255   
256   if ((session != nil) && ([cid length] > 0)) {
257     requestComponent = [session restorePageForContextID:cid];
258     
259     if (requestComponent == nil) {
260       /* could not restore page ... */
261       response = [app handlePageRestorationErrorInContext:context];
262       if (response != nil) {
263         [self logWithFormat:
264                 @"returning because of page restoration error ..."];
265         return response;
266       }
267     }
268   }
269   if (requestComponent) {
270     [context setPage:requestComponent];
271     [requestComponent _awakeWithContext:context];
272   }
273   
274   /* run transaction */
275
276   if (perflog)
277     startRunTx = [[NSDate date] timeIntervalSince1970];
278   
279   response = [self runTransactionWithContext:context];
280   
281   if (perflog) {
282     NSTimeInterval rt;
283     rt = [[NSDate date] timeIntervalSince1970] - startRunTx;
284     [self logWithFormat:@"running tx took %4.3fs.", rt < 0.0 ? -1.0 : rt];
285   }
286   
287   return response;
288 }
289
290 @end /* OWViewRequestHandler */