"""XML-RPC servlet base class
Written by Geoffrey Talvola
See Examples/XMLRPCExample.py for sample usage.
"""
import sys
import traceback
import xmlrpclib
from RPCServlet import RPCServlet
class XMLRPCServlet(RPCServlet):
    """XMLRPCServlet is a base class for XML-RPC servlets.
    See Examples/XMLRPCExample.py for sample usage.
    For more Pythonic convenience at the cost of language independence,
    see PickleRPCServlet.
    """
    
    
    allow_none = True
    def respondToPost(self, transaction):
        """Respond to a Post request.
        This is similar to the xmlrpcserver.py example from the xmlrpc
        library distribution, only it's been adapted to work within a
        WebKit servlet.
        """
        try:
            
            data = transaction.request().rawInput(rewind=1).read()
            encoding = _getXmlDeclAttr(data, "encoding")
            params, method = xmlrpclib.loads(data)
            
            try:
                
                
                
                if method == '__methods__.__getitem__':
                    response = self.exposedMethods()[params[0]]
                else:
                    response = self.call(method, *params)
                if not isinstance(response, tuple):
                    response = (response,)
            except xmlrpclib.Fault, fault:
                response = xmlrpclib.dumps(fault, encoding=encoding,
                    allow_none=self.allow_none)
                self.sendOK('text/xml', response, transaction)
                self.handleException(transaction)
            except Exception, e:
                fault = self.resultForException(e, transaction)
                response = xmlrpclib.dumps(xmlrpclib.Fault(1, fault),
                    encoding=encoding, allow_none=self.allow_none)
                self.sendOK('text/xml', response, transaction)
                self.handleException(transaction)
            except: 
                fault = self.resultForException(sys.exc_info()[0], transaction)
                response = xmlrpclib.dumps(xmlrpclib.Fault(1, fault),
                    encoding=encoding, allow_none=self.allow_none)
                self.sendOK('text/xml', response, transaction)
                self.handleException(transaction)
            else:
                response = xmlrpclib.dumps(response, methodresponse=1,
                    encoding=encoding, allow_none=self.allow_none)
                self.sendOK('text/xml', response, transaction)
        except Exception:
            
            print 'XMLRPCServlet internal error'
            print ''.join(traceback.format_exception(
                sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
            transaction.response().setStatus(500, 'Server Error')
            self.handleException(transaction)
def _getXmlDeclAttr(xml, attName):
    """Get attribute value from xml declaration (<?xml ... ?>)."""
    s = xml[6 : xml.find("?>")] 
    p = s.find(attName)
    if p < 0:
        return None
    s = s[p + len(attName):] 
    s = s[s.find('=') + 1:].strip() 
    return s[1:s.find(s[0], 1)]