001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.transport.amqp.message; 018 019import static org.apache.activemq.transport.amqp.message.AmqpMessageSupport.JMS_AMQP_MESSAGE_FORMAT; 020import static org.apache.activemq.transport.amqp.message.AmqpMessageSupport.getBinaryFromMessageBody; 021 022import javax.jms.JMSException; 023import javax.jms.MessageFormatException; 024 025import org.apache.activemq.command.ActiveMQBytesMessage; 026import org.apache.activemq.command.ActiveMQMessage; 027import org.apache.qpid.proton.amqp.Binary; 028import org.apache.qpid.proton.amqp.UnsignedInteger; 029import org.apache.qpid.proton.amqp.messaging.Header; 030import org.apache.qpid.proton.message.ProtonJMessage; 031 032public class AMQPNativeOutboundTransformer implements OutboundTransformer { 033 034 @Override 035 public EncodedMessage transform(ActiveMQMessage message) throws Exception { 036 if (message == null || !(message instanceof ActiveMQBytesMessage)) { 037 return null; 038 } 039 040 return transform(this, (ActiveMQBytesMessage) message); 041 } 042 043 static EncodedMessage transform(OutboundTransformer options, ActiveMQBytesMessage message) throws JMSException { 044 final long messageFormat; 045 if (message.propertyExists(JMS_AMQP_MESSAGE_FORMAT)) { 046 try { 047 messageFormat = message.getLongProperty(JMS_AMQP_MESSAGE_FORMAT); 048 } catch (MessageFormatException e) { 049 return null; 050 } 051 } else { 052 messageFormat = 0; 053 } 054 055 Binary encodedMessage = getBinaryFromMessageBody(message); 056 byte encodedData[] = encodedMessage.getArray(); 057 int encodedSize = encodedMessage.getLength(); 058 059 int count = message.getRedeliveryCounter(); 060 if (count >= 1) { 061 062 // decode... 063 ProtonJMessage amqp = (ProtonJMessage) org.apache.qpid.proton.message.Message.Factory.create(); 064 int offset = 0; 065 int len = encodedSize; 066 while (len > 0) { 067 final int decoded = amqp.decode(encodedData, offset, len); 068 assert decoded > 0 : "Make progress decoding the message"; 069 offset += decoded; 070 len -= decoded; 071 } 072 073 // Update the DeliveryCount header... 074 // The AMQP delivery-count field only includes prior failed delivery attempts, 075 // whereas JMSXDeliveryCount includes the first/current delivery attempt. Subtract 1. 076 if (amqp.getHeader() == null) { 077 amqp.setHeader(new Header()); 078 } 079 080 amqp.getHeader().setDeliveryCount(new UnsignedInteger(count)); 081 082 // Re-encode... 083 final AmqpWritableBuffer buffer = new AmqpWritableBuffer(); 084 int written = amqp.encode(buffer); 085 086 encodedData = buffer.getArray(); 087 encodedSize = written; 088 } 089 090 return new EncodedMessage(messageFormat, encodedData, 0, encodedSize); 091 } 092}