You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2016/10/07 14:51:03 UTC

[2/5] activemq-artemis git commit: ARTEMIS-770 AMQP Message Transformer refactor

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/62627bf2/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageIdHelperTest.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageIdHelperTest.java b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageIdHelperTest.java
new file mode 100644
index 0000000..c53cda5
--- /dev/null
+++ b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageIdHelperTest.java
@@ -0,0 +1,391 @@
+/*
+ *
+ * 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.activemq.artemis.protocol.amqp.converter.message;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.junit.Before;
+import org.junit.Test;
+
+public class AMQPMessageIdHelperTest {
+
+   private AMQPMessageIdHelper messageIdHelper;
+
+   @Before
+   public void setUp() throws Exception {
+      messageIdHelper = new AMQPMessageIdHelper();
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns null if given
+    * null
+    */
+   @Test
+   public void testToBaseMessageIdStringWithNull() {
+      String nullString = null;
+      assertNull("null string should have been returned", messageIdHelper.toBaseMessageIdString(nullString));
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} throws an IAE if given
+    * an unexpected object type.
+    */
+   @Test
+   public void testToBaseMessageIdStringThrowsIAEWithUnexpectedType() {
+      try {
+         messageIdHelper.toBaseMessageIdString(new Object());
+         fail("expected exception not thrown");
+      } catch (IllegalArgumentException iae) {
+         // expected
+      }
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns the given
+    * basic string unchanged
+    */
+   @Test
+   public void testToBaseMessageIdStringWithString() {
+      String stringMessageId = "myIdString";
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(stringMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", stringMessageId, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded string, when the given string happens to already begin with the
+    * {@link AMQPMessageIdHelper#AMQP_UUID_PREFIX}.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForUUID() {
+      String uuidStringMessageId = AMQPMessageIdHelper.AMQP_UUID_PREFIX + UUID.randomUUID();
+      String expected = AMQPMessageIdHelper.AMQP_STRING_PREFIX + uuidStringMessageId;
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(uuidStringMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded string, when the given string happens to already begin with the
+    * {@link AMQPMessageIdHelper#AMQP_ULONG_PREFIX}.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForLong() {
+      String longStringMessageId = AMQPMessageIdHelper.AMQP_ULONG_PREFIX + Long.valueOf(123456789L);
+      String expected = AMQPMessageIdHelper.AMQP_STRING_PREFIX + longStringMessageId;
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(longStringMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded string, when the given string happens to already begin with the
+    * {@link AMQPMessageIdHelper#AMQP_BINARY_PREFIX}.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForBinary() {
+      String binaryStringMessageId = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + "0123456789ABCDEF";
+      String expected = AMQPMessageIdHelper.AMQP_STRING_PREFIX + binaryStringMessageId;
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(binaryStringMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded string (effectively twice), when the given string happens to
+    * already begin with the {@link AMQPMessageIdHelper#AMQP_STRING_PREFIX}.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForString() {
+      String stringMessageId = AMQPMessageIdHelper.AMQP_STRING_PREFIX + "myStringId";
+      String expected = AMQPMessageIdHelper.AMQP_STRING_PREFIX + stringMessageId;
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(stringMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded UUID when given a UUID object.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithUUID() {
+      UUID uuidMessageId = UUID.randomUUID();
+      String expected = AMQPMessageIdHelper.AMQP_UUID_PREFIX + uuidMessageId.toString();
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(uuidMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded ulong when given a UnsignedLong object.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithUnsignedLong() {
+      UnsignedLong uLongMessageId = UnsignedLong.valueOf(123456789L);
+      String expected = AMQPMessageIdHelper.AMQP_ULONG_PREFIX + uLongMessageId.toString();
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(uLongMessageId);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toBaseMessageIdString(Object)} returns a string
+    * indicating an AMQP encoded binary when given a Binary object.
+    */
+   @Test
+   public void testToBaseMessageIdStringWithBinary() {
+      byte[] bytes = new byte[] {(byte) 0x00, (byte) 0xAB, (byte) 0x09, (byte) 0xFF};
+      Binary binary = new Binary(bytes);
+
+      String expected = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + "00AB09FF";
+
+      String baseMessageIdString = messageIdHelper.toBaseMessageIdString(binary);
+      assertNotNull("null string should not have been returned", baseMessageIdString);
+      assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns an UnsignedLong when
+    * given a string indicating an encoded AMQP ulong id.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithEncodedUlong() throws Exception {
+      UnsignedLong longId = UnsignedLong.valueOf(123456789L);
+      String provided = AMQPMessageIdHelper.AMQP_ULONG_PREFIX + "123456789";
+
+      Object idObject = messageIdHelper.toIdObject(provided);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", longId, idObject);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns a Binary when given a
+    * string indicating an encoded AMQP binary id, using upper case hex characters
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithEncodedBinaryUppercaseHexString() throws Exception {
+      byte[] bytes = new byte[] {(byte) 0x00, (byte) 0xAB, (byte) 0x09, (byte) 0xFF};
+      Binary binaryId = new Binary(bytes);
+
+      String provided = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + "00AB09FF";
+
+      Object idObject = messageIdHelper.toIdObject(provided);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", binaryId, idObject);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns null when given null.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithNull() throws Exception {
+      assertNull("null object should have been returned", messageIdHelper.toIdObject(null));
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns a Binary when given a
+    * string indicating an encoded AMQP binary id, using lower case hex characters.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithEncodedBinaryLowercaseHexString() throws Exception {
+      byte[] bytes = new byte[] {(byte) 0x00, (byte) 0xAB, (byte) 0x09, (byte) 0xFF};
+      Binary binaryId = new Binary(bytes);
+
+      String provided = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + "00ab09ff";
+
+      Object idObject = messageIdHelper.toIdObject(provided);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", binaryId, idObject);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns a UUID when given a
+    * string indicating an encoded AMQP uuid id.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithEncodedUuid() throws Exception {
+      UUID uuid = UUID.randomUUID();
+      String provided = AMQPMessageIdHelper.AMQP_UUID_PREFIX + uuid.toString();
+
+      Object idObject = messageIdHelper.toIdObject(provided);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", uuid, idObject);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns a string when given a
+    * string without any type encoding prefix.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithStringContainingNoEncodingPrefix() throws Exception {
+      String stringId = "myStringId";
+
+      Object idObject = messageIdHelper.toIdObject(stringId);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", stringId, idObject);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} returns the remainder of the
+    * provided string after removing the {@link AMQPMessageIdHelper#AMQP_STRING_PREFIX} prefix.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithStringContainingStringEncodingPrefix() throws Exception {
+      String suffix = "myStringSuffix";
+      String stringId = AMQPMessageIdHelper.AMQP_STRING_PREFIX + suffix;
+
+      Object idObject = messageIdHelper.toIdObject(stringId);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", suffix, idObject);
+   }
+
+   /**
+    * Test that when given a string with with the {@link AMQPMessageIdHelper#AMQP_STRING_PREFIX}
+    * prefix and then additionally the {@link AMQPMessageIdHelper#AMQP_UUID_PREFIX}, the
+    * {@link AMQPMessageIdHelper#toIdObject(String)} method returns the remainder of the
+    * provided string after removing the {@link AMQPMessageIdHelper#AMQP_STRING_PREFIX} prefix.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testToIdObjectWithStringContainingStringEncodingPrefixAndThenUuidPrefix() throws Exception {
+      String encodedUuidString = AMQPMessageIdHelper.AMQP_UUID_PREFIX + UUID.randomUUID().toString();
+      String stringId = AMQPMessageIdHelper.AMQP_STRING_PREFIX + encodedUuidString;
+
+      Object idObject = messageIdHelper.toIdObject(stringId);
+      assertNotNull("null object should not have been returned", idObject);
+      assertEquals("expected id object was not returned", encodedUuidString, idObject);
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} throws an
+    * {@link IdConversionException} when presented with an encoded binary hex string of uneven
+    * length (after the prefix) that thus can't be converted due to each byte using 2 characters
+    */
+   @Test
+   public void testToIdObjectWithStringContainingBinaryHexThrowsWithUnevenLengthString() {
+      String unevenHead = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + "123";
+
+      try {
+         messageIdHelper.toIdObject(unevenHead);
+         fail("expected exception was not thrown");
+      } catch (ActiveMQAMQPException ex) {
+         // expected
+      }
+   }
+
+   /**
+    * Test that {@link AMQPMessageIdHelper#toIdObject(String)} throws an
+    * {@link IdConversionException} when presented with an encoded binary hex string (after the
+    * prefix) that contains characters other than 0-9 and A-F and a-f, and thus can't be
+    * converted
+    */
+   @Test
+   public void testToIdObjectWithStringContainingBinaryHexThrowsWithNonHexCharacters() {
+
+      // char before '0'
+      char nonHexChar = '/';
+      String nonHexString = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + nonHexChar + nonHexChar;
+
+      try {
+         messageIdHelper.toIdObject(nonHexString);
+         fail("expected exception was not thrown");
+      } catch (ActiveMQAMQPException ex) {
+         // expected
+      }
+
+      // char after '9', before 'A'
+      nonHexChar = ':';
+      nonHexString = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + nonHexChar + nonHexChar;
+
+      try {
+         messageIdHelper.toIdObject(nonHexString);
+         fail("expected exception was not thrown");
+      } catch (ActiveMQAMQPException ex) {
+         // expected
+      }
+
+      // char after 'F', before 'a'
+      nonHexChar = 'G';
+      nonHexString = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + nonHexChar + nonHexChar;
+
+      try {
+         messageIdHelper.toIdObject(nonHexString);
+         fail("expected exception was not thrown");
+      } catch (ActiveMQAMQPException ex) {
+         // expected
+      }
+
+      // char after 'f'
+      nonHexChar = 'g';
+      nonHexString = AMQPMessageIdHelper.AMQP_BINARY_PREFIX + nonHexChar + nonHexChar;
+
+      try {
+         messageIdHelper.toIdObject(nonHexString);
+         fail("expected exception was not thrown");
+      } catch (ActiveMQAMQPException ex) {
+         // expected
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/62627bf2/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageSupportTest.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageSupportTest.java b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageSupportTest.java
new file mode 100644
index 0000000..d4e078f
--- /dev/null
+++ b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/AMQPMessageSupportTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.activemq.artemis.protocol.amqp.converter.message;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.proton.Proton;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
+import org.apache.qpid.proton.message.Message;
+import org.junit.Test;
+
+public class AMQPMessageSupportTest {
+
+   // ---------- getSymbol ---------------------------------------------------//
+
+   @Test
+   public void testGetSymbol() {
+      assertNotNull(AMQPMessageSupport.getSymbol("x-opt-something-or-other"));
+   }
+
+   // ---------- getMessageAnnotation ----------------------------------------//
+
+   @Test
+   public void testGetMessageAnnotationWhenMessageHasAnnotationsMap() {
+      Map<Symbol, Object> messageAnnotationsMap = new HashMap<>();
+      messageAnnotationsMap.put(Symbol.valueOf("x-opt-test"), Boolean.TRUE);
+      Message message = Proton.message();
+      message.setMessageAnnotations(new MessageAnnotations(messageAnnotationsMap));
+
+      assertNotNull(AMQPMessageSupport.getMessageAnnotation("x-opt-test", message));
+   }
+
+   @Test
+   public void testGetMessageAnnotationWhenMessageHasEmptyAnnotationsMap() {
+      Map<Symbol, Object> messageAnnotationsMap = new HashMap<>();
+      Message message = Proton.message();
+      message.setMessageAnnotations(new MessageAnnotations(messageAnnotationsMap));
+
+      assertNull(AMQPMessageSupport.getMessageAnnotation("x-opt-test", message));
+   }
+
+   @Test
+   public void testGetMessageAnnotationWhenMessageHasNoAnnotationsMap() {
+      Message message = Proton.message();
+      assertNull(AMQPMessageSupport.getMessageAnnotation("x-opt-test", message));
+   }
+
+   @Test
+   public void testGetMessageAnnotationWhenMessageIsNull() {
+      assertNull(AMQPMessageSupport.getMessageAnnotation("x-opt-test", null));
+   }
+
+   // ---------- isContentType -----------------------------------------------//
+
+   @Test
+   public void testIsContentTypeWithNullStringValueAndNullMessageContentType() {
+      Message message = Proton.message();
+      assertTrue(AMQPMessageSupport.isContentType(null, message));
+   }
+
+   @Test
+   public void testIsContentTypeWithNonNullStringValueAndNullMessageContentType() {
+      Message message = Proton.message();
+      assertFalse(AMQPMessageSupport.isContentType("test", message));
+   }
+
+   @Test
+   public void testIsContentTypeWithNonNullStringValueAndNonNullMessageContentTypeNotEqual() {
+      Message message = Proton.message();
+      message.setContentType("fails");
+      assertFalse(AMQPMessageSupport.isContentType("test", message));
+   }
+
+   @Test
+   public void testIsContentTypeWithNonNullStringValueAndNonNullMessageContentTypeEqual() {
+      Message message = Proton.message();
+      message.setContentType("test");
+      assertTrue(AMQPMessageSupport.isContentType("test", message));
+   }
+
+   @Test
+   public void testIsContentTypeWithNullStringValueAndNonNullMessageContentType() {
+      Message message = Proton.message();
+      message.setContentType("test");
+      assertFalse(AMQPMessageSupport.isContentType(null, message));
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/62627bf2/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/JMSMappingInboundTransformerTest.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/JMSMappingInboundTransformerTest.java b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/JMSMappingInboundTransformerTest.java
new file mode 100644
index 0000000..d7a948a
--- /dev/null
+++ b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/JMSMappingInboundTransformerTest.java
@@ -0,0 +1,718 @@
+/*
+ * 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.activemq.artemis.protocol.amqp.converter.message;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.jms.Destination;
+import javax.jms.MapMessage;
+import javax.jms.Queue;
+import javax.jms.TemporaryQueue;
+import javax.jms.TemporaryTopic;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+
+import org.apache.activemq.artemis.jms.client.ActiveMQMessage;
+import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSBytesMessage;
+import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMapMessage;
+import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSObjectMessage;
+import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSStreamMessage;
+import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSTextMessage;
+import org.apache.activemq.artemis.utils.IDGenerator;
+import org.apache.activemq.artemis.utils.SimpleIDGenerator;
+import org.apache.qpid.proton.Proton;
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
+import org.apache.qpid.proton.amqp.messaging.AmqpValue;
+import org.apache.qpid.proton.amqp.messaging.Data;
+import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
+import org.apache.qpid.proton.message.Message;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JMSMappingInboundTransformerTest {
+
+   private IDGenerator idGenerator;
+
+   @Before
+   public void setUp() {
+      this.idGenerator = new SimpleIDGenerator(0);
+   }
+
+   // ----- Null Body Section ------------------------------------------------//
+
+   /**
+    * Test that a message with no body section, but with the content type set to
+    * {@value AMQPMessageSupport#OCTET_STREAM_CONTENT_TYPE} results in a BytesMessage
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateBytesMessageFromNoBodySectionAndContentType() throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      Message message = Message.Factory.create();
+      message.setContentType(AMQPMessageSupport.OCTET_STREAM_CONTENT_TYPE);
+
+      EncodedMessage em = encodeMessage(message);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that a message with no body section, and no content-type results in a BytesMessage
+    * when not otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateBytesMessageFromNoBodySectionAndNoContentType() throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      Message message = Message.Factory.create();
+
+      EncodedMessage em = encodeMessage(message);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that a message with no body section, but with the content type set to
+    * {@value AMQPMessageSupport#SERIALIZED_JAVA_OBJECT_CONTENT_TYPE} results in an
+    * ObjectMessage when not otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateObjectMessageFromNoBodySectionAndContentType() throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      Message message = Message.Factory.create();
+      message.setContentType(AMQPMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE);
+
+      EncodedMessage em = encodeMessage(message);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSObjectMessage.class, jmsMessage.getClass());
+   }
+
+   @Test
+   public void testCreateTextMessageFromNoBodySectionAndContentType() throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      Message message = Message.Factory.create();
+      message.setContentType("text/plain");
+
+      EncodedMessage em = encodeMessage(message);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSTextMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that a message with no body section, and with the content type set to an unknown
+    * value results in a plain Message when not otherwise annotated to indicate the type of JMS
+    * message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   public void testCreateGenericMessageFromNoBodySectionAndUnknownContentType() throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      Message message = Message.Factory.create();
+      message.setContentType("unknown-content-type");
+
+      EncodedMessage em = encodeMessage(message);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ActiveMQMessage.class, jmsMessage.getClass());
+   }
+
+   // ----- Data Body Section ------------------------------------------------//
+
+   /**
+    * Test that a data body containing nothing, but with the content type set to
+    * {@value AMQPMessageSupport#OCTET_STREAM_CONTENT_TYPE} results in a BytesMessage when not
+    * otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateBytesMessageFromDataWithEmptyBinaryAndContentType() throws Exception {
+      Message message = Proton.message();
+      Binary binary = new Binary(new byte[0]);
+      message.setBody(new Data(binary));
+      message.setContentType(AMQPMessageSupport.OCTET_STREAM_CONTENT_TYPE);
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that a message with an empty data body section, and with the content type set to an
+    * unknown value results in a BytesMessage when not otherwise annotated to indicate the type
+    * of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   public void testCreateBytesMessageFromDataWithUnknownContentType() throws Exception {
+      Message message = Proton.message();
+      Binary binary = new Binary(new byte[0]);
+      message.setBody(new Data(binary));
+      message.setContentType("unknown-content-type");
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that a receiving a data body containing nothing and no content type being set results
+    * in a BytesMessage when not otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateBytesMessageFromDataWithEmptyBinaryAndNoContentType() throws Exception {
+      Message message = Proton.message();
+      Binary binary = new Binary(new byte[0]);
+      message.setBody(new Data(binary));
+
+      assertNull(message.getContentType());
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that receiving a data body containing nothing, but with the content type set to
+    * {@value AMQPMessageSupport#SERIALIZED_JAVA_OBJECT_CONTENT_TYPE} results in an
+    * ObjectMessage when not otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateObjectMessageFromDataWithContentTypeAndEmptyBinary() throws Exception {
+      Message message = Proton.message();
+      Binary binary = new Binary(new byte[0]);
+      message.setBody(new Data(binary));
+      message.setContentType(AMQPMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE);
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSObjectMessage.class, jmsMessage.getClass());
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeTextPlain() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeTextJson() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/json;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/json;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/json", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeTextHtml() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/html;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/html;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/html;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/html", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeTextFoo() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationJson() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/json;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/json;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/json", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationJsonVariant() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationJavascript() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationEcmascript() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationXml() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationXmlVariant() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml", StandardCharsets.UTF_8);
+   }
+
+   @Test
+   public void testCreateTextMessageFromDataWithContentTypeApplicationXmlDtd() throws Exception {
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd;charset=us-ascii", StandardCharsets.US_ASCII);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd;charset=utf-8", StandardCharsets.UTF_8);
+      doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd", StandardCharsets.UTF_8);
+   }
+
+   private void doCreateTextMessageFromDataWithContentTypeTestImpl(String contentType, Charset expectedCharset) throws Exception {
+      Message message = Proton.message();
+      Binary binary = new Binary(new byte[0]);
+      message.setBody(new Data(binary));
+      message.setContentType(contentType);
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      if (StandardCharsets.UTF_8.equals(expectedCharset)) {
+         assertEquals("Unexpected message class type", ServerJMSTextMessage.class, jmsMessage.getClass());
+      } else {
+         assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+      }
+   }
+
+   // ----- AmqpValue transformations ----------------------------------------//
+
+   /**
+    * Test that an amqp-value body containing a string results in a TextMessage when not
+    * otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateTextMessageFromAmqpValueWithString() throws Exception {
+      Message message = Proton.message();
+      message.setBody(new AmqpValue("content"));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSTextMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that an amqp-value body containing a null results in an TextMessage when not
+    * otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateTextMessageFromAmqpValueWithNull() throws Exception {
+      Message message = Proton.message();
+      message.setBody(new AmqpValue(null));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSTextMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that a message with an AmqpValue section containing a Binary, but with the content
+    * type set to {@value AMQPMessageSupport#SERIALIZED_JAVA_OBJECT_CONTENT_TYPE} results in an
+    * ObjectMessage when not otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateObjectMessageFromAmqpValueWithBinaryAndContentType() throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      Message message = Message.Factory.create();
+      message.setBody(new AmqpValue(new Binary(new byte[0])));
+      message.setContentType(AMQPMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE);
+
+      EncodedMessage em = encodeMessage(message);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSObjectMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that an amqp-value body containing a map results in an MapMessage when not otherwise
+    * annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateAmqpMapMessageFromAmqpValueWithMap() throws Exception {
+      Message message = Proton.message();
+      Map<String, String> map = new HashMap<>();
+      message.setBody(new AmqpValue(map));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSMapMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that an amqp-value body containing a map that has an AMQP Binary as one of the
+    * entries encoded into the Map results in an MapMessage where a byte array can be read from
+    * the entry.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateAmqpMapMessageFromAmqpValueWithMapContainingBinaryEntry() throws Exception {
+      final String ENTRY_NAME = "bytesEntry";
+
+      Message message = Proton.message();
+      Map<String, Object> map = new HashMap<>();
+
+      byte[] inputBytes = new byte[] {1, 2, 3, 4, 5};
+      map.put(ENTRY_NAME, new Binary(inputBytes));
+
+      message.setBody(new AmqpValue(map));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSMapMessage.class, jmsMessage.getClass());
+
+      MapMessage mapMessage = (MapMessage) jmsMessage;
+      byte[] outputBytes = mapMessage.getBytes(ENTRY_NAME);
+      assertNotNull(outputBytes);
+      assertTrue(Arrays.equals(inputBytes, outputBytes));
+   }
+
+   /**
+    * Test that an amqp-value body containing a list results in an StreamMessage when not
+    * otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateAmqpStreamMessageFromAmqpValueWithList() throws Exception {
+      Message message = Proton.message();
+      List<String> list = new ArrayList<>();
+      message.setBody(new AmqpValue(list));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSStreamMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that an amqp-sequence body containing a list results in an StreamMessage when not
+    * otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateAmqpStreamMessageFromAmqpSequence() throws Exception {
+      Message message = Proton.message();
+      List<String> list = new ArrayList<>();
+      message.setBody(new AmqpSequence(list));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSStreamMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that an amqp-value body containing a binary value results in BytesMessage when not
+    * otherwise annotated to indicate the type of JMS message it is.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateAmqpBytesMessageFromAmqpValueWithBinary() throws Exception {
+      Message message = Proton.message();
+      Binary binary = new Binary(new byte[0]);
+      message.setBody(new AmqpValue(binary));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   /**
+    * Test that an amqp-value body containing a value which can't be categorized results in an
+    * exception from the transformer and then try the transformer's own fallback transformer to
+    * result in an BytesMessage.
+    *
+    * @throws Exception
+    *         if an error occurs during the test.
+    */
+   @Test
+   public void testCreateBytesMessageFromAmqpValueWithUncategorisedContent() throws Exception {
+      Message message = Proton.message();
+      message.setBody(new AmqpValue(UUID.randomUUID()));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertNotNull("Message should not be null", jmsMessage);
+      assertEquals("Unexpected message class type", ServerJMSBytesMessage.class, jmsMessage.getClass());
+   }
+
+   @Test
+   public void testTransformMessageWithAmqpValueStringCreatesTextMessage() throws Exception {
+      String contentString = "myTextMessageContent";
+      Message message = Message.Factory.create();
+      message.setBody(new AmqpValue(contentString));
+
+      EncodedMessage em = encodeMessage(message);
+
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+      javax.jms.Message jmsMessage = transformer.transform(em);
+
+      assertTrue("Expected TextMessage", jmsMessage instanceof TextMessage);
+      assertEquals("Unexpected message class type", ServerJMSTextMessage.class, jmsMessage.getClass());
+
+      TextMessage textMessage = (TextMessage) jmsMessage;
+
+      assertNotNull(textMessage.getText());
+      assertEquals(contentString, textMessage.getText());
+   }
+
+   // ----- Destination Conversions ------------------------------------------//
+
+   @Test
+   public void testTransformWithNoToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithToTypeDestinationTypeAnnotationTestImpl(null, Destination.class);
+   }
+
+   @Test
+   public void testTransformWithQueueStringToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithToTypeDestinationTypeAnnotationTestImpl("queue", Queue.class);
+   }
+
+   @Test
+   public void testTransformWithTemporaryQueueStringToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithToTypeDestinationTypeAnnotationTestImpl("queue,temporary", TemporaryQueue.class);
+   }
+
+   @Test
+   public void testTransformWithTopicStringToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithToTypeDestinationTypeAnnotationTestImpl("topic", Topic.class);
+   }
+
+   @Test
+   public void testTransformWithTemporaryTopicStringToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithToTypeDestinationTypeAnnotationTestImpl("topic,temporary", TemporaryTopic.class);
+   }
+
+   private void doTransformWithToTypeDestinationTypeAnnotationTestImpl(Object toTypeAnnotationValue, Class<? extends Destination> expectedClass)
+      throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      String toAddress = "toAddress";
+      Message amqp = Message.Factory.create();
+      amqp.setBody(new AmqpValue("myTextMessageContent"));
+      amqp.setAddress(toAddress);
+      if (toTypeAnnotationValue != null) {
+         Map<Symbol, Object> map = new HashMap<>();
+         map.put(Symbol.valueOf("x-opt-to-type"), toTypeAnnotationValue);
+         MessageAnnotations ma = new MessageAnnotations(map);
+         amqp.setMessageAnnotations(ma);
+      }
+
+      EncodedMessage em = encodeMessage(amqp);
+
+      javax.jms.Message jmsMessage = transformer.transform(em);
+      assertTrue("Expected TextMessage", jmsMessage instanceof TextMessage);
+   }
+
+   // ----- ReplyTo Conversions ----------------------------------------------//
+
+   @Test
+   public void testTransformWithNoReplyToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl(null, Destination.class);
+   }
+
+   @Test
+   public void testTransformWithQueueStringReplyToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("queue", Queue.class);
+   }
+
+   @Test
+   public void testTransformWithTemporaryQueueStringReplyToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("queue,temporary", TemporaryQueue.class);
+   }
+
+   @Test
+   public void testTransformWithTopicStringReplyToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("topic", Topic.class);
+   }
+
+   @Test
+   public void testTransformWithTemporaryTopicStringReplyToTypeDestinationTypeAnnotation() throws Exception {
+      doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("topic,temporary", TemporaryTopic.class);
+   }
+
+   private void doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl(Object replyToTypeAnnotationValue, Class<? extends Destination> expectedClass)
+      throws Exception {
+      JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer(idGenerator);
+
+      String replyToAddress = "replyToAddress";
+      Message amqp = Message.Factory.create();
+      amqp.setBody(new AmqpValue("myTextMessageContent"));
+      amqp.setReplyTo(replyToAddress);
+      if (replyToTypeAnnotationValue != null) {
+         Map<Symbol, Object> map = new HashMap<>();
+         map.put(Symbol.valueOf("x-opt-reply-type"), replyToTypeAnnotationValue);
+         MessageAnnotations ma = new MessageAnnotations(map);
+         amqp.setMessageAnnotations(ma);
+      }
+
+      EncodedMessage em = encodeMessage(amqp);
+
+      javax.jms.Message jmsMessage = transformer.transform(em);
+      assertTrue("Expected TextMessage", jmsMessage instanceof TextMessage);
+   }
+
+   // ----- Utility Methods --------------------------------------------------//
+
+   private EncodedMessage encodeMessage(Message message) {
+      byte[] encodeBuffer = new byte[1024 * 8];
+      int encodedSize;
+      while (true) {
+         try {
+            encodedSize = message.encode(encodeBuffer, 0, encodeBuffer.length);
+            break;
+         } catch (java.nio.BufferOverflowException e) {
+            encodeBuffer = new byte[encodeBuffer.length * 2];
+         }
+      }
+
+      long messageFormat = 0;
+      return new EncodedMessage(messageFormat, encodeBuffer, 0, encodedSize);
+   }
+}