]> err.no Git - sope/blob - sope-appserver/NGXmlRpc/WODirectAction+XmlRpcIntrospection.m
fixed (all?) gcc 4.0 warnings
[sope] / sope-appserver / NGXmlRpc / WODirectAction+XmlRpcIntrospection.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 "WODirectAction+XmlRpcIntrospection.h"
23 #include "WODirectAction+XmlRpc.h"
24 #include "NSObject+Reflection.h"
25 #include <NGXmlRpc/XmlRpcMethodCall+WO.h>
26 #include <NGXmlRpc/XmlRpcMethodResponse+WO.h>
27 #include <NGObjWeb/WORequest.h>
28 #include "common.h"
29
30 @interface NSMethodSignature(XmlRpcSignature)
31
32 - (NSArray *)xmlRpcSignature;
33
34 @end
35
36 @implementation NSMethodSignature(XmlRpcSignature)
37
38 - (NSString *)xmlRpcTypeForObjCType:(const char *)_type {
39   if (_type == NULL) return nil;
40 #if GNU_RUNTIME
41   switch (*_type) {
42     case _C_ID:
43     case _C_CLASS:
44       return @"string";
45
46     case _C_SEL:
47     case _C_CHARPTR:
48       return @"string";
49       
50     case _C_CHR:
51     case _C_UCHR:
52       return @"boolean";
53       
54     case _C_INT:
55     case _C_UINT:
56     case _C_SHT:
57     case _C_USHT:
58     case _C_LNG:
59     case _C_ULNG:
60       return @"i4";
61
62     case _C_ARY_B:
63       return @"array";
64     case _C_STRUCT_B:
65       return @"struct";
66       
67     case _C_FLT:
68     case _C_DBL:
69       return @"double";
70   }
71 #endif
72   return @"string";
73 }
74
75 - (NSArray *)xmlRpcSignature {
76   NSMutableArray *signature;
77   unsigned i;
78
79   signature = [NSMutableArray arrayWithCapacity:8];
80
81   /* return value */
82   [signature addObject:[self xmlRpcTypeForObjCType:[self methodReturnType]]];
83   
84   /* arguments */
85   for (i = 2; i < [self numberOfArguments]; i++) {
86     const char *t;
87     
88     t = [self getArgumentTypeAtIndex:i];
89     [signature addObject:[self xmlRpcTypeForObjCType:t]];
90   }
91   
92   return signature;
93 }
94
95 @end /* NSMethodSignature(XmlRpcSignature) */
96
97 @implementation WODirectAction(XmlRpcIntrospection)
98
99 static NSArray *blacklist = nil;
100
101 - (NSArray *)system_listMethodsAction {
102   NSMutableArray *ma;
103   NSEnumerator   *sels;
104   NSString       *sel;
105   NSString       *namespace;
106   NSArray        *selectors;
107
108   namespace = [self xmlrpcComponentNamespace];
109
110   if (blacklist == nil) {  
111     blacklist = [[NSArray alloc] initWithObjects:@"RPC2Action",
112                                  @"RPC2InfoPageAction",
113                                  @"xmlrpcAction",
114                                  @"commitFailedAction",
115                                  @"WOStatsAction",
116                                  @"defaultAction",
117                                  @"missingAuthAction",
118                                  @"selectorForXmlRpcAction:",
119                                  @"accessDeniedAction",nil];
120   }
121
122   selectors = [self respondsToSelectors];
123   sels = [selectors objectEnumerator];
124
125   ma = [NSMutableArray arrayWithCapacity:[selectors count]];
126
127   while ((sel = [sels nextObject])) {
128     unsigned idx, len;
129     NSString *actionName;
130     NSRange rng;
131
132     if ([blacklist containsObject:sel])
133       continue;
134
135     rng = [sel rangeOfString:@"Action"];
136     if (rng.length <= 0) continue;
137     
138     /* strip Action */
139     actionName = [sel substringToIndex:rng.location];
140
141     /* ensure that only dots are following the 'Action' */
142     for (idx = (rng.location + rng.length), len = [sel length]; 
143          idx < len; idx++) {
144       unichar c = [sel characterAtIndex:idx];
145       if (c != ':') {
146         actionName = nil;
147         break;
148       }
149     }
150     
151     /* go to next selector if ... */
152     if ([actionName length] == 0) continue;
153     
154     /* make action name XMLRPC-style friendly */    
155     actionName = [actionName stringByReplacingString:@"_" withString:@"."];
156
157     if (namespace == nil)
158       [ma addObject:actionName];
159     else {
160       /* add to reflection set */
161       if ([actionName hasPrefix:@"system."])
162         [ma addObject:actionName];
163       else {
164         NSString *s;
165         
166         s = [[NSString alloc] initWithFormat:@"%@.%@", namespace,actionName];
167         [ma addObject:s];
168         [s release];
169       }
170     }
171   }
172
173   return [[[ma copy] autorelease] sortedArrayUsingSelector:
174                      @selector(caseInsensitiveCompare:)];
175 }
176
177 - (NSArray *)system_methodSignatureAction:(NSString *)_xmlrpcMethod {
178   /*
179     It returns an array of possible signatures for this method. A signature
180     is an array of types. The first of these types is the return type of the
181     method, the rest are parameters.
182
183     Multiple signatures (ie. overloading) are permitted: this is the reason
184     that an array of signatures are returned by this method.
185
186     Signatures themselves are restricted to the top level parameters expected
187     by a method. For instance if a method expects one array of structs as a
188     parameter, and it returns a string, its signature is simply
189     "string, array". If it expects three integers, its signature is
190     "string, int, int, int".
191
192     If no signature is defined for the method, a none-array value is returned.
193   */
194   NSMutableArray *signatures;
195   NSString       *actionName;
196   NSEnumerator   *sels;
197   NSString       *sel;
198   unsigned len;
199   Class clazz;
200
201   clazz      = [self class];
202   signatures = [NSMutableArray arrayWithCapacity:4];
203   actionName = [self selectorForXmlRpcAction:_xmlrpcMethod];
204   
205   len = [actionName length];
206   
207   sels = [[self respondsToSelectors] objectEnumerator];
208   while ((sel = [sels nextObject])) {
209     NSArray *signature;
210     NSMethodSignature *ms;
211     
212     if (![sel hasPrefix:actionName]) continue;
213     
214     ms = [self methodSignatureForSelector:NSSelectorFromString(sel)];
215     if (ms) {
216       signature = [ms xmlRpcSignature];
217     }
218     else {
219       [self logWithFormat:@"missing Objective-C method signature for %@ ...",
220               sel];
221       signature = nil;
222     }
223     
224     if (signature)
225       [signatures addObject:signature];
226   }
227   
228   return ([signatures count] > 0)
229     ? signatures
230     : (id)[NSNumber numberWithBool:NO];
231 }
232
233 - (NSString *)system_methodHelpAction:(NSString *)_xmlrpcMethod {
234   return
235     @"Note: the Objective-C runtime cannot return the correct XML-RPC type "
236     @"for object parameters automatically (only for base types ...).";
237 }
238
239 @end /* WODirectAction(XmlRpcIntrospection) */
240
241 #include <NGObjWeb/WOResponse.h>
242
243 @implementation WODirectAction(XmlRpcInfo)
244
245 - (id<WOActionResults>)RPC2InfoPageAction {
246   WOResponse *r;
247   NSEnumerator *e;
248   id tmp;
249
250   r = [WOResponse alloc];
251   r = [[r initWithRequest:[self request]] autorelease];
252   [r setHeader:@"text/html" forKey:@"content-type"];
253
254   [r appendContentString:@"<html><head><title>WebService at "];
255   [r appendContentHTMLString:[[self request] uri]];
256   [r appendContentString:@"</title></head><body bgcolor=\"#FFFFFF\">"];
257   
258   [r appendContentString:@"<h3>WebService at "];
259   [r appendContentHTMLString:[[self request] uri]];
260   [r appendContentString:@"</h3>"];
261   
262   [r appendContentString:@"<h4>methods</h4>"];
263
264   [r appendContentString:@"<table border='1'>\n"];
265   [r appendContentString:
266      @"<tr><th>name</th><th>signature</th><th>info</th></tr>\n"];
267   
268   e = [[self system_listMethodsAction] objectEnumerator];
269   while ((tmp = [e nextObject])) {
270     NSString *mname, *info;
271     id sig;
272
273     mname = [tmp stringValue];
274     [r appendContentString:@"<tr>"];
275     
276     [r appendContentString:@"<td>"];
277     [r appendContentHTMLString:mname];
278     [r appendContentString:@"</td>"];
279     
280     sig  = [self system_methodSignatureAction:mname];
281     info = [self system_methodHelpAction:mname];
282
283     [r appendContentString:@"<td>"];
284     if ([sig isKindOfClass:[NSArray class]]) {
285       [r appendContentHTMLString:[sig stringValue]];
286     }
287     [r appendContentString:@"</td>"];
288
289     if ([info length] > 0) {
290       [r appendContentString:@"<td>"];
291       [r appendContentString:info];
292       [r appendContentString:@"</td>"];
293     }
294     
295     [r appendContentString:@"</tr>\n"];
296   }
297   [r appendContentString:@"</table>"];
298   
299   [r appendContentString:@"</body></html>"];
300   
301   return r;
302 }
303
304 @end /* WODirectAction(XmlRpcInfo) */