You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by lq...@apache.org on 2017/08/10 16:18:55 UTC

qpid-broker-j git commit: QPID-7434: [Java Broker] Improve AMQP 1.0 to Internal content conversion and add unit tests

Repository: qpid-broker-j
Updated Branches:
  refs/heads/master 47c64a075 -> 2e809efcc


QPID-7434: [Java Broker] Improve AMQP 1.0 to Internal 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/2e809efc
Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/2e809efc
Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/2e809efc

Branch: refs/heads/master
Commit: 2e809efccb6d431a413c9497b6785a16cfb4d668
Parents: 47c64a0
Author: Lorenz Quack <lq...@apache.org>
Authored: Thu Aug 10 13:45:09 2017 +0100
Committer: Lorenz Quack <lq...@apache.org>
Committed: Thu Aug 10 17:18:19 2017 +0100

----------------------------------------------------------------------
 .../message/internal/InternalMessage.java       |  11 +-
 .../internal/InternalMessageMetaData.java       |  44 +-
 .../qpid/server/protocol/v0_8/FieldTable.java   |   5 +
 .../v1_0/MessageConverter_from_1_0.java         |  21 +-
 .../v1_0/MessageConverter_v1_0_to_Internal.java | 188 ++++-
 .../MessageConverter_v1_0_to_InternalTest.java  | 744 +++++++++++++++++++
 .../MessageConverter_1_0_to_v0_10.java          |   4 +-
 .../PropertyConverter_0_10_to_0_8Test.java      |  18 -
 .../v0_8_v1_0/MessageConverter_1_0_to_v0_8.java |   4 +-
 .../PropertyConverter_1_0_to_0_8Test.java       |  34 +
 10 files changed, 1011 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java
----------------------------------------------------------------------
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java b/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java
index 21c55bf..3382109 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java
@@ -40,9 +40,9 @@ import org.apache.qpid.server.store.MessageHandle;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.store.StoredMessage;
 import org.apache.qpid.server.store.TransactionLogResource;
-import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 import org.apache.qpid.server.util.ByteBufferInputStream;
 import org.apache.qpid.server.util.ByteBufferUtils;
+import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 
 public class InternalMessage extends AbstractServerMessageImpl<InternalMessage, InternalMessageMetaData>
 {
@@ -53,10 +53,10 @@ public class InternalMessage extends AbstractServerMessageImpl<InternalMessage,
     private final String _destinationName;
 
 
-    InternalMessage(final StoredMessage<InternalMessageMetaData> handle,
-                    final InternalMessageHeader header,
-                    final Object messageBody,
-                    final String destinationName)
+    public InternalMessage(final StoredMessage<InternalMessageMetaData> handle,
+                           final InternalMessageHeader header,
+                           final Object messageBody,
+                           final String destinationName)
     {
         super(handle, null);
         _header = header;
@@ -64,6 +64,7 @@ public class InternalMessage extends AbstractServerMessageImpl<InternalMessage,
         _destinationName = destinationName;
     }
 
+    // used by recovery path
     InternalMessage(final StoredMessage<InternalMessageMetaData> msg,
                     final String destinationName)
     {

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java
----------------------------------------------------------------------
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java b/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java
index 0d8728b..feb9992 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java
@@ -30,31 +30,16 @@ import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 
 public class InternalMessageMetaData implements StorableMessageMetaData
 {
-
-
-    private boolean _isPersistent;
-    private InternalMessageHeader _header;
-    private int _contentSize;
-    private byte[] _headerBytes;
+    private final boolean _isPersistent;
+    private final InternalMessageHeader _header;
+    private final int _contentSize;
+    private volatile byte[] _headerBytes;
 
     public InternalMessageMetaData(final boolean isPersistent, final InternalMessageHeader header, final int contentSize)
     {
         _isPersistent = isPersistent;
         _header = header;
         _contentSize = contentSize;
-
-        try(ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
-            ObjectOutputStream os = new ObjectOutputStream(bytesOut))
-        {
-            os.writeInt(contentSize);
-            os.writeObject(header);
-            os.close();
-            _headerBytes = bytesOut.toByteArray();
-        }
-        catch (IOException e)
-        {
-            throw new ConnectionScopedRuntimeException("Unexpected IO Exception on in memory operation", e);
-        }
     }
 
     @Override
@@ -66,12 +51,14 @@ public class InternalMessageMetaData implements StorableMessageMetaData
     @Override
     public int getStorableSize()
     {
+        ensureHeaderIsEncoded();
         return _headerBytes.length;
     }
 
     @Override
     public void writeToBuffer(final QpidByteBuffer dest)
     {
+        ensureHeaderIsEncoded();
         dest.put(_headerBytes);
     }
 
@@ -115,5 +102,22 @@ public class InternalMessageMetaData implements StorableMessageMetaData
         return new InternalMessageMetaData(persistent, header, contentSize);
     }
 
-
+    private void ensureHeaderIsEncoded()
+    {
+        if (_headerBytes == null)
+        {
+            try(ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+                ObjectOutputStream os = new ObjectOutputStream(bytesOut))
+            {
+                os.writeInt(_contentSize);
+                os.writeObject(_header);
+                os.close();
+                _headerBytes = bytesOut.toByteArray();
+            }
+            catch (IOException e)
+            {
+                throw new ConnectionScopedRuntimeException("Unexpected IO Exception on in memory operation", e);
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-core/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
----------------------------------------------------------------------
diff --git a/broker-core/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java b/broker-core/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
index c344bb8..3fd8408 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
@@ -31,6 +31,7 @@ import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -722,6 +723,10 @@ public class FieldTable
         {
             return setBytes(string, (byte[]) object);
         }
+        else if (object instanceof UUID)
+        {
+            return setString(string, object.toString());
+        }
 
         throw new AMQPInvalidClassException(AMQPInvalidClassException.INVALID_OBJECT_MSG + (object == null ? "null" : object.getClass()));
     }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/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 62230d8..d5581fa 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
@@ -74,7 +74,8 @@ public class MessageConverter_from_1_0
                                                                                         Character.class,
                                                                                         String.class,
                                                                                         byte[].class,
-                                                                                        UUID.class));
+                                                                                        UUID.class,
+                                                                                        Date.class));
 
     public static final Pattern TEXT_CONTENT_TYPES = Pattern.compile("^(text/.*)|(application/(xml|xml-dtd|.*\\+xml|json|.*\\+json|javascript|ecmascript))$");
     public static final Pattern MAP_MESSAGE_CONTENT_TYPES = Pattern.compile("^amqp/map|jms/map-message$");
@@ -206,10 +207,6 @@ public class MessageConverter_from_1_0
             {
                 return value.toString();
             }
-            else if(value instanceof Date)
-            {
-                return ((Date)value).getTime();
-            }
             else if(value instanceof Binary)
             {
                 return ((Binary)value).getArray();
@@ -237,7 +234,7 @@ public class MessageConverter_from_1_0
         return result;
     }
 
-    private static ContentHint getTypeHint(final Message_1_0 serverMsg)
+    private static ContentHint getAmqp0xTypeHint(final Message_1_0 serverMsg)
     {
         Symbol contentType = getContentType(serverMsg);
 
@@ -502,12 +499,12 @@ public class MessageConverter_from_1_0
         return messageId;
     }
 
-    public static ConvertedContentAndMimeType getConvertedContentAndMimeType(final Message_1_0 serverMsg)
+    public static ConvertedContentAndMimeType getAmqp0xConvertedContentAndMimeType(final Message_1_0 serverMsg)
     {
         Object bodyObject = convertBodyToObject(serverMsg);
         ObjectToMimeContentConverter converter = getBestFitObjectToMimeContentConverter(bodyObject);
 
-        ContentHint contentHint = getTypeHint(serverMsg);
+        ContentHint contentHint = getAmqp0xTypeHint(serverMsg);
         Class<?> typeHint = contentHint.getContentClass();
         if (typeHint == null && bodyObject == null)
         {
@@ -548,23 +545,23 @@ public class MessageConverter_from_1_0
         return new ConvertedContentAndMimeType(messageContent, mimeType);
     }
 
-    private static class ContentHint
+    public static class ContentHint
     {
         private final Class<?> _contentClass;
         private final String _contentType;
 
-        private ContentHint(final Class<?> contentClass, final String contentType)
+        public ContentHint(final Class<?> contentClass, final String contentType)
         {
             _contentClass = contentClass;
             _contentType = contentType;
         }
 
-        private Class<?> getContentClass()
+        public Class<?> getContentClass()
         {
             return _contentClass;
         }
 
-        private String getContentType()
+        public String getContentType()
         {
             return _contentType;
         }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java
----------------------------------------------------------------------
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java
index 35fc420..749c1a6 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java
@@ -20,11 +20,20 @@
  */
 package org.apache.qpid.server.protocol.v1_0;
 
-import org.apache.qpid.server.model.NamedAddressSpace;
-import org.apache.qpid.server.protocol.v1_0.type.codec.AMQPDescribedTypeRegistry;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.message.AMQMessageHeader;
 import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.message.internal.InternalMessageHeader;
+import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.plugin.MessageConverter;
 import org.apache.qpid.server.plugin.PluggableService;
+import org.apache.qpid.server.protocol.v1_0.type.Symbol;
+import org.apache.qpid.server.protocol.v1_0.type.codec.AMQPDescribedTypeRegistry;
+import org.apache.qpid.server.protocol.v1_0.type.messaging.MessageAnnotationsSection;
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
 
 @PluggableService
 public class MessageConverter_v1_0_to_Internal implements MessageConverter<Message_1_0, InternalMessage>
@@ -55,8 +64,31 @@ public class MessageConverter_v1_0_to_Internal implements MessageConverter<Messa
     public InternalMessage convert(Message_1_0 serverMessage, NamedAddressSpace addressSpace)
     {
         Object bodyObject = MessageConverter_from_1_0.convertBodyToObject(serverMessage);
+        final AMQMessageHeader convertHeader = convertHeader(serverMessage, addressSpace, bodyObject);
+        return InternalMessage.convert(serverMessage, convertHeader, bodyObject);
+    }
 
-        return InternalMessage.convert(serverMessage, serverMessage.getMessageHeader(), bodyObject);
+    private AMQMessageHeader convertHeader(final Message_1_0 serverMessage,
+                                           final NamedAddressSpace addressSpace,
+                                           final Object convertedBodyObject)
+    {
+        final String convertedMimeType = getInternalConvertedContentAndMimeType(serverMessage, convertedBodyObject);
+        final MessageMetaData_1_0.MessageHeader_1_0 messageHeader = serverMessage.getMessageHeader();
+        final InternalMessageHeader header = new InternalMessageHeader(messageHeader.getHeadersAsMap(),
+                                                                       messageHeader.getCorrelationId(),
+                                                                       messageHeader.getExpiration(),
+                                                                       messageHeader.getUserId(),
+                                                                       messageHeader.getAppId(),
+                                                                       messageHeader.getMessageId(),
+                                                                       convertedMimeType,
+                                                                       messageHeader.getEncoding(),
+                                                                       messageHeader.getPriority(),
+                                                                       messageHeader.getTimestamp(),
+                                                                       messageHeader.getNotValidBefore(),
+                                                                       messageHeader.getType(),
+                                                                       messageHeader.getReplyTo(),
+                                                                       serverMessage.getArrivalTime());
+        return header;
     }
 
     @Override
@@ -70,4 +102,154 @@ public class MessageConverter_v1_0_to_Internal implements MessageConverter<Messa
     {
         return "v1-0 to Internal";
     }
+
+    private static String getInternalConvertedContentAndMimeType(final Message_1_0 serverMsg,
+                                                                 final Object convertedBodyObject)
+    {
+        MessageConverter_from_1_0.ContentHint contentHint = getInternalTypeHint(serverMsg);
+
+        final Class<?> contentClassHint = contentHint.getContentClass();
+        final String originalContentType = contentHint.getContentType();
+        String mimeType = originalContentType;
+        if (convertedBodyObject == null)
+        {
+            if (contentClassHint == Void.class
+                || contentClassHint == Map.class
+                || contentClassHint == List.class)
+            {
+                mimeType = null;
+            }
+            else if (contentClassHint == Serializable.class)
+            {
+                mimeType = "application/x-java-serialized-object";
+            }
+            else if (contentClassHint == byte[].class)
+            {
+                mimeType = "application/octet-stream";
+            }
+            else if (contentClassHint == String.class
+                     && (originalContentType == null
+                         || !MessageConverter_from_1_0.TEXT_CONTENT_TYPES.matcher(originalContentType).matches()))
+            {
+                mimeType = "text/plain";
+            }
+        }
+        else if (convertedBodyObject instanceof byte[]
+                 && originalContentType == null)
+        {
+            if (contentClassHint == Serializable.class)
+            {
+                mimeType = "application/x-java-serialized-object";
+            }
+            else
+            {
+                mimeType = "application/octet-stream";
+            }
+        }
+        else if (convertedBodyObject instanceof List
+                 || convertedBodyObject instanceof Map)
+        {
+            mimeType = null;
+        }
+        else if (convertedBodyObject instanceof String
+                 && (originalContentType == null
+                     || !MessageConverter_from_1_0.TEXT_CONTENT_TYPES.matcher(originalContentType).matches()))
+        {
+            mimeType = "text/plain";
+        }
+
+        return mimeType;
+    }
+
+    private static MessageConverter_from_1_0.ContentHint getInternalTypeHint(final Message_1_0 serverMsg)
+    {
+        Symbol contentType = MessageConverter_from_1_0.getContentType(serverMsg);
+
+        JmsMessageTypeAnnotation jmsMessageTypeAnnotation = null;
+        MessageAnnotationsSection section = serverMsg.getMessageAnnotationsSection();
+        if (section != null)
+        {
+            Map<Symbol, Object> annotations = section.getValue();
+            if (annotations != null && annotations.containsKey(JmsMessageTypeAnnotation.ANNOTATION_KEY))
+            {
+                Object object = annotations.get(JmsMessageTypeAnnotation.ANNOTATION_KEY);
+                if (object instanceof Byte)
+                {
+                    try
+                    {
+                        jmsMessageTypeAnnotation = JmsMessageTypeAnnotation.valueOf(((Byte) object));
+                    }
+                    catch (IllegalArgumentException e)
+                    {
+                        // ignore
+                    }
+                }
+            }
+        }
+
+        Class<?> classHint = null;
+        String mimeTypeHint = null;
+
+        if (jmsMessageTypeAnnotation != null)
+        {
+            switch (jmsMessageTypeAnnotation)
+            {
+                case MESSAGE:
+                    classHint = Void.class;
+                    break;
+                case MAP_MESSAGE:
+                    classHint = Map.class;
+                    break;
+                case BYTES_MESSAGE:
+                    classHint = byte[].class;
+                    break;
+                case OBJECT_MESSAGE:
+                    classHint = Serializable.class;
+                    break;
+                case TEXT_MESSAGE:
+                    classHint = String.class;
+                    break;
+                case STREAM_MESSAGE:
+                    classHint = List.class;
+                    break;
+                default:
+                    throw new ServerScopedRuntimeException(String.format(
+                            "Unexpected jms message type annotation %s", jmsMessageTypeAnnotation));
+            }
+        }
+
+        if (contentType != null)
+        {
+            Class<?> contentTypeClassHint = null;
+            String type = contentType.toString();
+            if (MessageConverter_from_1_0.TEXT_CONTENT_TYPES.matcher(type).matches())
+            {
+                contentTypeClassHint = String.class;
+            }
+            else if (MessageConverter_from_1_0.MAP_MESSAGE_CONTENT_TYPES.matcher(type).matches())
+            {
+                contentTypeClassHint = Map.class;
+            }
+            else if (MessageConverter_from_1_0.LIST_MESSAGE_CONTENT_TYPES.matcher(type).matches())
+            {
+                contentTypeClassHint = List.class;
+            }
+            else if (MessageConverter_from_1_0.OBJECT_MESSAGE_CONTENT_TYPES.matcher(type).matches())
+            {
+                contentTypeClassHint = Serializable.class;
+            }
+            else if (MessageConverter_from_1_0.BYTES_MESSAGE_CONTENT_TYPES.matcher(type).matches())
+            {
+                contentTypeClassHint = byte[].class;
+            }
+
+            if (classHint == null || classHint == contentTypeClassHint)
+            {
+                classHint = contentTypeClassHint;
+            }
+            mimeTypeHint = contentType.toString();
+        }
+
+        return new MessageConverter_from_1_0.ContentHint(classHint, mimeTypeHint);
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-plugins/amqp-1-0-protocol/src/test/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_InternalTest.java
----------------------------------------------------------------------
diff --git a/broker-plugins/amqp-1-0-protocol/src/test/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_InternalTest.java b/broker-plugins/amqp-1-0-protocol/src/test/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_InternalTest.java
new file mode 100644
index 0000000..6c68154
--- /dev/null
+++ b/broker-plugins/amqp-1-0-protocol/src/test/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_InternalTest.java
@@ -0,0 +1,744 @@
+/*
+ * 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.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.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.google.common.io.ByteStreams;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.qpid.server.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.model.NamedAddressSpace;
+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.util.ByteBufferUtils;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class MessageConverter_v1_0_to_InternalTest 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_v1_0_to_Internal _converter;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _converter = new MessageConverter_v1_0_to_Internal();
+    }
+
+    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 InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+        assertEquals("Unexpected mime type", "text/plain", convertedMessage.getMessageHeader().getMimeType());
+    }
+
+    public void testAmqpValueWithNullWithMessageAnnotation() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage =
+                createTestMessage(MESSAGE_MESSAGE_ANNOTATION, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithNullWithObjectMessageAnnotation() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(OBJECT_MESSAGE_MESSAGE_ANNOTATION, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        final Collection<QpidByteBuffer> content = convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        assertEquals("Unexpected mime type",
+                     "application/x-java-serialized-object",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithNullWithMapMessageAnnotation() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(MAP_MESSAGE_MESSAGE_ANNOTATION, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        final Collection<QpidByteBuffer> content = convertedMessage.getContent(0, (int) convertedMessage.getSize());
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithNullWithBytesMessageAnnotation() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(BYTE_MESSAGE_MESSAGE_ANNOTATION, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/octet-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithNullWithStreamMessageAnnotation() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(STREAM_MESSAGE_MESSAGE_ANNOTATION, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithNullWithUnknownMessageAnnotation() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage =
+                createTestMessage(new MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
+                                                                                  (byte) 11)),
+                                  amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithNullWithContentType() throws Exception
+    {
+        Properties properties = new Properties();
+        final String mimeType = "foo/bar";
+        properties.setContentType(Symbol.valueOf(mimeType));
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(properties, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     mimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+
+    public void testAmqpValueWithNull() throws Exception
+    {
+        final Object expected = null;
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertNull("Unexpected content", convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithString() throws Exception
+    {
+        final String expected = "testContent";
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage 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, convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithStringWithKnownTextualContentType() throws Exception
+    {
+        Properties properties = new Properties();
+        final String mimeType = "text/foo";
+        properties.setContentType(Symbol.valueOf(mimeType));
+        final Object expected = "content";
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(properties, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     mimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", expected, convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpValueWithStringWithUnknownTextualContentType() throws Exception
+    {
+        Properties properties = new Properties();
+        final String mimeType = "foo/bar";
+        properties.setContentType(Symbol.valueOf(mimeType));
+        final Object expected = "content";
+        final AmqpValue amqpValue = new AmqpValue(expected);
+        Message_1_0 sourceMessage = createTestMessage(properties, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "text/plain", convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", expected, convertedMessage.getMessageBody());
+    }
+
+
+    public void testAmqpValueWithMap() throws Exception
+    {
+        final Map<Object, Object> originalMap = new LinkedHashMap<>();
+        originalMap.put("binaryEntry", new Binary(new byte[]{0x00, (byte) 0xFF}));
+        originalMap.put("intEntry", 42);
+        originalMap.put("uuidEntry", UUID.randomUUID());
+        originalMap.put("nullEntry", null);
+        originalMap.put(43, "nonstringkey");
+        originalMap.put("mapEntry", Collections.singletonMap("foo", "bar"));
+        final AmqpValue amqpValue = new AmqpValue(originalMap);
+        Message_1_0 sourceMessage = createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+
+        Map<Object, Object> convertedMap = (Map<Object, Object>) convertedMessage.getMessageBody();
+
+        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"));
+        assertEquals("Unexpected uuid entry", originalMap.get("uuidEntry"), convertedMap.get("uuidEntry"));
+        assertEquals("Unexpected nonstringkey entry", originalMap.get(43), convertedMap.get(43));
+        assertEquals("Unexpected map entry", new HashMap((Map) originalMap.get("mapEntry")), new HashMap((Map) convertedMap.get("mapEntry")));
+    }
+
+    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);
+        originalList.add(Collections.singletonMap("foo", "bar"));
+        final AmqpValue amqpValue = new AmqpValue(originalList);
+        Message_1_0 sourceMessage = createTestMessage(amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+
+        List<Object> convertedList = ((List<Object>) convertedMessage.getMessageBody());
+        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));
+        assertEquals("Unexpected map item", new HashMap((Map) originalList.get(3)), new HashMap((Map) convertedList.get(3)));
+    }
+
+
+    public void testAmqpValueWithAmqpType() throws Exception
+    {
+        final Date originalValue = new Date();
+        final AmqpValue amqpValue = new AmqpValue(originalValue);
+        Properties properties = new Properties();
+        final String mimeType = "foo/bar";
+        properties.setContentType(Symbol.valueOf(mimeType));
+        Message_1_0 sourceMessage = createTestMessage(properties, amqpValue.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", mimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", originalValue, convertedMessage.getMessageBody());
+    }
+
+    public void testAmqpSequenceWithSimpleTypes() throws Exception
+    {
+        final List<Object> originalList = new ArrayList<>();
+        originalList.add(37);
+        originalList.add(42F);
+        final AmqpSequence amqpSequence = new AmqpSequence(originalList);
+        Message_1_0 sourceMessage = createTestMessage(amqpSequence.createEncodingRetainingSection());
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        List<Object> convertedList = ((List<Object>) convertedMessage.getMessageBody());
+        assertEquals("Unexpected size", originalList.size(), convertedList.size());
+        assertEquals("Unexpected first item", originalList.get(0), convertedList.get(0));
+        assertEquals("Unexpected second item", originalList.get(1), convertedList.get(1));
+    }
+
+    public void testDataWithMessageAnnotation() throws Exception
+    {
+        final byte[] data = "helloworld".getBytes(UTF_8);
+        doTestDataWithAnnotation(data, MESSAGE_MESSAGE_ANNOTATION, null, "application/octet-stream");
+
+    }
+
+    public void testDataWithMessageAnnotationWithContentType() throws Exception
+    {
+        final byte[] data = "helloworld".getBytes(UTF_8);
+        final String mimeType = "foo/bar";
+        doTestDataWithAnnotation(data, MESSAGE_MESSAGE_ANNOTATION, mimeType, mimeType);
+    }
+
+    public void testDataWithObjectMessageAnnotation() throws Exception
+    {
+        byte[] bytes = "helloworld".getBytes(UTF_8);
+        final byte[] expected = getObjectBytes(bytes);
+        doTestDataWithAnnotation(expected, OBJECT_MESSAGE_MESSAGE_ANNOTATION,
+                                 null,
+                                 "application/x-java-serialized-object");
+    }
+
+    public void testDataWithObjectMessageAnnotationWithContentType() throws Exception
+    {
+        byte[] bytes = "helloworld".getBytes(UTF_8);
+        final byte[] expected = getObjectBytes(bytes);
+        final String mimeType = "foo/bar";
+        doTestDataWithAnnotation(expected, OBJECT_MESSAGE_MESSAGE_ANNOTATION, mimeType, mimeType);
+    }
+
+    public void testDataWithMapMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 MAP_MESSAGE_MESSAGE_ANNOTATION,
+                                 null, "application/octet-stream");
+    }
+
+    public void testDataWithMapMessageAnnotationWithContentType() throws Exception
+    {
+        final String mimeType = "foor/bar";
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 MAP_MESSAGE_MESSAGE_ANNOTATION,
+                                 mimeType, mimeType);
+    }
+
+    public void testDataWithBytesMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 BYTE_MESSAGE_MESSAGE_ANNOTATION,
+                                 null, "application/octet-stream");
+    }
+
+    public void testDataWithBytesMessageAnnotationWithContentType() throws Exception
+    {
+        final String mimeType = "foo/bar";
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 BYTE_MESSAGE_MESSAGE_ANNOTATION,
+                                 mimeType, mimeType);
+    }
+
+    public void testDataWithStreamMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), STREAM_MESSAGE_MESSAGE_ANNOTATION,
+                                 null, "application/octet-stream");
+    }
+
+    public void testDataWithStreamMessageAnnotationWithContentType() throws Exception
+    {
+        final String mimeType = "foo/bar";
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), STREAM_MESSAGE_MESSAGE_ANNOTATION,
+                                 mimeType, mimeType);
+    }
+
+    public void testDataWithTextMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), TEXT_MESSAGE_MESSAGE_ANNOTATION, null, "application/octet-stream");
+    }
+
+    public void testDataWithTextMessageAnnotationWithContentType() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8), TEXT_MESSAGE_MESSAGE_ANNOTATION, "foo/bar", "foo/bar");
+    }
+
+    public void testDataWithUnsupportedMessageAnnotation() throws Exception
+    {
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 new MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
+                                                                                 (byte) 11)),
+                                 null, "application/octet-stream");
+    }
+
+    public void testDataWithUnsupportedMessageAnnotationWithContentType() throws Exception
+    {
+        final String mimeType = "foo/bar";
+        doTestDataWithAnnotation("helloworld".getBytes(UTF_8),
+                                 new MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
+                                                                                 (byte) 11)),
+                                 mimeType, mimeType);
+    }
+
+    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 InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/octet-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertArrayEquals("Unexpected content", expected, ((byte[]) convertedMessage.getMessageBody()));
+    }
+
+    public void testNoBodyWithMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = createTestMessage(MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithObjectMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = createTestMessage(OBJECT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/x-java-serialized-object",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithMapMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = createTestMessage(MAP_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithBytesMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = createTestMessage(BYTE_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/octet-stream",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithStreamMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = createTestMessage(STREAM_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithTextMessageAnnotation() throws Exception
+    {
+        Message_1_0 sourceMessage = createTestMessage(TEXT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithTextMessageAnnotationWithKnownTextualContentType() throws Exception
+    {
+        final String mimeType = "text/foo";
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(mimeType));
+
+        Message_1_0 sourceMessage = createTestMessage(properties, TEXT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", mimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithTextMessageAnnotationWithUnknownTextualContentType() throws Exception
+    {
+        final String mimeType = "foo/bar";
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(mimeType));
+        Message_1_0 sourceMessage = createTestMessage(properties, TEXT_MESSAGE_MESSAGE_ANNOTATION, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", "text/plain", convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+
+    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 InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithUnknownMessageAnnotationWithContentType() throws Exception
+    {
+
+        final String mimeType = "foo/bar";
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(mimeType));
+        Message_1_0 sourceMessage =
+                createTestMessage(properties, new MessageAnnotations(Collections.singletonMap(Symbol.valueOf("x-opt-jms-msg-type"),
+                                                                                  (byte) 11)), null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", mimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBody() throws Exception
+    {
+        final Message_1_0 sourceMessage = createTestMessage(null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", null, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    public void testNoBodyWithContentTypeApplicationOctetStream() throws Exception
+    {
+        final String mimeType = "foo/bar";
+        Properties properties = new Properties();
+        properties.setContentType(Symbol.valueOf(mimeType));
+        final Message_1_0 sourceMessage = createTestMessage(properties, null);
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type", mimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    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 InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     "application/x-java-serialized-object",
+                     convertedMessage.getMessageHeader().getMimeType());
+        assertEquals("Unexpected content", null, convertedMessage.getMessageBody());
+    }
+
+    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 mimeType, final String expectedMimeType) throws Exception
+    {
+
+        final Data value = new Data(new Binary(data));
+
+        Message_1_0 sourceMessage;
+        if (mimeType != null)
+        {
+            Properties properties = new Properties();
+            properties.setContentType(Symbol.valueOf(mimeType));
+            sourceMessage = createTestMessage(properties, messageAnnotations, value.createEncodingRetainingSection());
+        }
+        else
+        {
+            sourceMessage = createTestMessage(messageAnnotations, value.createEncodingRetainingSection());
+        }
+
+        final InternalMessage convertedMessage = _converter.convert(sourceMessage, mock(NamedAddressSpace.class));
+
+        assertEquals("Unexpected mime type",
+                     expectedMimeType, convertedMessage.getMessageHeader().getMimeType());
+        assertArrayEquals("Unexpected content", data, ((byte[]) convertedMessage.getMessageBody()));
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/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 ad94f42..c10a232 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
@@ -23,7 +23,7 @@ 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.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.getAmqp0xConvertedContentAndMimeType;
 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;
@@ -103,7 +103,7 @@ 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)
     {
-        final ConvertedContentAndMimeType convertedContentAndMimeType = getConvertedContentAndMimeType(serverMsg);
+        final ConvertedContentAndMimeType convertedContentAndMimeType = getAmqp0xConvertedContentAndMimeType(serverMsg);
         final byte[] convertedContent = convertedContentAndMimeType.getContent();
         final MessageMetaData_0_10 messageMetaData_0_10 = convertMetaData(serverMsg,
                                                                           addressSpace,

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/PropertyConverter_0_10_to_0_8Test.java
----------------------------------------------------------------------
diff --git a/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/PropertyConverter_0_10_to_0_8Test.java b/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/PropertyConverter_0_10_to_0_8Test.java
index 1c2f2a1..e46d732 100644
--- a/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/PropertyConverter_0_10_to_0_8Test.java
+++ b/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/PropertyConverter_0_10_to_0_8Test.java
@@ -120,24 +120,6 @@ public class PropertyConverter_0_10_to_0_8Test extends QpidTestCase
         assertEquals("Unexpected subject in application properties", testSubject, applicationProperties.get("qpid.subject"));
     }
 
-    public void testApplicationHeadersConversionContainingInconvertibleValues()
-    {
-        Map<String, Object> headers = Collections.singletonMap("testUUID", UUID.randomUUID());
-        final MessageProperties messageProperties = new MessageProperties();
-        messageProperties.setApplicationHeaders(headers);
-        MessageTransferMessage message = createTestMessage(messageProperties);
-
-        try
-        {
-            _messageConverter.convert(message, _namedAddressSpace);
-            fail("Exception is not thrown");
-        }
-        catch (MessageConversionException e)
-        {
-            // pass
-        }
-    }
-
     public void testPersistentDeliveryModeConversion()
     {
         MessageDeliveryMode deliveryMode = MessageDeliveryMode.PERSISTENT;

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/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 30f4235..73e6b65 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
@@ -23,7 +23,7 @@ package org.apache.qpid.server.protocol.converter.v0_8_v1_0;
 
 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.getAmqp0xConvertedContentAndMimeType;
 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;
@@ -90,7 +90,7 @@ public class MessageConverter_1_0_to_v0_8 implements MessageConverter<Message_1_
     private StoredMessage<MessageMetaData> convertToStoredMessage(final Message_1_0 serverMsg,
                                                                   final NamedAddressSpace addressSpace)
     {
-        final ConvertedContentAndMimeType convertedContentAndMimeType = getConvertedContentAndMimeType(serverMsg);
+        final ConvertedContentAndMimeType convertedContentAndMimeType = getAmqp0xConvertedContentAndMimeType(serverMsg);
         final byte[] convertedContent = convertedContentAndMimeType.getContent();
 
         final MessageMetaData messageMetaData_0_8 = convertMetaData(serverMsg,

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2e809efc/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/PropertyConverter_1_0_to_0_8Test.java
----------------------------------------------------------------------
diff --git a/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/PropertyConverter_1_0_to_0_8Test.java b/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/PropertyConverter_1_0_to_0_8Test.java
index 067fe35..efd35fd 100644
--- a/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/PropertyConverter_1_0_to_0_8Test.java
+++ b/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/test/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/PropertyConverter_1_0_to_0_8Test.java
@@ -116,6 +116,40 @@ public class PropertyConverter_1_0_to_0_8Test extends QpidTestCase
         assertEquals("Unexpected headers", properties, new HashMap<>(headers));
     }
 
+    public void testApplicationPropertiesConversionWithUuid()
+    {
+        Map<String, Object> properties = new HashMap<>();
+        final String key = "uuidProperty";
+        properties.put(key, UUID.randomUUID());
+        ApplicationProperties applicationProperties = new ApplicationProperties(properties);
+        Message_1_0 message = createTestMessage(applicationProperties);
+
+        final AMQMessage convertedMessage = _messageConverter.convert(message, _namedAddressSpace);
+
+        BasicContentHeaderProperties convertedProperties = convertedMessage.getContentHeaderBody().getProperties();
+        final Map<String, Object> headers = FieldTable.convertToMap(convertedProperties.getHeaders());
+        assertEquals("Unexpected headers size", properties.size(), headers.size());
+        assertEquals("Unexpected headers", properties.get(key), UUID.fromString((String) headers.get(key)));
+
+    }
+
+    public void testApplicationPropertiesConversionWithDate()
+    {
+        Map<String, Object> properties = new HashMap<>();
+        final String key = "dateProperty";
+        properties.put(key, new Date());
+        ApplicationProperties applicationProperties = new ApplicationProperties(properties);
+        Message_1_0 message = createTestMessage(applicationProperties);
+
+        final AMQMessage convertedMessage = _messageConverter.convert(message, _namedAddressSpace);
+
+        BasicContentHeaderProperties convertedProperties = convertedMessage.getContentHeaderBody().getProperties();
+        final Map<String, Object> headers = FieldTable.convertToMap(convertedProperties.getHeaders());
+        assertEquals("Unexpected headers size", properties.size(), headers.size());
+        assertEquals("Unexpected headers", properties.get(key), new Date((Long) headers.get(key)));
+
+    }
+
     public void testSubjectConversion()
     {
         final String subject = "testSubject";


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