Java tutorial
/* * $Id$ * -------------------------------------------------------------------------------------- * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.transport.amqp; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.mule.api.MuleEvent; import org.mule.api.endpoint.ImmutableEndpoint; import org.mule.api.expression.ExpressionManager; import org.mule.util.StringUtils; import com.rabbitmq.client.AMQP.Queue.DeclareOk; import com.rabbitmq.client.Channel; public abstract class AmqpEndpointUtil { private static final Log LOG = LogFactory.getLog(AmqpEndpointUtil.class); public static final String QUEUE_EXCLUSIVE = "queueExclusive"; public static final String QUEUE_AUTO_DELETE = "queueAutoDelete"; public static final String QUEUE_DURABLE = "queueDurable"; public static final String EXCHANGE_AUTO_DELETE = "exchangeAutoDelete"; public static final String EXCHANGE_DURABLE = "exchangeDurable"; public static final String EXCHANGE_TYPE = "exchangeType"; public static final String ROUTING_KEY = "routingKey"; public static final String CONSUMER_TAG = "consumerTag"; public static final String QUEUE_PREFIX = "amqp-queue."; public static final String EXCHANGE_PREFIX = "amqp-exchange."; public static String getOrCreateQueue(final Channel channel, final ImmutableEndpoint endpoint, final boolean activeDeclarationsOnly) throws IOException { final String exchangeName = getOrCreateExchange(channel, endpoint, activeDeclarationsOnly); return getOrCreateQueue(channel, endpoint, activeDeclarationsOnly, exchangeName); } public static String getOrCreateQueue(final Channel channel, final ImmutableEndpoint endpoint, final boolean activeDeclarationsOnly, final String exchangeName) throws IOException { final String routingKey = getRoutingKey(endpoint); return getOrCreateQueue(channel, endpoint, activeDeclarationsOnly, exchangeName, routingKey); } public static String getOrCreateQueue(final Channel channel, final ImmutableEndpoint endpoint, final boolean activeDeclarationsOnly, final String exchangeName, final String routingKey) throws IOException { final String queueName = getQueueName(endpoint.getAddress()); if (StringUtils.isBlank(queueName)) { // no queue name -> create a private one on the server final DeclareOk queueDeclareResult = channel.queueDeclare(); final String privateQueueName = queueDeclareResult.getQueue(); LOG.info("Declared private queue: " + privateQueueName); bindQueue(channel, endpoint, exchangeName, routingKey, privateQueueName); return privateQueueName; } // queue name -> either create or ensure the queue exists if (endpoint.getProperties().containsKey(QUEUE_DURABLE) || endpoint.getProperties().containsKey(QUEUE_AUTO_DELETE) || endpoint.getProperties().containsKey(QUEUE_EXCLUSIVE)) { // any of the queue declaration parameter provided -> declare the queue final boolean queueDurable = BooleanUtils.toBoolean((String) endpoint.getProperty(QUEUE_DURABLE)); final boolean queueExclusive = BooleanUtils.toBoolean((String) endpoint.getProperty(QUEUE_EXCLUSIVE)); final boolean queueAutoDelete = BooleanUtils .toBoolean((String) endpoint.getProperty(QUEUE_AUTO_DELETE)); final Map<String, Object> arguments = getArguments(endpoint, QUEUE_PREFIX); channel.queueDeclare(queueName, queueDurable, queueExclusive, queueAutoDelete, arguments); LOG.info("Declared queue: " + queueName + ", durable: " + queueDurable + ", exclusive: " + queueExclusive + ", autoDelete: " + queueAutoDelete + ", arguments: " + arguments); bindQueue(channel, endpoint, exchangeName, routingKey, queueName); } else if (!activeDeclarationsOnly) { // no declaration parameter -> ensure the queue exists channel.queueDeclarePassive(queueName); if (LOG.isDebugEnabled()) { LOG.debug("Validated presence of queue: " + queueName); } } return queueName; } private static void bindQueue(final Channel channel, final ImmutableEndpoint endpoint, final String exchangeName, final String routingKey, final String queueName) throws IOException { if ((isDefaultExchange(exchangeName)) && (LOG.isDebugEnabled())) { LOG.debug("Skipped binding of queue: " + queueName + " to default exchange"); return; } // bind queue to exchange channel.queueBind(queueName, exchangeName, routingKey); LOG.info( "Bound queue: " + queueName + " to exchange: " + exchangeName + " with routing key: " + routingKey); } public static boolean isDefaultExchange(final String exchangeName) { return StringUtils.isBlank(exchangeName) || StringUtils.equals(exchangeName, AmqpConstants.DEFAULT_EXCHANGE_ALIAS); } public static String getOrCreateExchange(final Channel channel, final ImmutableEndpoint endpoint, final boolean activeDeclarationsOnly) throws IOException { final String endpointAddress = endpoint.getAddress(); final String exchangeName = getExchangeName(endpointAddress, endpoint.getConnector().getProtocol()); if (isDefaultExchange(exchangeName)) { if (LOG.isDebugEnabled()) { LOG.debug("Using default exchange for endpoint: " + endpoint); } return AmqpConstants.DEFAULT_EXCHANGE_ALIAS; } final String exchangeType = (String) endpoint.getProperty(EXCHANGE_TYPE); if (StringUtils.isNotBlank(exchangeType)) { // an exchange type is provided -> the exchange must be declared final boolean exchangeDurable = BooleanUtils.toBoolean((String) endpoint.getProperty(EXCHANGE_DURABLE)); final boolean exchangeAutoDelete = BooleanUtils .toBoolean((String) endpoint.getProperty(EXCHANGE_AUTO_DELETE)); final Map<String, Object> arguments = getArguments(endpoint, EXCHANGE_PREFIX); channel.exchangeDeclare(exchangeName, exchangeType, exchangeDurable, exchangeAutoDelete, arguments); LOG.info("Declared exchange: " + exchangeName + " of type: " + exchangeType + ", durable: " + exchangeDurable + ", autoDelete: " + exchangeAutoDelete + ", arguments: " + arguments); } else if (!activeDeclarationsOnly) { // no exchange type -> ensure the exchange exists channel.exchangeDeclarePassive(exchangeName); if (LOG.isDebugEnabled()) { LOG.debug("Validated presence of exchange: " + exchangeName); } } return exchangeName; } @SuppressWarnings("unchecked") private static Map<String, Object> getArguments(final ImmutableEndpoint endpoint, final String argumentPrefix) { final Map<String, Object> arguments = new HashMap<String, Object>(); for (final Entry<Object, Object> property : ((Map<Object, Object>) endpoint.getProperties()).entrySet()) { final String name = property.getKey().toString(); if (StringUtils.startsWith(name, argumentPrefix)) { arguments.put(StringUtils.substringAfter(name, argumentPrefix), property.getValue()); } } return arguments; } public static String getRoutingKey(final ImmutableEndpoint endpoint) { return StringUtils.defaultString((String) endpoint.getProperty(ROUTING_KEY)); } public static String getRoutingKey(final ImmutableEndpoint endpoint, final MuleEvent muleEvent) { final String eventRoutingKey = muleEvent.getMessage().getOutboundProperty(AmqpConstants.ROUTING_KEY, StringUtils.defaultString((String) endpoint.getProperty(ROUTING_KEY))); // MEL in exchange and queue is auto-resolved as being part of the endpoint URI but routing // key must be resolved by hand final ExpressionManager expressionManager = muleEvent.getMuleContext().getExpressionManager(); return expressionManager.parse(eventRoutingKey, muleEvent); } public static String getConsumerTag(final ImmutableEndpoint endpoint) { return StringUtils.defaultString((String) endpoint.getProperty(CONSUMER_TAG)); } public static String getQueueName(final String endpointAddress) { return StringUtils.defaultString(StringUtils.substringAfter(trimQuery(endpointAddress), QUEUE_PREFIX)); } public static String getExchangeName(final String endpointAddress, final String protocol) { final String trimmedQuery = trimQuery(endpointAddress); final String exchangeName = StringUtils.defaultString( StringUtils.substringBetween(trimmedQuery, protocol + "://", "/" + QUEUE_PREFIX), StringUtils.substringAfter(trimmedQuery, protocol + "://")); if (exchangeName.startsWith(QUEUE_PREFIX)) { return StringUtils.EMPTY; } return exchangeName; } private static String trimQuery(final String address) { return StringUtils.substringBefore(address, "?"); } }