reformated error for easier reading
[OpenSRF.git] / src / python / osrf / gateway.py
1 from xml.dom import minidom
2 from xml.sax import handler, make_parser, saxutils
3 from json import *
4 from net_obj import *
5 import urllib, urllib2, sys, re
6
7 defaultHost = None
8 #paramRegex = re.compile('\%27')
9
10 class GatewayRequest:
11     def __init__(self, service, method, params=[]):
12         self.service = service
13         self.method = method
14         self.params = params
15
16     def send(self):
17         params = self.buildPOSTParams()
18         request = urllib2.Request(self.buildURL(), data=params)
19         response = None
20         try:
21             response =urllib2.urlopen(request)
22         except urllib2.HTTPError, e:
23             # log this?
24             sys.stderr.write('%s => %s?%s\n' % (str(e), self.buildURL(), params))
25             raise e
26             
27         return self.handleResponse(response)
28
29     def buildPOSTParams(self):
30
31         params = urllib.urlencode({   
32             'service': self.service,
33             'method': self.method,
34             'format': self.getFormat(),
35             'input_format': self.getInputFormat()
36         })
37
38         for p in self.params:
39             params += '&param=%s' % urllib.quote(self.encodeParam(p), "'/")
40         return params
41
42     def setDefaultHost(host):
43         global defaultHost
44         defaultHost = host
45     setDefaultHost = staticmethod(setDefaultHost)
46
47     def buildURL(self):
48         return 'http://%s/gateway' % defaultHost
49
50
51 class XMLGatewayRequest(GatewayRequest):
52
53     def __init__(self, service, method, *params):
54         GatewayRequest.__init__(self, service, method, list(params))
55
56     def getFormat(self):
57         return 'xml'
58
59     def getInputFormat(self):
60         return self.getFormat()
61
62     def handleResponse(self, response):
63         handler = XMLGatewayParser()
64         parser = make_parser()
65         parser.setContentHandler(handler)
66         parser.parse(response)
67         return handler.getResult()
68
69     def encodeParam(self, param):
70         return osrfObjectToXML(param);
71
72 class XMLGatewayParser(handler.ContentHandler):
73
74     def __init__(self):
75         self.result = None
76         self.objStack = []
77         self.keyStack = []
78         self.posStack = [] # for tracking array-based hinted object indices
79
80         # true if we are parsing an element that may have character data
81         self.charsPending = 0 
82
83     def getResult(self):
84         return self.result
85
86     def __getAttr(self, attrs, name):
87         for (k, v) in attrs.items():
88             if k == name:
89                 return v
90         return None
91
92     def startElement(self, name, attrs):
93         
94         if self.charsPending:
95             # we just read a 'string' or 'number' element that resulted
96             # in no text data.  Appaned a None object
97             self.appendChild(None)
98
99         if name == 'null':
100             self.appendChild(None)
101             return
102
103         if name == 'string' or name == 'number':
104             self.charsPending = True
105             return
106
107         if name == 'element': # this is an object item wrapper
108             self.keyStack.append(self.__getAttr(attrs, 'key'))
109             return
110
111         hint = self.__getAttr(attrs, 'class_hint')
112         if hint:
113             obj = osrfNewObjectFromHint(hint)
114             self.appendChild(obj)
115             self.objStack.append(obj)
116             if name == 'array':
117                 self.posStack.append(0)
118             return
119
120         if name == 'array':
121             obj = []
122             self.appendChild(obj)
123             self.objStack.append(obj)
124             return
125
126         if name == 'object':
127             obj = {}
128             self.appendChild(obj)
129             self.objStack.append(obj)
130             return
131
132         if name == 'boolean':
133             self.appendChild((self.__getAttr(attrs, 'value') == 'true'))
134             return
135
136
137     def appendChild(self, child):
138
139         if self.result == None:
140             self.result = child
141
142         if not self.objStack: return;
143
144         parent = self.objStack[len(self.objStack)-1]
145
146         if isinstance(parent, list):
147             parent.append(child)
148         else:
149             if isinstance(parent, dict):
150                 parent[self.keyStack.pop()] = child
151             else:
152                 if isinstance(parent, osrfNetworkObject):
153                     key = None
154                     if parent.getRegistry().wireProtocol == 'array':
155                         keys = parent.getRegistry().keys
156                         i = self.posStack.pop()
157                         key = keys[i]
158                         if i+1 < len(keys):
159                             self.posStack.append(i+1)
160                     else:
161                         key = self.keyStack.pop()
162
163                     parent.setField(key, child)
164
165     def endElement(self, name):
166         if name == 'array' or name == 'object':
167             self.objStack.pop()
168
169     def characters(self, chars):
170         self.charsPending = False
171         self.appendChild(urllib.unquote_plus(chars))
172
173
174
175     
176