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