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 java.util.Map; 020import java.util.Set; 021 022import javax.jms.DeliveryMode; 023import javax.jms.JMSException; 024import javax.jms.Message; 025 026import org.apache.activemq.ScheduledMessage; 027import org.apache.qpid.proton.amqp.Binary; 028import org.apache.qpid.proton.amqp.Decimal128; 029import org.apache.qpid.proton.amqp.Decimal32; 030import org.apache.qpid.proton.amqp.Decimal64; 031import org.apache.qpid.proton.amqp.Symbol; 032import org.apache.qpid.proton.amqp.UnsignedByte; 033import org.apache.qpid.proton.amqp.UnsignedInteger; 034import org.apache.qpid.proton.amqp.UnsignedLong; 035import org.apache.qpid.proton.amqp.UnsignedShort; 036import org.apache.qpid.proton.amqp.messaging.ApplicationProperties; 037import org.apache.qpid.proton.amqp.messaging.Footer; 038import org.apache.qpid.proton.amqp.messaging.Header; 039import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; 040import org.apache.qpid.proton.amqp.messaging.Properties; 041 042public abstract class InboundTransformer { 043 044 JMSVendor vendor; 045 046 public static final String TRANSFORMER_NATIVE = "native"; 047 public static final String TRANSFORMER_RAW = "raw"; 048 public static final String TRANSFORMER_JMS = "jms"; 049 050 String prefixVendor = "JMS_AMQP_"; 051 String prefixDeliveryAnnotations = "DA_"; 052 String prefixMessageAnnotations = "MA_"; 053 String prefixFooter = "FT_"; 054 055 int defaultDeliveryMode = javax.jms.DeliveryMode.NON_PERSISTENT; 056 int defaultPriority = javax.jms.Message.DEFAULT_PRIORITY; 057 long defaultTtl = javax.jms.Message.DEFAULT_TIME_TO_LIVE; 058 059 public InboundTransformer(JMSVendor vendor) { 060 this.vendor = vendor; 061 } 062 063 public abstract Message transform(EncodedMessage amqpMessage) throws Exception; 064 065 public abstract String getTransformerName(); 066 067 public abstract InboundTransformer getFallbackTransformer(); 068 069 public int getDefaultDeliveryMode() { 070 return defaultDeliveryMode; 071 } 072 073 public void setDefaultDeliveryMode(int defaultDeliveryMode) { 074 this.defaultDeliveryMode = defaultDeliveryMode; 075 } 076 077 public int getDefaultPriority() { 078 return defaultPriority; 079 } 080 081 public void setDefaultPriority(int defaultPriority) { 082 this.defaultPriority = defaultPriority; 083 } 084 085 public long getDefaultTtl() { 086 return defaultTtl; 087 } 088 089 public void setDefaultTtl(long defaultTtl) { 090 this.defaultTtl = defaultTtl; 091 } 092 093 public String getPrefixVendor() { 094 return prefixVendor; 095 } 096 097 public void setPrefixVendor(String prefixVendor) { 098 this.prefixVendor = prefixVendor; 099 } 100 101 public JMSVendor getVendor() { 102 return vendor; 103 } 104 105 public void setVendor(JMSVendor vendor) { 106 this.vendor = vendor; 107 } 108 109 @SuppressWarnings("unchecked") 110 protected void populateMessage(Message jms, org.apache.qpid.proton.message.Message amqp) throws Exception { 111 Header header = amqp.getHeader(); 112 if (header == null) { 113 header = new Header(); 114 } 115 116 if (header.getDurable() != null) { 117 jms.setJMSDeliveryMode(header.getDurable().booleanValue() ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); 118 } else { 119 jms.setJMSDeliveryMode(defaultDeliveryMode); 120 } 121 if (header.getPriority() != null) { 122 jms.setJMSPriority(header.getPriority().intValue()); 123 } else { 124 jms.setJMSPriority(defaultPriority); 125 } 126 if (header.getFirstAcquirer() != null) { 127 jms.setBooleanProperty(prefixVendor + "FirstAcquirer", header.getFirstAcquirer()); 128 } 129 if (header.getDeliveryCount() != null) { 130 vendor.setJMSXDeliveryCount(jms, header.getDeliveryCount().longValue()); 131 } 132 133 final MessageAnnotations ma = amqp.getMessageAnnotations(); 134 if (ma != null) { 135 for (Map.Entry<?, ?> entry : ma.getValue().entrySet()) { 136 String key = entry.getKey().toString(); 137 if ("x-opt-jms-type".equals(key) && entry.getValue() != null) { 138 // Legacy annotation, JMSType value will be replaced by Subject further down if also present. 139 jms.setJMSType(entry.getValue().toString()); 140 } else if ("x-opt-delivery-time".equals(key) && entry.getValue() != null) { 141 long deliveryTime = ((Number) entry.getValue()).longValue(); 142 long delay = deliveryTime - System.currentTimeMillis(); 143 if (delay > 0) { 144 jms.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay); 145 } 146 } else if ("x-opt-delivery-delay".equals(key) && entry.getValue() != null) { 147 long delay = ((Number) entry.getValue()).longValue(); 148 if (delay > 0) { 149 jms.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay); 150 } 151 } else if ("x-opt-delivery-repeat".equals(key) && entry.getValue() != null) { 152 int repeat = ((Number) entry.getValue()).intValue(); 153 if (repeat > 0) { 154 jms.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, repeat); 155 } 156 } else if ("x-opt-delivery-period".equals(key) && entry.getValue() != null) { 157 long period = ((Number) entry.getValue()).longValue(); 158 if (period > 0) { 159 jms.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, period); 160 } 161 } else if ("x-opt-delivery-cron".equals(key) && entry.getValue() != null) { 162 String cronEntry = (String) entry.getValue(); 163 if (cronEntry != null) { 164 jms.setStringProperty(ScheduledMessage.AMQ_SCHEDULED_CRON, cronEntry); 165 } 166 } 167 168 setProperty(jms, prefixVendor + prefixMessageAnnotations + key, entry.getValue()); 169 } 170 } 171 172 final ApplicationProperties ap = amqp.getApplicationProperties(); 173 if (ap != null) { 174 for (Map.Entry<Object, Object> entry : (Set<Map.Entry<Object, Object>>) ap.getValue().entrySet()) { 175 String key = entry.getKey().toString(); 176 if ("JMSXGroupID".equals(key)) { 177 vendor.setJMSXGroupID(jms, entry.getValue().toString()); 178 } else if ("JMSXGroupSequence".equals(key)) { 179 vendor.setJMSXGroupSequence(jms, ((Number) entry.getValue()).intValue()); 180 } else if ("JMSXUserID".equals(key)) { 181 vendor.setJMSXUserID(jms, entry.getValue().toString()); 182 } else { 183 setProperty(jms, key, entry.getValue()); 184 } 185 } 186 } 187 188 final Properties properties = amqp.getProperties(); 189 if (properties != null) { 190 if (properties.getMessageId() != null) { 191 jms.setJMSMessageID(properties.getMessageId().toString()); 192 } 193 Binary userId = properties.getUserId(); 194 if (userId != null) { 195 vendor.setJMSXUserID(jms, new String(userId.getArray(), userId.getArrayOffset(), userId.getLength(), "UTF-8")); 196 } 197 if (properties.getTo() != null) { 198 jms.setJMSDestination(vendor.createDestination(properties.getTo())); 199 } 200 if (properties.getSubject() != null) { 201 jms.setJMSType(properties.getSubject()); 202 } 203 if (properties.getReplyTo() != null) { 204 jms.setJMSReplyTo(vendor.createDestination(properties.getReplyTo())); 205 } 206 if (properties.getCorrelationId() != null) { 207 jms.setJMSCorrelationID(properties.getCorrelationId().toString()); 208 } 209 if (properties.getContentType() != null) { 210 jms.setStringProperty(prefixVendor + "ContentType", properties.getContentType().toString()); 211 } 212 if (properties.getContentEncoding() != null) { 213 jms.setStringProperty(prefixVendor + "ContentEncoding", properties.getContentEncoding().toString()); 214 } 215 if (properties.getCreationTime() != null) { 216 jms.setJMSTimestamp(properties.getCreationTime().getTime()); 217 } 218 if (properties.getGroupId() != null) { 219 vendor.setJMSXGroupID(jms, properties.getGroupId()); 220 } 221 if (properties.getGroupSequence() != null) { 222 vendor.setJMSXGroupSequence(jms, properties.getGroupSequence().intValue()); 223 } 224 if (properties.getReplyToGroupId() != null) { 225 jms.setStringProperty(prefixVendor + "ReplyToGroupID", properties.getReplyToGroupId()); 226 } 227 if (properties.getAbsoluteExpiryTime() != null) { 228 jms.setJMSExpiration(properties.getAbsoluteExpiryTime().getTime()); 229 } 230 } 231 232 // If the jms expiration has not yet been set... 233 if (jms.getJMSExpiration() == 0) { 234 // Then lets try to set it based on the message ttl. 235 long ttl = defaultTtl; 236 if (header.getTtl() != null) { 237 ttl = header.getTtl().longValue(); 238 } 239 if (ttl == 0) { 240 jms.setJMSExpiration(0); 241 } else { 242 jms.setJMSExpiration(System.currentTimeMillis() + ttl); 243 } 244 } 245 246 final Footer fp = amqp.getFooter(); 247 if (fp != null) { 248 for (Map.Entry<Object, Object> entry : (Set<Map.Entry<Object, Object>>) fp.getValue().entrySet()) { 249 String key = entry.getKey().toString(); 250 setProperty(jms, prefixVendor + prefixFooter + key, entry.getValue()); 251 } 252 } 253 } 254 255 private void setProperty(Message msg, String key, Object value) throws JMSException { 256 if (value instanceof UnsignedLong) { 257 long v = ((UnsignedLong) value).longValue(); 258 msg.setLongProperty(key, v); 259 } else if (value instanceof UnsignedInteger) { 260 long v = ((UnsignedInteger) value).longValue(); 261 if (Integer.MIN_VALUE <= v && v <= Integer.MAX_VALUE) { 262 msg.setIntProperty(key, (int) v); 263 } else { 264 msg.setLongProperty(key, v); 265 } 266 } else if (value instanceof UnsignedShort) { 267 int v = ((UnsignedShort) value).intValue(); 268 if (Short.MIN_VALUE <= v && v <= Short.MAX_VALUE) { 269 msg.setShortProperty(key, (short) v); 270 } else { 271 msg.setIntProperty(key, v); 272 } 273 } else if (value instanceof UnsignedByte) { 274 short v = ((UnsignedByte) value).shortValue(); 275 if (Byte.MIN_VALUE <= v && v <= Byte.MAX_VALUE) { 276 msg.setByteProperty(key, (byte) v); 277 } else { 278 msg.setShortProperty(key, v); 279 } 280 } else if (value instanceof Symbol) { 281 msg.setStringProperty(key, value.toString()); 282 } else if (value instanceof Decimal128) { 283 msg.setDoubleProperty(key, ((Decimal128) value).doubleValue()); 284 } else if (value instanceof Decimal64) { 285 msg.setDoubleProperty(key, ((Decimal64) value).doubleValue()); 286 } else if (value instanceof Decimal32) { 287 msg.setFloatProperty(key, ((Decimal32) value).floatValue()); 288 } else if (value instanceof Binary) { 289 msg.setStringProperty(key, value.toString()); 290 } else { 291 msg.setObjectProperty(key, value); 292 } 293 } 294}