blob: 7a8052993a3a7d53a650d96e07958a4dc4f6bc34 [file] [log] [blame]
mblighe8819cd2008-02-15 16:48:40 +00001
2"""
3 Copyright (c) 2007 Jan-Klaas Kollhof
4
5 This file is part of jsonrpc.
6
7 jsonrpc is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 This software is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this software; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20"""
21
22import traceback
23
24from frontend.afe.simplejson import decoder, encoder
25
26def customConvertJson(value):
27 """\
28 Recursively process JSON values and do type conversions.
29 -change floats to ints
30 -change unicodes to strs
31 """
32 if isinstance(value, float):
33 return int(value)
34 elif isinstance(value, unicode):
35 return str(value)
36 elif isinstance(value, list):
37 return [customConvertJson(item) for item in value]
38 elif isinstance(value, dict):
39 new_dict = {}
40 for key, val in value.iteritems():
41 new_key = customConvertJson(key)
42 new_val = customConvertJson(val)
43 new_dict[new_key] = new_val
44 return new_dict
45 else:
46 return value
47
48json_encoder = encoder.JSONEncoder()
49json_decoder = decoder.JSONDecoder()
50
51
52def ServiceMethod(fn):
53 fn.IsServiceMethod = True
54 return fn
55
56class ServiceException(Exception):
57 pass
58
59class ServiceRequestNotTranslatable(ServiceException):
60 pass
61
62class BadServiceRequest(ServiceException):
63 pass
64
65class ServiceMethodNotFound(ServiceException):
66 pass
67
showard3d6ae112009-05-02 00:45:48 +000068
mblighe8819cd2008-02-15 16:48:40 +000069class ServiceHandler(object):
70
71 def __init__(self, service):
72 self.service=service
jadmanski0afbb632008-06-06 21:10:57 +000073
showard3d6ae112009-05-02 00:45:48 +000074 def dispatchRequest(self, request):
75 try:
76 methName = request['method']
77 args = request['params']
78 except KeyError:
79 raise BadServiceRequest(request)
mblighe8819cd2008-02-15 16:48:40 +000080
showard3d6ae112009-05-02 00:45:48 +000081 meth = self.findServiceEndpoint(methName)
82 result = self.invokeServiceEndpoint(meth, args)
83 return result
84
85 def _getRequestId(self, request):
86 try:
87 return request['id']
88 except KeyError:
89 raise BadServiceRequest(request)
90
91 def handleRequest(self, jsonRequest):
92 id_ = None
93 result = None
94 err = None
95 err_traceback = None
96
97 request = self.translateRequest(jsonRequest)
jadmanski0afbb632008-06-06 21:10:57 +000098
mblighe8819cd2008-02-15 16:48:40 +000099 try:
showard3d6ae112009-05-02 00:45:48 +0000100 id_ = self._getRequestId(request)
101 result = self.dispatchRequest(request)
102 except Exception, err:
103 err_traceback = traceback.format_exc()
mblighe8819cd2008-02-15 16:48:40 +0000104
showard3d6ae112009-05-02 00:45:48 +0000105 return self.translateResult(result, err, err_traceback, id_)
mblighe8819cd2008-02-15 16:48:40 +0000106
showardef6fe022009-03-27 20:55:16 +0000107 @staticmethod
108 def translateRequest(data):
mblighe8819cd2008-02-15 16:48:40 +0000109 try:
110 req = json_decoder.decode(data)
111 except:
112 raise ServiceRequestNotTranslatable(data)
showard3d6ae112009-05-02 00:45:48 +0000113 req = customConvertJson(req)
mblighe8819cd2008-02-15 16:48:40 +0000114 return req
showard5da17d42008-04-28 18:07:58 +0000115
mblighe8819cd2008-02-15 16:48:40 +0000116 def findServiceEndpoint(self, name):
117 try:
118 meth = getattr(self.service, name)
mblighe8819cd2008-02-15 16:48:40 +0000119 return meth
mblighe8819cd2008-02-15 16:48:40 +0000120 except AttributeError:
121 raise ServiceMethodNotFound(name)
122
123 def invokeServiceEndpoint(self, meth, args):
124 return meth(*args)
125
showardef6fe022009-03-27 20:55:16 +0000126 @staticmethod
127 def translateResult(rslt, err, err_traceback, id_):
mblighd876f452008-12-03 15:09:17 +0000128 if err is not None:
showard05fb6992008-03-25 17:03:46 +0000129 err = {"name": err.__class__.__name__, "message":str(err),
130 "traceback": err_traceback}
mblighe8819cd2008-02-15 16:48:40 +0000131 rslt = None
132
133 try:
134 data = json_encoder.encode({"result":rslt,"id":id_,"error":err})
135 except TypeError, e:
showard5da17d42008-04-28 18:07:58 +0000136 err_traceback = traceback.format_exc()
137 print err_traceback
138 err = {"name" : "JSONEncodeException",
139 "message" : "Result Object Not Serializable",
140 "traceback" : err_traceback}
mblighe8819cd2008-02-15 16:48:40 +0000141 data = json_encoder.encode({"result":None, "id":id_,"error":err})
showard5da17d42008-04-28 18:07:58 +0000142
mblighe8819cd2008-02-15 16:48:40 +0000143 return data