]> err.no Git - sope/blob - sope-appserver/NGXmlRpc/NGXmlRpcInvocation.m
INSTALL_ROOT_DIR patch
[sope] / sope-appserver / NGXmlRpc / NGXmlRpcInvocation.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "NGXmlRpcInvocation.h"
24 #include "NGXmlRpcMethodSignature.h"
25 #include "NGXmlRpcClient.h"
26 #include "common.h"
27
28 @implementation NGXmlRpcInvocation
29
30 static NSNull *null = nil;
31
32 - (void)_ensureArgs {
33   unsigned i, count;
34
35   if (self->arguments) return;
36   if (self->signature == nil) return;
37   if (null == nil) null = [[NSNull null] retain];
38
39   count = [self->signature numberOfArguments];
40   
41   self->arguments = [[NSMutableArray alloc] initWithCapacity:count];
42   for (i = 0; i < count; i++)
43     [self->arguments addObject:null];
44 }
45
46 - (id)initWithMethodSignature:(NGXmlRpcMethodSignature *)_sig {
47   if (_sig == nil) {
48     RELEASE(self);
49     return nil;
50   }
51   
52   self->signature = RETAIN(_sig);
53   [self _ensureArgs];
54   
55   return self;
56 }
57 - (id)init {
58   return [self initWithMethodSignature:nil];
59 }
60
61 - (void)dealloc {
62   RELEASE(self->arguments);
63   RELEASE(self->result);
64   RELEASE(self->target);
65   RELEASE(self->methodName);
66   RELEASE(self->signature);
67   [super dealloc];
68 }
69
70 /* arguments */
71
72 - (NGXmlRpcMethodSignature *)methodSignature {
73   return self->signature;
74 }
75
76 - (void)setArgument:(id)_argument atIndex:(int)_idx {
77   if (_argument == nil) _argument = null;
78   [self->arguments replaceObjectAtIndex:_idx withObject:_argument];
79 }
80 - (id)argumentAtIndex:(int)_idx {
81   id res;
82   
83   res = [self->arguments objectAtIndex:_idx];
84   if (res == null) res = nil;
85   return res;
86 }
87
88 - (void)setTarget:(NGXmlRpcClient *)_target {
89   ASSIGN(self->target, _target);
90 }
91 - (NGXmlRpcClient *)target {
92   return self->target;
93 }
94
95 - (void)setMethodName:(NSString *)_name {
96   ASSIGNCOPY(self->methodName, _name);
97 }
98 - (NSString *)methodName {
99   return self->methodName;
100 }
101
102 - (void)setReturnValue:(id)_result {
103   ASSIGN(self->result, _result);
104 }
105 - (id)returnValue {
106   return self->result;
107 }
108
109 /* Dispatching an Invocation */
110
111 - (void)invoke {
112   [self invokeWithTarget:[self target]];
113 }
114
115 - (void)invokeWithTarget:(NGXmlRpcClient *)_target {
116   NSAutoreleasePool *pool;
117   
118   pool = [[NSAutoreleasePool alloc] init];
119   {
120     NSArray *args;
121     id res;
122     unsigned count;
123     NGXmlRpcMethodSignature *sig;
124
125     sig = [self methodSignature];
126     
127     /* collect arguments, coerce types ... */
128     if ((count = [self->arguments count]) == 0)
129       args = self->arguments;
130     else if (sig) {
131       unsigned i;
132       id *aa;
133       
134       aa = calloc(count, sizeof(id));
135       for (i = 0; i < count; i++) {
136         NSString *xrtype;
137         id value;
138         
139         xrtype = [sig argumentTypeAtIndex:i];
140         
141         value = [self->arguments objectAtIndex:i];
142         value = [value asXmlRpcValueOfType:xrtype];
143         aa[i] = value ? value : null;
144       }
145       args = [NSArray arrayWithObjects:aa count:count];
146       if (aa) free(aa);
147     }
148     else
149       args = self->arguments;
150     
151     /* invoke remote method */
152     res = [_target invokeMethodNamed:[self methodName] parameters:args];
153     
154     /* store return value */
155     [self setReturnValue:res];
156   }
157   RELEASE(pool);
158 }
159
160 /* NSCoding */
161
162 - (void)encodeWithCoder:(NSCoder *)_coder {
163   [_coder encodeObject:self->target];
164   [_coder encodeObject:self->methodName];
165   [_coder encodeObject:self->signature];
166   [_coder encodeObject:self->arguments];
167   [_coder encodeObject:self->result];
168 }
169 - (id)initWithCoder:(NSCoder *)_coder {
170   if (null == nil) null = [[NSNull null] retain];
171   
172   self->target     = [[_coder decodeObject] retain];
173   self->methodName = [[_coder decodeObject] copy];
174   self->signature  = [[_coder decodeObject] retain];
175   self->arguments  = [[_coder decodeObject] retain];
176   self->result     = [[_coder decodeObject] retain];
177   
178   if (self->signature == nil) {
179     NSLog(@"%s: missing signature (required during decoding)",
180           __PRETTY_FUNCTION__);
181     RELEASE(self);
182     return nil;
183   }
184   [self _ensureArgs];
185   
186   return self;
187 }
188
189 @end /* NGXmlRpcInvocation */
190
191 @implementation NSObject(XmlRpcValue)
192
193 - (NSArray *)asXmlRpcArray {
194   if ([self respondsToSelector:@selector(objectEnumerator)]) {
195     return [[[NSArray alloc]
196                       initWithObjectsFromEnumerator:
197                         [(id)self objectEnumerator]]
198                       autorelease];
199   }
200   return nil;
201 }
202
203 - (NSDictionary *)asXmlRpcStruct {
204   return [self valuesForKeys:[[self classDescription] attributeKeys]];
205 }
206
207 - (NSString *)asXmlRpcString {
208   return [self stringValue];
209 }
210 - (int)asXmlRpcInt {
211   return [self intValue];
212 }
213 - (int)asXmlRpcDouble {
214   return [self doubleValue];
215 }
216
217 - (NSData *)asXmlRpcBase64 {
218   return [[self stringValue] dataUsingEncoding:NSUTF8StringEncoding];
219 }
220 - (NSDate *)asXmlRpcDateTime {
221   return [[[NSDate alloc] initWithString:[self stringValue]] autorelease];
222 }
223
224 - (id)asXmlRpcValueOfType:(NSString *)_xmlRpcValueType {
225   unsigned len;
226   
227   if ((len = [_xmlRpcValueType length]) == 0)
228     return self;
229
230   if ([_xmlRpcValueType isEqualToString:@"string"])
231     return [self asXmlRpcString];
232   if ([_xmlRpcValueType isEqualToString:@"int"])
233     return [NSNumber numberWithInt:[self asXmlRpcInt]];
234   if ([_xmlRpcValueType isEqualToString:@"i4"])
235     return [NSNumber numberWithInt:[self asXmlRpcInt]];
236   if ([_xmlRpcValueType isEqualToString:@"double"])
237     return [NSNumber numberWithDouble:[self asXmlRpcDouble]];
238   if ([_xmlRpcValueType isEqualToString:@"float"])
239     return [NSNumber numberWithDouble:[self asXmlRpcDouble]];
240   if ([_xmlRpcValueType isEqualToString:@"array"])
241     return [self asXmlRpcArray];
242   if ([_xmlRpcValueType isEqualToString:@"struct"])
243     return [self asXmlRpcStruct];
244   if ([_xmlRpcValueType isEqualToString:@"datetime"])
245     return [self asXmlRpcDateTime];
246   if ([_xmlRpcValueType isEqualToString:@"base64"])
247     return [self asXmlRpcBase64];
248   
249   return self;
250 }
251
252 @end /* NSObject(XmlRpcValue) */
253
254 @implementation NSArray(XmlRpcValue)
255
256 - (NSArray *)asXmlRpcArray {
257   return self;
258 }
259
260 - (id)asXmlRpcValueOfType:(NSString *)_xmlRpcValueType {
261   return self;
262 }
263
264 @end /* NSArray(XmlRpcValue) */
265
266 @implementation NSDictionary(XmlRpcValue)
267
268 - (NSArray *)asXmlRpcArray {
269   return [self allValues];
270 }
271
272 - (NSDictionary *)asXmlRpcStruct {
273   return self;
274 }
275
276 @end /* NSDictionary(XmlRpcValue) */
277
278 @implementation NSDate(XmlRpcValue)
279
280 - (NSDate *)asXmlRpcDateTime {
281   return self;
282 }
283
284 @end /* NSDate(XmlRpcValue) */
285
286 @implementation NSData(XmlRpcValue)
287
288 - (NSData *)asXmlRpcBase64 {
289   return self;
290 }
291
292 @end /* NSCalendarDate(XmlRpcValue) */