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