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 error. 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 @raise ServerCallFailed: Authorization is not supported in RemoteObject. 110 """ 111 ro_response = generate_acknowledgement(ro_request) 112 113 if ro_request.operation == messaging.CommandMessage.PING_OPERATION: 114 ro_response.body = True 115 116 return remoting.Response(ro_response) 117 elif ro_request.operation == messaging.CommandMessage.LOGIN_OPERATION: 118 raise ServerCallFailed("Authorization is not supported in RemoteObject") 119 elif ro_request.operation == messaging.CommandMessage.DISCONNECT_OPERATION: 120 return remoting.Response(ro_response) 121 else: 122 raise ServerCallFailed("Unknown Command operation %s" % ro_request.operation)
123
124 - def _processAsyncMessage(self, amf_request, ro_request, **kwargs):
125 ro_response = generate_acknowledgement(ro_request) 126 ro_response.body = True 127 128 return remoting.Response(ro_response)
129
130 - def _processRemotingMessage(self, amf_request, ro_request, **kwargs):
131 ro_response = generate_acknowledgement(ro_request) 132 133 service_name = ro_request.operation 134 135 if hasattr(ro_request, 'destination') and ro_request.destination: 136 service_name = '%s.%s' % (ro_request.destination, service_name) 137 138 service_request = self.gateway.getServiceRequest(amf_request, 139 service_name) 140 141 # fire the preprocessor (if there is one) 142 self.gateway.preprocessRequest(service_request, *ro_request.body, 143 **kwargs) 144 145 ro_response.body = self.gateway.callServiceRequest(service_request, 146 *ro_request.body, **kwargs) 147 148 return remoting.Response(ro_response)
149
150 - def __call__(self, amf_request, **kwargs):
151 """ 152 Processes an AMF3 Remote Object request. 153 154 @param amf_request: The request to be processed. 155 @type amf_request: L{Request<pyamf.remoting.Request>} 156 157 @return: The response to the request. 158 @rtype: L{Response<pyamf.remoting.Response>} 159 """ 160 ro_request = amf_request.body[0] 161 162 try: 163 return self._getBody(amf_request, ro_request, **kwargs) 164 except (KeyboardInterrupt, SystemExit): 165 raise 166 except: 167 return remoting.Response(self.buildErrorResponse(ro_request), 168 status=remoting.STATUS_ERROR)
169