org.apache.qpid.jms.provider.amqp.message.AmqpJmsMessageBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.qpid.jms.provider.amqp.message.AmqpJmsMessageBuilder.java

Source

/*
 * 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.provider.amqp.message;

import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_BYTES_MESSAGE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_MAP_MESSAGE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_MESSAGE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_MSG_TYPE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_OBJECT_MESSAGE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_STREAM_MESSAGE;
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.decodeMessage;
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;
import org.apache.qpid.jms.message.JmsMessage;
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;
import org.apache.qpid.proton.amqp.messaging.Data;
import org.apache.qpid.proton.amqp.messaging.Section;
import org.apache.qpid.proton.message.Message;

import io.netty.buffer.ByteBuf;

/**
 * Builder class used to construct the appropriate JmsMessage / JmsMessageFacade
 * objects to wrap an incoming AMQP Message.
 */
public class AmqpJmsMessageBuilder {

    /**
     * Create a new JmsMessage and underlying JmsMessageFacade that represents the proper
     * message type for the incoming AMQP message.
     *
     * @param consumer
     *        The provider AMQP Consumer instance where this message arrived at.
     * @param messageBytes
     *        The the raw bytes that compose the incoming message. (Read-Only)
     *
     * @return a JmsMessage instance properly configured for dispatch to the provider listener.
     *
     * @throws IOException if an error occurs while creating the message objects.
     */
    public static JmsMessage createJmsMessage(AmqpConsumer consumer, ByteBuf messageBytes) throws IOException {

        Message amqpMessage = decodeMessage(messageBytes);

        // First we try the easy way, if the annotation is there we don't have to work hard.
        JmsMessage result = createFromMsgAnnotation(consumer, amqpMessage, messageBytes);
        if (result != null) {
            return result;
        }

        // Next, match specific section structures and content types
        result = createWithoutAnnotation(consumer, amqpMessage, messageBytes);
        if (result != null) {
            return result;
        }

        throw new IOException("Could not create a JMS message from incoming message");
    }

    private static JmsMessage createFromMsgAnnotation(AmqpConsumer consumer, Message message, ByteBuf messageBytes)
            throws IOException {
        Object annotation = AmqpMessageSupport.getMessageAnnotation(JMS_MSG_TYPE, message);
        if (annotation != null) {

            switch ((byte) annotation) {
            case JMS_MESSAGE:
                return createMessage(consumer, message);
            case JMS_BYTES_MESSAGE:
                return createBytesMessage(consumer, message);
            case JMS_TEXT_MESSAGE:
                return createTextMessage(consumer, message, StandardCharsets.UTF_8);
            case JMS_MAP_MESSAGE:
                return createMapMessage(consumer, message);
            case JMS_STREAM_MESSAGE:
                return createStreamMessage(consumer, message);
            case JMS_OBJECT_MESSAGE:
                return createObjectMessage(consumer, message, messageBytes);
            default:
                throw new IOException("Invalid JMS Message Type annotation value found in message: " + annotation);
            }
        }

        return null;
    }

    private static JmsMessage createWithoutAnnotation(AmqpConsumer consumer, Message message,
            ByteBuf messageBytes) {
        Section body = message.getBody();

        if (body == null) {
            if (isContentType(SERIALIZED_JAVA_OBJECT_CONTENT_TYPE, message)) {
                return createObjectMessage(consumer, message, messageBytes);
            } else if (isContentType(OCTET_STREAM_CONTENT_TYPE, message) || isContentType(null, message)) {
                return createBytesMessage(consumer, message);
            } else {
                Charset charset = getCharsetForTextualContent(message.getContentType());
                if (charset != null) {
                    return createTextMessage(consumer, message, charset);
                } else {
                    return createMessage(consumer, message);
                }
            }
        } else if (body instanceof Data) {
            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, messageBytes);
            } else {
                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, StandardCharsets.UTF_8);
            } else if (value instanceof Binary) {
                return createBytesMessage(consumer, message);
            } else {
                return createObjectMessage(consumer, message, messageBytes);
            }
        } else if (body instanceof AmqpSequence) {
            return createObjectMessage(consumer, message, messageBytes);
        }

        return null;
    }

    private static JmsObjectMessage createObjectMessage(AmqpConsumer consumer, Message message,
            ByteBuf messageBytes) {
        return new JmsObjectMessage(new AmqpJmsObjectMessageFacade(consumer, message, messageBytes.copy()));
    }

    private static JmsStreamMessage createStreamMessage(AmqpConsumer consumer, Message message) {
        return new JmsStreamMessage(new AmqpJmsStreamMessageFacade(consumer, message));
    }

    private static JmsMapMessage createMapMessage(AmqpConsumer consumer, Message message) {
        return new JmsMapMessage(new AmqpJmsMapMessageFacade(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) {
        return new JmsBytesMessage(new AmqpJmsBytesMessageFacade(consumer, message));
    }

    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;
        }
    }
}