📄 xmlrpc.js
字号:
/*
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.3", 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){
if(obj.toXmlRpc){
return obj.toXmlRpc();
}else{
var s = "<struct>";
for(var attr in obj){
if(typeof obj[attr] != "function"){
s += "<member><name>" + attr + "</name><value>" + mod.marshall(obj[attr]) + "</value></member>";
}
}
s += "</struct>";
return s;
}
}
/**
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, xml);
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<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "fault": //a fault is thrown as an Exception
throw parseFault(child);
case "params":
var params = parseParams(child);
if(params.length == 1){//params should only have one param
return params[0];
}else{
throw new mod.MalformedXmlRpc("'params' element inside 'methodResponse' must have exactly ONE 'param' child element.\nFound: " + params.length);
}
default:
throw new mod.MalformedXmlRpc("'fault' or 'params' element expected.\nFound: '" + child.tagName + "'");
}
}
}
//no child elements found
throw new mod.MalformedXmlRpc("No child elements found.");
}catch(e){
if(e instanceof mod.Fault){
throw e;
}else{
throw new mod.MalformedXmlRpc("'methodResponse' element could not be parsed.",null,e);
}
}
}
/**
Parses a methodCall element.
@param node The methodCall element.
@return Array [methodName,params].
*/
var parseMethodCall = function(node){
try{
var methodName = null;
var params = new Array();//default is no parameters
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "methodName":
methodName = new String(child.firstChild.nodeValue);
break;
case "params":
params = parseParams(child);
break;
default:
throw new mod.MalformedXmlRpc("'methodName' or 'params' element expected.\nFound: '" + child.tagName + "'");
}
}
}
if(methodName==null){
throw new mod.MalformedXmlRpc("'methodName' element expected.");
}else{
return new Array(methodName, params);
}
}catch(e){
throw new mod.MalformedXmlRpc("'methodCall' element could not be parsed.",null,e);
}
}
/**
Parses a params element.
@param node The params element.
@return Array of params values.
*/
var parseParams = function(node){
try{
var params=new Array();
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "param":
params.push(parseParam(child));
break;
default:
throw new mod.MalformedXmlRpc("'param' element expected.\nFound: '" + child.tagName + "'");
}
}
}
//the specs say a 'params' element can contain any number of 'param' elements. That includes 0 ?!
return params;
}catch(e){
throw new mod.MalformedXmlRpc("'params' element could not be parsed.",null,e);
}
}
/**
Parses a param element.
@param node The param node.
@return The value of the param.
*/
var parseParam = function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "value":
return parseValue(child);
default:
throw new mod.MalformedXmlRpc("'value' element expected.\nFound: '" + child.tagName + "'");
}
}
}
//no child elements found, that's an error
throw new mod.MalformedXmlRpc("'value' element expected.But none found.");
}catch(e){
throw new mod.MalformedXmlRpc("'param' element could not be parsed.",null,e);
}
}
/**
Parses a value element.
@param node The value element.
@return The value.
*/
var parseValue = function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -