-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathGWSService.h
executable file
·604 lines (539 loc) · 22.9 KB
/
GWSService.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
/**
Copyright (C) 2008 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <[email protected]>
Date: January 2008
This file is part of the WebServices Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
$Date: 2007-09-14 13:54:55 +0100 (Fri, 14 Sep 2007) $ $Revision: 25485 $
*/
#ifndef INCLUDED_GWSSERVICE_H
#define INCLUDED_GWSSERVICE_H
#import <Foundation/NSObject.h>
#import <Foundation/NSDebug.h>
#if defined(__cplusplus)
extern "C" {
#endif
@class NSArray;
@class NSDate;
@class NSDictionary;
@class NSMutableArray;
@class NSMutableData;
@class NSMutableDictionary;
@class NSRecursiveLock;
@class NSString;
@class NSThread;
@class NSTimer;
@class NSTimeZone;
@class NSURL;
@class NSURLConnection;
@class GWSCoder;
@class GWSDocument;
@class GWSElement;
@class GWSPort;
/**
* <p>The GWSService class provides methods for makeing a Remote Procedure
* Call (RPC) as a web services client.<br />
* Instances of this class are (in an ideal world) created and owned by
* instances the GWSDocument class as it parses a WSDL document, and contain
* information parsed from that document allowing them to set up the coding
* mechanism and URL to talk to.<br />
* However, standalone instances may be created to allow you to perform RPCs
* to a web services server when you dont have a fully specified WSDL document
* (or if the GWSDocument mechanism isn't working).
* </p>
* <p>The class provides a method for making a synchronous RPC (with timeout),
* or an asynchronous RPC in which the call completion is handled by a delegate.
* </p>
* <p>In order to simply make a synchronous call to a server, all
* you need to do is write code like:
* </p>
* <example>
* GWSService *server;
* NSDictionary *result;
* server = [GWSService new];
* [server setURL: @"http://server/path"];
* [server setCoder: [GWSSOAPCoder coder]];
* result = [server invokeMethod: name
* parameters: p
* order: o
* timeout: 30];
* </example>
* <p>Saying that you want to call the specified method ('name') on the server,
* passing the parameters ('p') in the order they are listed in 'o'
* and with a 30 second timeout.<br />
* If there is a network or http-level error or a timeout, the result
* will contain <ref type="constant" id="GWSErrorKey">GWSErrorKey</ref>,
* otherwise it will contain
* <ref type="constant" id="GWSParametersKey">GWSParametersKey</ref>,
* and <ref type="constant" id="GWSOrderKey">GWSOrderKey</ref> on success,
* or <ref type="constant" id="GWSFaultKey">GWSFaultKey</ref> if the remote
* end returns a fault.
* </p>
*/
@interface GWSService : NSObject
#if defined(GNUSTEP)
<GSLogDelegate>
#endif
{
@private
NSString *_name;
GWSDocument *_document; // Not retained (our owner)
GWSElement *_documentation;
NSMutableDictionary *_ports;
NSMutableArray *_extensibility;
NSURL *_connectionURL;
NSURLConnection *_connection;
NSMutableData *_response;
NSTimer *_timer;
NSMutableDictionary *_result;
id _delegate; // Not retained.
NSTimeZone *_tz;
GWSCoder *_coder;
NSString *_HTTPMethod;
NSString *_SOAPAction;
BOOL _compact;
BOOL _debug;
BOOL _prioritised;
BOOL _cancelled; // Timeout occurred
BOOL _completedIO; // Comms completed
BOOL _newAPI;
NSString *_operation;
GWSPort *_port;
NSMutableDictionary *_parameters;
NSData *_request;
NSString *_clientCertificate;
NSString *_clientKey;
NSString *_clientPassword;
NSDictionary *_headers;
NSMutableDictionary *_extra;
int _code;
NSDate *_timeout;
NSString *_prepMethod;
NSDictionary *_prepParameters;
NSArray *_prepOrder;
NSThread *_queueThread;
NSThread *_ioThread;
NSRecursiveLock *_lock;
enum {
RPCIdle = 0, // Not performing RPC
RPCQueued, // In local queue waiting to do I/O or prepare
RPCPreparing, // Building request data to send.
RPCActive, // In the I/O thread
RPCParsing // Parsing the response data
} _stage;
NSString *_contentType;
}
/** Returns a description of the current asynchronous service queues.
*/
+ (NSString*) description;
/** Empty the cache of connections being kept alive to the specified
* URL or, if url is nil empty the entire cache.
*/
+ (void) flushConnections: (NSURL*)url;
/** Sets maximum concurrently active requests to a single host.<br />
* A host is actually specified by the combination of scheme, host,
* and port of a URL.<br />
* This is silently limited to be no more than the value set by
* the +setPool: method.
*/
+ (void) setPerHostPool: (unsigned)max;
/** Sets maximum queued requests to any single host.<br />
* This may be overridden for an individual host by using
* the +setReserve:forHost: method.
*/
+ (void) setPerHostQMax: (unsigned)max;
/** Sets the maximum number of simultaneous active async requests.<br />
* This is silently limited to the number of reserved hosts plus one on
* any attempt to set a lower value.
*/
+ (void) setPool: (unsigned)max;
/** Sets the maximum number of queued async requests.<br />
* This may be overridden for an individual host by using
* the +setReserve:forHost: method.
*/
+ (void) setQMax: (unsigned)max;
/** Sets a minimum queue size for a specific host ... if the queue for
* this host is not full, an RPC can be queued even if the normal queue
* limits have been reached.<br />
* Setting a non-zero value for a host also reserves a single space in
* the connection pool for this host, so it is always possible for at
* least one request to be in progress to the host.<br />
* The scheme, host and port combination of hostURL define the
* unique host that the queue refers to.<br />
* This setting overrides the values defined by the +setPerHostQMax: and
* +setQMax: methods.
*/
+ (void) setReserve: (unsigned)reserve forHost: (NSURL*)hostURL;
/** Sets whether the I/O for requests is to be performed in separate
* threads rather than the thread which queued the RPC.<br />
* Setting this option causes a small group of threads to be created
* and used to handle the I/O to the remote host.<br />
* If no work threads (see +setWorkThreads:) are enabled, the parsing
* of the response to the request is performed in the same thread that
* performed the I/O.<br />
* In any case, the -completedRPC: callback is sent to the thread which
* originally queued the RPC.
*/
+ (void) setUseIOThreads: (BOOL)aFlag;
/** Sets the number of threads to be used for the building of request
* data to be POSTed to the remote system, the parsing of data received
* in response to that POST, and the callbacks to the delegate involved
* up to but excluding the execution of the -completedRPC: callback.<br />
* By default this is zero ... so request data is built, and response
* data is parsed, in the thread which queues the request.
*/
+ (void) setWorkThreads: (NSUInteger)count;
/**
* Builds an RPC method call.<br />
* The method argument is the name of the operation to be performed,
* however, if the receiver is owned by a GWSDocument instance which
* defines multiple ports for the service, the operation name may not
* be unique, in which case it must be specified as the port type and
* operation names separated by a full stop (port.operation).<br />
* Parameters must be supplied as for the
* [GWSCoder-buildRequest:parameters:order:] method.<br />
*/
- (NSData*) buildRequest: (NSString*)method
parameters: (NSDictionary*)parameters
order: (NSArray*)order;
/**
* Returns the coder instance used to serialize/deserialize for this
* instance.<br />
*/
- (GWSCoder*) coder;
/** Returns YES if debug is enabled, NO otherwise. The default value of this
* is obtained from the GWSDebug user default (or NO if no default
* is set), but may also be adjusted by a call to the -setDebug: method.
*/
- (BOOL) debug;
/**
* Returns the delegate previously set by the -setDelegate: method.<br />
* The delegate handles completion of asynchronous method calls to the
* URL specified when the receiver was initialised (if any).
*/
- (id) delegate;
/** Return the documentation for the receiver.
*/
- (GWSElement*) documentation;
/** Method called (if GNUstep debug logging is turned on) when a chunk of
* data from the HTTP request has been written. The default implementation
* returns NO (so default logging is used) unless the delegate supports the
* method (in which case the delegate method is used), but subclasses may
* override it to provide their own logging and return YES.
* When the delegate method is called, the handle sent to it is the GWSService
* instance.
*/
- (BOOL) getBytes: (const uint8_t*)bytes
ofLength: (NSUInteger)length
byHandle: (NSObject*)anObject;
/** Returns the value set by a previous call to the -setHeaders: method.
*/
- (NSDictionary*) headers;
/**
* Calls -sendRequest:parameters:order:timeout:prioritised: and waits for the
* response.<br />
* Parameters must be supplied as for the
* [GWSCoder-buildRequest:parameters:order:] method.<br />
* Returns the response dictionary containing values for the
* success or failure of the call (as returned by -result).<br />
* Returns nil if it was impossible to build a valid request
* from the supplied parameters.
*/
- (NSMutableDictionary*) invokeMethod: (NSString*)method
parameters: (NSDictionary*)parameters
order: (NSArray*)order
timeout: (int)seconds;
/** Returns the name of this WSDL service.
*/
- (NSString*) name;
/** Returns the extra information (if any) associated with aKey by an
* earlier call to the -setObject:forKey: method.
*/
- (id) objectForKey: (NSString*)aKey;
/** Method called (if GNUstep debug logging is turned on) when a chunk of
* data from the HTTP request has been written. The default implementation
* returns NO (so default logging is used) unless the delegate supports the
* method (in which case the delegate method is used), but subclasses may
* override it to provide their own logging and return YES.
* When the delegate method is called, the handle sent to it is the GWSService
* instance.
*/
- (BOOL) putBytes: (const uint8_t*)bytes
ofLength: (NSUInteger)length
byHandle: (NSObject*)anObject;
/**
* Returns the result of the last method call, or nil if there has been
* no method call or one is in progress.<br />
* The result is as produced by the [GWSCoder-parseMessage:] method.<br />
* NB. Any containers (arrays or dictionaries) in the parsed parameters
* of a success response will be mutable, so you can modify this data
* structure as you like.
*/
- (NSMutableDictionary*) result;
/**
* Calls -sendRequest:parameters:order:timeout:prioritised: for a
* normal (non urgent) request.
*/
- (BOOL) sendRequest: (NSString*)method
parameters: (NSDictionary*)parameters
order: (NSArray*)order
timeout: (int)seconds;
/**
* Send an asynchronous RPC method call with the specified timeout.<br />
* The method argument is the name of the operation to be performed,
* however, if the receiver is owned by a GWSDocument instance which
* defines multiple ports for the service, the operation name may not
* be unique, in which case it must be specified as the port type and
* operation names separated by a full stop (port.operation).<br />
* A delegate should have been set to handle the result of this call,
* but if one was not set the state of the asynchronous call may be polled
* by calling the -result method, which will return nil as long as the
* call has not completed.<br />
* The call may be cancelled by calling the -timeout: method.<br />
* This method returns YES if the call was started,
* NO if it could not be started (eg because there is already a call in
* progress for the receiver, or too many other calls are in progress
* in total, or because of bad arguments).<br />
* NB. For the asynchronous operation to proceed, the current [NSRunLoop]
* must be run.<br />
* Parameters must be supplied as for the
* [GWSCoder-buildRequest:parameters:order:] method.<br />
*/
- (BOOL) sendRequest: (NSString*)method
parameters: (NSDictionary*)parameters
order: (NSArray*)order
timeout: (int)seconds
prioritised: (BOOL)urgent;
/** Sets the coder to be used by the receiver for encoding to XML and
* decoding from XML. If this is not called, the receiver creates a
* coder as needed.<br />
* Calling this method sets the receiver as the delegate of the coder,
* or raises an NSInvalidArgumentException if the coder already had a
* different delegate.
*/
- (void) setCoder: (GWSCoder*)aCoder;
/**
* Sets the value of the Content-Type header to be sent with a request.<br />
* Setting a nil or empty string value reverts to the default of text/xml.
*/
- (void) setContentType: (NSString*)cType;
/** Specifies whether debug information is enabled. See -debug for more
* information.<br />
* A non-zero setting sets debug to YES while a zero setting sets it to NO.
* The method returns the previous setting.
*/
- (int) setDebug: (int)flag;
/**
* Sets the delegate object which will receive callbacks when an RPC
* call completes.<br />
* NB. this delegate is <em>not</em> retained, and should be removed
* before it is deallocated (call -setDelegate: again with a nil argument
* to remove the delegate).
*/
- (void) setDelegate: (id)aDelegate;
/** Set the documentation for the receiver.
*/
- (void) setDocumentation: (GWSElement*)documentation;
/** Sets extra headers to be sent as part of any HTTP or HTTPS request
* initiated by this service.<br />
* NB. These headers are set *after* the default headers set for content
* type and user agent etc, so you can override the values normally set
* by the service.
*/
- (void) setHeaders: (NSDictionary*)headers;
/** Sets the value of the HTTP method to be used for a request.<br />
* Setting an nil string reverts to the default 'POST' method.<br />
*/
- (void) setHTTPMethod: (NSString*)method;
/** Controls whether the new (NSURLConnection/NSURLRequest) API is used
* or the old (NSURLHandle) API is used. The default depends on the
* platform (GNUstep uses the old API while Apple uses the new).<br />
* Turning on debug or the use of client certificates overrides this
* to use the old API since the new one does not yet support those
* features.
*/
- (BOOL) setNewAPI: (BOOL)aFlag;
/** Tags the service with entra information in the form of anObject
* references by aKey. if anObject is nil, this removes any previous
* association for aKey.<br />
* This facility is not used by the WebServices library, and is present
* purely so that delegates can associate extra information with the
* services they are handling.
*/
- (void) setObject: (id)anObject forKey: (NSString*)aKey;
/** Sets the value of the SOAPAction header to be sent with a request.<br />
* Setting an nil string value suppresses the sending of this header.<br />
* Most servers expect two double quotes characters for this,
* so you should probably set @"\"\"" as the action.<br />
*/
- (void) setSOAPAction: (NSString*)action;
/**
* Sets the time zone for use when sending/receiving date/time values.<br />
* The XMLRPC specification says that timezone is server dependent so you
* will need to set it according to the server you are connecting to.<br />
* If this is not set, UCT is assumed.
*/
- (void) setTimeZone: (NSTimeZone*)timeZone;
/**
* Sets up the receiver to make XMLRPC calls to the specified URL.<br />
* This method just calls -initWithURL:certificate:privateKey:password:
* with nil arguments for the SSL credentials.
*/
- (void) setURL: (id)url;
/**
* Sets up the receiver to make XMLRPC calls to the specified url
* and (optionally) with the specified SSL parameters.<br />
* The url argument may be nil, in which case the receiver will be
* unable to make XMLRPC calls, but can be used to parse incoming
* requests and build responses.<br />
* The url can actually be either a string or an instance of NSURL.<br />
* If the SSL credentials are non-nil, connections to the remote server
* will be authenticated using the supplied certificate so that the
* remote system knows who is contacting it.<br />
* Certificate based authentication currently <em>NOT</em> implemented
** for MacOS-X (though it is for GNUstep).<br />
* Please could someone let me know how
* certificate based authentication is done for HTTPS on MacOS-X?
*/
- (void) setURL: (id)url
certificate: (NSString*)cert
privateKey: (NSString*)pKey
password: (NSString*)pwd;
/**
* Handles timeouts, passing information to delegate ... you don't need to
* call this method, but you <em>may</em> call it (with nil as its argument)
* in order to cancel an asynchronous request as if it had timed out.
*/
- (void) timeout: (NSTimer*)t;
/**
* Return the time zone currently set.
*/
- (NSTimeZone*) timeZone;
/** Return a tree representation of the receiver for output as part of
* a WSDL document.
*/
- (GWSElement*) tree;
/** Returns the name of the current operation being performed,
* or nil if there is no operation in progress.<br />
* In conjunction with -webServicePort this method can be used to look
* up all the details of the WSDL definition of the operation being
* performed.
*/
- (NSString*) webServiceOperation;
/** Returns the parameter dictionary of the current operation being performed,
* or nil if there is no operation in progress.<br />
* This method can be used to determine exactly what data is being passed
* in the current operation.
*/
- (NSMutableDictionary*) webServiceParameters;
/** Returns the port of the current operation being performed,
* or nil if there is no operation in progress.<br />
* In conjunction with -webServiceOperation this method can be used to look
* up all the details of the WSDL definition of the operation being
* performed.
*/
- (GWSPort*) webServicePort;
@end
/**
* Delegates should implement this method in order to be informed of
* the success or failure of an XMLRPC method call which was initiated
* by the -sendRequest:parameters:order:timeout: method.<br />
*/
@interface GWSService (Delegate)
/** <override-dummy />
* Called by the sender when an RPC method call completes (either success
* or failure).
* The delegate may then call the -result method to retrieve the result of
* the method call from the sender.
*/
- (void) completedRPC: (GWSService*)sender;
/** This method informs the delegate that the service is about to configure
* itsself to build the request data for a request (by calling the
* -buildRequest:parameters:order: method). If the delegate method returns
* an NSData object, the request will not be built and the returned object
* will be used instead. If the delegate method returns nil, the normal
* request build will go ahead.
*/
- (NSData*) webService: (GWSService*)service
buildRequest: (NSString*)method
parameters: (NSDictionary*)parameters
order: (NSArray*)order;
/** This method is used to inform the delegate of the encoded XML request
* (a [GWSElement] instance) which will be sent to the remote system.<br />
* The delegate may modify or replace this and must return the replacement
* value or the modified element tree.
*/
- (GWSElement*) webService: (GWSService*)service
didEncode: (GWSElement*)element;
/** This method informs the delegate that the service is about to parse
* response data from the remote system and place the results in a
* mutable dictionary.<br />
* If the delegate method returns nil, the response data will be processed
* as normal, otherwise the delegate is reponsible for the parsing of the
* data and production of the results dictionary.
*/
- (NSMutableDictionary*) webService: (GWSService*)service
handleResponse: (NSData*)response;
/** This method is used to inform the delegate of the
* GWSElement instance being decoded as the SOAP Envelope, Header, Body,
* Fault or Method.<br />
* The instance to be decoded will contain the children from the
* document being decoded.<br />
* The delegate implementation should return the proposed instance
* (possibly modified) or a different object that it wishes the
* coder to use.
*/
- (GWSElement*) webService: (GWSService*)service
willDecode: (GWSElement*)element;
/** This method is used to inform the delegate of the proposed
* [GWSElement] instance used to encode SOAP Envelope, Header, Body, Fault
* or Method elements.<br />
* The proposed instance will not have any children at the point
* where this method is called (they are added later in the
* encoding process.<br />
* This method may be called with a nil value for the element parameter in
* the case where no Header element would be encoded ... in this situation
* the delegate may return a Header element to be used, or may return some
* other element, which will be automatically inserted into a standard
* header.<br />
* The delegate implementation should return the proposed instance
* (possibly modified) or a different object that it wishes the
* coder to encode instead.<br />
* The default implementation returns element.<br />
* NB. A Fault or Method will obviously only be provided where the message
* contain such an element, and the Header will only be provided where
* the message has been told to contain headers by use of the
* <ref type="constant" id="GWSSOAPMessageHeadersKey">
* GWSSOAPMessageHeadersKey</ref> in the parameters dictionary.
*/
- (GWSElement*) webService: (GWSService*)service
willEncode: (GWSElement*)element;
/** <override-dummy />
* Called by the sender when it is about to handle response data from a
* remote server. The delegate may return a different data item to be
* decoded and/or take this opportunity to change the service settings
* before the response is handled.
*/
- (NSData*) webService: (GWSService*)sender willHandleResponse: (NSData*)data;
/** <override-dummy />
* Called by the sender when it is about to send an encoded request to a
* remote server. The delegate may return a different data item to be
* sent and/or take this opportunity to change the service settings
* (such as the URL to send to) before the data is actualy sent.
*/
- (NSData*) webService: (GWSService*)sender willSendRequest: (NSData*)data;
@end
#if defined(__cplusplus)
}
#endif
#endif