qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rob...@apache.org
Subject qpid-jms git commit: QPIDJMS-52, QPIDJMS-53: support the charset param in content-type, and treat messages with Data sections and common textual content-types as TextMessage rahter than BytesMessage
Date Tue, 19 May 2015 17:04:58 GMT
Repository: qpid-jms
Updated Branches:
  refs/heads/master 3637ec999 -> 021867fd1


QPIDJMS-52, QPIDJMS-53: support the charset param in content-type, and treat messages with
Data sections and common textual content-types as TextMessage rahter than BytesMessage


Project: http://git-wip-us.apache.org/repos/asf/qpid-jms/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-jms/commit/021867fd
Tree: http://git-wip-us.apache.org/repos/asf/qpid-jms/tree/021867fd
Diff: http://git-wip-us.apache.org/repos/asf/qpid-jms/diff/021867fd

Branch: refs/heads/master
Commit: 021867fd17f835f3d665f35d3b94abd6d51c9f5c
Parents: 3637ec9
Author: Robert Gemmell <robbie@apache.org>
Authored: Tue May 19 17:58:29 2015 +0100
Committer: Robert Gemmell <robbie@apache.org>
Committed: Tue May 19 17:58:29 2015 +0100

----------------------------------------------------------------------
 .../amqp/message/AmqpJmsMessageBuilder.java     |  49 ++--
 .../amqp/message/AmqpJmsTextMessageFacade.java  |  25 +-
 .../amqp/message/AmqpMessageSupport.java        |   5 -
 .../qpid/jms/util/ContentTypeSupport.java       | 142 ++++++++++++
 .../jms/util/InvalidContentTypeException.java   |  26 +++
 .../amqp/message/AmqpJmsMessageBuilderTest.java | 109 ++++++++-
 .../message/AmqpJmsMessageTypesTestCase.java    |   4 +-
 .../qpid/jms/util/ContentTypeSupportTest.java   | 229 +++++++++++++++++++
 8 files changed, 545 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilder.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilder.java
b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilder.java
index eb66b03..713a7d8 100644
--- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilder.java
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilder.java
@@ -25,10 +25,11 @@ import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_S
 import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_TEXT_MESSAGE;
 import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.OCTET_STREAM_CONTENT_TYPE;
 import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE;
-import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.TEXT_PLAIN_CONTENT_TYPE;
 import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.isContentType;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.qpid.jms.message.JmsBytesMessage;
 import org.apache.qpid.jms.message.JmsMapMessage;
@@ -37,6 +38,8 @@ import org.apache.qpid.jms.message.JmsObjectMessage;
 import org.apache.qpid.jms.message.JmsStreamMessage;
 import org.apache.qpid.jms.message.JmsTextMessage;
 import org.apache.qpid.jms.provider.amqp.AmqpConsumer;
+import org.apache.qpid.jms.util.ContentTypeSupport;
+import org.apache.qpid.jms.util.InvalidContentTypeException;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
 import org.apache.qpid.proton.amqp.messaging.AmqpValue;
@@ -91,7 +94,7 @@ public class AmqpJmsMessageBuilder {
                 case JMS_BYTES_MESSAGE:
                     return createBytesMessage(consumer, message);
                 case JMS_TEXT_MESSAGE:
-                    return createTextMessage(consumer, message);
+                    return createTextMessage(consumer, message, StandardCharsets.UTF_8);
                 case JMS_MAP_MESSAGE:
                     return createMapMessage(consumer, message);
                 case JMS_STREAM_MESSAGE:
@@ -110,32 +113,36 @@ public class AmqpJmsMessageBuilder {
         Section body = message.getBody();
 
         if (body == null) {
-            // TODO: accept textual content types other than strictly "text/plain"
-            if (isContentType(TEXT_PLAIN_CONTENT_TYPE, message)) {
-                return createTextMessage(consumer, message);
-            } else if (isContentType(SERIALIZED_JAVA_OBJECT_CONTENT_TYPE, message)) {
+            if (isContentType(SERIALIZED_JAVA_OBJECT_CONTENT_TYPE, message)) {
                 return createObjectMessage(consumer, message);
             } else if (isContentType(OCTET_STREAM_CONTENT_TYPE, message) || isContentType(null,
message)) {
                 return createBytesMessage(consumer, message);
             } else {
-                return createMessage(consumer, message);
+                Charset charset = getCharsetForTextualContent(message.getContentType());
+                if (charset != null) {
+                    return createTextMessage(consumer, message, charset);
+                } else {
+                    return createMessage(consumer, message);
+                }
             }
         } else if (body instanceof Data) {
-            // TODO: accept textual content types other than strictly "text/plain"
-            if (isContentType(TEXT_PLAIN_CONTENT_TYPE, message)) {
-                return createTextMessage(consumer, message);
-            } else if (isContentType(OCTET_STREAM_CONTENT_TYPE, message) || isContentType(null,
message)) {
+            if (isContentType(OCTET_STREAM_CONTENT_TYPE, message) || isContentType(null,
message)) {
                 return createBytesMessage(consumer, message);
             } else if (isContentType(SERIALIZED_JAVA_OBJECT_CONTENT_TYPE, message)) {
                 return createObjectMessage(consumer, message);
             } else {
-                return createBytesMessage(consumer, message);
+                Charset charset = getCharsetForTextualContent(message.getContentType());
+                if (charset != null) {
+                    return createTextMessage(consumer, message, charset);
+                } else {
+                    return createBytesMessage(consumer, message);
+                }
             }
         } else if (body instanceof AmqpValue) {
             Object value = ((AmqpValue) body).getValue();
 
             if (value == null || value instanceof String) {
-                return createTextMessage(consumer, message);
+                return createTextMessage(consumer, message, StandardCharsets.UTF_8);
             } else if (value instanceof Binary) {
                 return createBytesMessage(consumer, message);
             } else {
@@ -160,8 +167,8 @@ public class AmqpJmsMessageBuilder {
         return new JmsMapMessage(new AmqpJmsMapMessageFacade(consumer, message));
     }
 
-    private static JmsTextMessage createTextMessage(AmqpConsumer consumer, Message message)
{
-        return new JmsTextMessage(new AmqpJmsTextMessageFacade(consumer, message));
+    private static JmsTextMessage createTextMessage(AmqpConsumer consumer, Message message,
Charset charset) {
+        return new JmsTextMessage(new AmqpJmsTextMessageFacade(consumer, message, charset));
     }
 
     private static JmsBytesMessage createBytesMessage(AmqpConsumer consumer, Message message)
{
@@ -171,4 +178,16 @@ public class AmqpJmsMessageBuilder {
     private static JmsMessage createMessage(AmqpConsumer consumer, Message message) {
         return new JmsMessage(new AmqpJmsMessageFacade(consumer, message));
     }
+
+    /**
+     * @param contentType the contentType of the received message
+     * @return the character set to use, or null if not to treat the message as text
+     */
+    private static Charset getCharsetForTextualContent(String contentType) {
+        try {
+            return ContentTypeSupport.parseContentTypeForTextualCharset(contentType);
+        } catch (InvalidContentTypeException e) {
+            return null;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsTextMessageFacade.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsTextMessageFacade.java
b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsTextMessageFacade.java
index 6a4850e..064c49d 100644
--- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsTextMessageFacade.java
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsTextMessageFacade.java
@@ -24,6 +24,7 @@ import java.nio.CharBuffer;
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
+import java.nio.charset.StandardCharsets;
 
 import javax.jms.JMSException;
 
@@ -43,15 +44,7 @@ import org.apache.qpid.proton.message.Message;
  */
 public class AmqpJmsTextMessageFacade extends AmqpJmsMessageFacade implements JmsTextMessageFacade
{
 
-    private static final String UTF_8 = "UTF-8";
-
-    /**
-     * Content type, only to be used when message uses a data
-     * body section, and not when using an amqp-value body section
-     */
-    public static final String CONTENT_TYPE = "text/plain";
-
-    private final CharsetDecoder decoder =  Charset.forName(UTF_8).newDecoder();
+    private final Charset charset;
 
     /**
      * Create a new AMQP Message facade ready for sending.
@@ -63,6 +56,7 @@ public class AmqpJmsTextMessageFacade extends AmqpJmsMessageFacade implements
Jm
         super(connection);
         setMessageAnnotation(JMS_MSG_TYPE, JMS_TEXT_MESSAGE);
         setText(null);
+        charset = StandardCharsets.UTF_8;
     }
 
     /**
@@ -73,9 +67,12 @@ public class AmqpJmsTextMessageFacade extends AmqpJmsMessageFacade implements
Jm
      *        the consumer that received this message.
      * @param message
      *        the incoming Message instance that is being wrapped.
+     * @param charset
+     *        the character set to use when decoding the text when the body is a Data section
      */
-    public AmqpJmsTextMessageFacade(AmqpConsumer consumer, Message message) {
+    public AmqpJmsTextMessageFacade(AmqpConsumer consumer, Message message, Charset charset)
{
         super(consumer, message);
+        this.charset = charset;
     }
 
     /**
@@ -109,10 +106,10 @@ public class AmqpJmsTextMessageFacade extends AmqpJmsMessageFacade implements
Jm
                 ByteBuffer buf = ByteBuffer.wrap(b.getArray(), b.getArrayOffset(), b.getLength());
 
                 try {
-                    CharBuffer chars = decoder.decode(buf);
+                    CharBuffer chars = charset.newDecoder().decode(buf);
                     return String.valueOf(chars);
                 } catch (CharacterCodingException e) {
-                    throw JmsExceptionSupport.create("Cannot decode String in UFT-8", e);
+                    throw JmsExceptionSupport.create("Cannot decode String in " + charset.displayName(),
e);
                 }
             }
         } else if (body instanceof AmqpValue) {
@@ -166,4 +163,8 @@ public class AmqpJmsTextMessageFacade extends AmqpJmsMessageFacade implements
Jm
 
         return false;
     }
+
+    Charset getCharset() {
+        return charset;
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpMessageSupport.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpMessageSupport.java
b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpMessageSupport.java
index 644d50f..d1c3d59 100644
--- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpMessageSupport.java
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpMessageSupport.java
@@ -80,11 +80,6 @@ public final class AmqpMessageSupport {
     public static final String JMS_AMQP_TYPED_ENCODING = "JMS_AMQP_TYPED_ENCODING";
 
     /**
-     * Content type used to mark Data sections as containing text.
-     */
-    public static final String TEXT_PLAIN_CONTENT_TYPE = "text/plain";
-
-    /**
      * Content type used to mark Data sections as containing a serialized java object.
      */
     public static final String SERIALIZED_JAVA_OBJECT_CONTENT_TYPE = "application/x-java-serialized-object";

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ContentTypeSupport.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ContentTypeSupport.java
b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ContentTypeSupport.java
new file mode 100644
index 0000000..6a3fff1
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ContentTypeSupport.java
@@ -0,0 +1,142 @@
+/*
+ * 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.jms.util;
+
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.StringTokenizer;
+
+public final class ContentTypeSupport {
+
+    private static final String UTF_8 = "UTF-8";
+    private static final String CHARSET = "charset";
+    private static final String TEXT = "text";
+    private static final String APPLICATION = "application";
+    private static final String JAVASCRIPT = "javascript";
+    private static final String XML = "xml";
+    private static final String XML_VARIANT = "+xml";
+    private static final String JSON = "json";
+    private static final String JSON_VARIANT = "+json";
+    private static final String XML_DTD = "xml-dtd";
+    private static final String ECMASCRIPT = "ecmascript";
+
+    /**
+     * @param contentType the contentType of the received message
+     * @return the character set to use, or null if not to treat the message as text
+     * @throws InvalidContentTypeException if the content-type is invalid in some way.
+     */
+    public static Charset parseContentTypeForTextualCharset(final String contentType) throws
InvalidContentTypeException {
+        if (contentType == null || contentType.trim().isEmpty()) {
+            throw new InvalidContentTypeException("Content type can't be null or empty");
+        }
+
+        int subTypeSeparator = contentType.indexOf("/");
+        if(subTypeSeparator == -1) {
+            throw new InvalidContentTypeException("Content type has no '/' separator: " +
contentType);
+        }
+
+        final String type = contentType.substring(0, subTypeSeparator).toLowerCase().trim();
+
+        String subTypePart = contentType.substring(subTypeSeparator +1).toLowerCase().trim();
+
+        String parameterPart = null;
+        int parameterSeparator = subTypePart.indexOf(";");
+        if(parameterSeparator != -1)
+        {
+            if(parameterSeparator < subTypePart.length() - 1) {
+                parameterPart = contentType.substring(subTypeSeparator + 1).toLowerCase().trim();
+            }
+            subTypePart = subTypePart.substring(0, parameterSeparator).trim();
+        }
+
+        if(subTypePart.isEmpty()) {
+            throw new InvalidContentTypeException("Content type has no subtype after '/'"
+ contentType);
+        }
+
+        final String subType = subTypePart;
+
+        if(isTextual(type, subType)) {
+            String charset = findCharset(parameterPart);
+            if(charset == null) {
+                charset = UTF_8;
+            }
+
+            if (UTF_8.equals(charset)) {
+                return StandardCharsets.UTF_8;
+            } else {
+                try {
+                    return Charset.forName(charset);
+                } catch (IllegalCharsetNameException icne) {
+                    throw new InvalidContentTypeException("Illegal charset: " + charset);
+                } catch (UnsupportedCharsetException uce) {
+                    throw new InvalidContentTypeException("Unsupported charset: " + charset);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private static boolean isTextual(String type, String subType) {
+        if (TEXT.equals(type)) {
+            return true;
+        }
+
+        if (APPLICATION.equals(type)) {
+            if (XML.equals(subType) || JSON.equals(subType) || JAVASCRIPT.equals(subType)
+                    || subType.endsWith(XML_VARIANT) || subType.endsWith(JSON_VARIANT)
+                         || XML_DTD.equals(subType) || ECMASCRIPT.equals(subType) ) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static String findCharset(String paramaterPart) {
+        String charset = null;
+
+        if (paramaterPart != null) {
+            StringTokenizer tokenizer = new StringTokenizer(paramaterPart, ";");
+            while (tokenizer.hasMoreTokens()) {
+                String parameter = tokenizer.nextToken().trim();
+                int eqIndex = parameter.indexOf('=');
+                if (eqIndex != -1) {
+                    String name = parameter.substring(0, eqIndex);
+                    if (CHARSET.equalsIgnoreCase(name.trim())) {
+                        String value = unquote(parameter.substring(eqIndex + 1));
+
+                        charset = value.toUpperCase();
+                        break;
+                    }
+                }
+            }
+        }
+
+        return charset;
+    }
+
+    private static String unquote(String s) {
+        if (s.length() > 1 && (s.startsWith("\"") && s.endsWith("\"")))
{
+            return s.substring(1, s.length() - 1);
+        } else {
+            return s;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/InvalidContentTypeException.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/InvalidContentTypeException.java
b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/InvalidContentTypeException.java
new file mode 100644
index 0000000..1547ca3
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/InvalidContentTypeException.java
@@ -0,0 +1,26 @@
+/*
+ * 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.jms.util;
+
+public class InvalidContentTypeException extends Exception {
+
+    private static final long serialVersionUID = -2172537375174014839L;
+
+    public InvalidContentTypeException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilderTest.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilderTest.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilderTest.java
index 569b456..48686da 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilderTest.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageBuilderTest.java
@@ -26,6 +26,8 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -300,15 +302,10 @@ public class AmqpJmsMessageBuilderTest extends QpidJmsTestCase {
         assertTrue("Unexpected delegate type: " + delegate, delegate instanceof AmqpSerializedObjectDelegate);
     }
 
-    /**
-     * Test that a message with no body section, but with the content type set to
-     * {@value AmqpMessageSupport#TEXT_PLAIN_CONTENT_TYPE} results in a TextMessage
-     * when not otherwise annotated to indicate the type of JMS message it is.
-     */
     @Test
     public void testCreateTextMessageFromNoBodySectionAndContentType() throws Exception {
         Message message = Proton.message();
-        message.setContentType(AmqpMessageSupport.TEXT_PLAIN_CONTENT_TYPE);
+        message.setContentType("text/plain");
 
         JmsMessage jmsMessage = AmqpJmsMessageBuilder.createJmsMessage(mockConsumer, message);
         assertNotNull("Message should not be null", jmsMessage);
@@ -427,16 +424,103 @@ public class AmqpJmsMessageBuilderTest extends QpidJmsTestCase {
     }
 
     /**
-     * Test that receiving a data body containing nothing, but with the content type set
to
-     * {@value AmqpMessageSupport#TEXT_PLAIN_CONTENT_TYPE} results in a TextMessage when
-     * not otherwise annotated to indicate the type of JMS message it is.
+     * Test that receiving a Data body section with the content type set to
+     * 'text/plain' results in a TextMessage when not otherwise annotated to
+     * indicate the type of JMS message it is.
      */
     @Test
-    public void testCreateTextMessageFromDataWithContentTypeAndEmptyBinary() throws Exception
{
+    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 IOException {
         Message message = Proton.message();
         Binary binary = new Binary(new byte[0]);
         message.setBody(new Data(binary));
-        message.setContentType(AmqpMessageSupport.TEXT_PLAIN_CONTENT_TYPE);
+        message.setContentType(contentType);
 
         JmsMessage jmsMessage = AmqpJmsMessageBuilder.createJmsMessage(mockConsumer, message);
         assertNotNull("Message should not be null", jmsMessage);
@@ -445,6 +529,9 @@ public class AmqpJmsMessageBuilderTest extends QpidJmsTestCase {
         JmsMessageFacade facade = jmsMessage.getFacade();
         assertNotNull("Facade should not be null", facade);
         assertEquals("Unexpected facade class type", AmqpJmsTextMessageFacade.class, facade.getClass());
+
+        AmqpJmsTextMessageFacade textFacade = (AmqpJmsTextMessageFacade) facade;
+        assertEquals("Unexpected character set", expectedCharset, textFacade.getCharset());
     }
 
     // --------- AmqpValue Body Section ---------

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageTypesTestCase.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageTypesTestCase.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageTypesTestCase.java
index 6324b75..3d5d197 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageTypesTestCase.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpJmsMessageTypesTestCase.java
@@ -16,6 +16,8 @@
  */
 package org.apache.qpid.jms.provider.amqp.message;
 
+import java.nio.charset.StandardCharsets;
+
 import org.apache.qpid.jms.JmsDestination;
 import org.apache.qpid.jms.JmsTopic;
 import org.apache.qpid.jms.provider.amqp.AmqpConnection;
@@ -51,7 +53,7 @@ public class AmqpJmsMessageTypesTestCase extends QpidJmsTestCase {
     }
 
     protected AmqpJmsTextMessageFacade createReceivedTextMessageFacade(AmqpConsumer amqpConsumer,
Message message) {
-        return new AmqpJmsTextMessageFacade(amqpConsumer, message);
+        return new AmqpJmsTextMessageFacade(amqpConsumer, message, StandardCharsets.UTF_8);
     }
 
     protected AmqpJmsBytesMessageFacade createNewBytesMessageFacade() {

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/021867fd/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ContentTypeSupportTest.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ContentTypeSupportTest.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ContentTypeSupportTest.java
new file mode 100644
index 0000000..d1f44b0
--- /dev/null
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ContentTypeSupportTest.java
@@ -0,0 +1,229 @@
+/*
+ * 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.jms.util;
+
+import static org.junit.Assert.*;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport;
+import org.junit.Test;
+
+public class ContentTypeSupportTest {
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeWithOnlyType() throws Exception {
+        doParseContentTypeTestImpl("type", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeEndsWithSlash() throws Exception {
+        doParseContentTypeTestImpl("type/", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeMissingSubtype() throws Exception {
+        doParseContentTypeTestImpl("type/;", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeEmptyString() throws Exception {
+        doParseContentTypeTestImpl("", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeNullString() throws Exception {
+        doParseContentTypeTestImpl(null, null);
+    }
+
+    @Test
+    public void testParseContentTypeNoParamsAfterSeparatorNonTextual() throws Exception {
+        // Expect null as this is not a textual type
+        doParseContentTypeTestImpl("type/subtype;", null);
+    }
+
+    @Test
+    public void testParseContentTypeNoParamsAfterSeparatorTextualType() throws Exception
{
+        doParseContentTypeTestImpl("text/plain;", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeEmptyParamsAfterSeparator() throws Exception {
+        doParseContentTypeTestImpl("text/plain;;", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeNoParams() throws Exception {
+        doParseContentTypeTestImpl("text/plain", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithCharsetUtf8() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=utf-8", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithCharsetAscii() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=us-ascii", StandardCharsets.US_ASCII);
+    }
+
+    @Test
+    public void testParseContentTypeWithMultipleParams() throws Exception {
+        doParseContentTypeTestImpl("text/plain; param=value; charset=us-ascii", StandardCharsets.US_ASCII);
+    }
+
+    @Test
+    public void testParseContentTypeWithCharsetQuoted() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=\"us-ascii\"", StandardCharsets.US_ASCII);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeWithCharsetQuotedEmpty() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=\"\"", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeWithCharsetQuoteNotClosed() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=\"unclosed", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeWithCharsetQuoteNotClosedEmpty() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=\"", null);
+    }
+
+    @Test (expected = InvalidContentTypeException.class)
+    public void testParseContentTypeWithNoCharsetValue() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=", null);
+    }
+
+    @Test
+    public void testParseContentTypeWithTextPlain() throws Exception {
+        doParseContentTypeTestImpl("text/plain;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("text/plain;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("text/plain;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("text/plain", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithTextJson() throws Exception {
+        doParseContentTypeTestImpl("text/json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("text/json;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("text/json;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("text/json", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithTextHtml() throws Exception {
+        doParseContentTypeTestImpl("text/html;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("text/html;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("text/html;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("text/html", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithTextFoo() throws Exception {
+        doParseContentTypeTestImpl("text/foo;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("text/foo;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("text/foo;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("text/foo", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationJson() throws Exception {
+        doParseContentTypeTestImpl("application/json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/json;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/json;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/json", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationJsonVariant() throws Exception {
+        doParseContentTypeTestImpl("application/something+json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/something+json;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/something+json;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/something+json", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationJavascript() throws Exception {
+        doParseContentTypeTestImpl("application/javascript;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/javascript;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/javascript;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/javascript", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationEcmascript() throws Exception {
+        doParseContentTypeTestImpl("application/ecmascript;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/ecmascript;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/ecmascript;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/ecmascript", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationXml() throws Exception {
+        doParseContentTypeTestImpl("application/xml;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/xml;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/xml;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/xml", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationXmlVariant() throws Exception {
+        doParseContentTypeTestImpl("application/something+xml;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/something+xml;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/something+xml;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/something+xml", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationXmlDtd() throws Exception {
+        doParseContentTypeTestImpl("application/xml-dtd;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
+        doParseContentTypeTestImpl("application/xml-dtd;charset=us-ascii", StandardCharsets.US_ASCII);
+        doParseContentTypeTestImpl("application/xml-dtd;charset=utf-8", StandardCharsets.UTF_8);
+        doParseContentTypeTestImpl("application/xml-dtd", StandardCharsets.UTF_8);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationOtherNotTextual() throws Exception {
+        // Expect null as this is not a textual type
+        doParseContentTypeTestImpl("application/other", null);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationOctetStream() throws Exception {
+        // Expect null as this is not a textual type
+        doParseContentTypeTestImpl(AmqpMessageSupport.OCTET_STREAM_CONTENT_TYPE, null);
+    }
+
+    @Test
+    public void testParseContentTypeWithApplicationJavaSerialized() throws Exception {
+        // Expect null as this is not a textual type
+        doParseContentTypeTestImpl(AmqpMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE,
null);
+    }
+
+    private void doParseContentTypeTestImpl(String contentType, Charset expected) throws
InvalidContentTypeException {
+        Charset charset = ContentTypeSupport.parseContentTypeForTextualCharset(contentType);
+        if (expected == null) {
+            assertNull("Expected no charset, but got:" + charset, charset);
+        } else {
+            assertEquals("Charset not as expected", expected, charset);
+        }
+    }
+}


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


Mime
View raw message