2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
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.
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
23 #include "WODirectAction+XmlRpcIntrospection.h"
24 #include "WODirectAction+XmlRpc.h"
25 #include "NSObject+Reflection.h"
26 #include <NGXmlRpc/XmlRpcMethodCall+WO.h>
27 #include <NGXmlRpc/XmlRpcMethodResponse+WO.h>
28 #include <NGObjWeb/WORequest.h>
31 @interface NSMethodSignature(XmlRpcSignature)
33 - (NSArray *)xmlRpcSignature;
37 @implementation NSMethodSignature(XmlRpcSignature)
39 - (NSString *)xmlRpcTypeForObjCType:(const char *)_type {
40 if (_type == NULL) return nil;
76 - (NSArray *)xmlRpcSignature {
77 NSMutableArray *signature;
80 signature = [NSMutableArray arrayWithCapacity:8];
83 [signature addObject:[self xmlRpcTypeForObjCType:[self methodReturnType]]];
86 for (i = 2; i < [self numberOfArguments]; i++) {
89 t = [self getArgumentTypeAtIndex:i];
90 [signature addObject:[self xmlRpcTypeForObjCType:t]];
96 @end /* NSMethodSignature(XmlRpcSignature) */
98 @implementation WODirectAction(XmlRpcIntrospection)
100 static NSArray *blacklist = nil;
102 - (NSArray *)system_listMethodsAction {
109 namespace = [self xmlrpcComponentNamespace];
111 if (blacklist == nil) {
112 blacklist = [[NSArray alloc] initWithObjects:@"RPC2Action",
113 @"RPC2InfoPageAction",
115 @"commitFailedAction",
118 @"missingAuthAction",
119 @"selectorForXmlRpcAction:",
120 @"accessDeniedAction",nil];
123 selectors = [self respondsToSelectors];
124 sels = [selectors objectEnumerator];
126 ma = [NSMutableArray arrayWithCapacity:[selectors count]];
128 while ((sel = [sels nextObject])) {
130 NSString *actionName;
133 if ([blacklist containsObject:sel])
136 rng = [sel rangeOfString:@"Action"];
137 if (rng.length <= 0) continue;
140 actionName = [sel substringToIndex:rng.location];
142 /* ensure that only dots are following the 'Action' */
143 for (idx = (rng.location + rng.length), len = [sel length];
145 unichar c = [sel characterAtIndex:idx];
152 /* go to next selector if ... */
153 if ([actionName length] == 0) continue;
155 /* make action name XMLRPC-style friendly */
156 actionName = [actionName stringByReplacingString:@"_" withString:@"."];
158 if (namespace == nil)
159 [ma addObject:actionName];
161 /* add to reflection set */
162 if ([actionName hasPrefix:@"system."])
163 [ma addObject:actionName];
167 s = [[NSString alloc] initWithFormat:@"%@.%@", namespace,actionName];
174 return [[[ma copy] autorelease] sortedArrayUsingSelector:
175 @selector(caseInsensitiveCompare:)];
178 - (NSArray *)system_methodSignatureAction:(NSString *)_xmlrpcMethod {
180 It returns an array of possible signatures for this method. A signature
181 is an array of types. The first of these types is the return type of the
182 method, the rest are parameters.
184 Multiple signatures (ie. overloading) are permitted: this is the reason
185 that an array of signatures are returned by this method.
187 Signatures themselves are restricted to the top level parameters expected
188 by a method. For instance if a method expects one array of structs as a
189 parameter, and it returns a string, its signature is simply
190 "string, array". If it expects three integers, its signature is
191 "string, int, int, int".
193 If no signature is defined for the method, a none-array value is returned.
195 NSMutableArray *signatures;
196 NSString *actionName;
202 clazz = [self class];
203 signatures = [NSMutableArray arrayWithCapacity:4];
204 actionName = [self selectorForXmlRpcAction:_xmlrpcMethod];
206 len = [actionName length];
208 sels = [[self respondsToSelectors] objectEnumerator];
209 while ((sel = [sels nextObject])) {
211 NSMethodSignature *ms;
213 if (![sel hasPrefix:actionName]) continue;
215 ms = [self methodSignatureForSelector:NSSelectorFromString(sel)];
217 signature = [ms xmlRpcSignature];
220 [self logWithFormat:@"missing Objective-C method signature for %@ ...",
226 [signatures addObject:signature];
229 return ([signatures count] > 0)
231 : (id)[NSNumber numberWithBool:NO];
234 - (NSString *)system_methodHelpAction:(NSString *)_xmlrpcMethod {
236 @"Note: the Objective-C runtime cannot return the correct XML-RPC type "
237 @"for object parameters automatically (only for base types ...).";
240 @end /* WODirectAction(XmlRpcIntrospection) */
242 #include <NGObjWeb/WOResponse.h>
244 @implementation WODirectAction(XmlRpcInfo)
246 - (id<WOActionResults>)RPC2InfoPageAction {
251 r = [WOResponse alloc];
252 r = [[r initWithRequest:[self request]] autorelease];
253 [r setHeader:@"text/html" forKey:@"content-type"];
255 [r appendContentString:@"<html><head><title>WebService at "];
256 [r appendContentHTMLString:[[self request] uri]];
257 [r appendContentString:@"</title></head><body bgcolor=\"#FFFFFF\">"];
259 [r appendContentString:@"<h3>WebService at "];
260 [r appendContentHTMLString:[[self request] uri]];
261 [r appendContentString:@"</h3>"];
263 [r appendContentString:@"<h4>methods</h4>"];
265 [r appendContentString:@"<table border='1'>\n"];
266 [r appendContentString:
267 @"<tr><th>name</th><th>signature</th><th>info</th></tr>\n"];
269 e = [[self system_listMethodsAction] objectEnumerator];
270 while ((tmp = [e nextObject])) {
271 NSString *mname, *info;
274 mname = [tmp stringValue];
275 [r appendContentString:@"<tr>"];
277 [r appendContentString:@"<td>"];
278 [r appendContentHTMLString:mname];
279 [r appendContentString:@"</td>"];
281 sig = [self system_methodSignatureAction:mname];
282 info = [self system_methodHelpAction:mname];
284 [r appendContentString:@"<td>"];
285 if ([sig isKindOfClass:[NSArray class]]) {
286 [r appendContentHTMLString:[sig stringValue]];
288 [r appendContentString:@"</td>"];
290 if ([info length] > 0) {
291 [r appendContentString:@"<td>"];
292 [r appendContentString:info];
293 [r appendContentString:@"</td>"];
296 [r appendContentString:@"</tr>\n"];
298 [r appendContentString:@"</table>"];
300 [r appendContentString:@"</body></html>"];
305 @end /* WODirectAction(XmlRpcInfo) */