def testDoubleConvert(self): """ Checks the beheavior after a second call to to_jabsorb """ value = {"list": [1, 2, 3], "tuple": (1, 2, 3), "set": {1, 2, 3}, "dict": {"a": "b", "c": "d"}, "int": 42, "float": 3.14, None: None, 3.10: 51} # Double conversion: no modification on second pass first = jabsorb.to_jabsorb(value) second = jabsorb.to_jabsorb(first) self.assertDictEqual(second, first) # Double revert revert_second = jabsorb.from_jabsorb(second) revert_first = jabsorb.from_jabsorb(revert_second) # Check results self.assertDictEqual(revert_second, value) self.assertDictEqual(revert_first, value)
def _simple_dispatch(self, name, params): """ Dispatch method """ # Normalize parameters if params: if isinstance(params, (list, tuple)): params = [jabsorb.from_jabsorb(param) for param in params] else: params = {key: jabsorb.from_jabsorb(value) for key, value in params.items()} # Dispatch like JSON-RPC return super(JabsorbRpcDispatcher, self)._simple_dispatch(name, params)
def testBeanInTheMiddle(self): """ Tests the conversion of the content of a bean (half parsed stream) """ class Bean(object): def __init__(self): self.list = jabsorb.to_jabsorb([1, 2, 3]) self.tuple = jabsorb.to_jabsorb((1, 2, 3)) self.set = jabsorb.to_jabsorb(set((1, 2, 3))) def __eq__(self, other): return self.list == other.list \ and self.tuple == other.tuple \ and self.set == other.set # Prepare the bean bean = Bean() # Parse its content revert = jabsorb.from_jabsorb(bean) self.assertIs(revert, bean) self.assertEqual(revert.list, [1, 2, 3]) self.assertEqual(revert.tuple, (1, 2, 3)) self.assertEqual(revert.set, {1, 2, 3})
def testCustomClass(self): """ Tests the conversion of a custom class """ # Basic class class Custom(object): javaClass = "test.Custom" def __init__(self): self.value = str(uuid.uuid4()) self._value = str(uuid.uuid4()) self.__value = str(uuid.uuid4()) # Convert it value = Custom() jabsorb_value = jabsorb.to_jabsorb(value) revert = jabsorb.from_jabsorb(jabsorb_value) # Check Jabsorb public value self.assertEqual(jabsorb_value[jabsorb.JAVA_CLASS], Custom.javaClass) self.assertEqual(jabsorb_value['value'], value.value) # Check absence of private value self.assertNotIn('_value', jabsorb_value) self.assertNotIn('__value', jabsorb_value) self.assertNotIn('_Custom__value', jabsorb_value) # Check revert value self.assertEqual(revert[jabsorb.JAVA_CLASS], Custom.javaClass) self.assertEqual(revert['value'], value.value) self.assertEqual(revert.javaClass, Custom.javaClass) self.assertEqual(revert.value, value.value)
def testMirror(self): """ Tests the result of to_jabsorb + from_jabsorb """ value = { "list": [1, 2, 3], "tuple": (1, 2, 3), "set": set((1, 2, 3)), "dict": { "a": "b", "c": "d" }, "int": 42, "float": 3.14, None: None, 3.10: 51 } # Convert to Jabsorb jabsorb_value = jabsorb.to_jabsorb(value) # ... back to "normal" Python revert_value = jabsorb.from_jabsorb(jabsorb_value) # Check content self.assertDictEqual(revert_value, value)
def do_POST(self, request, response): """ Handle a POST request :param request: The HTTP request bean :param request: The HTTP response handler """ # Get the request JSON content data = jsonrpclib.loads(to_str(request.read_data())) # Convert from Jabsorb data = jabsorb.from_jabsorb(data) # Dispatch try: result = self._unmarshaled_dispatch(data, self._simple_dispatch) except NoMulticallResult: # No result (never happens, but who knows...) result = None if result is not None: # Convert result to Jabsorb if 'result' in result: result['result'] = jabsorb.to_jabsorb(result['result']) # Store JSON result = jsonrpclib.jdumps(result) else: # It was a notification result = '' # Send the result response.send_content(200, result, 'application/json-rpc')
def _simple_dispatch(self, name, params): """ Dispatch method """ # Normalize parameters if params: if isinstance(params, (list, tuple)): params = [jabsorb.from_jabsorb(param) for param in params] else: params = { key: jabsorb.from_jabsorb(value) for key, value in params.items() } # Dispatch like JSON-RPC return super(JabsorbRpcDispatcher, self)._simple_dispatch(name, params)
def do_POST(self, request, response): """ Handle a POST request :param request: The HTTP request bean :param request: The HTTP response handler """ # Get the request JSON content data = jsonrpclib.loads(to_str(request.read_data())) # Convert from Jabsorb data = jabsorb.from_jabsorb(data) # Dispatch try: result = self._unmarshaled_dispatch(data, self._simple_dispatch) except NoMulticallResult: # No result (never happens, but who knows...) result = None if result is not None: # Convert result to Jabsorb if 'result' in result: result['result'] = jabsorb.to_jabsorb(result['result']) # Store JSON result = jsonrpclib.jdumps(result) else: # It was a notification result = '' # Send the result response.send_content(200, result, 'application/json-rpc')
def from_json(json_string): """ Returns a new MessageReceived from the provided json_string string """ # parse the provided json_message try: parsed_msg = json.loads(json_string) except ValueError as ex: # if the provided json_message is not a valid JSON return None except TypeError as ex: # if json_message not string or buffer return None herald_version = None # check if it is a valid Herald JSON message if herald.MESSAGE_HEADERS in parsed_msg: if herald.MESSAGE_HERALD_VERSION in parsed_msg[herald.MESSAGE_HEADERS]: herald_version = parsed_msg[herald.MESSAGE_HEADERS].get( herald.MESSAGE_HERALD_VERSION) if herald_version is None or herald_version != herald.HERALD_SPECIFICATION_VERSION: _logger.error( "Herald specification of the received message is not supported!") return None # construct new Message object from the provided JSON object msg = herald.beans.MessageReceived( uid=(parsed_msg[herald.MESSAGE_HEADERS].get(herald.MESSAGE_HEADER_UID) or None), subject=parsed_msg[herald.MESSAGE_SUBJECT], content=None, sender_uid=(parsed_msg[herald.MESSAGE_HEADERS].get( herald.MESSAGE_HEADER_SENDER_UID) or None), reply_to=(parsed_msg[herald.MESSAGE_HEADERS].get( herald.MESSAGE_HEADER_REPLIES_TO) or None), access=None, timestamp=(parsed_msg[herald.MESSAGE_HEADERS].get( herald.MESSAGE_HEADER_TIMESTAMP) or None)) # set content try: if herald.MESSAGE_CONTENT in parsed_msg: parsed_content = parsed_msg[herald.MESSAGE_CONTENT] if parsed_content is not None: if isinstance(parsed_content, str): msg.set_content(parsed_content) else: msg.set_content(jabsorb.from_jabsorb(parsed_content)) except KeyError as ex: _logger.error("Error retrieving message content! " + str(ex)) # other headers if herald.MESSAGE_HEADERS in parsed_msg: for key in parsed_msg[herald.MESSAGE_HEADERS]: if key not in msg._headers: msg._headers[key] = parsed_msg[herald.MESSAGE_HEADERS][key] # metadata if herald.MESSAGE_METADATA in parsed_msg: for key in parsed_msg[herald.MESSAGE_METADATA]: if key not in msg._metadata: msg._metadata[key] = parsed_msg[herald.MESSAGE_METADATA][key] return msg
def _simple_dispatch(self, name, params): """ Dispatch method """ # Normalize parameters if params: params = [jabsorb.from_jabsorb(param) for param in params] # Dispatch like JSON-RPC return super(JabsorbRpcDispatcher, self)._simple_dispatch(name, params)
def _simple_dispatch(self, name, params): """ Dispatch method """ # Normalize parameters if params: params = [jabsorb.from_jabsorb(param) for param in params] # Dispatch like JSON-RPC return super(JabsorbRpcDispatcher, self)._simple_dispatch(name, params)
def from_json(json_string): """ Returns a new MessageReceived from the provided json_string string """ # parse the provided json_message try: parsed_msg = json.loads(json_string) except ValueError as ex: # if the provided json_message is not a valid JSON _logger.error('ValueError') return None except TypeError as ex: _logger.error('TypeError') # if json_message not string or buffer return None herald_version = None # check if it is a valid Herald JSON message if herald.MESSAGE_HEADERS in parsed_msg: if herald.MESSAGE_HERALD_VERSION in parsed_msg[herald.MESSAGE_HEADERS]: herald_version = parsed_msg[herald.MESSAGE_HEADERS].get(herald.MESSAGE_HERALD_VERSION) if herald_version is None or herald_version != herald.HERALD_SPECIFICATION_VERSION: _logger.error("Herald specification of the received message is not supported!") return None # construct new Message object from the provided JSON object msg = herald.beans.MessageReceived(uid=(parsed_msg[herald.MESSAGE_HEADERS].get(herald.MESSAGE_HEADER_UID) or None), subject=parsed_msg[herald.MESSAGE_SUBJECT], content=None, sender_uid=(parsed_msg[herald.MESSAGE_HEADERS].get(herald.MESSAGE_HEADER_SENDER_UID) or None), reply_to=(parsed_msg[herald.MESSAGE_HEADERS].get(herald.MESSAGE_HEADER_REPLIES_TO) or None), access=None, timestamp=(parsed_msg[herald.MESSAGE_HEADERS].get(herald.MESSAGE_HEADER_TIMESTAMP) or None) ) # set content try: if herald.MESSAGE_CONTENT in parsed_msg: parsed_content = parsed_msg[herald.MESSAGE_CONTENT] if parsed_content is not None: if isinstance(parsed_content, str): msg.set_content(parsed_content) else: msg.set_content(jabsorb.from_jabsorb(parsed_content)) except KeyError as ex: _logger.error("Error retrieving message content! " + str(ex)) # other headers if herald.MESSAGE_HEADERS in parsed_msg: for key in parsed_msg[herald.MESSAGE_HEADERS]: if key not in msg._headers: msg._headers[key] = parsed_msg[herald.MESSAGE_HEADERS][key] # metadata if herald.MESSAGE_METADATA in parsed_msg: for key in parsed_msg[herald.MESSAGE_METADATA]: if key not in msg._metadata: msg._metadata[key] = parsed_msg[herald.MESSAGE_METADATA][key] return msg
def wrapped_call(*args, **kwargs): """ Wrapped call """ # Get the method from the proxy method = getattr(proxy, "{0}.{1}".format(self.__name, name)) # Convert arguments args = [jabsorb.to_jabsorb(arg) for arg in args] kwargs = dict((key, jabsorb.to_jabsorb(value)) for key, value in kwargs.items()) result = method(*args, **kwargs) return jabsorb.from_jabsorb(result)
def wrapped_call(*args, **kwargs): """ Wrapped call """ # Get the method from the proxy method = getattr(proxy, "{0}.{1}".format(self.__name, name)) # Convert arguments args = [jabsorb.to_jabsorb(arg) for arg in args] kwargs = dict((key, jabsorb.to_jabsorb(value)) for key, value in kwargs.items()) result = method(*args, **kwargs) return jabsorb.from_jabsorb(result)
def __call__(self, *args): """ Method is being called """ # Forge the request if args: args = [jabsorb.to_jabsorb(arg) for arg in args] request = jsonrpclib.dumps(args, self.__name, encoding='utf-8') # Send it reply_message = self.__send(self.__peer, self.__subject, request) # Parse the reply and check for errors result = jabsorb.from_jabsorb(jsonrpclib.loads(reply_message.content)) jsonrpclib.jsonrpc.check_for_errors(result) return result['result']
def testJsonAndJavaClass(self): """ Tests the conservation of the __jsonclass__ attribute """ for has_json in (True, False): for has_java in (True, False): if not any((has_json, has_java)): # Out of the scope of this test continue # Prepare a fake bean value = { "list": [1, 2, 3], "tuple": (1, 2, 3), "set": set((1, 2, 3)), "dict": { "a": "b", "c": "d" }, "int": 42, "float": 3.14, None: None, 3.10: 51 } if has_json: value[jabsorb.JSON_CLASS] = [1, 2, 3, [4, 5]] if has_java: value[jabsorb.JAVA_CLASS] = 'test.Bean' # Convert it jabsorb_value = jabsorb.to_jabsorb(value) # Check the value of the JSON class if has_json: self.assertEqual(jabsorb_value[jabsorb.JSON_CLASS], value[jabsorb.JSON_CLASS]) if has_java: self.assertEqual(jabsorb_value[jabsorb.JAVA_CLASS], value[jabsorb.JAVA_CLASS]) # Revert revert = jabsorb.from_jabsorb(jabsorb_value) self.assertDictEqual(revert, value)
def __call__(self, *args): """ Method is being called """ # Forge the request if args: args = [jabsorb.to_jabsorb(arg) for arg in args] request = jsonrpclib.dumps(args, self.__name, encoding='utf-8') # Send it reply_message = self.__send(self.__peer, self.__subject, request) # Parse the reply and check for errors result = jabsorb.from_jabsorb(jsonrpclib.loads(reply_message.content)) jsonrpclib.jsonrpc.check_for_errors(result) return result['result']
def testJsonAndJavaClass(self): """ Tests the conservation of the __jsonclass__ attribute """ for has_json in (True, False): for has_java in (True, False): if not any((has_json, has_java)): # Out of the scope of this test continue # Prepare a fake bean value = {"list": [1, 2, 3], "tuple": (1, 2, 3), "set": {1, 2, 3}, "dict": {"a": "b", "c": "d"}, "int": 42, "float": 3.14, None: None, 3.10: 51} if has_json: value[jabsorb.JSON_CLASS] = [1, 2, 3, [4, 5]] if has_java: value[jabsorb.JAVA_CLASS] = 'test.Bean' # Convert it jabsorb_value = jabsorb.to_jabsorb(value) # Check the value of the JSON class if has_json: self.assertEqual(jabsorb_value[jabsorb.JSON_CLASS], value[jabsorb.JSON_CLASS]) if has_java: self.assertEqual(jabsorb_value[jabsorb.JAVA_CLASS], value[jabsorb.JAVA_CLASS]) # Revert revert = jabsorb.from_jabsorb(jabsorb_value) self.assertDictEqual(revert, value)
def testMirror(self): """ Tests the result of to_jabsorb + from_jabsorb """ value = {"list": [1, 2, 3], "tuple": (1, 2, 3), "set": {1, 2, 3}, "dict": {"a": "b", "c": "d"}, "int": 42, "float": 3.14, None: None, 3.10: 51} # Convert to Jabsorb jabsorb_value = jabsorb.to_jabsorb(value) # ... back to "normal" Python revert_value = jabsorb.from_jabsorb(jabsorb_value) # Check content self.assertDictEqual(revert_value, value)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Extract headers content_type = request.get_header('content-type') subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') raw_content = to_unicode(request.read_data()) # Client information host = utils.normalize_ip(request.get_client_address()[0]) if not uid or not subject or content_type != CONTENT_TYPE_JSON: # Raw message uid = str(uuid.uuid4()) subject = herald.SUBJECT_RAW msg_content = raw_content port = -1 extra = {'host': host, 'raw': True} else: # Herald message msg_content = jabsorb.from_jabsorb(json.loads(raw_content)) # Store sender information port = int(request.get_header('herald-port', 80)) extra = {'host': host, 'port': port, 'path': request.get_header('herald-path'), 'parent_uid': uid} try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access( sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError: # Unknown peer UID: keep it as is pass # Prepare the bean message = herald.beans.MessageReceived(uid, subject, msg_content, sender_uid, reply_to, ACCESS_ID, timestamp, extra) # Log before giving message to Herald self._probe.store( herald.PROBE_CHANNEL_MSG_RECV, {"uid": message.uid, "timestamp": time.time(), "transport": ACCESS_ID, "subject": message.subject, "source": sender_uid, "repliesTo": reply_to or "", "transportSource": "[{0}]:{1}".format(host, port)}) if subject.startswith(peer_contact.SUBJECT_DISCOVERY_PREFIX): # Handle discovery message self.__contact.herald_message(self._core, message) else: # All other messages are given to Herald Core self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def __on_message(self, msg): """ Received an XMPP message :param msg: A message stanza """ if msg['delay']['stamp'] is not None: # Delayed message: ignore return subject = msg['subject'] if not subject: # No subject: not an Herald message, treat it differently self.__handle_raw_message(msg) return # Check if the message is from Multi-User Chat or direct muc_message = msg['type'] == 'groupchat' \ or msg['from'].domain == self.__muc_service sender_jid = msg['from'].full try: if muc_message: # Group message: resource is the isolate UID sender_uid = msg['from'].resource else: sender_uid = self._xmpp_directory.from_jid(sender_jid).uid except KeyError: sender_uid = "<unknown>" try: content = jabsorb.from_jabsorb(json.loads(msg['body'])) except ValueError: # Content can't be decoded, use its string representation as is content = msg['body'] uid = msg['thread'] reply_to = msg['parent_thread'] # Extra parameters, for a reply extra = {"parent_uid": uid, "sender_jid": sender_jid} # Call back the core service message = beans.MessageReceived(uid, subject, content, sender_uid, reply_to, self._access_id, extra=extra) # Log before giving message to Herald self._probe.store( herald.PROBE_CHANNEL_MSG_RECV, {"uid": message.uid, "timestamp": time.time(), "transport": ACCESS_ID, "subject": message.subject, "source": sender_uid, "repliesTo": reply_to or "", "transportSource": str(sender_jid)}) if subject.startswith(peer_contact.SUBJECT_DISCOVERY_PREFIX): # Handle discovery message self.__contact.herald_message(self._herald, message) else: # All other messages are given to Herald Core self._herald.handle_message(message)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Check content type content_type = request.get_header('content-type') if content_type not in (None, CONTENT_TYPE_JSON): # Unknown content type -> Error 412 "Precondition failed" _logger.critical("Bad content type: %s", content_type) code, content = _make_json_result(412, "Unknown content type") else: # Extract headers subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') json_content = to_unicode(request.read_data()) msg_content = jabsorb.from_jabsorb(json.loads(json_content)) # Store sender information host = request.get_client_address()[0] port = int(request.get_header('herald-port', 80)) extra = {'host': host, 'port': port, 'path': request.get_header('herald-path'), 'parent_uid': uid} try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access(sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError as ex: # Unknown peer UID: keep it as is pass # Let Herald handle the message message = herald.beans.MessageReceived(uid, subject, msg_content, sender_uid, reply_to, ACCESS_ID, timestamp, extra) self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Check content type content_type = request.get_header('content-type') if content_type not in (None, CONTENT_TYPE_JSON): # Unknown content type -> Error 412 "Precondition failed" _logger.critical("Bad content type: %s", content_type) code, content = _make_json_result(412, "Unknown content type") else: # Extract headers subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') json_content = to_unicode(request.read_data()) msg_content = jabsorb.from_jabsorb(json.loads(json_content)) # Store sender information host = request.get_client_address()[0] port = int(request.get_header('herald-port', 80)) extra = { 'host': host, 'port': port, 'path': request.get_header('herald-path'), 'parent_uid': uid } try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access( sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError as ex: # Unknown peer UID: keep it as is pass # Let Herald handle the message message = herald.beans.MessageReceived(uid, subject, msg_content, sender_uid, reply_to, ACCESS_ID, timestamp, extra) self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)