]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WOComponentRequestHandler.m
overhauled logging for NGExtensions which NGObjWeb uses
[sope] / sope-appserver / NGObjWeb / WOComponentRequestHandler.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 "WOComponentRequestHandler.h"
23 #include "WORequestHandler+private.h"
24 #include "WOContext+private.h"
25 #include <NGObjWeb/WOApplication.h>
26 #include <NGObjWeb/WORequest.h>
27 #include <NGObjWeb/WOResponse.h>
28 #include <NGObjWeb/WOSession.h>
29 #include <NGObjWeb/WOComponent.h>
30 #include "common.h"
31
32 @interface WOApplication(Privates)
33 - (WOSession *)_initializeSessionInContext:(WOContext *)_ctx;
34 - (void)_setCurrentContext:(WOContext *)_ctx;
35 @end
36
37 @implementation WOComponentRequestHandler
38
39 + (int)version {
40   return [super version] + 0 /* 2 */;
41 }
42 + (void)initialize {
43   NSAssert2([super version] == 2,
44             @"invalid superclass (%@) version %i !",
45             NSStringFromClass([self superclass]), [super version]);
46 }
47
48 - (WOResponse *)restoreSessionWithID:(NSString *)_sid
49   inContext:(WOContext *)_ctx
50 {
51   WOApplication *app = [WOApplication application];
52   WOResponse *response = nil;
53   
54   if (_sid == nil) {
55     // invalid session ID (or no session-ID ?!, which is no error ?) */
56     response = [app handleSessionRestorationErrorInContext:_ctx];
57   }
58   else {
59     WOSession *session = nil;
60     
61     if ((session = [app restoreSessionWithID:_sid inContext:_ctx])) {
62       // awake restored session
63       [_ctx setSession:session];
64       [session _awakeWithContext:_ctx];
65       
66       [session awake];
67       response = nil;
68     }
69     else {
70       response = [app handleSessionRestorationErrorInContext:_ctx];
71     }
72   }
73   return response;
74 }
75
76 /*
77   The request handler path of a component URI looks like this:
78
79     sessionID/componentName/contextID/elementID/instance/server
80 */
81
82 - (WOResponse *)handleRequest:(WORequest *)_request {
83   NSString      *sessionID        = nil;
84   WOApplication *application      = nil;
85   WOContext     *context          = nil;
86   WOResponse    *response         = nil;
87   WOSession     *session          = nil;
88   WOComponent   *component        = nil;
89   BOOL          isLocked          = NO;
90   NSString      *handlerPath      = nil;
91
92   if (_request == nil) return nil;
93
94   application = [WOApplication application];
95   handlerPath = [_request requestHandlerPath];
96
97 #if 0
98   NSLog(@"[component request handler] path=%@ ..", handlerPath);
99 #endif
100
101   if (![application allowsConcurrentRequestHandling]) {
102     [application lockRequestHandling];
103     isLocked = YES;
104   }
105   
106   context = [WOContext contextWithRequest:_request];
107   [application _setCurrentContext:context];
108   
109   /*
110     parse handler path (URL)
111
112     The format is:
113
114       session/context.element-id
115   */
116   if ([handlerPath length] > 0) {
117     NSArray *spath = [_request requestHandlerPathArray];
118
119     if ([spath count] > 1)
120       [context setRequestSenderID:[spath objectAtIndex:1]];
121     if ([spath count] > 0)
122       sessionID = [spath objectAtIndex:0];
123   }
124   
125   if ([sessionID length] == 0)
126     sessionID = [application sessionIDFromRequest:_request];
127   
128 #if 0
129   NSLog(@"%s: made context %@ (cid=%@, sn=%@) ..", __PRETTY_FUNCTION__
130         context, [context contextID], sessionID);
131 #endif
132   
133   [application awake];
134   
135   /* restore or create session */
136   if (sessionID) {
137     response = [self restoreSessionWithID:sessionID inContext:context];
138     session = response ? nil : [context session];
139     
140     if (session) {
141       /* awake stored page */
142       component = [session restorePageForContextID:[context currentElementID]];
143       
144       if (component == nil)
145         response = [application handlePageRestorationErrorInContext:context];
146 #if DEBUG
147       else {
148         NSLog(@"%s: restored request component %@", __PRETTY_FUNCTION__,
149               component);
150       }
151 #endif
152     }
153     else if (response == nil) {
154       [[WOApplication application] warnWithFormat:
155                                      @"got no session restoration error, "
156                                      @"but missing session !"];
157     }
158   }
159   else {
160     /* create new session */
161     session = [application _initializeSessionInContext:context];
162     if (session) {
163       /* awake created session */
164       [session awake];
165       component = [application pageWithName:nil inContext:context];
166     }
167     else
168       response = [application handleSessionCreationErrorInContext:context];
169   }
170   
171   if ((session != nil) && (component != nil) && (response == nil)) {
172     WOComponent *newPage = nil;
173
174     [[session retain] autorelease];
175     
176 #if DEBUG
177     NSAssert(application, @"missing application object ..");
178     NSAssert(session,     @"missing session object ..");
179 #endif
180     
181     /* set request page in context */
182     [context setPage:component];
183     
184     /* run take-values phase */
185     [application takeValuesFromRequest:_request inContext:context];
186     
187     /* run invoke-action phase */
188     newPage = [application invokeActionForRequest:_request inContext:context];
189
190     /* process resulting page */
191     if (newPage == nil) {
192       if ((newPage = [context page]) == nil) {
193         newPage = [application pageWithName:nil inContext:context];
194         [context setPage:newPage];
195       }
196     }
197     else if ([newPage isKindOfClass:[WOComponent class]])
198       [context setPage:newPage];
199
200 #if DEBUG
201     [self debugWithFormat:@"%s: new page: %@", __PRETTY_FUNCTION__, newPage];
202 #endif
203     
204     /* generate response */
205 #if 1 /* new code, ensure that _fixupResponse is called */
206     response = [self generateResponseForComponent:[context page]
207                      inContext:context
208                      application:application];
209 #else /* old code */
210     response = [context response];
211     [application appendToResponse:response inContext:context];
212 #endif
213   }
214   else {
215     [self warnWithFormat:@"%s: did not enter request/response transaction ...",
216             __PRETTY_FUNCTION__];
217   }
218
219   /* tear down */
220
221   /* sleep objects */
222   [context sleepComponents];
223   [session sleep];
224   
225   /* save objects */
226   if (session) {
227     if ([context savePageRequired])
228       [session savePage:[context page]];
229     
230     NSLog(@"saving session %@", [session sessionID]);
231     [application saveSessionForContext:context];
232   }
233   
234   [application sleep];
235   
236   /* locking */
237   
238   if (isLocked) {
239     [application unlockRequestHandling];
240     isLocked = NO;
241   }
242   
243   [application _setCurrentContext:nil];
244   return response;
245 }
246
247 @end /* WOComponentRequestHandler */