clucumber 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +4 -9
  3. data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
  4. data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
  5. data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
  6. data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
  7. data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
  8. data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
  9. data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
  10. data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
  11. data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
  12. data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
  13. data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
  14. data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
  15. data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
  16. data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
  17. data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
  18. data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
  19. data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
  20. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
  21. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
  22. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
  23. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
  24. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
  25. data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
  26. data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
  27. data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
  28. data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
  29. data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
  30. data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
  31. data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
  32. data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
  33. data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
  34. data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
  35. data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
  36. data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
  37. data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
  38. data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
  39. data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
  40. data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
  41. data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
  42. data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
  43. data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
  44. data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
  45. data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
  46. data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
  47. data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
  48. data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
  49. data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
  50. data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
  51. data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
  52. data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
  53. data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
  54. data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
  55. data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
  56. data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
  57. data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
  58. data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
  59. data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
  60. data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
  61. data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
  62. data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
  63. data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
  64. data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
  65. data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
  66. data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
  67. data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
  68. data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
  69. data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
  70. data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
  71. data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
  72. data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
  73. data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
  74. data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
  75. data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
  76. data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
  77. data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
  78. data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
  79. data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
  80. data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
  81. data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
  82. data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
  83. data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
  84. data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
  85. data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
  86. data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
  87. data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
  88. data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
  89. data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
  90. data/lib/clucumber/vendor/lift/lift.asd +77 -0
  91. data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
  92. data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
  93. data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
  94. data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
  95. data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
  96. data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
  97. data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
  98. data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
  99. data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
  100. data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
  101. data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
  102. data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
  103. data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
  104. data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
  105. data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
  106. data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
  107. data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
  108. data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
  109. data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
  110. data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
  111. data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
  112. data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
  113. data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
  114. data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
  115. data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
  116. data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
  117. data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
  118. data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
  119. data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
  120. data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
  121. data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
  122. data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
  123. data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
  124. data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
  125. data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
  126. data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
  127. data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
  128. data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
  129. data/lib/clucumber/vendor/usocket/package.lisp +82 -0
  130. data/lib/clucumber/vendor/usocket/server.lisp +45 -0
  131. data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
  132. data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
  133. data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
  134. data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
  135. data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
  136. data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
  137. data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
  138. data/lib/clucumber.rb +29 -7
  139. metadata +151 -5
@@ -0,0 +1,491 @@
1
+ ;;;; $Id: armedbear.lisp 515 2010-01-07 18:26:06Z ctian $
2
+ ;;;; $URL: svn://common-lisp.net/project/usocket/svn/usocket/trunk/backend/armedbear.lisp $
3
+
4
+ ;;;; See LICENSE for licensing information.
5
+
6
+ (in-package :usocket)
7
+
8
+
9
+ ;;; Proposed contribution to the JAVA package
10
+
11
+ (defpackage :jdi
12
+ (:use :cl)
13
+ (:export #:jcoerce
14
+ #:jop-deref
15
+ #:do-jmethod-call
16
+ #:do-jmethod
17
+ #:do-jstatic-call
18
+ #:do-jstatic
19
+ #:do-jnew-call
20
+ #:do-jfield
21
+ #:jequals))
22
+ ;; but still requires the :java package.
23
+
24
+ (in-package :jdi)
25
+
26
+ (defstruct (java-object-proxy (:conc-name :jop-)
27
+ :copier)
28
+ value
29
+ class)
30
+
31
+ (defvar *jm-get-return-type*
32
+ (java:jmethod "java.lang.reflect.Method" "getReturnType"))
33
+
34
+ (defvar *jf-get-type*
35
+ (java:jmethod "java.lang.reflect.Field" "getType"))
36
+
37
+ (defvar *jc-get-declaring-class*
38
+ (java:jmethod "java.lang.reflect.Constructor" "getDeclaringClass"))
39
+
40
+ (declaim (inline make-return-type-proxy))
41
+ (defun make-return-type-proxy (jmethod jreturned-value)
42
+ (if (java:java-object-p jreturned-value)
43
+ (let ((rt (java:jcall *jm-get-return-type* jmethod)))
44
+ (make-java-object-proxy :value jreturned-value
45
+ :class rt))
46
+ jreturned-value))
47
+
48
+ (defun make-field-type-proxy (jfield jreturned-value)
49
+ (if (java:java-object-p jreturned-value)
50
+ (let ((rt (java:jcall *jf-get-type* jfield)))
51
+ (make-java-object-proxy :value jreturned-value
52
+ :class rt))
53
+ jreturned-value))
54
+
55
+ (defun make-constructor-type-proxy (jconstructor jreturned-value)
56
+ (if (java:java-object-p jreturned-value)
57
+ (let ((rt (java:jcall *jc-get-declaring-class* jconstructor)))
58
+ (make-java-object-proxy :value jreturned-value
59
+ :class rt))
60
+ jreturned-value))
61
+
62
+ (defun jcoerce (instance &optional output-type-spec)
63
+ (cond
64
+ ((java-object-proxy-p instance)
65
+ (let ((new-instance (copy-structure (the java-object-proxy instance))))
66
+ (setf (jop-class new-instance)
67
+ (java:jclass output-type-spec))
68
+ new-instance))
69
+ ((java:java-object-p instance)
70
+ (make-java-object-proxy :class (java:jclass output-type-spec)
71
+ :value instance))
72
+ ((stringp instance)
73
+ (make-java-object-proxy :class "java.lang.String"
74
+ :value instance))
75
+ ((keywordp output-type-spec)
76
+ ;; all that remains is creating an immediate type...
77
+ (let ((jval (java:make-immediate-object instance output-type-spec)))
78
+ (make-java-object-proxy :class output-type-spec
79
+ :value jval)))
80
+ ))
81
+
82
+ (defun jtype-of (instance) ;;instance must be a jop
83
+ (cond
84
+ ((stringp instance)
85
+ "java.lang.String")
86
+ ((keywordp (jop-class instance))
87
+ (string-downcase (symbol-name (jop-class instance))))
88
+ (t
89
+ (java:jclass-name (jop-class instance)))))
90
+
91
+ (declaim (inline jop-deref))
92
+ (defun jop-deref (instance)
93
+ (if (java-object-proxy-p instance)
94
+ (jop-value instance)
95
+ instance))
96
+
97
+ (defun java-value-and-class (object)
98
+ (values (jop-deref object)
99
+ (jtype-of object)))
100
+
101
+ (defun do-jmethod-call (object method-name &rest arguments)
102
+ (multiple-value-bind
103
+ (instance class-name)
104
+ (java-value-and-class object)
105
+ (let* ((argument-types (mapcar #'jtype-of arguments))
106
+ (jm (apply #'java:jmethod class-name method-name argument-types))
107
+ (rv (apply #'java:jcall jm instance
108
+ (mapcar #'jop-deref arguments))))
109
+ (make-return-type-proxy jm rv))))
110
+
111
+ (defun do-jstatic-call (class-name method-name &rest arguments)
112
+ (let* ((argument-types (mapcar #'jtype-of arguments))
113
+ (jm (apply #'java:jmethod class-name method-name argument-types))
114
+ (rv (apply #'java:jstatic jm (java:jclass class-name)
115
+ (mapcar #'jop-deref arguments))))
116
+ (make-return-type-proxy jm rv)))
117
+
118
+ (defun do-jnew-call (class-name &rest arguments)
119
+ (let* ((argument-types (mapcar #'jtype-of arguments))
120
+ (jm (apply #'java:jconstructor class-name argument-types))
121
+ (rv (apply #'java:jnew jm (mapcar #'jop-deref arguments))))
122
+ (make-constructor-type-proxy jm rv)))
123
+
124
+ (defun do-jfield (class-or-instance-or-name field-name)
125
+ (let* ((class (cond
126
+ ((stringp class-or-instance-or-name)
127
+ (java:jclass class-or-instance-or-name))
128
+ ((java:java-object-p class-or-instance-or-name)
129
+ (java:jclass-of class-or-instance-or-name))
130
+ ((java-object-proxy-p class-or-instance-or-name)
131
+ (java:jclass (jtype-of class-or-instance-or-name)))))
132
+ (jf (java:jcall (java:jmethod "java.lang.Class" "getField"
133
+ "java.lang.String")
134
+ class field-name)))
135
+ (make-field-type-proxy jf
136
+ (java:jfield class field-name)))) ;;class))))
137
+
138
+ (defmacro do-jstatic (&rest arguments)
139
+ `(do-jstatic-call ,@arguments))
140
+
141
+ (defmacro do-jmethod (&rest arguments)
142
+ `(do-jmethod-call ,@arguments))
143
+
144
+ ;;
145
+
146
+ (defmacro jstatic-call (class-name (method-name &rest arg-spec)
147
+ &rest args)
148
+ (let ((class-sym (gensym)))
149
+ `(let ((,class-sym ,class-name))
150
+ (java:jstatic
151
+ (java:jmethod ,class-sym ,method-name ,@arg-spec)
152
+ (java:jclass ,class-sym) ,@args))))
153
+
154
+ (defmacro jmethod-call (instance-and-class (method &rest arg-spec) &rest args)
155
+ (let ((isym (gensym)))
156
+ (multiple-value-bind
157
+ (instance class-name)
158
+ (if (listp instance-and-class)
159
+ (values (first instance-and-class)
160
+ (second instance-and-class))
161
+ (values instance-and-class))
162
+ (when (null class-name)
163
+ (setf class-name `(java:jclass-name (java:jclass-of ,isym))))
164
+ `(let* ((,isym ,instance))
165
+ (java:jcall (java:jmethod ,class-name ,method ,@arg-spec)
166
+ ,isym ,@args)))))
167
+
168
+ (defun jequals (x y)
169
+ (do-jmethod-call (jcoerce x "java.lang.Object") "equals"
170
+ (jcoerce y "java.lang.Object")))
171
+
172
+ (defmacro jnew-call ((class &rest arg-spec) &rest args)
173
+ `(java:jnew (java:jconstructor ,class ,@arg-spec)
174
+ ,@args))
175
+
176
+
177
+
178
+ (in-package :usocket)
179
+
180
+ (defun get-host-name ()
181
+ (jdi:do-jmethod-call (jdi:do-jstatic-call "java.net.InetAddress"
182
+ "getLocalHost")
183
+ "getHostName"))
184
+
185
+ (defun handle-condition (condition &optional socket)
186
+ (typecase condition
187
+ (error (error 'unknown-error :socket socket :real-error condition))))
188
+
189
+ (defun socket-connect (host port &key (protocol :stream) (element-type 'character)
190
+ timeout deadline (nodelay nil nodelay-specified)
191
+ local-host local-port)
192
+ (when deadline (unsupported 'deadline 'socket-connect))
193
+
194
+ (let ((usock))
195
+ (with-mapped-conditions (usock)
196
+ (let* ((sock-addr (when (and host port)
197
+ (jdi:jcoerce
198
+ (jdi:do-jnew-call "java.net.InetSocketAddress"
199
+ (host-to-hostname host)
200
+ (jdi:jcoerce port :int))
201
+ "java.net.SocketAddress")))
202
+ (local-addr (when (or local-host local-port)
203
+ (jdi:jcoerce
204
+ (jdi:do-jnew-call "java.net.InetSocketAddress"
205
+ (host-to-hostname (or host *wildcard-host*))
206
+ (jdi:jcoerce (or port *auto-port*) :int))
207
+ "java.net.SocketAddress")))
208
+ (jchan (jdi:do-jstatic-call (ecase protocol
209
+ (:stream "java.nio.channels.SocketChannel")
210
+ (:datagram "java.nio.channels.DatagramChannel"))
211
+ "open"))
212
+ (sock (jdi:do-jmethod-call jchan "socket")))
213
+ ;; TODO: Fix it
214
+ (when (or local-host local-port)
215
+ (jdi:do-jmethod-call sock "bind" local-addr))
216
+ (when (and host port)
217
+ (jdi:do-jmethod-call jchan "connect" sock-addr))
218
+ (when (and (eq protocol 'stream) nodelay-specified)
219
+ (jdi:do-jmethod-call sock "setTcpNoDelay"
220
+ (if nodelay
221
+ (java:make-immediate-object t :boolean)
222
+ (java:make-immediate-object nil :boolean))))
223
+ (when timeout
224
+ (jdi:do-jmethod-call sock "setSoTimeout"
225
+ (truncate (* 1000 timeout))))
226
+ (setf usock
227
+ (ecase protocol
228
+ (:stream
229
+ (make-stream-socket
230
+ :socket jchan
231
+ :stream (ext:get-socket-stream (jdi:jop-deref sock)
232
+ :element-type element-type)))
233
+ (:datagram
234
+ (make-datagram-socket jchan))))))))
235
+
236
+ (defun socket-listen (host port
237
+ &key reuseaddress
238
+ (reuse-address nil reuse-address-supplied-p)
239
+ (backlog 5)
240
+ (element-type 'character))
241
+ (let* ((reuseaddress (if reuse-address-supplied-p reuse-address reuseaddress))
242
+ (sock-addr (jdi:do-jnew-call "java.net.InetSocketAddress"
243
+ (host-to-hostname host)
244
+ (jdi:jcoerce port :int)))
245
+ (chan (jdi:do-jstatic-call "java.nio.channels.ServerSocketChannel"
246
+ "open"))
247
+ (sock (jdi:do-jmethod-call chan "socket")))
248
+ (when reuseaddress
249
+ (with-mapped-conditions ()
250
+ (jdi:do-jmethod-call sock
251
+ "setReuseAddress"
252
+ (jdi:jcoerce reuseaddress :boolean))))
253
+ (with-mapped-conditions ()
254
+ (jdi:do-jmethod-call sock
255
+ "bind"
256
+ (jdi:jcoerce sock-addr
257
+ "java.net.SocketAddress")
258
+ (jdi:jcoerce backlog :int)))
259
+ (make-stream-server-socket chan :element-type element-type)))
260
+
261
+ (defmethod socket-accept ((socket stream-server-usocket) &key element-type)
262
+ (let* ((jsock (socket socket))
263
+ (jacc-chan (with-mapped-conditions (socket)
264
+ (jdi:do-jmethod-call jsock "accept")))
265
+ (jacc-stream
266
+ (ext:get-socket-stream (jdi:jop-deref
267
+ (jdi:do-jmethod-call jacc-chan "socket"))
268
+ :element-type (or element-type
269
+ (element-type socket)))))
270
+ (make-stream-socket :socket jacc-chan
271
+ :stream jacc-stream)))
272
+
273
+ ;;(defun print-java-exception (e)
274
+ ;; (let* ((native-exception (java-exception-cause e)))
275
+ ;; (print (jcall (jmethod "java.net.BindException" "getMessage") native-exception))))
276
+
277
+ (defmethod socket-close ((usocket usocket))
278
+ (when (wait-list usocket)
279
+ (remove-waiter (wait-list usocket) usocket))
280
+ (with-mapped-conditions (usocket)
281
+ (jdi:do-jmethod (socket usocket) "close")))
282
+
283
+ ;; Socket streams are different objects than
284
+ ;; socket streams. Closing the stream flushes
285
+ ;; its buffers *and* closes the socket.
286
+ (defmethod socket-close ((usocket stream-usocket))
287
+ (when (wait-list usocket)
288
+ (remove-waiter (wait-list usocket) usocket))
289
+ (with-mapped-conditions (usocket)
290
+ (close (socket-stream usocket))))
291
+
292
+ (defmethod get-local-address ((usocket usocket))
293
+ (dotted-quad-to-vector-quad (ext:socket-local-address
294
+ (jdi:jop-deref
295
+ (jdi:do-jmethod-call (socket usocket)
296
+ "socket")))))
297
+
298
+ (defmethod get-peer-address ((usocket stream-usocket))
299
+ (dotted-quad-to-vector-quad (ext:socket-peer-address
300
+ (jdi:jop-deref
301
+ (jdi:do-jmethod-call (socket usocket)
302
+ "socket")))))
303
+
304
+ (defmethod get-local-port ((usocket usocket))
305
+ (ext:socket-local-port (jdi:jop-deref
306
+ (jdi:do-jmethod-call (socket usocket) "socket"))))
307
+
308
+ (defmethod get-peer-port ((usocket stream-usocket))
309
+ (ext:socket-peer-port (jdi:jop-deref
310
+ (jdi:do-jmethod-call (socket usocket) "socket"))))
311
+
312
+ (defmethod get-local-name ((usocket usocket))
313
+ (values (get-local-address usocket)
314
+ (get-local-port usocket)))
315
+
316
+ (defmethod get-peer-name ((usocket stream-usocket))
317
+ (values (get-peer-address usocket)
318
+ (get-peer-port usocket)))
319
+
320
+
321
+ #|
322
+ Pseudo code version of what we're trying to do:
323
+
324
+ We're being called with 2 args:
325
+
326
+ - sockets (list)
327
+ - timeout (non-negative real)
328
+
329
+ Selector := java.nio.channels.Selector.open()
330
+
331
+ For all usockets
332
+ get the java socket
333
+ get its channel
334
+ register the channel with the selector
335
+ with ops (operations) OP_READ and OP_ACCEPT
336
+
337
+ make the selector wait trunc(timeout*1000) miliseconds,
338
+ unless (null timeout), because then:
339
+ selectNow()
340
+
341
+ retrieve the selectedKeys() set from the selector
342
+ unless select() returned 0 selected keys.
343
+
344
+ for set-iterator.hasNextKey()
345
+ with that key
346
+ retrieve the channel
347
+ retrieve the channel's socket
348
+ add the retrieved socket to the list of ready sockets
349
+
350
+ for all usockets
351
+ check if the associated java object
352
+ is in the list of ready sockets
353
+ it is? add it to the function result list
354
+
355
+ close() the selector
356
+
357
+ return the function result list.
358
+
359
+ |#
360
+
361
+ (defun op-read ()
362
+ (jdi:do-jfield "java.nio.channels.SelectionKey"
363
+ "OP_READ"))
364
+
365
+ (defun op-accept ()
366
+ (jdi:do-jfield "java.nio.channels.SelectionKey"
367
+ "OP_ACCEPT"))
368
+
369
+ (defun op-connect ()
370
+ (jdi:do-jfield "java.nio.channels.SelectionKey"
371
+ "OP_CONNECT"))
372
+
373
+ (defun valid-ops (jchannel)
374
+ (jdi:do-jmethod-call jchannel "validOps"))
375
+
376
+ (defun channel-class (jchannel)
377
+ (let ((valid-ops (valid-ops jchannel)))
378
+ (cond ((/= 0 (logand valid-ops (op-connect)))
379
+ "java.nio.channels.SocketChannel")
380
+ ((/= 0 (logand valid-ops (op-accept)))
381
+ "java.nio.channels.ServerSocketChannel")
382
+ (t
383
+ "java.nio.channels.DatagramChannel"))))
384
+
385
+ (defun socket-channel-class (socket)
386
+ (cond
387
+ ((stream-usocket-p socket)
388
+ "java.nio.channels.SocketChannel")
389
+ ((stream-server-usocket-p socket)
390
+ "java.nio.channels.ServerSocketChannel")
391
+ ((datagram-usocket-p socket)
392
+ "java.nio.channels.DatagramChannel")))
393
+
394
+ (defun wait-for-input-internal (wait-list &key timeout)
395
+ (let* ((sockets (wait-list-waiters wait-list))
396
+ (ops (logior (op-read) (op-accept)))
397
+ (selector (jdi:do-jstatic "java.nio.channels.Selector" "open"))
398
+ (channels (mapcar #'socket sockets)))
399
+ (unwind-protect
400
+ (with-mapped-conditions ()
401
+ (let ((sel (jdi:jop-deref selector)))
402
+ (dolist (channel channels)
403
+ (let ((chan (jdi:jop-deref channel)))
404
+ (java:jcall (java:jmethod "java.nio.channels.SelectableChannel"
405
+ "configureBlocking"
406
+ "boolean")
407
+ chan (java:make-immediate-object nil :boolean))
408
+ (java:jcall (java:jmethod "java.nio.channels.SelectableChannel"
409
+ "register"
410
+ "java.nio.channels.Selector" "int")
411
+ chan sel (logand ops (valid-ops channel)))))
412
+ (let ((ready-count
413
+ (java:jcall (java:jmethod "java.nio.channels.Selector"
414
+ "select"
415
+ "long")
416
+ sel (truncate (* timeout 1000)))))
417
+ (when (< 0 ready-count)
418
+ ;; we actually have work to do
419
+ (let* ((selkeys (jdi:do-jmethod selector "selectedKeys"))
420
+ (selkey-iterator (jdi:do-jmethod selkeys "iterator"))
421
+ (%wait (wait-list-%wait wait-list)))
422
+ (loop while (java:jcall
423
+ (java:jmethod "java.util.Iterator" "hasNext")
424
+ (jdi:jop-deref selkey-iterator))
425
+ do (let* ((key (jdi:jcoerce
426
+ (jdi:do-jmethod selkey-iterator "next")
427
+ "java.nio.channels.SelectionKey"))
428
+ (chan (jdi:jop-deref
429
+ (jdi:do-jmethod key "channel"))))
430
+ (setf (state (gethash chan %wait))
431
+ :READ))))))))
432
+ ;; close the selector: all keys will be deregistered
433
+ (java:jcall (java:jmethod "java.nio.channels.Selector" "close")
434
+ (jdi:jop-deref selector))
435
+ ;; make all sockets blocking again.
436
+ (dolist (channel channels)
437
+ (java:jcall (java:jmethod "java.nio.channels.SelectableChannel"
438
+ "configureBlocking"
439
+ "boolean")
440
+ (jdi:jop-deref channel)
441
+ (java:make-immediate-object t :boolean))))))
442
+
443
+
444
+ ;;
445
+ ;;
446
+ ;;
447
+ ;; The WAIT-LIST part
448
+ ;;
449
+
450
+ ;;
451
+ ;; Note that even though Java has the concept of the Selector class, which
452
+ ;; remotely looks like a wait-list, it requires the sockets to be non-blocking.
453
+ ;; usocket however doesn't make any such guarantees and is therefore unable to
454
+ ;; use the concept outside of the waiting routine itself (blergh!).
455
+ ;;
456
+
457
+ (defun %setup-wait-list (wl)
458
+ (setf (wait-list-%wait wl)
459
+ (make-hash-table :test #'equal :rehash-size 1.3d0)))
460
+
461
+ (defun %add-waiter (wl w)
462
+ (setf (gethash (jdi:jop-deref (socket w)) (wait-list-%wait wl))
463
+ w))
464
+
465
+ (defun %remove-waiter (wl w)
466
+ (remhash (socket w) (wait-list-%wait wl)))
467
+
468
+ ;;
469
+ ;; UDP support
470
+ ;;
471
+
472
+ (defmethod socket-send ((socket datagram-usocket) buffer length &key host port)
473
+ (let ((jchan (socket socket)))
474
+ (let ((srcs (jdi:jcoerce buffer "java.nio.ByteBuffer"))
475
+ (offset (jdi:jcoerce 0 :int))
476
+ (length (jdi:jcoerce length :int)))
477
+ (if (and host port)
478
+ (let ((target (jdi:jcoerce
479
+ (jdi:do-jnew-call "java.net.InetSocketAddress"
480
+ (host-to-hostname host)
481
+ (jdi:jcoerce port :int))
482
+ "java.net.SocketAddress")))
483
+ ;; how to use "length" argument here? --binghe, 2009/12/12
484
+ (jdi:do-jmethod-call jchan "send" buffer target))
485
+ (jdi:do-jmethod-call jchan "write" srcs offset length)))))
486
+
487
+ (defmethod socket-receive ((socket datagram-usocket) buffer length &key)
488
+ (let ((jchan (socket socket)))
489
+ (multiple-value-bind (buffer size host port)
490
+ 0
491
+ (values buffer size host port))))