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

Source Code for Module pyamf.remoting.amf3

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