00001
00002
00003
00004
00005
00006
00007
00008
00009 #import "WIRemoting.h"
00010
00011 @interface RMCall (Private)
00012 - (void)responseDone:(RMResponse*) response;
00013 @end
00014
00015 @implementation RMCall (Private)
00016
00017 - (void)responseDone:(RMResponse*) response
00018 {
00019 [responseQueue removeObject: response];
00020 }
00021
00022 @end
00023
00024
00025 @implementation RMCall
00026
00027 @synthesize protocol;
00028 @dynamic semaphore;
00029
00030 - (id)initWithProtocol: (id<RMCallProtocol>) proto
00031 {
00032
00033 assert(proto != nil);
00034
00035
00036 self = [super init];
00037
00038 if (nil != self) {
00039
00040 protocol = [proto retain];
00041
00042 protocolStack = [[NSMutableArray alloc] initWithCapacity:3];
00043
00044 [protocolStack addObject:proto];
00045
00046 responseQueue = [[NSMutableArray alloc] initWithCapacity:3];
00047
00048 delegateChain = [[NSMutableArray alloc] initWithCapacity:1];
00049
00050 autoReleasePool = [[NSAutoreleasePool alloc] init];
00051 }
00052
00053 return self;
00054 }
00055
00056 - (void)dealloc
00057 {
00058
00059 [protocolStack release];
00060
00061 [protocol release];
00062
00063 [autoReleasePool release];
00064
00065 [delegateChain release];
00066
00067 [super dealloc];
00068 }
00069
00070 - (BOOL)call:(NSString*) method
00071 arguments:(NSDictionary*) arguments
00072 {
00073 return [self call:method
00074 arguments:arguments
00075 protocol:nil];
00076 }
00077
00078 - (BOOL)call:(NSString*) method
00079 arguments:(NSDictionary*) arguments
00080 delegate:(id) delegate
00081 {
00082 BOOL r;
00083 @synchronized(self.semaphore) {
00084 [self addDelegate:delegate];
00085 r = [self call:method arguments:arguments];
00086 [self removeDelegate:delegate];
00087 }
00088 return r;
00089 }
00090
00091 - (BOOL)call:(NSString*) method
00092 arguments:(NSDictionary*) arguments
00093 delegate:(id) delegate
00094 protocol:(id<RMCallProtocol>) aProtocol
00095 {
00096 BOOL r;
00097 @synchronized(self.semaphore) {
00098 [self addDelegate:delegate];
00099 r = [self call:method arguments:arguments protocol:aProtocol];
00100 [self removeDelegate:delegate];
00101 }
00102 return r;
00103 }
00104
00105 - (BOOL)call:(NSString*) method
00106 arguments:(NSDictionary*) arguments
00107 protocol:(id<RMCallProtocol>) aProtocol
00108 {
00109
00110 BOOL agreement;
00111
00112
00113 assert(method != nil);
00114 if (nil == arguments) {
00115 arguments = [[NSDictionary alloc] init];
00116 }
00117 else {
00118 [arguments retain];
00119 }
00120
00121 @synchronized(self.semaphore) {
00122
00123
00124 ASIFormDataRequest *req = [ASIFormDataRequest
00125 requestWithURL:
00126 [NSURL URLWithString:@"http://127.0.0.1/"]];
00127
00128
00129 for (id<RMCallProtocol> proto in protocolStack) {
00130 [proto adjustRequest:req
00131 method:method
00132 arguments:arguments];
00133 }
00134
00135 if (nil != aProtocol) {
00136 [aProtocol adjustRequest:req
00137 method:method
00138 arguments:arguments];
00139 }
00140
00141
00142 agreement = YES;
00143 for (id<RMCallProtocol> proto in protocolStack) {
00144 if ([proto respondsToSelector:@selector(requestShouldSend:method:arguments:)]) {
00145 agreement &= [proto requestShouldSend:req
00146 method:method
00147 arguments:arguments];
00148 }
00149 }
00150
00151 if (nil != aProtocol) {
00152 if ([aProtocol respondsToSelector:
00153 @selector(requestShouldSend:method:arguments:)]) {
00154 agreement &= [aProtocol requestShouldSend:req
00155 method:method
00156 arguments:arguments];
00157 }
00158 }
00159
00160
00161 if (!agreement) {
00162 [arguments release];
00163 return NO;
00164 }
00165
00166
00167 for (id<RMCallProtocol> proto in protocolStack) {
00168 if ([proto respondsToSelector:
00169 @selector(requestWillSend:method:arguments:)]) {
00170 [proto requestWillSend:req
00171 method:method
00172 arguments:arguments];
00173 }
00174 }
00175
00176 if (nil != aProtocol) {
00177 if ([aProtocol respondsToSelector:
00178 @selector(requestWillSend:method:arguments:)]) {
00179 [aProtocol requestWillSend:req
00180 method:method
00181 arguments:arguments];
00182 }
00183 }
00184
00185
00186 RMResponse *response = [RMResponse responseWithCall:self
00187 request:req
00188 delegate:delegateChain];
00189
00190
00191 [responseQueue addObject:response];
00192
00193
00194 [req setDelegate:response];
00195
00196 BOOL async = YES;
00197
00198 for (id<RMCallProtocol> proto in protocolStack) {
00199 if ([proto respondsToSelector:
00200 @selector(isAsynchronous)]) {
00201 async = [proto isAsynchronous];
00202 }
00203 }
00204
00205 if ([aProtocol respondsToSelector:
00206 @selector(isAsynchronous)]) {
00207 async = [aProtocol isAsynchronous];
00208 }
00209
00210
00211 if (async) {
00212 [req startAsynchronous];
00213 }
00214 else {
00215 [req start];
00216 }
00217
00218
00219 for (id<RMCallProtocol> proto in protocolStack) {
00220 if ([proto respondsToSelector:
00221 @selector(requestDidSend:method:arguments:)]) {
00222 [proto requestDidSend:req
00223 method:method
00224 arguments:arguments];
00225 }
00226 }
00227
00228 if (nil != aProtocol) {
00229 if ([aProtocol respondsToSelector:
00230 @selector(requestDidSend:method:arguments:)]) {
00231 [aProtocol requestDidSend:req
00232 method:method
00233 arguments:arguments];
00234 }
00235 }
00236 }
00237
00238 [arguments release];
00239 return YES;
00240 }
00241
00242 - (void)pushProtocol:(id<RMCallProtocol>)proto
00243 {
00244 [protocolStack addObject:proto];
00245 }
00246
00247 - (id<RMCallProtocol>)popProtocol
00248 {
00249 id proto = [[protocolStack lastObject] retain];
00250 [protocolStack removeLastObject];
00251 return [proto autorelease];
00252 }
00253
00254 - (id<RMCallProtocol>)topProtocol
00255 {
00256 return [protocolStack lastObject];
00257 }
00258
00259 - (void) addDelegate: (id<RMResultDelegate>) delegate
00260 {
00261 @synchronized(self.semaphore) {
00262 [delegateChain addObject:delegate];
00263 }
00264 }
00265
00266 - (void) removeDelegate: (id<RMResultDelegate>) delegate
00267 {
00268 @synchronized(self.semaphore) {
00269 [delegateChain removeObject:delegate];
00270 }
00271 }
00272
00273 - (id) semaphore
00274 {
00275 return self;
00276 }
00277
00278 @end