XmlRpc: Improved error handling

git-svn-id: svn://ultimatepp.org/upp/trunk@2207 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2010-03-10 10:52:29 +00:00
parent 8a606a5145
commit 90b2cec2b8
4 changed files with 93 additions and 26 deletions

View file

@ -1223,7 +1223,7 @@ bool FileSel::Execute(int _mode) {
dir.Add(GetHomeDirectory());
#ifdef PLATFORM_POSIX
Array<FileSystemInfo::FileInfo> root = filesystem->Find("/media/*");
dir.Add(GetHomeDirFile("Desktop"));
dir.Add(GetDesktopFolder());
dir.Add("/");
for(i = 0; i < root.GetCount(); i++) {
String ugly = root[i].filename;

View file

@ -2,13 +2,36 @@
#define LLOG(x) // LOG(x)
XmlRpcCall::XmlRpcCall(const char *url)
XmlRpcCall& XmlRpcCall::URL(const char *url)
{
shorted = true;
if(url && *url) {
server.URL(url);
shorted = false;
}
shouldExecute = true;
return *this;
}
XmlRpcCall& XmlRpcCall::Method(const char *name)
{
shouldExecute = true;
method = name;
data.Reset();
error.Clear();
return *this;
}
XmlRpcCall::XmlRpcCall(const char *url)
{
URL(url);
server.ContentType("text/xml");
timeout = 30000;
}
XmlRpcCall::XmlRpcCall()
{
URL(NULL);
server.ContentType("text/xml");
timeout = 30000;
}
@ -17,6 +40,9 @@ String XmlRpcExecute(const String& request, const char *group, const char *peera
Value XmlRpcCall::Execute()
{
if(!shouldExecute)
return Value();
shouldExecute = false;
String request = XmlHeader();
request << XmlTag("methodCall")(XmlTag("methodName")(method) + FormatXmlRpcParams(data.out));
String response;
@ -26,8 +52,11 @@ Value XmlRpcCall::Execute()
response = server.Post(request).TimeoutMsecs(timeout).ExecuteRedirect();
LLOG("response: " << response);
if(IsNull(response)) {
LLOG("ERROR: " << server.GetError());
return ErrorValue("Http request failed: " + server.GetError());
faultCode = XMLRPC_CLIENT_HTTP_ERROR;
faultString = server.GetError();
error = "Http request failed: " + faultString;
LLOG(error);
return ErrorValue(error);
}
XmlParser p(response);
try {
@ -37,11 +66,12 @@ Value XmlRpcCall::Execute()
Value m = ParseXmlRpcValue(p);
if(IsValueMap(m)) {
ValueMap mm = m;
String s;
s << "Failed '" << mm["faultString"] << "' (" << mm["faultCode"] << ')';
error = s;
faultString = mm["faultString"];
faultCode = mm["faultCode"];
error.Clear();
error << "Failed '" << faultString << "' (" << faultCode << ')';
LLOG(s);
return ErrorValue(s);
return ErrorValue(error);
}
}
else {
@ -52,18 +82,19 @@ Value XmlRpcCall::Execute()
}
catch(XmlError e) {
String s;
s << "XmlError " << e << ": " << p.GetPtr();
LLOG(s);
error = s;
return ErrorValue(s);
faultString = e;
faultCode = XMLRPC_CLIENT_XML_ERROR;
error.Clear();
error << "XML Error: " << faultString;
LLOG(error << ": " << p.GetPtr());
return ErrorValue(error);
}
return data.in.GetCount() ? data.in[0] : Null;
}
Value XmlRpcCall::Ret()
void XmlRpcCall::ClearError()
{
Value v;
if(*this >> v)
return v;
return Value();
faultCode = 0;
faultString.Clear();
error.Clear();
}

View file

@ -14,6 +14,19 @@ void Register(const char *name, void (*method)(XmlRpcData&), const char *group)
XmlRpcMap(group).Add(name, method);
}
struct XmlRpcError {
int code;
String text;
};
void ThrowXmlRpcError(int code, const char *s)
{
XmlRpcError e;
e.code = code;
e.text = s;
throw e;
}
String XmlRpcExecute(const String& request, const char *group, const char *peeraddr)
{
VectorMap< String, void (*)(XmlRpcData&) >& xmlrpcmap = XmlRpcMap(group);
@ -33,13 +46,13 @@ String XmlRpcExecute(const String& request, const char *group, const char *peera
data.in = ParseXmlRpcParams(p);
int q = xmlrpcmap.Find(methodname);
if(q < 0)
return FormatXmlRpcError(4, methodname + " method is unknown");
return FormatXmlRpcError(XMLRPC_UNKNOWN_METHOD_ERROR, "\'" + methodname + "\' method is unknown");
else {
(*xmlrpcmap[q])(data);
if(IsValueArray(data.out)) {
if(IsError(data.out[0])) {
LLOG("ProcessingError");
return FormatXmlRpcError(3, methodname + " Processing error: " + GetErrorText(data.out[0]));
return FormatXmlRpcError(XMLRPC_SERVER_PROCESSING_ERROR, "Processing error: " + GetErrorText(data.out[0]));
}
r << FormatXmlRpcParams(data.out);
}
@ -48,13 +61,17 @@ String XmlRpcExecute(const String& request, const char *group, const char *peera
p.PassEnd();
return r;
}
catch(XmlRpcError e) {
LLOG("Client error: " << e.text);
return FormatXmlRpcError(e.code, e.text);
}
catch(XmlError e) {
LLOG("XmlError " << e << ": " << p.GetPtr());
return FormatXmlRpcError(1, methodname + " XML Error: " + e);
return FormatXmlRpcError(XMLRPC_SERVER_XML_ERROR, "XML Error: " + e);
}
catch(ValueTypeMismatch) {
LLOG("ValueTypeMismatch at parameter " << data.ii);
return FormatXmlRpcError(2, methodname + " Value type mismatch at parameter " + AsString(data.ii));
return FormatXmlRpcError(XMLRPC_SERVER_PARAM_ERROR, "Parameter mismatch at parameter " + AsString(data.ii));
}
return Null;
}

View file

@ -5,6 +5,16 @@
using namespace Upp;
enum {
XMLRPC_CLIENT_HTTP_ERROR = -1000000,
XMLRPC_CLIENT_XML_ERROR,
XMLRPC_CLIENT_RETTYPE_ERROR,
XMLRPC_SERVER_PARAM_ERROR,
XMLRPC_SERVER_XML_ERROR,
XMLRPC_SERVER_PROCESSING_ERROR,
XMLRPC_UNKNOWN_METHOD_ERROR,
};
struct ValueTypeMismatch {};
void ValueCheck(bool b);
@ -123,16 +133,21 @@ void xmlrpc##x(XmlRpcData& rpc); \
INITBLOCK { Register(#x, xmlrpc##x, group); } \
void xmlrpc##x(XmlRpcData& rpc)
void ThrowXmlRpcError(int code, const char *s);
class XmlRpcCall {
bool shorted;
HttpClient server;
XmlRpcData data;
String method;
String error;
String faultString;
int faultCode;
int timeout;
bool shouldExecute;
public:
XmlRpcCall& Method(const char *name) { method = name; data.Reset(); error.Clear(); return *this; }
XmlRpcCall& Method(const char *name);
template <class T>
XmlRpcCall& operator<<(const T& x) { data << x; return *this; }
@ -140,10 +155,8 @@ public:
Value Execute();
template <class T>
bool operator>>(T& x) { if(IsError(Execute())) return false; try { data >> x; } catch(ValueTypeMismatch) { return false; } return true; }
Value Ret();
bool operator>>(T& x) { if(IsError(Execute())) return false;
try { data >> x; } catch(ValueTypeMismatch) { return false; } return true; }
XmlRpcCall& operator()(const char *method) { Method(method); return *this; }
#define E__Templ(I) class COMBINE(T, I)
@ -164,10 +177,16 @@ public:
#undef E__Param
#undef E__Body
String GetFaultString() const { return faultString; }
int GetFaultCode() const { return faultCode; }
String GetError() const { return error; }
void ClearError();
XmlRpcCall& TimeOut(int msec) { timeout = msec; }
XmlRpcCall& URL(const char *url);
XmlRpcCall(const char *url);
XmlRpcCall();
};
#endif