Package pyamf :: Package remoting :: Module amf3
[hide private]
[frames] | no frames]

Source Code for Module pyamf.remoting.amf3

  1  # Copyright (c) 2007-2008 The PyAMF Project. 
  2  # See LICENSE for details. 
  3   
  4  """ 
  5  AMF3 RemoteObject support. 
  6   
  7  @see: U{RemoteObject on LiveDocs 
  8  <http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/RemoteObject.html>} 
  9   
 10  @author: U{Nick Joyce<mailto:nick@boxdesign.co.uk>} 
 11   
 12  @since: 0.1.0 
 13  """ 
 14   
 15  import calendar, time, uuid, sys 
 16   
 17  import pyamf 
 18  from pyamf import remoting 
 19  from pyamf.flex.messaging import * 
 20   
 21  error_alias = pyamf.get_class_alias(ErrorMessage) 
 22   
23 -class BaseServerError(pyamf.BaseError):
24 """ 25 Base server errror 26 """
27
28 -class ServerCallFailed(BaseServerError):
29 """ 30 A catchall error. 31 """ 32 33 _amf_code = 'Server.Call.Failed'
34 35 pyamf.register_class(ServerCallFailed, attrs=error_alias.attrs) 36 37 del error_alias 38
39 -def generate_random_id():
40 return str(uuid.uuid4())
41
42 -def generate_acknowledgement(request=None):
43 ack = AcknowledgeMessage() 44 45 ack.messageId = generate_random_id() 46 ack.clientId = generate_random_id() 47 ack.timestamp = calendar.timegm(time.gmtime()) 48 49 if request: 50 ack.correlationId = request.messageId 51 52 return ack
53
54 -def generate_error(request, cls, e, tb):
55 """ 56 Builds an L{pyamf.flex.messaging.ErrorMessage} based on the last traceback 57 and the request that was sent 58 """ 59 import traceback 60 61 if hasattr(cls, '_amf_code'): 62 code = cls._amf_code 63 else: 64 code = cls.__name__ 65 66 detail = [] 67 68 for x in traceback.format_exception(cls, e, tb): 69 detail.append(x.replace("\\n", '')) 70 71 return ErrorMessage(messageId=generate_random_id(), clientId=generate_random_id(), 72 timestamp=calendar.timegm(time.gmtime()), correlationId = request.messageId, 73 faultCode=code, faultString=str(e), faultDetail=str(detail), extendedData=detail)
74
75 -class RequestProcessor(object):
76 - def __init__(self, gateway):
77 self.gateway = gateway
78
79 - def buildErrorResponse(self, request, error=None):
80 """ 81 Builds an error response. 82 83 @param request: The AMF request 84 @type request: L{Request<pyamf.remoting.Request>} 85 @return: The AMF response 86 @rtype: L{Response<pyamf.remoting.Response>} 87 """ 88 if error is not None: 89 cls, e, tb = error 90 else: 91 cls, e, tb = sys.exc_info() 92 93 return generate_error(request, cls, e, tb)
94
95 - def _getBody(self, amf_request, ro_request, **kwargs):
96 if isinstance(ro_request, CommandMessage): 97 return self._processCommandMessage(amf_request, ro_request, **kwargs) 98 elif isinstance(ro_request, RemotingMessage): 99 return self._processRemotingMessage(amf_request, ro_request, **kwargs) 100 else: 101 raise ServerCallFailed, "Unknown RemoteObject request"
102
103 - def _processCommandMessage(self, amf_request, ro_request, **kwargs):
104 ro_response = generate_acknowledgement(ro_request) 105 106 if ro_request.operation == CommandMessage.PING_OPERATION: 107 ro_response.body = True 108 109 return remoting.Response(ro_response) 110 elif ro_request.operation == CommandMessage.LOGIN_OPERATION: 111 raise ServerCallFailed, "Authorisation is not supported in RemoteObject" 112 else: 113 raise ServerCallFailed, "Unknown command operation %s" % ro_request.operation
114
115 - def _processRemotingMessage(self, amf_request, ro_request, **kwargs):
116 ro_response = generate_acknowledgement(ro_request) 117 118 service_name = ro_request.operation 119 120 if hasattr(ro_request, 'destination') and ro_request.destination: 121 service_name = '%s.%s' % (ro_request.destination, service_name) 122 123 service_request = self.gateway.getServiceRequest(amf_request, service_name) 124 125 # fire the preprocessor (if there is one) 126 self.gateway.preprocessRequest(service_request, *ro_request.body, **kwargs) 127 128 ro_response.body = self.gateway.callServiceRequest(service_request, *ro_request.body, **kwargs) 129 130 return remoting.Response(ro_response)
131
132 - def __call__(self, amf_request, **kwargs):
133 """ 134 Processes an AMF3 Remote Object request. 135 136 @param amf_request: The request to be processed. 137 @type amf_request: L{Request<pyamf.remoting.Request>} 138 139 @return: The response to the request. 140 @rtype: L{Response<pyamf.remoting.Response>} 141 """ 142 ro_request = amf_request.body[0] 143 144 try: 145 return self._getBody(amf_request, ro_request, **kwargs) 146 except (KeyboardInterrupt, SystemExit): 147 raise 148 except: 149 return remoting.Response(self.buildErrorResponse(ro_request), status=remoting.STATUS_ERROR)
150