clucumber 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.md +4 -9
- data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
- data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
- data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
- data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
- data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
- data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
- data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
- data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
- data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
- data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
- data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
- data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
- data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
- data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
- data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
- data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
- data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
- data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
- data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
- data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
- data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
- data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
- data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
- data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
- data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
- data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
- data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
- data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
- data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
- data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
- data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
- data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
- data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
- data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
- data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
- data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
- data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
- data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
- data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
- data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
- data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
- data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
- data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
- data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
- data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
- data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
- data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
- data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
- data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
- data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
- data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
- data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
- data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
- data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
- data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
- data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
- data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
- data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
- data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
- data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
- data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
- data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
- data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
- data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
- data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
- data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
- data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
- data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
- data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
- data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
- data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
- data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
- data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
- data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
- data/lib/clucumber/vendor/lift/lift.asd +77 -0
- data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
- data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
- data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
- data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
- data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
- data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
- data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
- data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
- data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
- data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
- data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
- data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
- data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
- data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
- data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
- data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
- data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
- data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
- data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
- data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
- data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
- data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
- data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
- data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
- data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
- data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
- data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
- data/lib/clucumber/vendor/usocket/package.lisp +82 -0
- data/lib/clucumber/vendor/usocket/server.lisp +45 -0
- data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
- data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
- data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
- data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
- data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
- data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
- data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
- data/lib/clucumber.rb +29 -7
- 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))))
|