/* Copyright (c) 2003-2004 Jan-Klaas Kollhof This file is part of the JavaScript o lait library(jsolait). jsolait is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** Provides an XML-RPC imlementation. It is similar to python's xmlrpclib module. */ Module("xmlrpc","1.3.1", function(mod){ var xmlext = importModule("xml"); var urllib = importModule("urllib"); /** Thrown if a server did not respond with response status 200 (OK). */ mod.InvalidServerResponse = Class("InvalidServerResponse", mod.Exception, function(publ, supr){ /** Initializes the Exception. @param status The status returned by the server. */ publ.init= function(status){ supr(this).init("The server did not respond with a status 200 (OK) but with: " + status); this.status = status; } ///The status returned by the server. publ.status; }) /** Thrown if an XML-RPC response is not well formed. */ mod.MalformedXmlRpc = Class("MalformedXmlRpc", mod.Exception, function(publ, supr){ /** Initializes the Exception. @param msg The error message of the user. @param xml The xml document's source. @param trace=null The error causing this Exception */ publ.init= function(msg, xml, trace){ supr(this).init(msg,trace); this.xml = xml; } ///The xml source which was mal formed. publ.xml; }) /** Thrown if the RPC response is a Fault. */ mod.Fault = Class("Fault", mod.Exception, function(publ, supr){ /** Initializes the Exception. @param faultCode The fault code returned by the rpc call. @param faultString The fault string returned by the rpc call. */ publ.init= function(faultCode, faultString){ supr(this).init("XML-RPC Fault: " + faultCode + "\n\n" + faultString); this.faultCode = faultCode; this.faultString = faultString; } ///The fault code returned from the rpc call. publ.faultCode; ///The fault string returned from the rpc call. publ.faultString; }) /** Marshalls an object to XML-RPC.(Converts an object into XML-RPC conforming xml.) It just calls the toXmlRpc function of the objcect. So, to customize serialization of objects one just needs to specify/override the toXmlRpc method which should return an xml string conforming with XML-RPC spec. @param obj The object to marshall @return An xml representation of the object. */ mod.marshall = function(obj){ //vcb return obj.toXmlRpc() } /** Unmarshalls an XML document to a JavaScript object. (Converts xml to JavaScript object.) It parses the xml source and creates a JavaScript object. @param xml The xml document source to unmarshall. @return The JavaScript object created from the XML. */ mod.unmarshall = function(xml){ try {//try to parse xml ... this will throw an Exception if failed var doc = xmlext.parseXML(xml); }catch(e){ throw new mod.MalformedXmlRpc("The server's response could not be parsed.", xml, e); } var rslt = mod.unmarshallDoc(doc); doc=null; return rslt; } /** Unmarshalls an XML document to a JavaScript object like unmarshall but expects a DOM document as parameter. It parses the xml source and creates a JavaScript object. @param doc The xml document(DOM compatible) to unmarshall. @return The JavaScript object created from the XML. */ mod.unmarshallDoc = function(doc, xml){ try{ var node = doc.documentElement; if(node==null){ /* just in case parse xml didn't throw an Exception but returned nothing usefull. */ throw new mod.MalformedXmlRpc("No documentElement found.", xml); } switch(node.tagName){ case "methodResponse": return parseMethodResponse(node); case "methodCall": return parseMethodCall(node); default://nothing usefull returned by parseXML. throw new mod.MalformedXmlRpc("'methodCall' or 'methodResponse' element expected.\nFound: '" + node.tagName + "'", xml); } }catch(e){ if(e instanceof mod.Fault){//just rethrow the fault. throw e; }else { throw new mod.MalformedXmlRpc("Unmarshalling of XML failed.", xml, e); } } } /** Parses a methodeResponse element. @param node The methodResponse element. @return The return value of the XML-RPC. */ var parseMethodResponse=function(node){ try{ for(var i=0;i'; if (args.length>0){ data += ""; for(var i=0;i'; } data += ''; } data += ''; return data; } /** Initializes the XML-RPC method. @param url The URL of the service providing the method. @param methodName The name of the method to invoke. @param user=null The user name to use for HTTP authentication. @param pass=null The password to use for HTTP authentication. */ publ.init = function(url, methodName, user, pass){ //this is pretty much a hack. //we create a function which mimics this class and return it instead of really instanciating an object. var fn=function(){ //sync or async call if(typeof arguments[arguments.length-1] != "function"){ var data=getXML(fn.methodName,arguments); var resp = postData(fn.url, fn.user, fn.password, data); return handleResponse(resp); }else{ var args=new Array(); for(var i=0;i 0){ var tryIntrospection=false; }else{ var tryIntrospection=true; } }else{ pass=user; user=methodNames; methodNames=[]; var tryIntrospection=true; } this._url = url; this._user = user; this._password = pass; this._addMethodNames(methodNames); if(tryIntrospection){ try{//it's ok if it fails. this._introspect(); }catch(e){ } } } /** Adds new XMLRPCMethods to the proxy server which can then be invoked. @param methodNames Array of names of methods that can be called on the server. */ publ._addMethodNames = function(methodNames){ for(var i=0;i" + this[attr].toXmlRpc() + ""; } } s += ""; return s } */ /** XML-RPC representation of a string. All '&' and '<' are replaced with the '&' and '<'. @return A string containing the String's representation in XML. */ /* String.prototype.toXmlRpc = function(){ return "" + this.replace(/&/g, "&").replace(/"; }*/ /** XML-RPC representation of a number. @return A string containing the Number's representation in XML. */ /* Number.prototype.toXmlRpc = function(){ if(this == parseInt(this)){ return "" + this + ""; }else if(this == parseFloat(this)){ return "" + this + ""; }else{ return false.toXmlRpc(); } } */ /** XML-RPC representation of a boolean. @return A string containing the Boolean's representation in XML. */ /* Boolean.prototype.toXmlRpc = function(){ if(this == true) { return "1"; }else{ return "0"; } } */ /** XML-RPC representation of a date(iso 8601). @return A string containing the Date's representation in XML. */ /* Date.prototype.toXmlRpc = function(){ var padd=function(s, p){ s=p+s return s.substring(s.length - p.length) } var y = padd(this.getUTCFullYear(), "0000"); var m = padd(this.getUTCMonth() + 1, "00"); var d = padd(this.getUTCDate(), "00"); var h = padd(this.getUTCHours(), "00"); var min = padd(this.getUTCMinutes(), "00"); var s = padd(this.getUTCSeconds(), "00"); var isodate = y + m + d + "T" + h + ":" + min + ":" + s return "" + isodate + ""; } */ /** XML-RPC representation of an array. Each entry in the array is a value in the XML-RPC. @return A string containing the Array's representation in XML. */ /* Array.prototype.toXmlRpc = function(){ var retstr = ""; for(var i=0;i"; } return retstr + ""; } */ })