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 "SxComponentInvocation.h"
24 #include "SxComponentMethodSignature.h"
25 #include "SxComponent.h"
26 #include <NGExtensions/NSString+Ext.h>
29 @implementation SxComponentInvocation
31 static NSNull *null = nil;
40 if (self->arguments) return;
41 if (self->signature == nil) return;
42 if (null == nil) null = [[NSNull null] retain];
44 count = [self->signature numberOfArguments];
46 self->arguments = [[NSMutableArray alloc] initWithCapacity:count];
47 for (i = 0; i < count; i++)
48 [self->arguments addObject:null];
51 - (id)initWithMethodSignature:(id)_sig {
57 self->signature = [_sig retain];
63 return [self initWithMethodSignature:nil];
65 - (id)initWithComponent:(SxComponent *)_component
66 methodName:(NSString *)_method
67 signature:(SxComponentMethodSignature *)_signature
69 if ((self = [self initWithMethodSignature:_signature])) {
70 self->methodName = [_method copy];
71 self->target = [_component retain];
77 [self->credentials release];
78 [self->lastException release];
79 [self->arguments release];
80 [self->result release];
81 [self->target release];
82 [self->methodName release];
83 [self->signature release];
89 - (SxComponentMethodSignature *)methodSignature {
90 return self->signature;
93 - (void)setArgument:(id)_argument atIndex:(int)_idx {
94 if (_argument == nil) _argument = null;
95 [self->arguments replaceObjectAtIndex:_idx withObject:_argument];
97 - (id)argumentAtIndex:(int)_idx {
100 res = [self->arguments objectAtIndex:_idx];
101 if (res == null) res = nil;
104 - (void)setArguments:(NSArray *)_args {
105 NSAssert2(([self->signature numberOfArguments] == [_args count]),
106 @"arg count mismatch (%i expected, got %i)",
107 [self->signature numberOfArguments],
110 [self->arguments removeAllObjects];
111 [self->arguments addObjectsFromArray:_args];
113 - (NSArray *)arguments {
114 return [[self->arguments copy] autorelease];
117 - (BOOL)argumentsRetained {
121 - (void)setTarget:(SxComponent *)_target {
122 ASSIGN(self->target, _target);
124 - (SxComponent *)target {
128 - (void)setMethodName:(NSString *)_name {
129 ASSIGNCOPY(self->methodName, _name);
131 - (NSString *)methodName {
132 return self->methodName;
135 - (void)setReturnValue:(id)_result {
136 ASSIGN(self->result, _result);
142 - (void)setLastException:(NSException *)_exception {
143 ASSIGN(self->lastException, _exception);
146 - (NSException *)lastException {
147 return self->lastException;
149 - (BOOL)lastCallFailed {
150 return self->lastException != nil ? YES : NO;
152 - (void)resetLastException {
153 ASSIGN(self->lastException, (id)nil);
158 - (void)setCredentials:(id)_credentials {
159 ASSIGN(self->credentials, _credentials);
162 return self->credentials;
165 /* Dispatching an Invocation */
167 - (NSArray *)argumentsForCall {
168 return self->arguments;
171 - (id)_call:(NSString *)_methodName
172 onTarget:(SxComponent *)_target
173 arguments:(NSArray *)_params
175 return [_target call:_methodName arguments:_params];
177 - (BOOL)_asyncCall:(NSString *)_methodName
178 onTarget:(SxComponent *)_target
179 arguments:(NSArray *)_params
181 return [_target asyncCall:_methodName arguments:_params] ? YES : NO;
184 - (BOOL)invokeWithTarget:(SxComponent *)_target {
185 NSAutoreleasePool *pool;
188 pool = [[NSAutoreleasePool alloc] init];
194 [self->lastException release]; self->lastException = nil;
195 [self->result release]; self->result = nil;
198 args = [self argumentsForCall];
200 /* invoke remote method */
201 res = [self _call:[self methodName] onTarget:_target arguments:args];
203 /* check for errors */
205 if (self->lastException) {
207 [self setReturnValue:nil];
210 /* store return value */
211 [self setReturnValue:res];
220 return [self invokeWithTarget:[self target]];
225 - (void)asyncResultReady:(NSNotification *)_notification {
228 if (self->result != [_notification object]) {
229 NSLog(@"%s: WARNING, got an invalid aync result notification: %@",
230 __PRETTY_FUNCTION__, _notification);
234 proxy = [self->result retain];
235 [self->result release]; self->result = nil;
237 if ([proxy asyncCallFailed]) {
238 self->lastException = [[proxy asyncResult] retain];
239 [self setReturnValue:nil];
242 [self setReturnValue:[proxy asyncResult]];
244 [proxy release]; proxy = nil;
246 [[self->target notificationCenter]
247 postNotificationName:SxAsyncResultReadyNotificationName
251 - (BOOL)asyncInvoke {
252 NSAutoreleasePool *pool;
255 pool = [[NSAutoreleasePool alloc] init];
261 [self->lastException release]; self->lastException = nil;
262 [self->result release]; self->result = nil;
265 args = [self argumentsForCall];
267 /* invoke remote method */
269 res = [self->target asyncCall:[self methodName] arguments:args];
271 if (![res isAsyncResultPending]) {
272 /* result is ready :-) */
274 /* check for errors */
275 if ([self->target lastCallFailed]) {
276 self->lastException = [res retain];
277 [self setReturnValue:nil];
281 /* store return value */
282 [self setReturnValue:res];
287 /* result isn't ready yet, register for notification */
289 self->result = [res retain];
291 [[self->target notificationCenter]
292 addObserver:self selector:@selector(asyncResultReady:)
293 name:SxAsyncResultReadyNotificationName
294 object:self->result];
302 - (BOOL)isAsyncResultPending {
303 return [self->result isAsyncResultPending];
308 - (void)encodeWithCoder:(NSCoder *)_coder {
309 [_coder encodeObject:self->target];
310 [_coder encodeObject:self->methodName];
311 [_coder encodeObject:self->signature];
312 [_coder encodeObject:self->arguments];
313 [_coder encodeObject:self->result];
314 [_coder encodeObject:self->lastException];
316 - (id)initWithCoder:(NSCoder *)_coder {
317 if (null == nil) null = [[NSNull null] retain];
319 self->target = [[_coder decodeObject] retain];
320 self->methodName = [[_coder decodeObject] copy];
321 self->signature = [[_coder decodeObject] retain];
322 self->arguments = [[_coder decodeObject] retain];
323 self->result = [[_coder decodeObject] retain];
324 self->lastException = [[_coder decodeObject] retain];
326 if (self->signature == nil) {
327 NSLog(@"%s: missing signature (required during decoding)",
328 __PRETTY_FUNCTION__);
339 /* access the arguments with key "arg<element position>"
340 e.g. 'arg0' for the first element
343 - (int)_indexForKey:(NSString *)_key {
348 if(![_key hasPrefix:prefix])
351 return [[_key substringFromIndex:[prefix length]] intValue];
354 - (void)takeValue:(id)_value forKey:(NSString *)_key {
357 if ((index = [self _indexForKey:_key]) != -1)
358 [self setArgument:_value atIndex:index];
361 - (id)valueForKey:(NSString *)_key {
364 if ((index = [self _indexForKey:_key]) != -1)
365 return [self argumentAtIndex:index];
372 - (NSString *)description {
375 ms = [NSMutableString stringWithCapacity:128];
376 [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
377 [ms appendFormat:@" %@", self->methodName];
379 [ms appendFormat:@" #args=%i", [self->arguments count]];
381 [ms appendString:@" no-args"];
382 if (self->lastException)
383 [ms appendString:@" exception-is-set"];
385 [ms appendString:@" result-is-set"];
386 if (self->signature == nil)
387 [ms appendString:@" no-signature"];
389 [ms appendFormat:@" signature=%@",
390 [[self->signature xmlRpcTypes]
391 componentsJoinedByString:@","]];
392 if ([self->signature isOneway])
393 [ms appendString:@" oneway"];
395 [ms appendString:@">"];
399 @end /* SxComponentInvocation */