]> err.no Git - sope/blob - sope-appserver/NGXmlRpc/NGXmlRpcRequestHandler.m
fixed (all?) gcc 4.0 warnings
[sope] / sope-appserver / NGXmlRpc / NGXmlRpcRequestHandler.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 <NGXmlRpc/NGXmlRpcRequestHandler.h>
23 #include <NGXmlRpc/NGXmlRpcAction.h>
24 #include <NGXmlRpc/NGXmlRpc.h>
25 #include <NGXmlRpc/XmlRpcMethodCall+WO.h>
26 #include <NGXmlRpc/XmlRpcMethodResponse+WO.h>
27 #include <NGObjWeb/WOApplication.h>
28 #include <NGObjWeb/WORequest.h>
29 #include <NGObjWeb/WOContext.h>
30 #include <NGObjWeb/WOResponse.h>
31 #include <NGObjWeb/WOStatisticsStore.h>
32 #include "common.h"
33
34 static BOOL  perflog = NO;
35 static Class NSDateClass = Nil;
36
37 //#define USE_POOLS 1
38
39 @interface NSObject(RPC2)
40 - (id<WOActionResults>)RPC2Action;
41 @end
42
43 @implementation NGXmlRpcRequestHandler
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   NSDateClass = [NSDate class];
54   perflog = [[NSUserDefaults standardUserDefaults]
55                              boolForKey:
56                                @"WOProfileXmlRpcActionRequestHandler"];
57 }
58
59 /*
60   The request handler part of a direct action URI looks like this:
61
62     [actionClass/]actionName[?key=value&key=value&...]
63 */
64
65 - (WOResponse *)_runObject:(NGXmlRpcAction *)_object
66   request:(WORequest *)_req 
67 {
68   WOResponse       *result;
69   XmlRpcMethodCall *call;
70   
71   if (_object == nil) return nil;
72   
73   if (![[_req method] isEqualToString:@"POST"]) {
74     /* only POST is allowed ! */
75     return nil;
76   }
77     
78   call = [(XmlRpcMethodCall *)[XmlRpcMethodCall alloc] initWithRequest:_req];
79   call = [call autorelease];
80     
81   if (call == nil) {
82     NSData *content;
83       
84     content = [_req content];
85     
86     [self logWithFormat:@"couldn't decode XMLRPC content:\n"];
87     [self logWithFormat:@"  content-len: %d", [content length]];
88     [self logWithFormat:@"  encoding:    %d", [_req contentEncoding]];
89     result = nil;
90   }
91   else {
92     [_object awake];
93     result = [[_object performMethodCall:call] generateResponse];
94     [_object sleep];
95   }
96   
97   if (result == nil)
98     return nil;
99   
100   if (![result isKindOfClass:[WOResponse class]]) {
101     /* morph an object result into a XML-RPC response .. */
102     XmlRpcMethodResponse *r;
103     
104     r = [[XmlRpcMethodResponse alloc] initWithResult:result];
105     result = [[[r generateResponse] retain] autorelease];
106     [r release];
107   }
108   
109   return result;
110 }
111
112 - (WOResponse *)handleRequest:(WORequest *)_request {
113   NSTimeInterval    startHandling = 0.0;
114 #if USE_POOLS
115   NSAutoreleasePool *pool = nil;
116 #endif
117   WOApplication *app;
118   NSString      *handlerPath = nil;
119   NSString      *actionClassName;
120   WOResponse    *response   = nil;
121   WOContext     *context    = nil;
122   NSThread      *thread;
123   NSMutableDictionary *threadDict;
124   Class         actionClass = Nil;
125   
126   if (![[_request method] isEqualToString:@"POST"]) {
127     [self logWithFormat:@"only POST requests are valid XML-RPC requests ..."];
128     return nil;
129   }
130   
131   if (perflog)
132     startHandling = [[NSDateClass date] timeIntervalSince1970];
133   
134   thread = [NSThread currentThread];
135   NSAssert(thread, @"missing current thread ...");
136   threadDict = [thread threadDictionary];
137   NSAssert(threadDict, @"missing current thread's dictionary ...");
138   
139   if (_request == nil) return nil;
140   
141   *(&app)             = nil;
142   *(&actionClassName) = nil;
143   
144   app = [WOApplication application];
145   
146   handlerPath = [_request uri];
147   actionClass = [NGXmlRpcAction actionClassForURI:handlerPath];
148   
149   if (actionClass == Nil) {
150     [self logWithFormat:@"found no action class for URI: %@", handlerPath];
151     actionClass = [app defaultActionClassForRequest:_request];
152   }
153   
154 #if DEBUG_XMLRPC_ACTION
155   NSLog(@"[XML-RPC request handler] class=%@ ..",
156         actionClassName);
157 #endif
158   
159 #if USE_POOLS
160   *(&pool) = [[NSAutoreleasePool alloc] init];
161 #endif
162   {
163     /* setup context */
164     context = [WOContext contextWithRequest:_request];
165     NSAssert(context, @"no context assigned ..");
166     NSAssert(threadDict, @"missing current thread's dictionary ...");
167     [threadDict setObject:context forKey:@"WOContext"];
168     
169     NS_DURING {
170       [app awake];
171       {
172         NGXmlRpcAction      *actionObject = nil;
173         id<WOActionResults> result = nil;
174
175         *(&result) = nil;
176         
177         NS_DURING {
178 #if USE_POOLS
179           NSAutoreleasePool *pool2 = [NSAutoreleasePool new];
180 #endif
181
182           {
183             /* create direct action object */
184             actionObject = [actionClass alloc];
185             actionObject = [actionObject initWithContext:context];
186             actionObject = [actionObject autorelease];
187             
188             if (actionObject == nil) {
189               [app logWithFormat:
190                    @"ERROR: could not create direct action object of class %@",
191                    actionClassName];
192               actionObject = nil;
193             }
194             else {
195               result = [self _runObject:actionObject request:_request];
196               result = [(id)result retain];
197               
198               if (result == nil) {
199                 [self logWithFormat:
200                       @"WARNING: got empty result from action .."];
201                 response = [WOResponse alloc];
202                 response = [response initWithRequest:_request];
203                 [response setStatus:500];
204               }
205               else {
206                 /* generate response */
207                 response = [[result generateResponse] retain];
208               }
209               
210               [(id)result release]; result = nil;
211             }
212           }
213
214 #if USE_POOLS
215           RELEASE(pool2); pool2 = nil;
216 #endif
217           response = [response autorelease];
218         }
219         NS_HANDLER {
220           response = [app handleException:localException inContext:context];
221         }
222         NS_ENDHANDLER;
223         
224         response = [response retain];
225       }
226       [app sleep];
227     }  
228     NS_HANDLER {
229       response = [app handleException:localException inContext:context];
230       response = [response retain];
231     }
232     NS_ENDHANDLER;
233     
234     NSAssert(threadDict, @"missing current thread's dictionary ...");
235     [threadDict removeObjectForKey:@"WOContext"];
236   }
237 #if USE_POOLS
238   [pool release]; pool = nil;
239 #endif
240
241   if (perflog) {
242     NSTimeInterval rt;
243     rt = [[NSDateClass date] timeIntervalSince1970] - startHandling;
244     NSLog(@"[da-handler]: handleRequest took %4.3fs.",
245           rt < 0.0 ? -1.0 : rt);
246   }
247   
248   return AUTORELEASE(response);
249 }
250
251 @end /* NGXmlRpcRequestHandler */