2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
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>
30 @interface NSMethodSignature(XmlRpcSignature)
32 - (NSArray *)xmlRpcSignature;
36 @implementation NSMethodSignature(XmlRpcSignature)
38 - (NSString *)xmlRpcTypeForObjCType:(const char *)_type {
39 if (_type == NULL) return nil;
75 - (NSArray *)xmlRpcSignature {
76 NSMutableArray *signature;
79 signature = [NSMutableArray arrayWithCapacity:8];
82 [signature addObject:[self xmlRpcTypeForObjCType:[self methodReturnType]]];
85 for (i = 2; i < [self numberOfArguments]; i++) {
88 t = [self getArgumentTypeAtIndex:i];
89 [signature addObject:[self xmlRpcTypeForObjCType:t]];
95 @end /* NSMethodSignature(XmlRpcSignature) */
97 @implementation WODirectAction(XmlRpcIntrospection)
99 static NSArray *blacklist = nil;
101 - (NSArray *)system_listMethodsAction {
108 namespace = [self xmlrpcComponentNamespace];
110 if (blacklist == nil) {
111 blacklist = [[NSArray alloc] initWithObjects:@"RPC2Action",
112 @"RPC2InfoPageAction",
114 @"commitFailedAction",
117 @"missingAuthAction",
118 @"selectorForXmlRpcAction:",
119 @"accessDeniedAction",nil];
122 selectors = [self respondsToSelectors];
123 sels = [selectors objectEnumerator];
125 ma = [NSMutableArray arrayWithCapacity:[selectors count]];
127 while ((sel = [sels nextObject])) {
129 NSString *actionName;
132 if ([blacklist containsObject:sel])
135 rng = [sel rangeOfString:@"Action"];
136 if (rng.length <= 0) continue;
139 actionName = [sel substringToIndex:rng.location];
141 /* ensure that only dots are following the 'Action' */
142 for (idx = (rng.location + rng.length), len = [sel length];
144 unichar c = [sel characterAtIndex:idx];
151 /* go to next selector if ... */
152 if ([actionName length] == 0) continue;
154 /* make action name XMLRPC-style friendly */
155 actionName = [actionName stringByReplacingString:@"_" withString:@"."];
157 if (namespace == nil)
158 [ma addObject:actionName];
160 /* add to reflection set */
161 if ([actionName hasPrefix:@"system."])
162 [ma addObject:actionName];
166 s = [[NSString alloc] initWithFormat:@"%@.%@", namespace,actionName];
173 return [[[ma copy] autorelease] sortedArrayUsingSelector:
174 @selector(caseInsensitiveCompare:)];
177 - (NSArray *)system_methodSignatureAction:(NSString *)_xmlrpcMethod {
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.
183 Multiple signatures (ie. overloading) are permitted: this is the reason
184 that an array of signatures are returned by this method.
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".
192 If no signature is defined for the method, a none-array value is returned.
194 NSMutableArray *signatures;
195 NSString *actionName;
201 clazz = [self class];
202 signatures = [NSMutableArray arrayWithCapacity:4];
203 actionName = [self selectorForXmlRpcAction:_xmlrpcMethod];
205 len = [actionName length];
207 sels = [[self respondsToSelectors] objectEnumerator];
208 while ((sel = [sels nextObject])) {
210 NSMethodSignature *ms;
212 if (![sel hasPrefix:actionName]) continue;
214 ms = [self methodSignatureForSelector:NSSelectorFromString(sel)];
216 signature = [ms xmlRpcSignature];
219 [self logWithFormat:@"missing Objective-C method signature for %@ ...",
225 [signatures addObject:signature];
228 return ([signatures count] > 0)
230 : (id)[NSNumber numberWithBool:NO];
233 - (NSString *)system_methodHelpAction:(NSString *)_xmlrpcMethod {
235 @"Note: the Objective-C runtime cannot return the correct XML-RPC type "
236 @"for object parameters automatically (only for base types ...).";
239 @end /* WODirectAction(XmlRpcIntrospection) */
241 #include <NGObjWeb/WOResponse.h>
243 @implementation WODirectAction(XmlRpcInfo)
245 - (id<WOActionResults>)RPC2InfoPageAction {
250 r = [WOResponse alloc];
251 r = [[r initWithRequest:[self request]] autorelease];
252 [r setHeader:@"text/html" forKey:@"content-type"];
254 [r appendContentString:@"<html><head><title>WebService at "];
255 [r appendContentHTMLString:[[self request] uri]];
256 [r appendContentString:@"</title></head><body bgcolor=\"#FFFFFF\">"];
258 [r appendContentString:@"<h3>WebService at "];
259 [r appendContentHTMLString:[[self request] uri]];
260 [r appendContentString:@"</h3>"];
262 [r appendContentString:@"<h4>methods</h4>"];
264 [r appendContentString:@"<table border='1'>\n"];
265 [r appendContentString:
266 @"<tr><th>name</th><th>signature</th><th>info</th></tr>\n"];
268 e = [[self system_listMethodsAction] objectEnumerator];
269 while ((tmp = [e nextObject])) {
270 NSString *mname, *info;
273 mname = [tmp stringValue];
274 [r appendContentString:@"<tr>"];
276 [r appendContentString:@"<td>"];
277 [r appendContentHTMLString:mname];
278 [r appendContentString:@"</td>"];
280 sig = [self system_methodSignatureAction:mname];
281 info = [self system_methodHelpAction:mname];
283 [r appendContentString:@"<td>"];
284 if ([sig isKindOfClass:[NSArray class]]) {
285 [r appendContentHTMLString:[sig stringValue]];
287 [r appendContentString:@"</td>"];
289 if ([info length] > 0) {
290 [r appendContentString:@"<td>"];
291 [r appendContentString:info];
292 [r appendContentString:@"</td>"];
295 [r appendContentString:@"</tr>\n"];
297 [r appendContentString:@"</table>"];
299 [r appendContentString:@"</body></html>"];
304 @end /* WODirectAction(XmlRpcInfo) */