iCuke 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/.gitmodules +1 -1
  2. data/Gemfile +12 -0
  3. data/Gemfile.lock +41 -0
  4. data/README.markdown +126 -0
  5. data/Rakefile +34 -12
  6. data/VERSION +1 -1
  7. data/bin/icuke +12 -10
  8. data/ext/Rakefile +6 -0
  9. data/ext/iCuke/{sdk3.1/DefaultsResponse.h → DefaultsResponse.h} +0 -0
  10. data/ext/iCuke/{sdk3.1/DefaultsResponse.m → DefaultsResponse.m} +0 -0
  11. data/ext/iCuke/{sdk3.1/EventResponse.h → EventResponse.h} +0 -0
  12. data/ext/iCuke/{sdk3.1/EventResponse.m → EventResponse.m} +0 -0
  13. data/ext/iCuke/{sdk3.1/ModuleResponse.h → ModuleResponse.h} +0 -0
  14. data/ext/iCuke/{sdk3.1/ModuleResponse.m → ModuleResponse.m} +0 -0
  15. data/ext/iCuke/{sdk3.1/QuitResponse.h → QuitResponse.h} +0 -0
  16. data/ext/iCuke/{sdk3.1/QuitResponse.m → QuitResponse.m} +0 -0
  17. data/ext/iCuke/Rakefile +14 -13
  18. data/ext/iCuke/{sdk3.1/Recorder.h → Recorder.h} +0 -0
  19. data/ext/iCuke/{sdk3.1/Recorder.m → Recorder.m} +0 -0
  20. data/ext/iCuke/{sdk3.1/RecorderResponse.h → RecorderResponse.h} +0 -0
  21. data/ext/iCuke/{sdk3.1/RecorderResponse.m → RecorderResponse.m} +0 -0
  22. data/ext/iCuke/{sdk3.1/SynthesizeSingleton.h → SynthesizeSingleton.h} +0 -0
  23. data/ext/iCuke/{sdk3.1/ViewResponse.h → ViewResponse.h} +0 -0
  24. data/ext/iCuke/{sdk3.1/ViewResponse.m → ViewResponse.m} +0 -0
  25. data/ext/iCuke/{sdk3.1/Viewer.h → Viewer.h} +0 -0
  26. data/ext/iCuke/{sdk4.0/Viewer.m → Viewer.m} +0 -0
  27. data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.h → iCukeHTTPResponseHandler.h} +0 -0
  28. data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.m → iCukeHTTPResponseHandler.m} +0 -0
  29. data/ext/iCuke/{sdk3.1/iCukeHTTPServer.h → iCukeHTTPServer.h} +0 -0
  30. data/ext/iCuke/{sdk4.0/iCukeHTTPServer.m → iCukeHTTPServer.m} +4 -2
  31. data/ext/iCuke/{sdk3.1/iCukeServer.h → iCukeServer.h} +0 -0
  32. data/ext/iCuke/{sdk3.1/iCukeServer.m → iCukeServer.m} +0 -0
  33. data/ext/iCuke/{sdk3.1/json → json}/JSON.h +0 -0
  34. data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.h +0 -0
  35. data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.m +0 -0
  36. data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.h +0 -0
  37. data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.m +0 -0
  38. data/ext/iCuke/{sdk3.1/json → json}/SBJSON.h +0 -0
  39. data/ext/iCuke/{sdk3.1/json → json}/SBJSON.m +0 -0
  40. data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.h +0 -0
  41. data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.m +0 -0
  42. data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.h +0 -0
  43. data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.m +0 -0
  44. data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.h +0 -0
  45. data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.m +0 -0
  46. data/features/starting_project.feature +18 -0
  47. data/features/step_definitions/shell.rb +41 -0
  48. data/features/support/env.rb +2 -0
  49. data/features/support/environment.rb +40 -0
  50. data/features/supported_sdks.feature +12 -0
  51. data/iCuke.gemspec +149 -161
  52. data/lib/icuke/configuration.rb +19 -0
  53. data/lib/icuke/core_ext.rb +27 -0
  54. data/lib/icuke/cucumber.rb +29 -265
  55. data/lib/icuke/cucumber_compat.rb +4 -0
  56. data/lib/icuke/icuke_world.rb +149 -0
  57. data/lib/icuke/sdk.rb +5 -13
  58. data/lib/icuke/simulator_driver.rb +201 -0
  59. data/lib/icuke/waxsim.rb +47 -9
  60. data/spec/cucumber_spec.rb +130 -0
  61. data/spec/fixtures/controls_page.xml +252 -0
  62. data/spec/process_spec.rb +76 -0
  63. data/spec/screen_spec.rb +173 -0
  64. data/spec/simulate_spec.rb +75 -0
  65. data/spec/simulator_spec.rb +28 -0
  66. data/spec/spec.opts +2 -0
  67. data/spec/spec_helper.rb +67 -0
  68. metadata +222 -121
  69. data/.gitignore +0 -15
  70. data/README.rdoc +0 -68
  71. data/ext/WaxSim/Simulator.h +0 -31
  72. data/ext/WaxSim/Simulator.m +0 -131
  73. data/ext/WaxSim/WaxSim.m +0 -110
  74. data/ext/WaxSim/WaxSim.xcodeproj/project.pbxproj +0 -238
  75. data/ext/WaxSim/WaxSim_Prefix.pch +0 -7
  76. data/ext/WaxSim/build/Release/waxsim +0 -0
  77. data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Info.plist +0 -20
  78. data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Resources/DWARF/waxsim +0 -0
  79. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/Simulator.o +0 -0
  80. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/WaxSim.o +0 -0
  81. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/waxsim.LinkFileList +0 -2
  82. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim.dep +0 -6
  83. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim~.dep +0 -6
  84. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state.dat +0 -227
  85. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state~.dat +0 -227
  86. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-all-target-headers.hmap +0 -0
  87. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-generated-files.hmap +0 -0
  88. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-own-target-headers.hmap +0 -0
  89. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-project-headers.hmap +0 -0
  90. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim.hmap +0 -0
  91. data/ext/WaxSim/iPhoneSimulatorRemoteClient/iPhoneSimulatorRemoteClient.h +0 -126
  92. data/ext/iCuke/sdk3.1/Rakefile +0 -20
  93. data/ext/iCuke/sdk3.1/Viewer.m +0 -203
  94. data/ext/iCuke/sdk3.1/iCukeHTTPServer.m +0 -365
  95. data/ext/iCuke/sdk4.0/DefaultsResponse.h +0 -5
  96. data/ext/iCuke/sdk4.0/DefaultsResponse.m +0 -66
  97. data/ext/iCuke/sdk4.0/EventResponse.h +0 -5
  98. data/ext/iCuke/sdk4.0/EventResponse.m +0 -130
  99. data/ext/iCuke/sdk4.0/ModuleResponse.h +0 -5
  100. data/ext/iCuke/sdk4.0/ModuleResponse.m +0 -76
  101. data/ext/iCuke/sdk4.0/QuitResponse.h +0 -5
  102. data/ext/iCuke/sdk4.0/QuitResponse.m +0 -23
  103. data/ext/iCuke/sdk4.0/Rakefile +0 -20
  104. data/ext/iCuke/sdk4.0/Recorder.h +0 -17
  105. data/ext/iCuke/sdk4.0/Recorder.m +0 -90
  106. data/ext/iCuke/sdk4.0/RecorderResponse.h +0 -6
  107. data/ext/iCuke/sdk4.0/RecorderResponse.m +0 -68
  108. data/ext/iCuke/sdk4.0/SynthesizeSingleton.h +0 -68
  109. data/ext/iCuke/sdk4.0/ViewResponse.h +0 -5
  110. data/ext/iCuke/sdk4.0/ViewResponse.m +0 -84
  111. data/ext/iCuke/sdk4.0/Viewer.h +0 -8
  112. data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.h +0 -50
  113. data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.m +0 -381
  114. data/ext/iCuke/sdk4.0/iCukeHTTPServer.h +0 -53
  115. data/ext/iCuke/sdk4.0/iCukeServer.h +0 -14
  116. data/ext/iCuke/sdk4.0/iCukeServer.m +0 -65
  117. data/ext/iCuke/sdk4.0/json/JSON.h +0 -50
  118. data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.h +0 -68
  119. data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.m +0 -53
  120. data/ext/iCuke/sdk4.0/json/NSString+SBJSON.h +0 -58
  121. data/ext/iCuke/sdk4.0/json/NSString+SBJSON.m +0 -55
  122. data/ext/iCuke/sdk4.0/json/SBJSON.h +0 -75
  123. data/ext/iCuke/sdk4.0/json/SBJSON.m +0 -212
  124. data/ext/iCuke/sdk4.0/json/SBJsonBase.h +0 -86
  125. data/ext/iCuke/sdk4.0/json/SBJsonBase.m +0 -78
  126. data/ext/iCuke/sdk4.0/json/SBJsonParser.h +0 -87
  127. data/ext/iCuke/sdk4.0/json/SBJsonParser.m +0 -475
  128. data/ext/iCuke/sdk4.0/json/SBJsonWriter.h +0 -129
  129. data/ext/iCuke/sdk4.0/json/SBJsonWriter.m +0 -228
@@ -1,6 +0,0 @@
1
- #import "iCukeHTTPResponseHandler.h"
2
-
3
- @interface RecorderResponse : iCukeHTTPResponseHandler {
4
- }
5
- - (void)finishResponse;
6
- @end
@@ -1,68 +0,0 @@
1
- #import "RecorderResponse.h"
2
- #import "iCukeHTTPServer.h"
3
- #import "Recorder.h"
4
-
5
- @implementation RecorderResponse
6
- + (void)load
7
- {
8
- [iCukeHTTPResponseHandler registerHandler:self];
9
- }
10
-
11
- + (BOOL)canHandleRequest:(CFHTTPMessageRef)aRequest
12
- method:(NSString *)requestMethod
13
- url:(NSURL *)requestURL
14
- headerFields:(NSDictionary *)requestHeaderFields
15
- {
16
- if ([requestURL.path isEqualToString:@"/record"] ||
17
- [requestURL.path isEqualToString:@"/play"] ||
18
- [requestURL.path isEqualToString:@"/load"] ||
19
- [requestURL.path isEqualToString:@"/save"] ||
20
- [requestURL.path isEqualToString:@"/stop"])
21
- return YES;
22
-
23
- return NO;
24
- }
25
-
26
- - (void)startResponse
27
- {
28
- if ([url.path isEqualToString:@"/record"]) {
29
- [[Recorder sharedRecorder] record];
30
- [self finishResponse];
31
- } else if ([url.path isEqualToString:@"/play"]) {
32
- [[Recorder sharedRecorder] playbackWithDelegate: self doneSelector: @selector(finishResponse)];
33
- } else if ([url.path isEqualToString:@"/load"]) {
34
- [[Recorder sharedRecorder] loadFromFile: [[url query] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
35
- [self finishResponse];
36
- } else if ([url.path isEqualToString:@"/save"]) {
37
- [[Recorder sharedRecorder] saveToFile: [[url query] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
38
- [self finishResponse];
39
- } else if ([url.path isEqualToString:@"/stop"]) {
40
- [[Recorder sharedRecorder] stop];
41
- [self finishResponse];
42
- }
43
-
44
- }
45
-
46
- - (void)finishResponse
47
- {
48
- CFHTTPMessageRef response = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
49
- CFHTTPMessageSetHeaderFieldValue(response, (CFStringRef)@"Connection", (CFStringRef)@"close");
50
- CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
51
-
52
- @try
53
- {
54
- [fileHandle writeData:(NSData *)headerData];
55
- }
56
- @catch (NSException *exception)
57
- {
58
- // Ignore the exception, it normally just means the client
59
- // closed the connection from the other end.
60
- }
61
- @finally
62
- {
63
- CFRelease(headerData);
64
- [server closeHandler:self];
65
- }
66
- }
67
-
68
- @end
@@ -1,68 +0,0 @@
1
- //
2
- // SynthesizeSingleton.h
3
- // iTrackSportsBets
4
- //
5
- // Created by Matt Gallagher on 20/10/08.
6
- // Copyright 2008 Matt Gallagher. All rights reserved.
7
- //
8
- // Permission is given to use this source code file, free of charge, in any
9
- // project, commercial or otherwise, entirely at your risk, with the condition
10
- // that any redistribution (in part or whole) of source code must retain
11
- // this copyright and permission notice. Attribution in compiled projects is
12
- // appreciated but not required.
13
- //
14
-
15
- #define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
16
- \
17
- static classname *shared##classname = nil; \
18
- \
19
- + (classname *)shared##classname \
20
- { \
21
- @synchronized(self) \
22
- { \
23
- if (shared##classname == nil) \
24
- { \
25
- shared##classname = [[self alloc] init]; \
26
- } \
27
- } \
28
- \
29
- return shared##classname; \
30
- } \
31
- \
32
- + (id)allocWithZone:(NSZone *)zone \
33
- { \
34
- @synchronized(self) \
35
- { \
36
- if (shared##classname == nil) \
37
- { \
38
- shared##classname = [super allocWithZone:zone]; \
39
- return shared##classname; \
40
- } \
41
- } \
42
- \
43
- return nil; \
44
- } \
45
- \
46
- - (id)copyWithZone:(NSZone *)zone \
47
- { \
48
- return self; \
49
- } \
50
- \
51
- - (id)retain \
52
- { \
53
- return self; \
54
- } \
55
- \
56
- - (NSUInteger)retainCount \
57
- { \
58
- return NSUIntegerMax; \
59
- } \
60
- \
61
- - (void)release \
62
- { \
63
- } \
64
- \
65
- - (id)autorelease \
66
- { \
67
- return self; \
68
- }
@@ -1,5 +0,0 @@
1
- #import "iCukeHTTPResponseHandler.h"
2
-
3
- @interface ViewResponse : iCukeHTTPResponseHandler {
4
- }
5
- @end
@@ -1,84 +0,0 @@
1
- #import "ViewResponse.h"
2
- #import "iCukeHTTPServer.h"
3
- #import "Viewer.h"
4
-
5
- // AX API
6
- extern Boolean AXAPIEnabled(void);
7
-
8
- @implementation ViewResponse
9
- + (void)load
10
- {
11
- [iCukeHTTPResponseHandler registerHandler:self];
12
- }
13
-
14
- + (BOOL)canHandleRequest:(CFHTTPMessageRef)aRequest
15
- method:(NSString *)requestMethod
16
- url:(NSURL *)requestURL
17
- headerFields:(NSDictionary *)requestHeaderFields
18
- {
19
- return [requestURL.path isEqualToString:@"/view"];
20
- }
21
-
22
- - (void)startResponse
23
- {
24
- if (!AXAPIEnabled()) {
25
- CFHTTPMessageRef response =
26
- CFHTTPMessageCreateResponse(
27
- kCFAllocatorDefault, 500, NULL, kCFHTTPVersion1_1);
28
- CFHTTPMessageSetHeaderFieldValue(
29
- response, (CFStringRef)@"Content-Type", (CFStringRef)@"text/plain");
30
- CFHTTPMessageSetHeaderFieldValue(
31
- response, (CFStringRef)@"Connection", (CFStringRef)@"close");
32
- CFHTTPMessageSetBody(
33
- response,
34
- (CFDataRef)[[NSString stringWithFormat:
35
- @"Accessiblity Inspector Disabled: "
36
- @"Please enable the accessibilty inspector in the simulator and retry"]
37
- dataUsingEncoding:NSUTF8StringEncoding]);
38
- CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
39
- @try
40
- {
41
- [fileHandle writeData:(NSData *)headerData];
42
- }
43
- @catch (NSException *exception)
44
- {
45
- // Ignore the exception, it normally just means the client
46
- // closed the connection from the other end.
47
- }
48
- @finally
49
- {
50
- CFRelease(headerData);
51
- CFRelease(response);
52
- [server closeHandler:self];
53
- }
54
-
55
- return;
56
- }
57
-
58
- CFHTTPMessageRef response = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
59
- CFHTTPMessageSetHeaderFieldValue(response, (CFStringRef)@"Content-Type", (CFStringRef)@"text/xml");
60
- CFHTTPMessageSetHeaderFieldValue(response, (CFStringRef)@"Connection", (CFStringRef)@"close");
61
-
62
- NSData *viewData = [[[Viewer sharedViewer] screen] dataUsingEncoding:NSUTF8StringEncoding];
63
-
64
- CFHTTPMessageSetHeaderFieldValue(response, (CFStringRef)@"Content-Length",
65
- (CFStringRef)[NSString stringWithFormat:@"%ld", [viewData length]]);
66
- CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
67
-
68
- @try
69
- {
70
- [fileHandle writeData:(NSData *)headerData];
71
- [fileHandle writeData:viewData];
72
- }
73
- @catch (NSException *exception)
74
- {
75
- // Ignore the exception, it normally just means the client
76
- // closed the connection from the other end.
77
- }
78
- @finally
79
- {
80
- CFRelease(headerData);
81
- [server closeHandler:self];
82
- }
83
- }
84
- @end
@@ -1,8 +0,0 @@
1
- #import <Foundation/Foundation.h>
2
-
3
- @interface Viewer : NSObject
4
-
5
- +(Viewer*)sharedViewer;
6
- -(NSString*)screen;
7
-
8
- @end
@@ -1,50 +0,0 @@
1
- //
2
- // HTTPResponseHandler.h
3
- // TextTransfer
4
- //
5
- // Created by Matt Gallagher on 2009/07/13.
6
- // Copyright 2009 Matt Gallagher. All rights reserved.
7
- //
8
- // Permission is given to use this source code file, free of charge, in any
9
- // project, commercial or otherwise, entirely at your risk, with the condition
10
- // that any redistribution (in part or whole) of source code must retain
11
- // this copyright and permission notice. Attribution in compiled projects is
12
- // appreciated but not required.
13
- //
14
-
15
- #if TARGET_OS_IPHONE
16
- #import <UIKit/UIKit.h>
17
- #import <CFNetwork/CFNetwork.h>
18
- #else
19
- #import <Cocoa/Cocoa.h>
20
- #endif
21
-
22
- @class iCukeHTTPServer;
23
-
24
- @interface iCukeHTTPResponseHandler : NSObject
25
- {
26
- CFHTTPMessageRef request;
27
- NSString *requestMethod;
28
- NSDictionary *headerFields;
29
- NSFileHandle *fileHandle;
30
- iCukeHTTPServer *server;
31
- NSURL *url;
32
- }
33
-
34
- + (NSUInteger)priority;
35
- + (void)registerHandler:(Class)handlerClass;
36
-
37
- + (iCukeHTTPResponseHandler *)handlerForRequest:(CFHTTPMessageRef)aRequest
38
- fileHandle:(NSFileHandle *)requestFileHandle
39
- server:(iCukeHTTPServer *)aServer;
40
-
41
- - (id)initWithRequest:(CFHTTPMessageRef)aRequest
42
- method:(NSString *)method
43
- url:(NSURL *)requestURL
44
- headerFields:(NSDictionary *)requestHeaderFields
45
- fileHandle:(NSFileHandle *)requestFileHandle
46
- server:(iCukeHTTPServer *)aServer;
47
- - (void)startResponse;
48
- - (void)endResponse;
49
-
50
- @end
@@ -1,381 +0,0 @@
1
- //
2
- // HTTPResponseHandler.m
3
- // TextTransfer
4
- //
5
- // Created by Matt Gallagher on 2009/07/13.
6
- // Copyright 2009 Matt Gallagher. All rights reserved.
7
- //
8
- // Permission is given to use this source code file, free of charge, in any
9
- // project, commercial or otherwise, entirely at your risk, with the condition
10
- // that any redistribution (in part or whole) of source code must retain
11
- // this copyright and permission notice. Attribution in compiled projects is
12
- // appreciated but not required.
13
- //
14
-
15
- #import "iCukeHTTPResponseHandler.h"
16
- #import "iCukeHTTPServer.h"
17
- #import "ViewResponse.h"
18
-
19
- @implementation iCukeHTTPResponseHandler
20
-
21
- static NSMutableArray *registeredHandlers = nil;
22
-
23
- //
24
- // priority
25
- //
26
- // The priority determines which request handlers are given the option to
27
- // handle a request first. The highest number goes first, with the base class
28
- // (HTTPResponseHandler) implementing a 501 error response at priority 0
29
- // (the lowest priorty).
30
- //
31
- // Even if subclasses have a 0 priority, they will always receive precedence
32
- // over the base class, since the base class' implementation is intended as
33
- // an error condition only.
34
- //
35
- // returns the priority.
36
- //
37
- + (NSUInteger)priority
38
- {
39
- return 0;
40
- }
41
-
42
- //
43
- // load
44
- //
45
- // Implementing the load method and invoking
46
- // [HTTPResponseHandler registerHandler:self] causes HTTPResponseHandler
47
- // to register this class in the list of registered HTTP response handlers.
48
- //
49
- + (void)load
50
- {
51
- [iCukeHTTPResponseHandler registerHandler:self];
52
- }
53
-
54
- //
55
- // registerHandler:
56
- //
57
- // Inserts the HTTPResponseHandler class into the priority list.
58
- //
59
- + (void)registerHandler:(Class)handlerClass
60
- {
61
- if (registeredHandlers == nil)
62
- {
63
- registeredHandlers = [[NSMutableArray alloc] init];
64
- }
65
-
66
- NSUInteger i;
67
- NSUInteger count = [registeredHandlers count];
68
- for (i = 0; i < count; i++)
69
- {
70
- if ([handlerClass priority] >= [[registeredHandlers objectAtIndex:i] priority])
71
- {
72
- break;
73
- }
74
- }
75
- [registeredHandlers insertObject:handlerClass atIndex:i];
76
- }
77
-
78
- //
79
- // canHandleRequest:method:url:headerFields:
80
- //
81
- // Class method to determine if the response handler class can handle
82
- // a given request.
83
- //
84
- // Parameters:
85
- // aRequest - the request
86
- // requestMethod - the request method
87
- // requestURL - the request URL
88
- // requestHeaderFields - the request headers
89
- //
90
- // returns YES (if the handler can handle the request), NO (otherwise)
91
- //
92
- + (BOOL)canHandleRequest:(CFHTTPMessageRef)aRequest
93
- method:(NSString *)requestMethod
94
- url:(NSURL *)requestURL
95
- headerFields:(NSDictionary *)requestHeaderFields
96
- {
97
- return YES;
98
- }
99
-
100
- //
101
- // handlerClassForRequest:method:url:headerFields:
102
- //
103
- // Important method to edit for your application.
104
- //
105
- // This method determines (from the HTTP request message, URL and headers)
106
- // which
107
- //
108
- // Parameters:
109
- // aRequest - the CFHTTPMessageRef, with data at least as far as the end
110
- // of the headers
111
- // requestMethod - the request method (GET, POST, PUT, DELETE etc)
112
- // requestURL - the URL (likely only contains a path)
113
- // requestHeaderFields - the parsed header fields
114
- //
115
- // returns the class to handle the request, or nil if no handler exists.
116
- //
117
- + (Class)handlerClassForRequest:(CFHTTPMessageRef)aRequest
118
- method:(NSString *)requestMethod
119
- url:(NSURL *)requestURL
120
- headerFields:(NSDictionary *)requestHeaderFields
121
- {
122
- for (Class handlerClass in registeredHandlers)
123
- {
124
- if ([handlerClass canHandleRequest:aRequest
125
- method:requestMethod
126
- url:requestURL
127
- headerFields:requestHeaderFields])
128
- {
129
- return handlerClass;
130
- }
131
- }
132
-
133
- return nil;
134
- }
135
-
136
- //
137
- // handleRequest:fileHandle:server:
138
- //
139
- // This method parses the request method and header components, invokes
140
- // +[handlerClassForRequest:method:url:headerFields:] to determine a handler
141
- // class (if any) and creates the handler.
142
- //
143
- // Parameters:
144
- // aRequest - the CFHTTPMessageRef request requiring a response
145
- // requestFileHandle - the file handle for the incoming request (still
146
- // open and possibly receiving data) and for the outgoing response
147
- // aServer - the server that is invoking us
148
- //
149
- // returns the initialized handler (if one can handle the request) or nil
150
- // (if no valid handler exists).
151
- //
152
- + (iCukeHTTPResponseHandler *)handlerForRequest:(CFHTTPMessageRef)aRequest
153
- fileHandle:(NSFileHandle *)requestFileHandle
154
- server:(iCukeHTTPServer *)aServer
155
- {
156
- NSDictionary *requestHeaderFields =
157
- [(NSDictionary *)CFHTTPMessageCopyAllHeaderFields(aRequest)
158
- autorelease];
159
- NSURL *requestURL =
160
- [(NSURL *)CFHTTPMessageCopyRequestURL(aRequest) autorelease];
161
- NSString *method =
162
- [(NSString *)CFHTTPMessageCopyRequestMethod(aRequest)
163
- autorelease];
164
-
165
- Class classForRequest =
166
- [self handlerClassForRequest:aRequest
167
- method:method
168
- url:requestURL
169
- headerFields:requestHeaderFields];
170
-
171
- iCukeHTTPResponseHandler *handler =
172
- [[[classForRequest alloc]
173
- initWithRequest:aRequest
174
- method:method
175
- url:requestURL
176
- headerFields:requestHeaderFields
177
- fileHandle:requestFileHandle
178
- server:aServer]
179
- autorelease];
180
-
181
- return handler;
182
- }
183
-
184
- //
185
- // initWithRequest:method:url:headerFields:fileHandle:server:
186
- //
187
- // Init method for the handler. This method is mostly just a value copy operation
188
- // so that the parts of the request don't need to be reparsed.
189
- //
190
- // Parameters:
191
- // aRequest - the CFHTTPMessageRef
192
- // method - the request method
193
- // requestURL - the URL
194
- // requestHeaderFields - the CFHTTPMessageRef header fields
195
- // requestFileHandle - the incoming request file handle, also used for
196
- // the outgoing response.
197
- // aServer - the server that spawned us
198
- //
199
- // returns the initialized object
200
- //
201
- - (id)initWithRequest:(CFHTTPMessageRef)aRequest
202
- method:(NSString *)method
203
- url:(NSURL *)requestURL
204
- headerFields:(NSDictionary *)requestHeaderFields
205
- fileHandle:(NSFileHandle *)requestFileHandle
206
- server:(iCukeHTTPServer *)aServer
207
- {
208
- self = [super init];
209
- if (self != nil)
210
- {
211
- request = (CFHTTPMessageRef)[(id)aRequest retain];
212
- requestMethod = [method retain];
213
- url = [requestURL retain];
214
- headerFields = [requestHeaderFields retain];
215
- fileHandle = [requestFileHandle retain];
216
- server = [aServer retain];
217
-
218
- [[NSNotificationCenter defaultCenter]
219
- addObserver:self
220
- selector:@selector(receiveIncomingDataNotification:)
221
- name:NSFileHandleDataAvailableNotification
222
- object:fileHandle];
223
-
224
- [fileHandle waitForDataInBackgroundAndNotify];
225
- }
226
- return self;
227
- }
228
-
229
- //
230
- // startResponse
231
- //
232
- // Begin sending a response over the fileHandle. Trivial cases can
233
- // synchronously return a response but everything else should spawn a thread
234
- // or otherwise asynchronously start returning the response data.
235
- //
236
- // THIS IS THE PRIMARY METHOD FOR SUBCLASSES TO OVERRIDE. YOU DO NOT NEED
237
- // TO INVOKE SUPER FOR THIS METHOD.
238
- //
239
- // This method should only be invoked from HTTPServer (it needs to add the
240
- // object to its responseHandlers before this method is invoked).
241
- //
242
- // [server closeHandler:self] should be invoked when done sending data.
243
- //
244
- - (void)startResponse
245
- {
246
- CFHTTPMessageRef response =
247
- CFHTTPMessageCreateResponse(
248
- kCFAllocatorDefault, 501, NULL, kCFHTTPVersion1_1);
249
- CFHTTPMessageSetHeaderFieldValue(
250
- response, (CFStringRef)@"Content-Type", (CFStringRef)@"text/plain");
251
- CFHTTPMessageSetHeaderFieldValue(
252
- response, (CFStringRef)@"Connection", (CFStringRef)@"close");
253
- CFHTTPMessageSetBody(
254
- response,
255
- (CFDataRef)[[NSString stringWithFormat:
256
- @"No handler exists to handle %@.",
257
- [url absoluteString]]
258
- dataUsingEncoding:NSUTF8StringEncoding]);
259
- CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
260
- @try
261
- {
262
- [fileHandle writeData:(NSData *)headerData];
263
- }
264
- @catch (NSException *exception)
265
- {
266
- // Ignore the exception, it normally just means the client
267
- // closed the connection from the other end.
268
- }
269
- @finally
270
- {
271
- CFRelease(headerData);
272
- CFRelease(response);
273
- [server closeHandler:self];
274
- }
275
- }
276
-
277
- //
278
- // endResponse
279
- //
280
- // Closes the outgoing file handle.
281
- //
282
- // You should not invoke this method directly. It should only be invoked from
283
- // HTTPServer (it needs to remove the object from its responseHandlers before
284
- // this method is invoked). To close a reponse handler, use
285
- // [server closeHandler:responseHandler].
286
- //
287
- // Subclasses should stop any other activity when this method is invoked and
288
- // invoke super to close the file handle.
289
- //
290
- // If the connection is persistent, you must set fileHandle to nil (without
291
- // closing the file) to prevent the connection getting closed by this method.
292
- //
293
- - (void)endResponse
294
- {
295
- if (fileHandle)
296
- {
297
- [[NSNotificationCenter defaultCenter]
298
- removeObserver:self
299
- name:NSFileHandleDataAvailableNotification
300
- object:fileHandle];
301
- [fileHandle closeFile];
302
- [fileHandle release];
303
- fileHandle = nil;
304
- }
305
-
306
- [server release];
307
- server = nil;
308
- }
309
-
310
- //
311
- // receiveIncomingDataNotification:
312
- //
313
- // Continues to receive incoming data for the connection. Remember that the
314
- // first data past the end of the headers may already have been read into
315
- // the request.
316
- //
317
- // Override this method to read the complete HTTP Request Body. This is a
318
- // complicated process if you want to handle both Content-Length and all common
319
- // Transfer-Encodings, so I haven't implemented it.
320
- //
321
- // If you want to handle persistent connections, you would need careful handling
322
- // to determine the end of the request, seek the fileHandle so it points
323
- // to the byte immediately after then end of this request, and then send an
324
- // NSFileHandleConnectionAcceptedNotification notification with the fileHandle
325
- // as the NSFileHandleNotificationFileHandleItem in the userInfo dictionary
326
- // back to the server to handle the fileHandle as a new incoming request again
327
- // (before setting fileHandle to nil so the connection won't get closed when this
328
- // handler ends).
329
- //
330
- // Parameters:
331
- // notification - notification that more data is available
332
- //
333
- - (void)receiveIncomingDataNotification:(NSNotification *)notification
334
- {
335
- NSFileHandle *incomingFileHandle = [notification object];
336
- NSData *data = [incomingFileHandle availableData];
337
-
338
- if ([data length] == 0)
339
- {
340
- [server closeHandler:self];
341
- }
342
-
343
- //
344
- // This is a default implementation and simply ignores all data.
345
- // If you need the HTTP body, you need to override this method to continue
346
- // accumulating data. Don't forget that new data may need to be combined
347
- // with any HTTP body data that may have already been received in the
348
- // "request" body.
349
- //
350
-
351
- [incomingFileHandle waitForDataInBackgroundAndNotify];
352
- }
353
-
354
- //
355
- // dealloc
356
- //
357
- // Stops the response if still running.
358
- //
359
- - (void)dealloc
360
- {
361
- if (server)
362
- {
363
- [self endResponse];
364
- }
365
-
366
- [(id)request release];
367
- request = nil;
368
-
369
- [requestMethod release];
370
- requestMethod = nil;
371
-
372
- [url release];
373
- url = nil;
374
-
375
- [headerFields release];
376
- headerFields = nil;
377
-
378
- [super dealloc];
379
- }
380
-
381
- @end