factor/basis/xml-rpc/xml-rpc.factor

183 lines
4.5 KiB
Factor
Raw Normal View History

2009-01-30 12:29:30 -05:00
! Copyright (C) 2005, 2009 Daniel Ehrenberg
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-08-29 05:33:05 -04:00
USING: accessors kernel xml arrays math generic http.client
combinators hashtables namespaces io base64 sequences strings
2009-02-05 22:17:03 -05:00
calendar xml.data xml.writer xml.traversal assocs math.parser
debugger calendar.format math.order xml.syntax ;
2008-04-26 12:03:41 -04:00
IN: xml-rpc
2007-09-20 18:09:08 -04:00
! * Sending RPC requests
! TODO: time
! The word for what this does is "serialization"! Wow!
GENERIC: item>xml ( object -- xml )
M: integer item>xml
dup 31 2^ neg 31 2^ 1 - between?
[ "Integers must fit in 32 bits" throw ] unless
2009-01-27 14:38:13 -05:00
[XML <i4><-></i4> XML] ;
2007-09-20 18:09:08 -04:00
2008-08-29 05:33:05 -04:00
UNION: boolean t POSTPONE: f ;
2007-09-20 18:09:08 -04:00
M: boolean item>xml
2009-01-26 17:48:14 -05:00
"1" "0" ? [XML <boolean><-></boolean> XML] ;
2007-09-20 18:09:08 -04:00
M: float item>xml
2009-01-26 17:48:14 -05:00
number>string [XML <double><-></double> XML] ;
2007-09-20 18:09:08 -04:00
2009-01-26 17:48:14 -05:00
M: string item>xml
[XML <string><-></string> XML] ;
2007-09-20 18:09:08 -04:00
: struct-member ( name value -- tag )
2009-01-26 17:48:14 -05:00
over string? [ "Struct member name must be string" throw ] unless
item>xml
[XML
<member>
<name><-></name>
<value><-></value>
</member>
XML] ;
2007-09-20 18:09:08 -04:00
M: hashtable item>xml
2007-10-16 04:15:16 -04:00
[ struct-member ] { } assoc>map
2009-01-26 17:48:14 -05:00
[XML <struct><-></struct> XML] ;
2007-09-20 18:09:08 -04:00
M: array item>xml
2009-01-26 17:48:14 -05:00
[ item>xml [XML <value><-></value> XML] ] map
[XML <array><data><-></data></array> XML] ;
2007-09-20 18:09:08 -04:00
TUPLE: base64 string ;
C: <base64> base64
M: base64 item>xml
2009-01-26 17:48:14 -05:00
string>> >base64
[XML <base64><-></base64> XML] ;
2007-09-20 18:09:08 -04:00
: params ( seq -- xml )
2009-01-26 17:48:14 -05:00
[ item>xml [XML <param><value><-></value></param> XML] ] map
[XML <params><-></params> XML] ;
2007-09-20 18:09:08 -04:00
: method-call ( name seq -- xml )
2009-01-26 17:48:14 -05:00
params
<XML
<methodCall>
<methodName><-></methodName>
<->
</methodCall>
XML> ;
2007-09-20 18:09:08 -04:00
: return-params ( seq -- xml )
2009-01-26 17:48:14 -05:00
params <XML <methodResponse><-></methodResponse> XML> ;
2007-09-20 18:09:08 -04:00
: return-fault ( fault-code fault-string -- xml )
[ "faultString" set "faultCode" set ] H{ } make-assoc item>xml
2009-01-26 17:48:14 -05:00
<XML
<methodResponse>
<fault>
<value><-></value>
</fault>
</methodResponse>
XML> ;
2007-09-20 18:09:08 -04:00
TUPLE: rpc-method name params ;
C: <rpc-method> rpc-method
TUPLE: rpc-response params ;
C: <rpc-response> rpc-response
TUPLE: rpc-fault code string ;
C: <rpc-fault> rpc-fault
GENERIC: send-rpc ( rpc -- xml )
M: rpc-method send-rpc
2008-09-02 13:36:15 -04:00
[ name>> ] [ params>> ] bi method-call ;
2007-09-20 18:09:08 -04:00
M: rpc-response send-rpc
2008-09-02 13:36:15 -04:00
params>> return-params ;
2007-09-20 18:09:08 -04:00
M: rpc-fault send-rpc
2008-09-02 13:36:15 -04:00
[ code>> ] [ string>> ] bi return-fault ;
2007-09-20 18:09:08 -04:00
! * Recieving RPC requests
! this needs to have much better error checking
TUPLE: server-error tag message ;
: server-error ( tag message -- * )
\ server-error boa throw ;
2007-09-20 18:09:08 -04:00
M: server-error error.
"Error in XML supplied to server" print
2008-09-02 13:36:15 -04:00
"Description: " write dup message>> print
"Tag: " write tag>> xml>string print ;
2007-09-20 18:09:08 -04:00
2009-02-04 02:25:48 -05:00
TAGS: xml>item ( tag -- object )
2007-09-20 18:09:08 -04:00
TAG: string xml>item
children>string ;
2009-02-04 02:25:48 -05:00
: children>number ( tag -- n )
2007-09-20 18:09:08 -04:00
children>string string>number ;
2009-02-04 02:25:48 -05:00
TAG: i4 xml>item children>number ;
TAG: int xml>item children>number ;
TAG: double xml>item children>number ;
2007-09-20 18:09:08 -04:00
TAG: boolean xml>item
2009-02-09 19:36:36 -05:00
children>string {
{ "1" [ t ] }
{ "0" [ f ] }
2008-04-11 13:57:43 -04:00
[ "Bad boolean" server-error ]
2009-02-09 19:36:36 -05:00
} case ;
2007-09-20 18:09:08 -04:00
: unstruct-member ( tag -- )
children-tags first2
first-child-tag xml>item
2008-12-17 20:17:37 -05:00
[ children>string ] dip swap set ;
2007-09-20 18:09:08 -04:00
TAG: struct xml>item
[
children-tags [ unstruct-member ] each
] H{ } make-assoc ;
TAG: base64 xml>item
children>string base64> <base64> ;
TAG: array xml>item
first-child-tag children-tags
[ first-child-tag xml>item ] map ;
: params>array ( tag -- array )
children-tags
[ first-child-tag first-child-tag xml>item ] map ;
: parse-rpc-response ( xml -- array )
first-child-tag params>array ;
: parse-method ( xml -- string array )
2008-09-02 13:36:15 -04:00
children-tags first2
[ children>string ] [ params>array ] bi* ;
2007-09-20 18:09:08 -04:00
: parse-fault ( xml -- fault-code fault-string )
first-child-tag first-child-tag first-child-tag
xml>item [ "faultCode" get "faultString" get ] bind ;
: receive-rpc ( xml -- rpc )
2008-08-29 05:33:05 -04:00
dup main>> dup "methodCall" =
2007-09-20 18:09:08 -04:00
[ drop parse-method <rpc-method> ] [
"methodResponse" = [
2008-08-29 05:33:05 -04:00
dup first-child-tag main>> "fault" =
2007-09-20 18:09:08 -04:00
[ parse-fault <rpc-fault> ]
[ parse-rpc-response <rpc-response> ] if
] [ "Bad main tag name" server-error ] if
] if ;
: post-rpc ( rpc url -- rpc )
! This needs to do something in the event of an error
2008-12-17 20:17:37 -05:00
[ send-rpc ] dip http-post nip string>xml receive-rpc ;
2007-09-20 18:09:08 -04:00
: invoke-method ( params method url -- response )
2008-12-17 20:17:37 -05:00
[ swap <rpc-method> ] dip post-rpc ;