Repository: qpid-broker-j
Updated Branches:
  refs/heads/master 00f614e96 -> d9027a0b9


QPID-7434: [Java Broker] Improve AMQP 1.0 to 0-10 content conversion and add 
unit tests


Project: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/commit/d9027a0b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/d9027a0b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/d9027a0b

Branch: refs/heads/master
Commit: d9027a0b9b20d3fa81450eb46cd46789dad506ab
Parents: 00f614e
Author: Alex Rudyy <oru...@apache.org>
Authored: Tue Aug 8 11:36:16 2017 +0100
Committer: Alex Rudyy <oru...@apache.org>
Committed: Tue Aug 8 11:36:38 2017 +0100

----------------------------------------------------------------------
 .../v1_0/MessageConverter_from_1_0.java         |  82 +-
 .../MessageConverter_1_0_to_v0_10.java          |  22 +-
 .../MessageConverter_1_0_to_v0_10Test.java      | 913 +++++++++++++++++++
 .../v0_8_v1_0/MessageConverter_1_0_to_v0_8.java |  67 +-
 4 files changed, 1015 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/d9027a0b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_from_1_0.java
----------------------------------------------------------------------
diff --git 
a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_from_1_0.java
 
b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_from_1_0.java
index cafdc7d..71add9e 100644
--- 
a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_from_1_0.java
+++ 
b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_from_1_0.java
@@ -20,6 +20,8 @@
  */
 package org.apache.qpid.server.protocol.v1_0;
 
+import static 
org.apache.qpid.server.message.mimecontentconverter.MimeContentConverterRegistry.getBestFitObjectToMimeContentConverter;
+
 import java.io.Serializable;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -37,6 +39,7 @@ import java.util.UUID;
 import java.util.regex.Pattern;
 
 import org.apache.qpid.server.bytebuffer.QpidByteBuffer;
+import 
org.apache.qpid.server.message.mimecontentconverter.ObjectToMimeContentConverter;
 import org.apache.qpid.server.protocol.converter.MessageConversionException;
 import org.apache.qpid.server.protocol.v1_0.messaging.SectionDecoderImpl;
 import org.apache.qpid.server.protocol.v1_0.type.AmqpErrorException;
@@ -79,7 +82,7 @@ public class MessageConverter_from_1_0
     private static final Pattern
             OBJECT_MESSAGE_CONTENT_TYPES = 
Pattern.compile("^application/x-java-serialized-object|application/java-object-stream$");
 
-    public static Object convertBodyToObject(final Message_1_0 serverMessage)
+    static Object convertBodyToObject(final Message_1_0 serverMessage)
     {
         final Collection<QpidByteBuffer> allData = serverMessage.getContent(0, 
(int) serverMessage.getSize());
         SectionDecoderImpl sectionDecoder = new 
SectionDecoderImpl(MessageConverter_v1_0_to_Internal.TYPE_REGISTRY.getSectionDecoderRegistry());
@@ -233,7 +236,7 @@ public class MessageConverter_from_1_0
         return result;
     }
 
-    public static ContentHint getTypeHint(final Message_1_0 serverMsg)
+    private static ContentHint getTypeHint(final Message_1_0 serverMsg)
     {
         Symbol contentType = getContentType(serverMsg);
 
@@ -493,26 +496,93 @@ public class MessageConverter_from_1_0
         return messageId;
     }
 
-    public static class ContentHint
+    public static ConvertedContentAndMimeType 
getConvertedContentAndMimeType(final Message_1_0 serverMsg)
+    {
+        Object bodyObject = convertBodyToObject(serverMsg);
+        ObjectToMimeContentConverter converter = 
getBestFitObjectToMimeContentConverter(bodyObject);
+
+        ContentHint contentHint = getTypeHint(serverMsg);
+        Class<?> typeHint = contentHint.getContentClass();
+        if (typeHint == null && bodyObject == null)
+        {
+            typeHint = Void.class;
+        }
+
+        if (converter == null)
+        {
+            converter = getBestFitObjectToMimeContentConverter(bodyObject, 
typeHint);
+
+            if (converter == null)
+            {
+                throw new MessageConversionException(String.format(
+                        "Could not convert message from 1.0 to 0-x because 
conversion of content failed."
+                        + " Could not find mime type converter for the content 
'%s'.",
+                        bodyObject == null ? null : 
bodyObject.getClass().getSimpleName()));
+            }
+        }
+
+        final byte[] messageContent = converter.toMimeContent(bodyObject);
+        String mimeType = converter.getMimeType();
+        if (bodyObject instanceof byte[])
+        {
+            if (Serializable.class == typeHint)
+            {
+                mimeType = "application/java-object-stream";
+            }
+            else if (String.class == typeHint)
+            {
+                mimeType = "text/plain";
+            }
+            else if ((Map.class == typeHint || List.class == typeHint) && 
contentHint.getContentType() != null)
+            {
+                mimeType = contentHint.getContentType();
+            }
+        }
+
+        return new ConvertedContentAndMimeType(messageContent, mimeType);
+    }
+
+    private static class ContentHint
     {
         private final Class<?> _contentClass;
         private final String _contentType;
 
-        public ContentHint(final Class<?> contentClass, final String 
contentType)
+        private ContentHint(final Class<?> contentClass, final String 
contentType)
         {
             _contentClass = contentClass;
             _contentType = contentType;
         }
 
-        public Class<?> getContentClass()
+        private Class<?> getContentClass()
         {
             return _contentClass;
         }
 
-        public String getContentType()
+        private String getContentType()
         {
             return _contentType;
         }
     }
 
+    public static class ConvertedContentAndMimeType
+    {
+        private final byte[] _content;
+        private final String _mimeType;
+
+        private ConvertedContentAndMimeType(final byte[] content, final String 
mimeType)
+        {
+            _content = content;
+            _mimeType = mimeType;
+        }
+
+        public byte[] getContent()
+        {
+            return _content;
+        }
+
+        public String getMimeType()
+        {
+            return _mimeType;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/d9027a0b/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10.java
----------------------------------------------------------------------
diff --git 
a/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10.java
 
b/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10.java
index 3d67655..ad94f42 100644
--- 
a/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10.java
+++ 
b/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10.java
@@ -21,9 +21,9 @@
 package org.apache.qpid.server.protocol.converter.v0_10_v1_0;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
-import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.convertBodyToObject;
 import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.convertValue;
 import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getAbsoluteExpiryTime;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getConvertedContentAndMimeType;
 import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getCorrelationId;
 import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getCreationTime;
 import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getGroupId;
@@ -42,8 +42,6 @@ import java.util.UUID;
 
 import org.apache.qpid.server.bytebuffer.QpidByteBuffer;
 import org.apache.qpid.server.message.MessageDestination;
-import 
org.apache.qpid.server.message.mimecontentconverter.MimeContentConverterRegistry;
-import 
org.apache.qpid.server.message.mimecontentconverter.ObjectToMimeContentConverter;
 import org.apache.qpid.server.model.Exchange;
 import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.model.Queue;
@@ -58,6 +56,7 @@ import 
org.apache.qpid.server.protocol.v0_10.transport.MessageDeliveryMode;
 import org.apache.qpid.server.protocol.v0_10.transport.MessageDeliveryPriority;
 import org.apache.qpid.server.protocol.v0_10.transport.MessageProperties;
 import org.apache.qpid.server.protocol.v0_10.transport.ReplyTo;
+import 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.ConvertedContentAndMimeType;
 import org.apache.qpid.server.protocol.v1_0.MessageMetaData_1_0;
 import org.apache.qpid.server.protocol.v1_0.Message_1_0;
 import org.apache.qpid.server.protocol.v1_0.type.Binary;
@@ -104,16 +103,12 @@ public class MessageConverter_1_0_to_v0_10 implements 
MessageConverter<Message_1
     private StoredMessage<MessageMetaData_0_10> convertToStoredMessage(final 
Message_1_0 serverMsg,
                                                                        final 
NamedAddressSpace addressSpace)
     {
-        Object bodyObject = convertBodyToObject(serverMsg);
-
-        final ObjectToMimeContentConverter converter = 
MimeContentConverterRegistry.getBestFitObjectToMimeContentConverter(bodyObject);
-        final byte[] messageContent = converter == null ? new byte[] {} : 
converter.toMimeContent(bodyObject);
-        final String mimeType = converter == null ? null  : 
converter.getMimeType();
-
+        final ConvertedContentAndMimeType convertedContentAndMimeType = 
getConvertedContentAndMimeType(serverMsg);
+        final byte[] convertedContent = 
convertedContentAndMimeType.getContent();
         final MessageMetaData_0_10 messageMetaData_0_10 = 
convertMetaData(serverMsg,
                                                                           
addressSpace,
-                                                                          
mimeType,
-                                                                          
messageContent.length);
+                                                                          
convertedContentAndMimeType.getMimeType(),
+                                                                          
convertedContent.length);
         final int metadataSize = messageMetaData_0_10.getStorableSize();
 
         return new StoredMessage<MessageMetaData_0_10>()
@@ -133,13 +128,13 @@ public class MessageConverter_1_0_to_v0_10 implements 
MessageConverter<Message_1
             @Override
             public Collection<QpidByteBuffer> getContent(final int offset, 
final int length)
             {
-                return 
Collections.singleton(QpidByteBuffer.wrap(messageContent, offset, length));
+                return 
Collections.singleton(QpidByteBuffer.wrap(convertedContent, offset, length));
             }
 
             @Override
             public int getContentSize()
             {
-                return messageContent.length;
+                return convertedContent.length;
             }
 
             @Override
@@ -488,5 +483,4 @@ public class MessageConverter_1_0_to_v0_10 implements 
MessageConverter<Message_1
         }
         return buffer.array();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/d9027a0b/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10Test.java
----------------------------------------------------------------------
diff --git 
a/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10Test.java
 
b/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10Test.java
new file mode 100644
index 0000000..9e59fe6
--- /dev/null
+++ 
b/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_1_0_to_v0_10Test.java
@@ -0,0 +1,913 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol.converter.v0_10_v1_0;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertArrayEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.io.ByteStreams;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.qpid.server.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.server.model.NamedAddressSpace;
+import org.apache.qpid.server.protocol.converter.MessageConversionException;
+import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage;
+import 
org.apache.qpid.server.protocol.v0_10.transport.mimecontentconverter.AmqpListToListConverter;
+import 
org.apache.qpid.server.protocol.v0_10.transport.mimecontentconverter.AmqpMapToMapConverter;
+import 
org.apache.qpid.server.protocol.v0_10.transport.mimecontentconverter.ListToAmqpListConverter;
+import 
org.apache.qpid.server.protocol.v0_10.transport.mimecontentconverter.MapToAmqpMapConverter;
+import org.apache.qpid.server.protocol.v1_0.MessageMetaData_1_0;
+import org.apache.qpid.server.protocol.v1_0.Message_1_0;
+import org.apache.qpid.server.protocol.v1_0.type.Binary;
+import org.apache.qpid.server.protocol.v1_0.type.Symbol;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.AmqpSequence;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.AmqpValue;
+import 
org.apache.qpid.server.protocol.v1_0.type.messaging.ApplicationProperties;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.Data;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.DeliveryAnnotations;
+import 
org.apache.qpid.server.protocol.v1_0.type.messaging.EncodingRetainingSection;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.Footer;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.Header;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.MessageAnnotations;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.Properties;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.Source;
+import org.apache.qpid.server.store.StoredMessage;
+import 
org.apache.qpid.server.typedmessage.mimecontentconverter.JmsMapMessageToMap;
+import 
org.apache.qpid.server.typedmessage.mimecontentconverter.JmsStreamMessageToList;
+import 
org.apache.qpid.server.typedmessage.mimecontentconverter.ListToJmsStreamMessage;
+import 
org.apache.qpid.server.typedmessage.mimecontentconverter.MapToJmsMapMessage;
+import org.apache.qpid.server.util.ByteBufferUtils;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class MessageConverter_1_0_to_v0_10Test extends QpidTestCase
+{
+    private static final MessageAnnotations MESSAGE_MESSAGE_ANNOTATION =
+            new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
 (byte) 0));
+    private static final MessageAnnotations OBJECT_MESSAGE_MESSAGE_ANNOTATION =
+            new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
 (byte) 1));
+    private static final MessageAnnotations MAP_MESSAGE_MESSAGE_ANNOTATION =
+            new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
 (byte) 2));
+    private static final MessageAnnotations BYTE_MESSAGE_MESSAGE_ANNOTATION =
+            new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
 (byte) 3));
+    private static final MessageAnnotations STREAM_MESSAGE_MESSAGE_ANNOTATION =
+            new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
 (byte) 4));
+    private static final MessageAnnotations TEXT_MESSAGE_MESSAGE_ANNOTATION =
+            new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
 (byte) 5));
+    private MessageConverter_1_0_to_v0_10 _converter;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _converter = new MessageConverter_1_0_to_v0_10();
+    }
+
+    public void testAmqpValueWithNull() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testAmqpValueWithNullWithTextMessageAnnotation() throws 
Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage =
+                createTestMessage(TEXT_MESSAGE_MESSAGE_ANNOTATION, 
amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testAmqpValueWithString() throws Exception
+    {
+        final String expected = "testContent";
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertEquals("Unexpected content", expected, new 
String(getBytes(content), UTF_8));
+    }
+
+    public void testAmqpValueWithStringWithTextMessageAnnotation() throws 
Exception
+    {
+        final String expected = "testContent";
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage =
+                createTestMessage(TEXT_MESSAGE_MESSAGE_ANNOTATION, 
amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertEquals("Unexpected content", expected, new 
String(getBytes(content), UTF_8));
+    }
+
+    public void testAmqpValueWithMap() throws Exception
+    {
+        final Map<String, Object> originalMap = new LinkedHashMap<>();
+        originalMap.put("binaryEntry", new Binary(new byte[]{0x00, (byte) 
0xFF}));
+        originalMap.put("intEntry", 42);
+        originalMap.put("nullEntry", null);
+        final AmqpValue amqpValue = new AmqpValue(originalMap);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "jms/map-message", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        Map<String, Object> convertedMap = new 
JmsMapMessageToMap().toObject(getBytes(content));
+        assertEquals("Unexpected size", originalMap.size(), 
convertedMap.size());
+        assertArrayEquals("Unexpected binary entry", ((Binary) 
originalMap.get("binaryEntry")).getArray(),
+                          (byte[]) convertedMap.get("binaryEntry"));
+        assertEquals("Unexpected int entry", originalMap.get("intEntry"), 
convertedMap.get("intEntry"));
+        assertEquals("Unexpected null entry", originalMap.get("nullEntry"), 
convertedMap.get("nullEntry"));
+    }
+
+    public void testAmqpValueWithMapContainingMap() throws Exception
+    {
+        final Map<String, Object> originalMap =
+                Collections.singletonMap("testMap", 
Collections.singletonMap("innerKey", "testValue"));
+
+        final AmqpValue amqpValue = new AmqpValue(originalMap);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "amqp/map", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        Map<String, Object> convertedMap = new 
AmqpMapToMapConverter().toObject(getBytes(content));
+        assertEquals("Unexpected size", originalMap.size(), 
convertedMap.size());
+        assertEquals("Unexpected binary entry", new HashMap((Map<String, 
Object>) originalMap.get("testMap")),
+                     new HashMap((Map<String, Object>) 
convertedMap.get("testMap")));
+    }
+
+    public void testAmqpValueWithMapContainingNonFieldTableCompliantEntries() 
throws Exception
+    {
+        final AmqpValue amqpValue = new AmqpValue(Collections.<Object, 
Object>singletonMap(13, 42));
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        try
+        {
+            _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+            fail("expected exception not thrown.");
+        }
+        catch (MessageConversionException e)
+        {
+            // pass
+        }
+    }
+
+    public void testAmqpValueWithList() throws Exception
+    {
+        final List<Object> originalList = new ArrayList<>();
+        originalList.add(new Binary(new byte[]{0x00, (byte) 0xFF}));
+        originalList.add(42);
+        originalList.add(null);
+        final AmqpValue amqpValue = new AmqpValue(originalList);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "jms/stream-message", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        List<Object> convertedList = new 
JmsStreamMessageToList().toObject(getBytes(content));
+        assertEquals("Unexpected size", originalList.size(), 
convertedList.size());
+        assertArrayEquals("Unexpected binary item", ((Binary) 
originalList.get(0)).getArray(),
+                          (byte[]) convertedList.get(0));
+        assertEquals("Unexpected int item", originalList.get(1), 
convertedList.get(1));
+        assertEquals("Unexpected null item", originalList.get(2), 
convertedList.get(2));
+    }
+
+    public void testAmqpValueWithListContainingMap() throws Exception
+    {
+        final List<Object> originalList = 
Collections.singletonList(Collections.singletonMap("testKey", "testValue"));
+        final AmqpValue amqpValue = new AmqpValue(originalList);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "amqp/list", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        List<Object> convertedList = new 
AmqpListToListConverter().toObject(getBytes(content));
+        assertEquals("Unexpected size", originalList.size(), 
convertedList.size());
+        assertEquals("Unexpected map item", new HashMap<String, Object>((Map) 
originalList.get(0)),
+                     new HashMap<String, Object>((Map) convertedList.get(0)));
+    }
+
+    public void testAmqpValueWithListContainingUnsupportedType() throws 
Exception
+    {
+        final List<Object> originalList = Collections.singletonList(new 
Source());
+        final AmqpValue amqpValue = new AmqpValue(originalList);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        try
+        {
+            _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+            fail("expected exception not thrown.");
+        }
+        catch (MessageConversionException e)
+        {
+            // pass
+        }
+    }
+
+    public void testAmqpValueWithUnsupportedType() throws Exception
+    {
+        final Integer originalValue = 42;
+        final AmqpValue amqpValue = new AmqpValue(originalValue);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        try
+        {
+            _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+            fail("expected exception not thrown.");
+        }
+        catch (MessageConversionException e)
+        {
+            // pass
+        }
+    }
+
+    public void testAmqpSequenceWithSimpleTypes() throws Exception
+    {
+        final List<Integer> expected = new ArrayList<>();
+        expected.add(37);
+        expected.add(42);
+        final AmqpSequence amqpSequence = new AmqpSequence(expected);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpSequence.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "jms/stream-message", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertEquals("Unexpected content", expected, new 
JmsStreamMessageToList().toObject(getBytes(content)));
+    }
+
+    public void testAmqpSequenceWithMap() throws Exception
+    {
+        final List<Object> originalList = 
Collections.singletonList(Collections.singletonMap("testKey", "testValue"));
+        final AmqpSequence amqpSequence = new AmqpSequence(originalList);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpSequence.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "amqp/list", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        List<Object> convertedList = new 
AmqpListToListConverter().toObject(getBytes(content));
+        assertEquals("Unexpected size", originalList.size(), 
convertedList.size());
+        assertEquals("Unexpected map item", new HashMap<String, Object>((Map) 
originalList.get(0)),
+                     new HashMap<String, Object>((Map) convertedList.get(0)));
+    }
+
+    public void testAmqpSequenceWithUnsupportedType() throws Exception
+    {
+        final List<Object> originalList = Collections.singletonList(new 
Source());
+        final AmqpSequence amqpSequence = new AmqpSequence(originalList);
+        Message_1_0 sourceMessage = 
createTestMessage(amqpSequence.createEncodingRetainingSection());
+
+        try
+        {
+            _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+            fail("expected exception not thrown.");
+        }
+        catch (MessageConversionException e)
+        {
+            // pass
+        }
+    }
+
+    public void testDataWithMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), 
MESSAGE_MESSAGE_ANNOTATION, "application/octet-stream");
+    }
+
+    public void testDataWithObjectMessageAnnotation() throws Exception
+    {
+        byte[] bytes = "helloworld".getBytes(UTF_8);
+        final byte[] expected = getObjectBytes(bytes);
+        doTestDataWithAnnotation(expected, OBJECT_MESSAGE_MESSAGE_ANNOTATION, 
"application/java-object-stream");
+    }
+
+    public void testDataWithMapMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 MAP_MESSAGE_MESSAGE_ANNOTATION,
+                                 "application/octet-stream");
+    }
+
+    public void testDataWithMapMessageAnnotationAndContentTypeJmsMapMessage() 
throws Exception
+    {
+        Map<String, Object> originalMap = Collections.singletonMap("testKey", 
"testValue");
+        byte[] data = new MapToJmsMapMessage().toMimeContent(originalMap);
+        String expectedMimeType = "jms/map-message";
+        final Data value = new Data(new Binary(data));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(expectedMimeType));
+        Message_1_0 sourceMessage = createTestMessage(properties,
+                                                      
MAP_MESSAGE_MESSAGE_ANNOTATION,
+                                                      
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     expectedMimeType, 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", data, getBytes(content));
+    }
+
+    public void testDataWithMapMessageAnnotationAndContentTypeAmqpMap() throws 
Exception
+    {
+        Map<String, Object> originalMap = Collections.singletonMap("testKey", 
"testValue");
+        byte[] data = new MapToAmqpMapConverter().toMimeContent(originalMap);
+        String expectedMimeType = "amqp/map";
+        final Data value = new Data(new Binary(data));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(expectedMimeType));
+        Message_1_0 sourceMessage = createTestMessage(properties,
+                                                      
MAP_MESSAGE_MESSAGE_ANNOTATION,
+                                                      
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     expectedMimeType, 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", data, getBytes(content));
+    }
+
+    public void testDataWithBytesMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 BYTE_MESSAGE_MESSAGE_ANNOTATION,
+                                 "application/octet-stream");
+    }
+
+    public void testDataWithStreamMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), 
STREAM_MESSAGE_MESSAGE_ANNOTATION,
+                                 "application/octet-stream");
+    }
+
+    public void 
testDataWithStreamMessageAnnotationAndContentTypeJmsStreamMessage() throws 
Exception
+    {
+        List<Object> originalList = Collections.singletonList("testValue");
+        byte[] data = new ListToJmsStreamMessage().toMimeContent(originalList);
+        String expectedMimeType = "jms/stream-message";
+        final Data value = new Data(new Binary(data));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(expectedMimeType));
+        Message_1_0 sourceMessage = createTestMessage(properties,
+                                                      
STREAM_MESSAGE_MESSAGE_ANNOTATION,
+                                                      
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     expectedMimeType, 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", data, getBytes(content));
+    }
+
+    public void testDataWithStreamMessageAnnotationAndContentTypeAmqpList() 
throws Exception
+    {
+        List<Object> originalList = Collections.singletonList("testValue");
+        byte[] data = new 
ListToAmqpListConverter().toMimeContent(originalList);
+        String expectedMimeType = "amqp/list";
+        final Data value = new Data(new Binary(data));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(expectedMimeType));
+        Message_1_0 sourceMessage = createTestMessage(properties,
+                                                      
STREAM_MESSAGE_MESSAGE_ANNOTATION,
+                                                      
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     expectedMimeType, 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", data, getBytes(content));
+    }
+
+    public void testDataWithTextMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), 
TEXT_MESSAGE_MESSAGE_ANNOTATION, "text/plain");
+    }
+
+    public void testDataWithUnsupportedMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
+                                                                               
  (byte) 11)),
+                                 "application/octet-stream");
+    }
+
+    public void testDataWithContentTypeText() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("text/foobar");
+    }
+
+    public void testDataWithContentTypeApplicationXml() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/xml");
+    }
+
+    public void testDataWithContentTypeApplicationXmlDtd() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/xml-dtd");
+    }
+
+    public void testDataWithContentTypeApplicationFooXml() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/foo+xml");
+    }
+
+    public void testDataWithContentTypeApplicationJson() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/json");
+    }
+
+    public void testDataWithContentTypeApplicationFooJson() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/foo+json");
+    }
+
+    public void testDataWithContentTypeApplicationJavascript() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/javascript");
+    }
+
+    public void testDataWithContentTypeApplicationEcmascript() throws Exception
+    {
+        doTestConvertOfDataSectionForTextualType("application/ecmascript");
+    }
+
+    public void testDataWithContentTypeAmqpMap() throws Exception
+    {
+        Map<String, Object> originalMap = Collections.singletonMap("testKey", 
"testValue");
+        byte[] bytes = new MapToAmqpMapConverter().toMimeContent(originalMap);
+
+        final Data value = new Data(new Binary(bytes));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("amqp/map"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "amqp/map", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", bytes, getBytes(content));
+    }
+
+    public void testDataWithContentTypeJmsMapMessage() throws Exception
+    {
+        Map<String, Object> originalMap = Collections.singletonMap("testKey", 
"testValue");
+        byte[] bytes = new MapToJmsMapMessage().toMimeContent(originalMap);
+
+        final Data value = new Data(new Binary(bytes));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("jms/map-message"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "jms/map-message", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", bytes, getBytes(content));
+    }
+
+    public void testDataWithContentTypeAmqpList() throws Exception
+    {
+        List<Object> originalMap = Collections.singletonList("testValue");
+        byte[] bytes = new 
ListToAmqpListConverter().toMimeContent(originalMap);
+
+        final Data value = new Data(new Binary(bytes));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("amqp/list"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "amqp/list", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", bytes, getBytes(content));
+    }
+
+    public void testDataWithContentTypeJmsStreamMessage() throws Exception
+    {
+        List<Object> originalMap = Collections.singletonList("testValue");
+        byte[] bytes = new ListToJmsStreamMessage().toMimeContent(originalMap);
+
+        final Data value = new Data(new Binary(bytes));
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("jms/stream-message"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "jms/stream-message", 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", bytes, getBytes(content));
+    }
+
+    public void testDataWithContentTypeJavaSerializedObject() throws Exception
+    {
+        final byte[] expected = getObjectBytes("helloworld".getBytes(UTF_8));
+        final Data value = new Data(new Binary(expected));
+        Properties properties = new Properties();
+        
properties.setContentType(Symbol.valueOf("application/x-java-serialized-object"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/java-object-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", expected, getBytes(content));
+    }
+
+
+    public void testDataWithContentTypeJavaObjectStream() throws Exception
+    {
+        final byte[] expected = getObjectBytes("helloworld".getBytes(UTF_8));
+        final Data value = new Data(new Binary(expected));
+        Properties properties = new Properties();
+        
properties.setContentType(Symbol.valueOf("application/java-object-stream"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/java-object-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", expected, getBytes(content));
+    }
+
+    public void testDataWithContentTypeOther() throws Exception
+    {
+        final byte[] expected = "helloworld".getBytes(UTF_8);
+        final Data value = new Data(new Binary(expected));
+        final Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("application/bin"));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/octet-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", expected, getBytes(content));
+    }
+
+    public void testData() throws Exception
+    {
+        final byte[] expected = getObjectBytes("helloworld".getBytes(UTF_8));
+        final Data value = new Data(new Binary(expected));
+        final Message_1_0 sourceMessage = 
createTestMessage(value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/octet-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", expected, getBytes(content));
+    }
+
+    public void testNoBodyWithMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = 
createTestMessage(MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithObjectMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = 
createTestMessage(OBJECT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        assertEquals("Unexpected mime type",
+                     "application/java-object-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertArrayEquals("Unexpected content size", getObjectBytes(null), 
getBytes(content));
+    }
+
+    public void testNoBodyWithMapMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = 
createTestMessage(MAP_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        assertEquals("Unexpected mime type", "jms/map-message", 
convertedMessage.getMessageHeader().getMimeType());
+        assertArrayEquals("Unexpected content size",
+                          new 
MapToJmsMapMessage().toMimeContent(Collections.emptyMap()),
+                          getBytes(content));
+    }
+
+    public void testNoBodyWithBytesMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = 
createTestMessage(BYTE_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/octet-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithStreamMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = 
createTestMessage(STREAM_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "jms/stream-message", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithTextMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = 
createTestMessage(TEXT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithUnknownMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage =
+                createTestMessage(new 
MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
+                                                                               
   (byte) 11)), null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBody() throws Exception
+    {
+        final Message_1_0 sourceMessage = createTestMessage(null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithContentTypeApplicationOctetStream() throws 
Exception
+    {
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("application/octet-stream"));
+        final Message_1_0 sourceMessage = createTestMessage(properties, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size", 0, convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithObjectMessageContentType() throws Exception
+    {
+        final Properties properties = new Properties();
+        
properties.setContentType(Symbol.valueOf("application/x-java-serialized-object"));
+        final Message_1_0 sourceMessage = createTestMessage(properties, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/java-object-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+
+        assertEquals("Unexpected content size",
+                     getObjectBytes(null).length,
+                     convertedMessage.getSize());
+    }
+
+    public void testNoBodyWithJmsMapContentType() throws Exception
+    {
+        final Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("jms/map-message"));
+        final Message_1_0 sourceMessage = createTestMessage(properties, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        assertEquals("Unexpected mime type", "jms/map-message", 
convertedMessage.getMessageHeader().getMimeType());
+
+        assertArrayEquals("Unexpected content size",
+                          new 
MapToJmsMapMessage().toMimeContent(Collections.emptyMap()),
+                          getBytes(content));
+    }
+
+    public void testMessageAnnotationTakesPrecedenceOverContentType() throws 
Exception
+    {
+        final Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf("application/octet-stream"));
+        final Message_1_0 sourceMessage = 
createTestMessage(OBJECT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/java-object-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content size",
+                     getObjectBytes(null).length,
+                     convertedMessage.getSize());
+    }
+
+    private void doTestConvertOfDataSectionForTextualType(final String 
contentType) throws Exception
+    {
+        final String expected = "testContent";
+        final Data value = new Data(new Binary(expected.getBytes(UTF_8)));
+        final Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(contentType));
+        Message_1_0 sourceMessage = createTestMessage(properties, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertEquals("Unexpected content", expected, new 
String(getBytes(content), UTF_8));
+
+        assertEquals("Unexpected mime type", "text/plain", 
convertedMessage.getMessageHeader().getMimeType());
+    }
+
+    private byte[] getBytes(final Collection<QpidByteBuffer> content) throws 
Exception
+    {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        for (QpidByteBuffer buf : content)
+        {
+            ByteStreams.copy(buf.asInputStream(), bos);
+            buf.dispose();
+        }
+        return bos.toByteArray();
+    }
+
+    private Message_1_0 createTestMessage(final EncodingRetainingSection 
encodingRetainingSection)
+    {
+        return createTestMessage(new Properties(), encodingRetainingSection);
+    }
+
+    private Message_1_0 createTestMessage(final Properties properties, final 
EncodingRetainingSection section)
+    {
+        return createTestMessage(new Header(),
+                                 new 
DeliveryAnnotations(Collections.emptyMap()),
+                                 new 
MessageAnnotations(Collections.emptyMap()),
+                                 properties,
+                                 new 
ApplicationProperties(Collections.emptyMap()),
+                                 0,
+                                 section);
+    }
+
+    private Message_1_0 createTestMessage(final Properties properties,
+                                          final MessageAnnotations 
messageAnnotations,
+                                          final EncodingRetainingSection 
section)
+    {
+        return createTestMessage(new Header(),
+                                 new 
DeliveryAnnotations(Collections.emptyMap()),
+                                 messageAnnotations,
+                                 properties,
+                                 new 
ApplicationProperties(Collections.emptyMap()),
+                                 0,
+                                 section);
+    }
+
+    private Message_1_0 createTestMessage(final MessageAnnotations 
messageAnnotations,
+                                          final EncodingRetainingSection 
section)
+    {
+        return createTestMessage(new Header(),
+                                 new 
DeliveryAnnotations(Collections.emptyMap()),
+                                 messageAnnotations,
+                                 new Properties(),
+                                 new 
ApplicationProperties(Collections.emptyMap()),
+                                 0,
+                                 section);
+    }
+
+    private Message_1_0 createTestMessage(final Header header,
+                                          final DeliveryAnnotations 
deliveryAnnotations,
+                                          final MessageAnnotations 
messageAnnotations,
+                                          final Properties properties,
+                                          final ApplicationProperties 
applicationProperties,
+                                          final long arrivalTime,
+                                          final EncodingRetainingSection 
section)
+    {
+        final StoredMessage<MessageMetaData_1_0> storedMessage = 
mock(StoredMessage.class);
+        MessageMetaData_1_0 metaData = new 
MessageMetaData_1_0(header.createEncodingRetainingSection(),
+                                                               
deliveryAnnotations.createEncodingRetainingSection(),
+                                                               
messageAnnotations.createEncodingRetainingSection(),
+                                                               
properties.createEncodingRetainingSection(),
+                                                               
applicationProperties.createEncodingRetainingSection(),
+                                                               new 
Footer(Collections.emptyMap()).createEncodingRetainingSection(),
+                                                               arrivalTime,
+                                                               0);
+        when(storedMessage.getMetaData()).thenReturn(metaData);
+
+        if (section != null)
+        {
+            final QpidByteBuffer combined = 
QpidByteBuffer.wrap(ByteBufferUtils.combine(section.getEncodedForm()));
+            when(storedMessage.getContentSize()).thenReturn((int) 
section.getEncodedSize());
+            final ArgumentCaptor<Integer> offsetCaptor = 
ArgumentCaptor.forClass(Integer.class);
+            final ArgumentCaptor<Integer> sizeCaptor = 
ArgumentCaptor.forClass(Integer.class);
+
+            when(storedMessage.getContent(offsetCaptor.capture(),
+                                          
sizeCaptor.capture())).then(invocation ->
+                                                                      {
+                                                                          
final QpidByteBuffer view = combined.view(
+                                                                               
   offsetCaptor.getValue(),
+                                                                               
   sizeCaptor.getValue());
+                                                                          
return Collections.singleton(view);
+                                                                      });
+        }
+        return new Message_1_0(storedMessage);
+    }
+
+    private byte[] getObjectBytes(final Object object) throws IOException
+    {
+        final byte[] expected;
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(baos))
+        {
+            oos.writeObject(object);
+            expected = baos.toByteArray();
+        }
+        return expected;
+    }
+
+    private void doTestDataWithAnnotation(final byte[] data,
+                                          final MessageAnnotations 
messageAnnotations,
+                                          final String expectedMimeType) 
throws Exception
+    {
+        final Data value = new Data(new Binary(data));
+        Message_1_0 sourceMessage = createTestMessage(messageAnnotations, 
value.createEncodingRetainingSection());
+
+        final MessageTransferMessage convertedMessage = 
_converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     expectedMimeType, 
convertedMessage.getMessageHeader().getMimeType());
+        final Collection<QpidByteBuffer> content = 
convertedMessage.getContent(0, (int) convertedMessage.getSize());
+        assertArrayEquals("Unexpected content", data, getBytes(content));
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/d9027a0b/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_1_0_to_v0_8.java
----------------------------------------------------------------------
diff --git 
a/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_1_0_to_v0_8.java
 
b/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_1_0_to_v0_8.java
index 5eb43a5..30f4235 100644
--- 
a/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_1_0_to_v0_8.java
+++ 
b/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_1_0_to_v0_8.java
@@ -20,21 +20,26 @@
  */
 package org.apache.qpid.server.protocol.converter.v0_8_v1_0;
 
-import static org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.*;
 
-import java.io.Serializable;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.convertValue;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getAbsoluteExpiryTime;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getConvertedContentAndMimeType;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getCorrelationId;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getCreationTime;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getGroupId;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getGroupSequence;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getMessageId;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getTtl;
+import static 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.getUserId;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.qpid.server.bytebuffer.QpidByteBuffer;
 import org.apache.qpid.server.message.MessageDestination;
-import 
org.apache.qpid.server.message.mimecontentconverter.ByteArrayToOctetStream;
-import 
org.apache.qpid.server.message.mimecontentconverter.MimeContentConverterRegistry;
-import 
org.apache.qpid.server.message.mimecontentconverter.ObjectToMimeContentConverter;
 import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.model.Queue;
 import org.apache.qpid.server.plugin.MessageConverter;
@@ -47,10 +52,10 @@ import org.apache.qpid.server.protocol.v0_8.MessageMetaData;
 import 
org.apache.qpid.server.protocol.v0_8.transport.BasicContentHeaderProperties;
 import org.apache.qpid.server.protocol.v0_8.transport.ContentHeaderBody;
 import org.apache.qpid.server.protocol.v0_8.transport.MessagePublishInfo;
+import 
org.apache.qpid.server.protocol.v1_0.MessageConverter_from_1_0.ConvertedContentAndMimeType;
 import org.apache.qpid.server.protocol.v1_0.MessageMetaData_1_0;
 import org.apache.qpid.server.protocol.v1_0.Message_1_0;
 import org.apache.qpid.server.protocol.v1_0.type.Binary;
-import org.apache.qpid.server.protocol.v1_0.type.Symbol;
 import org.apache.qpid.server.protocol.v1_0.type.UnsignedInteger;
 import org.apache.qpid.server.store.StoredMessage;
 
@@ -85,48 +90,12 @@ public class MessageConverter_1_0_to_v0_8 implements 
MessageConverter<Message_1_
     private StoredMessage<MessageMetaData> convertToStoredMessage(final 
Message_1_0 serverMsg,
                                                                   final 
NamedAddressSpace addressSpace)
     {
-        Object bodyObject = convertBodyToObject(serverMsg);
-        ObjectToMimeContentConverter converter = 
MimeContentConverterRegistry.getBestFitObjectToMimeContentConverter(bodyObject);
-
-        ContentHint contentHint = getTypeHint(serverMsg);
-        Class<?> typeHint = contentHint.getContentClass();
-        if (typeHint == null && bodyObject == null)
-        {
-            typeHint = Void.class;
-        }
-
-        if (converter == null)
-        {
-            converter = 
MimeContentConverterRegistry.getBestFitObjectToMimeContentConverter(bodyObject, 
typeHint);
-
-            if (converter == null)
-            {
-                throw new MessageConversionException(String.format(
-                        "Could not convert message from 1.0 to 0-8 because 
conversion of content failed. Could not find mime type converter for the 
content '%s'.", bodyObject == null ? null : 
bodyObject.getClass().getSimpleName()));
-            }
-        }
-
-        final byte[] messageContent = converter.toMimeContent(bodyObject);
-        String mimeType = converter.getMimeType();
-        if (bodyObject instanceof byte[])
-        {
-            if (Serializable.class == typeHint)
-            {
-                mimeType = "application/java-object-stream";
-            }
-            else if (String.class == typeHint)
-            {
-                mimeType = "text/plain";
-            }
-            else if ((Map.class == typeHint || List.class == typeHint) && 
contentHint.getContentType() != null)
-            {
-                mimeType = contentHint.getContentType();
-            }
-        }
+        final ConvertedContentAndMimeType convertedContentAndMimeType = 
getConvertedContentAndMimeType(serverMsg);
+        final byte[] convertedContent = 
convertedContentAndMimeType.getContent();
 
         final MessageMetaData messageMetaData_0_8 = convertMetaData(serverMsg,
-                                                                    mimeType,
-                                                                    
messageContent.length,
+                                                                    
convertedContentAndMimeType.getMimeType(),
+                                                                    
convertedContent.length,
                                                                     
addressSpace);
         final int metadataSize = messageMetaData_0_8.getStorableSize();
 
@@ -147,13 +116,13 @@ public class MessageConverter_1_0_to_v0_8 implements 
MessageConverter<Message_1_
             @Override
             public Collection<QpidByteBuffer> getContent(final int offset, 
final int length)
             {
-                return 
Collections.singleton(QpidByteBuffer.wrap(messageContent, offset, length));
+                return 
Collections.singleton(QpidByteBuffer.wrap(convertedContent, offset, length));
             }
 
             @Override
             public int getContentSize()
             {
-                return messageContent.length;
+                return convertedContent.length;
             }
 
             @Override


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to