1 ! Copyright (C) 2005, 2006 Daniel Ehrenberg
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: kernel xml arrays math generic http.client combinators
5 hashtables namespaces io base64 sequences strings calendar
6 xml.data xml.writer xml.utilities assocs math.parser debugger ;
8 ! * Sending RPC requests
10 ! The word for what this does is "serialization"! Wow!
12 GENERIC: item>xml ( object -- xml )
15 dup 31 2^ neg 31 2^ 1 - between?
16 [ "Integers must fit in 32 bits" throw ] unless
17 number>string "i4" build-tag ;
19 PREDICATE: object boolean { t f } member? ;
22 "1" "0" ? "boolean" build-tag ;
25 number>string "double" build-tag ;
27 M: string item>xml ! This should change < and &
30 : struct-member ( name value -- tag )
32 [ "Struct member name must be string" throw ] unless
34 item>xml "value" build-tag
35 2array "member" build-tag* ;
38 [ [ struct-member , ] assoc-each ] { } make
42 [ item>xml "value" build-tag ] map
43 "data" build-tag* "array" build-tag ;
45 TUPLE: base64 string ;
50 base64-string >base64 "base64" build-tag ;
52 : params ( seq -- xml )
53 [ item>xml "value" build-tag "param" build-tag ] map
56 : method-call ( name seq -- xml )
57 params >r "methodName" build-tag r>
58 2array "methodCall" build-tag* build-xml ;
60 : return-params ( seq -- xml )
61 params "methodResponse" build-tag build-xml ;
63 : return-fault ( fault-code fault-string -- xml )
64 [ "faultString" set "faultCode" set ] H{ } make-assoc item>xml
65 "value" build-tag "fault" build-tag "methodResponse" build-tag
68 TUPLE: rpc-method name params ;
70 C: <rpc-method> rpc-method
72 TUPLE: rpc-response params ;
74 C: <rpc-response> rpc-response
76 TUPLE: rpc-fault code string ;
78 C: <rpc-fault> rpc-fault
80 GENERIC: send-rpc ( rpc -- xml )
81 M: rpc-method send-rpc
82 [ rpc-method-name ] keep rpc-method-params method-call ;
83 M: rpc-response send-rpc
84 rpc-response-params return-params ;
86 [ rpc-fault-code ] keep rpc-fault-string return-fault ;
88 ! * Recieving RPC requests
89 ! this needs to have much better error checking
91 TUPLE: server-error tag message ;
93 : server-error ( tag message -- * )
94 \ server-error construct-boa throw ;
96 M: server-error error.
97 "Error in XML supplied to server" print
98 "Description: " write dup server-error-message print
99 "Tag: " write server-error-tag xml>string print ;
101 PROCESS: xml>item ( tag -- object )
106 TAG: i4/int/double xml>item
107 children>string string>number ;
109 TAG: boolean xml>item
110 dup children>string {
111 { [ dup "1" = ] [ 2drop t ] }
112 { [ "0" = ] [ drop f ] }
113 { [ t ] [ "Bad boolean" server-error ] }
116 : unstruct-member ( tag -- )
118 first-child-tag xml>item
119 >r children>string r> swap set ;
123 children-tags [ unstruct-member ] each
127 children>string base64> <base64> ;
130 first-child-tag children-tags
131 [ first-child-tag xml>item ] map ;
133 : params>array ( tag -- array )
135 [ first-child-tag first-child-tag xml>item ] map ;
137 : parse-rpc-response ( xml -- array )
138 first-child-tag params>array ;
140 : parse-method ( xml -- string array )
141 children-tags dup first children>string
142 swap second params>array ;
144 : parse-fault ( xml -- fault-code fault-string )
145 first-child-tag first-child-tag first-child-tag
146 xml>item [ "faultCode" get "faultString" get ] bind ;
148 : receive-rpc ( xml -- rpc )
149 dup name-tag dup "methodCall" =
150 [ drop parse-method <rpc-method> ] [
152 dup first-child-tag name-tag "fault" =
153 [ parse-fault <rpc-fault> ]
154 [ parse-rpc-response <rpc-response> ] if
155 ] [ "Bad main tag name" server-error ] if
158 : post-rpc ( rpc url -- rpc )
159 ! This needs to do something in the event of an error
160 >r "text/xml" swap send-rpc xml>string r> http-post
161 2nip string>xml receive-rpc ;
163 : invoke-method ( params method url -- )
164 >r swap <rpc-method> r> post-rpc ;
166 : put-http-response ( string -- )
167 "HTTP/1.1 200 OK\nConnection: close\nContent-Length: " write
168 dup length number>string write
169 "\nContent-Type: text/xml\nDate: " write
170 now timestamp>http-string write "\n\n" write