org.springframework.amqp.rabbit.support.RabbitUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.amqp.rabbit.support.RabbitUtils.java

Source

/*
 * Copyright 2002-2010 the original author or authors.
 * 
 * Licensed 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.springframework.amqp.rabbit.support;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.AmqpConnectException;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.AmqpIOException;
import org.springframework.amqp.AmqpUnsupportedEncodingException;
import org.springframework.amqp.UncategorizedAmqpException;
import org.springframework.amqp.core.Address;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Envelope;

/**
 * @author Mark Fisher
 * @author Mark Pollack
 */
public abstract class RabbitUtils {

    public static final int DEFAULT_PORT = AMQP.PROTOCOL.PORT;

    private static final Log logger = LogFactory.getLog(RabbitUtils.class);

    /**
     * Close the given RabbitMQ Connection and ignore any thrown exception. This is useful for typical
     * <code>finally</code> blocks in manual RabbitMQ code.
     * @param connection the RabbitMQ Connection to close (may be <code>null</code>)
     */
    public static void closeConnection(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (Exception ex) {
                logger.debug("Ignoring Connection exception - assuming already closed: " + ex);
            }
        }
    }

    /**
     * Close the given RabbitMQ Channel and ignore any thrown exception. This is useful for typical <code>finally</code>
     * blocks in manual RabbitMQ code.
     * @param channel the RabbitMQ Channel to close (may be <code>null</code>)
     */
    public static void closeChannel(Channel channel) {
        if (channel != null) {
            try {
                channel.close();
            } catch (IOException ex) {
                logger.debug("Could not close RabbitMQ Channel", ex);
            } catch (Throwable ex) {
                logger.debug("Unexpected exception on closing RabbitMQ Channel", ex);
            }
        }
    }

    /**
     * Commit the Channel if not within a JTA transaction.
     * @param channel the RabbitMQ Channel to commit
     */
    public static void commitIfNecessary(Channel channel) {
        Assert.notNull(channel, "Channel must not be null");
        try {
            channel.txCommit();
        } catch (IOException ex) {
            throw new AmqpIOException(ex);
        }
    }

    public static void rollbackIfNecessary(Channel channel) {
        Assert.notNull(channel, "Channel must not be null");
        try {
            channel.txRollback();
        } catch (IOException ex) {
            throw new AmqpIOException(ex);
        }
    }

    public static AmqpException convertRabbitAccessException(Throwable ex) {
        Assert.notNull(ex, "Exception must not be null");
        if (ex instanceof AmqpException) {
            return (AmqpException) ex;
        }
        if (ex instanceof ConnectException) {
            return new AmqpConnectException((ConnectException) ex);
        }
        if (ex instanceof IOException) {
            return new AmqpIOException((IOException) ex);
        }
        if (ex instanceof UnsupportedEncodingException) {
            return new AmqpUnsupportedEncodingException(ex);
        }
        // fallback
        return new UncategorizedAmqpException(ex);
    }

    public static void closeMessageConsumer(Channel channel, String consumerTag, boolean transactional) {
        if (!channel.isOpen()) {
            return;
        }
        try {
            channel.basicCancel(consumerTag);
            if (transactional) {
                /*
                 * Re-queue in-flight messages if any (after the consumer is cancelled to prevent the broker from simply
                 * sending them back to us).  Does not require a tx.commit.
                 */
                channel.basicRecover(true);
            }
        } catch (Exception ex) {
            throw convertRabbitAccessException(ex);
        }
    }

    public static MessageProperties createMessageProperties(final BasicProperties source, final Envelope envelope,
            final String charset) {
        MessageProperties target = new MessageProperties();
        Map<String, Object> headers = source.getHeaders();
        if (!CollectionUtils.isEmpty(headers)) {
            for (Map.Entry<String, Object> entry : headers.entrySet()) {
                target.setHeader(entry.getKey(), entry.getValue());
            }
        }
        target.setTimestamp(source.getTimestamp());
        target.setMessageId(source.getMessageId());
        target.setUserId(source.getUserId());
        target.setAppId(source.getAppId());
        target.setClusterId(source.getClusterId());
        target.setType(source.getType());
        Integer deliverMode = source.getDeliveryMode();
        if (deliverMode != null) {
            target.setDeliveryMode(MessageDeliveryMode.fromInt(deliverMode));
        }
        target.setExpiration(source.getExpiration());
        target.setPriority(source.getPriority());
        target.setContentType(source.getContentType());
        target.setContentEncoding(source.getContentEncoding());
        String correlationId = source.getCorrelationId();
        if (correlationId != null) {
            try {
                target.setCorrelationId(source.getCorrelationId().getBytes(charset));
            } catch (UnsupportedEncodingException ex) {
                throw new AmqpUnsupportedEncodingException(ex);
            }
        }
        String replyTo = source.getReplyTo();
        if (replyTo != null) {
            target.setReplyTo(new Address(replyTo));
        }
        if (envelope != null) {
            target.setReceivedExchange(envelope.getExchange());
            target.setReceivedRoutingKey(envelope.getRoutingKey());
            target.setRedelivered(envelope.isRedeliver());
            target.setDeliveryTag(envelope.getDeliveryTag());
        }
        // TODO: what about messageCount?
        return target;
    }

    public static BasicProperties extractBasicProperties(Message message, String charset) {
        if (message == null || message.getMessageProperties() == null) {
            return null;
        }
        MessageProperties source = message.getMessageProperties();
        BasicProperties target = new BasicProperties();
        target.setHeaders(source.getHeaders());
        target.setTimestamp(source.getTimestamp());
        target.setMessageId(source.getMessageId());
        target.setUserId(source.getUserId());
        target.setAppId(source.getAppId());
        target.setClusterId(source.getClusterId());
        target.setType(source.getType());
        MessageDeliveryMode deliveryMode = source.getDeliveryMode();
        if (deliveryMode != null) {
            target.setDeliveryMode(MessageDeliveryMode.toInt(deliveryMode));
        }
        target.setExpiration(source.getExpiration());
        target.setPriority(source.getPriority());
        target.setContentType(source.getContentType());
        target.setContentEncoding(source.getContentEncoding());
        byte[] correlationId = source.getCorrelationId();
        if (correlationId != null && correlationId.length > 0) {
            try {
                target.setCorrelationId(new String(correlationId, charset));
            } catch (UnsupportedEncodingException ex) {
                throw new AmqpUnsupportedEncodingException(ex);
            }
        }
        Address replyTo = source.getReplyTo();
        if (replyTo != null) {
            target.setReplyTo(replyTo.toString());
        }
        return target;
    }

    /**
     * Declare to that broker that a channel is going to be used transactionally, and convert exceptions that arise.
     * 
     * @param channel the channel to use
     */
    public static void declareTransactional(Channel channel) {
        try {
            channel.txSelect();
        } catch (IOException e) {
            throw RabbitUtils.convertRabbitAccessException(e);
        }
    }

}