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 <NGXmlRpc/NGXmlRpcAction.h>
25 @interface NGXmlRpcActionSelMapping : NSObject
27 NSMutableArray *signatures;
28 NSMutableArray *selectors;
32 - (void)registerSelector:(SEL)_sel forSignature:(NSArray *)_signature;
33 - (SEL)selectorForSignature:(NSArray *)_signature;
34 - (NSArray *)signatures;
38 @implementation NGXmlRpcActionSelMapping
40 static int logSelMapping = -1;
43 if (logSelMapping == -1) {
44 logSelMapping = [[NSUserDefaults standardUserDefaults]
45 boolForKey:@"WOLogXmlRpcSelectorMapping"]
49 self->signatures = [[NSMutableArray alloc] initWithCapacity:2];
50 self->selectors = [[NSMutableArray alloc] initWithCapacity:2];
54 RELEASE(self->selectors);
55 RELEASE(self->signatures);
59 - (void)registerSelector:(SEL)_sel forSignature:(NSArray *)_signature {
60 [self->signatures addObject:_signature];
61 [self->selectors addObject:NSStringFromSelector(_sel)];
65 - (BOOL)signature:(NSArray *)_base matches:(NSArray *)_query {
70 if (bc != qc) return NO;
71 /* should check further */
74 - (SEL)selectorForSignature:(NSArray *)_signature {
77 for (i = 0; i < self->count; i++) {
80 sig = [self->signatures objectAtIndex:i];
81 if ([self signature:sig matches:_signature])
82 return NSSelectorFromString([self->selectors objectAtIndex:i]);
85 if (self->count > 0) {
86 [self debugWithFormat:
87 @"found no signature matching argcount %i, signatures: %@, got: %@",
88 ([_signature count] - 1),
89 self->signatures, _signature];
94 - (NSArray *)signatures {
95 return self->signatures;
98 @end /* NGXmlRpcActionSelMapping */
100 @implementation NGXmlRpcAction(Registry)
104 static NSMutableDictionary *uriToClass = nil;
105 static NSMutableDictionary *classToMethodDict = nil;
107 + (void)registerActionClass:(Class)_class forURI:(NSString *)_uri {
108 [(id<NSObject>)_class self]; /* ensure initialize */
109 if (uriToClass == nil)
110 uriToClass = [[NSMutableDictionary alloc] initWithCapacity:4];
111 [uriToClass setObject:_class forKey:_uri];
113 NSLog(@"%s: mapped uri '%@' to class %@", __PRETTY_FUNCTION__,
114 _uri, NSStringFromClass(_class));
116 + (Class)actionClassForURI:(NSString *)_uri {
117 return [uriToClass objectForKey:_uri];
120 + (void)registerSelector:(SEL)_selector
121 forMethodNamed:(NSString *)_method
122 signature:(id)_signature
124 NSMutableDictionary *md;
125 NGXmlRpcActionSelMapping *methodInfo;
127 if (![_signature isKindOfClass:[NSArray class]])
128 _signature = [[_signature stringValue] componentsSeparatedByString:@","];
130 if (classToMethodDict == nil)
131 classToMethodDict = [[NSMutableDictionary alloc] initWithCapacity:4];
133 if ((md = [classToMethodDict objectForKey:self]) == nil) {
134 md = [[NSMutableDictionary alloc] initWithCapacity:16];
135 [classToMethodDict setObject:md forKey:self];
139 if ((methodInfo = [md objectForKey:_method]) == nil) {
140 methodInfo = [[NGXmlRpcActionSelMapping alloc] init];
141 [md setObject:methodInfo forKey:_method];
145 [methodInfo registerSelector:_selector forSignature:_signature];
148 NSLog(@"%@: registered selector %@ for method %@ %@",
149 NSStringFromClass(self),
150 NSStringFromSelector(_selector),
152 [_signature componentsJoinedByString:@","]);
155 + (SEL)selectorForActionNamed:(NSString *)_name
156 signature:(NSArray *)_signature
158 NSMutableDictionary *methodDict;
159 NGXmlRpcActionSelMapping *methodInfo;
161 if ((methodDict = [classToMethodDict objectForKey:self]) == nil)
162 /* nothing registered */
165 if ((methodInfo = [methodDict objectForKey:_name]) == nil)
166 /* no action with that name is registered */
169 return [methodInfo selectorForSignature:_signature];
172 + (NSArray *)registeredMethodNames {
173 NSMutableDictionary *methodDict;
175 if ((methodDict = [classToMethodDict objectForKey:self]) == nil)
176 /* nothing registered */
178 return [methodDict allKeys];
180 + (NSArray *)signaturesForMethodNamed:(NSString *)_name {
181 NSMutableDictionary *methodDict;
182 NGXmlRpcActionSelMapping *methodInfo;
184 if ((methodDict = [classToMethodDict objectForKey:self]) == nil)
185 /* nothing registered */
188 if ((methodInfo = [methodDict objectForKey:_name]) == nil)
189 /* no action with that name is registered */
192 return [methodInfo signatures];
197 + (BOOL)registerSystemMethods {
198 if ([self instancesRespondToSelector:@selector(system_listMethodsAction)]) {
199 [self registerSelector:@selector(system_listMethodsAction)
200 forMethodNamed:@"system.listMethods"
201 signature:[NSArray arrayWithObject:@"array"]];
204 NSLog(@"WARNING(%s): class does not have a listMethods action !",
205 __PRETTY_FUNCTION__);
207 if ([self instancesRespondToSelector:
208 @selector(system_methodSignatureAction:)]) {
209 [self registerSelector:@selector(system_methodSignatureAction:)
210 forMethodNamed:@"system.methodSignature"
211 signature:[NSArray arrayWithObjects:@"array", @"string", nil]];
213 if ([self instancesRespondToSelector:
214 @selector(system_methodHelpAction:)]) {
215 [self registerSelector:@selector(system_methodHelpAction:)
216 forMethodNamed:@"system.methodHelp"
217 signature:[NSArray arrayWithObjects:@"string", @"string", nil]];
222 + (BOOL)registerMappingsInFile:(NSString *)_path {
226 NSString *methodName;
228 if (![_path isAbsolutePath]) {
231 b = [NSBundle bundleForClass:self];
232 if ((path = [b pathForResource:_path ofType:@"plist"]) == nil)
238 NSLog(@"%s: register mappings in file %@", __PRETTY_FUNCTION__, path);
240 if ((cfg = [NSDictionary dictionaryWithContentsOfFile:path]) == nil) {
241 NSLog(@"%s: could not load file %@", __PRETTY_FUNCTION__, path);
245 if (![self registerSystemMethods])
248 keys = [cfg keyEnumerator];
249 while ((methodName = [keys nextObject])) {
254 if ([methodName hasPrefix:@"__"])
257 mi = [cfg objectForKey:methodName];
258 if (![mi respondsToSelector:@selector(keyEnumerator)]) {
259 [self logWithFormat:@"entry '%@' in mapping file is no dictionary, skipping: %@", methodName, mi];
263 sigs = [mi keyEnumerator];
264 while ((sig = [sigs nextObject])) {
268 selName = [mi objectForKey:sig];
270 if ((sel = NSSelectorFromString(selName)) == NULL) {
271 NSLog(@"%s: did not find selector '%@'", __PRETTY_FUNCTION__,
276 if (![self instancesRespondToSelector:sel]) {
277 NSLog(@"WARNING(%s): instances of %@ do not respond to selector '%@'",
278 __PRETTY_FUNCTION__, NSStringFromClass(self),
282 [self registerSelector:sel
283 forMethodNamed:methodName
290 @end /* NGXmlRpcAction(Registry) */