/** * 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 io.hawtjms.provider.stomp.message; import static io.hawtjms.provider.stomp.StompConstants.CONTENT_LENGTH; import static io.hawtjms.provider.stomp.StompConstants.CORRELATION_ID; import static io.hawtjms.provider.stomp.StompConstants.DESTINATION; import static io.hawtjms.provider.stomp.StompConstants.EXPIRATION_TIME; import static io.hawtjms.provider.stomp.StompConstants.FALSE; import static io.hawtjms.provider.stomp.StompConstants.JMSX_DELIVERY_COUNT; import static io.hawtjms.provider.stomp.StompConstants.JMSX_GROUP_ID; import static io.hawtjms.provider.stomp.StompConstants.JMSX_GROUP_SEQUENCE; import static io.hawtjms.provider.stomp.StompConstants.MESSAGE_ID; import static io.hawtjms.provider.stomp.StompConstants.PERSISTENT; import static io.hawtjms.provider.stomp.StompConstants.PRIORITY; import static io.hawtjms.provider.stomp.StompConstants.RECEIPT_REQUESTED; import static io.hawtjms.provider.stomp.StompConstants.REDELIVERED; import static io.hawtjms.provider.stomp.StompConstants.REPLY_TO; import static io.hawtjms.provider.stomp.StompConstants.SUBSCRIPTION; import static io.hawtjms.provider.stomp.StompConstants.TIMESTAMP; import static io.hawtjms.provider.stomp.StompConstants.TRANSFORMATION; import static io.hawtjms.provider.stomp.StompConstants.TRUE; import static io.hawtjms.provider.stomp.StompConstants.TYPE; import static io.hawtjms.provider.stomp.StompConstants.USERID; import io.hawtjms.jms.JmsDestination; import io.hawtjms.jms.message.JmsMessageFacade; import io.hawtjms.jms.meta.JmsMessageId; import io.hawtjms.provider.stomp.StompConnection; import io.hawtjms.provider.stomp.StompFrame; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import javax.jms.JMSException; /** * A STOMP based JmsMessageFacade that wraps a given STOMP frame containing a * MESSAGE command. The facade will map the standard JMS properties onto the * appropriate STOMP properties and */ public class StompJmsMessageFacade implements JmsMessageFacade { static HashSet<String> RESERVED_HEADER_NAMES = new HashSet<String>(); static{ RESERVED_HEADER_NAMES.add(DESTINATION); RESERVED_HEADER_NAMES.add(REPLY_TO); RESERVED_HEADER_NAMES.add(MESSAGE_ID); RESERVED_HEADER_NAMES.add(CORRELATION_ID); RESERVED_HEADER_NAMES.add(EXPIRATION_TIME); RESERVED_HEADER_NAMES.add(TIMESTAMP); RESERVED_HEADER_NAMES.add(PRIORITY); RESERVED_HEADER_NAMES.add(REDELIVERED); RESERVED_HEADER_NAMES.add(TYPE); RESERVED_HEADER_NAMES.add(PERSISTENT); RESERVED_HEADER_NAMES.add(RECEIPT_REQUESTED); RESERVED_HEADER_NAMES.add(TRANSFORMATION); RESERVED_HEADER_NAMES.add(SUBSCRIPTION); RESERVED_HEADER_NAMES.add(CONTENT_LENGTH); RESERVED_HEADER_NAMES.add(JMSX_DELIVERY_COUNT); RESERVED_HEADER_NAMES.add(JMSX_GROUP_ID); RESERVED_HEADER_NAMES.add(JMSX_GROUP_SEQUENCE); } private final StompFrame message; private final StompConnection connection; /** * Creates a new wrapper around the StompFrame Message instance. * * @param message * the STOMP message to wrap. * @param connection * the STOMP connection instance to assign to this Facade. */ public StompJmsMessageFacade(StompFrame message, StompConnection connection) { this.message = message; this.connection = connection; } /** * @return the underlying STOMP frame that backs this Facade. */ public StompFrame getStompMessage() { return this.message; } /** * @return the StompConnection for this message facade. */ public StompConnection getStompConnection() { return this.connection; } @Override public Map<String, Object> getProperties() throws IOException { Map<String, Object> properties = new HashMap<String, Object>(); for (Entry<String, String> entry : message.getProperties().entrySet()) { if (!RESERVED_HEADER_NAMES.contains(entry.getKey())) { properties.put(entry.getKey(), entry.getValue()); } } return Collections.unmodifiableMap(properties); } @Override public boolean propertyExists(String key) throws IOException { return message.getProperty(key) != null; } @Override public Object getProperty(String key) throws IOException { return message.getProperty(key); } @Override public void setProperty(String key, Object value) throws IOException { if (!RESERVED_HEADER_NAMES.contains(key)) { message.setProperty(key, value.toString()); } } @Override public void onSend() throws JMSException { // TODO - Nothing yet needed here. } @Override public void clearBody() { message.setContent(null); } @Override public void clearProperties() { message.getProperties().entrySet().retainAll(RESERVED_HEADER_NAMES); } @Override public JmsMessageFacade copy() { return new StompJmsMessageFacade(message.clone(), connection); } @Override public JmsMessageId getMessageId() { return new JmsMessageId(message.getProperty(MESSAGE_ID)); } @Override public void setMessageId(JmsMessageId messageId) { message.setProperty(MESSAGE_ID, messageId.toString()); } @Override public long getTimestamp() { return or(getLongProperty(TIMESTAMP), 0L); } @Override public void setTimestamp(long timestamp) { setLongProperty(TIMESTAMP, timestamp); } @Override public String getCorrelationId() { return message.getProperty(CORRELATION_ID); } @Override public void setCorrelationId(String correlationId) { setStringProperty(CORRELATION_ID, correlationId); } @Override public boolean isPersistent() { return or(getBooleanProperty(PERSISTENT), false); } @Override public void setPersistent(boolean value) { setBooleanProperty(PERSISTENT, value); } @Override public int getRedeliveryCounter() { return or(getIntProperty(JMSX_DELIVERY_COUNT), 0); } @Override public void setRedeliveryCounter(int redeliveryCount) { setIntegerProperty(JMSX_DELIVERY_COUNT, redeliveryCount); } @Override public String getType() { return message.getProperty(TYPE); } @Override public void setType(String type) { setStringProperty(TYPE, type); } @Override public byte getPriority() { return or(getByteProperty(PRIORITY), (byte) 4); } @Override public void setPriority(byte priority) { setByteProperty(PRIORITY, priority); } @Override public long getExpiration() { return or(getLongProperty(EXPIRATION_TIME), 0L); } @Override public void setExpiration(long expiration) { setLongProperty(EXPIRATION_TIME, expiration); } @Override public JmsDestination getDestination() throws JMSException { return toJmsDestination(message.getProperty(DESTINATION)); } @Override public void setDestination(JmsDestination destination) { setStringProperty(DESTINATION, toStompDestination(destination)); } @Override public JmsDestination getReplyTo() throws JMSException { return toJmsDestination(message.getProperty(REPLY_TO)); } @Override public void setReplyTo(JmsDestination replyTo) { setStringProperty(REPLY_TO, toStompDestination(replyTo)); } @Override public String getUserId() { return message.getProperty(USERID); } @Override public void setUserId(String userId) { setStringProperty(USERID, userId); } @Override public String getGroupId() { return message.getProperty(JMSX_GROUP_ID); } @Override public void setGroupId(String groupId) { setStringProperty(JMSX_GROUP_ID, groupId); } @Override public int getGroupSequence() { return or(getIntProperty(JMSX_GROUP_SEQUENCE), 0); } @Override public void setGroupSequence(int groupSequence) { setIntegerProperty(JMSX_GROUP_SEQUENCE, groupSequence); } private void setStringProperty(String key, String value) { if (value == null) { message.removeProperty(key); } else { message.setProperty(key, value); } } private void setLongProperty(String key, Long value) { if (value == null) { message.removeProperty(key); } else { message.setProperty(key, value.toString()); } } private Long getLongProperty(String key) { String vale = message.getProperty(key); if (vale == null) { return null; } else { return Long.parseLong(vale.toString()); } } private Integer getIntProperty(String key) { String vale = message.getProperty(key); if (vale == null) { return null; } else { return Integer.parseInt(vale.toString()); } } private void setIntegerProperty(String key, Integer value) { if (value == null) { message.removeProperty(key); } else { message.setProperty(key, value.toString()); } } private Byte getByteProperty(String key) { String vale = message.getProperty(key); if (vale == null) { return null; } else { return Byte.parseByte(vale.toString()); } } private void setByteProperty(String key, Byte value) { if (value == null) { message.removeProperty(key); } else { message.setProperty(key, value.toString()); } } private Boolean getBooleanProperty(String key) { String vale = message.getProperty(key); if (vale == null) { return null; } else { return Boolean.parseBoolean(vale.toString()); } } private void setBooleanProperty(String key, Boolean value) { if (value == null) { message.removeProperty(key); } else { message.setProperty(key, value.booleanValue() ? TRUE : FALSE); } } private <T> T or(T value, T other) { if (value != null) { return value; } else { return other; } } private String toStompDestination(JmsDestination destination) { return connection.getServerAdapter().toStompDestination(destination); } private JmsDestination toJmsDestination(String destinationName) throws JMSException { return connection.getServerAdapter().toJmsDestination(destinationName); } }