/*
* 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 org.apache.activemq.artemis.protocol.amqp.broker;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.api.core.RefCountMessage;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.persistence.Persister;
import org.apache.activemq.artemis.protocol.amqp.converter.AMQPConverter;
import org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport;
import org.apache.activemq.artemis.protocol.amqp.util.NettyWritable;
import org.apache.activemq.artemis.protocol.amqp.util.TLSEncode;
import org.apache.activemq.artemis.reader.MessageUtil;
import org.apache.activemq.artemis.utils.DataConstants;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.UnsignedByte;
import org.apache.qpid.proton.amqp.UnsignedInteger;
import org.apache.qpid.proton.amqp.UnsignedLong;
import org.apache.qpid.proton.amqp.UnsignedShort;
import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
import org.apache.qpid.proton.amqp.messaging.DeliveryAnnotations;
import org.apache.qpid.proton.amqp.messaging.Header;
import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
import org.apache.qpid.proton.amqp.messaging.Properties;
import org.apache.qpid.proton.amqp.messaging.Section;
import org.apache.qpid.proton.codec.DecoderImpl;
import org.apache.qpid.proton.codec.WritableBuffer;
import org.apache.qpid.proton.message.Message;
import org.apache.qpid.proton.message.impl.MessageImpl;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.Unpooled;
// see https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-message-format
public class AMQPMessage extends RefCountMessage {
public static final int DEFAULT_MESSAGE_PRIORITY = 4;
public static final int MAX_MESSAGE_PRIORITY = 9;
final long messageFormat;
ByteBuf data;
boolean bufferValid;
Boolean durable;
long messageID;
String address;
MessageImpl protonMessage;
private volatile int memoryEstimate = -1;
private long expiration = 0;
// this is to store where to start sending bytes, ignoring header and delivery annotations.
private int sendFrom = 0;
private boolean parsedHeaders = false;
private Header _header;
private DeliveryAnnotations _deliveryAnnotations;
private MessageAnnotations _messageAnnotations;
private Properties _properties;
private int appLocation = -1;
private ApplicationProperties applicationProperties;
private long scheduledTime = -1;
private String connectionID;
Set<Object> rejectedConsumers;
public AMQPMessage(long messageFormat, byte[] data) {
this.data = Unpooled.wrappedBuffer(data);
this.messageFormat = messageFormat;
this.bufferValid = true;
parseHeaders();
}
/** for persistence reload */
public AMQPMessage(long messageFormat) {
this.messageFormat = messageFormat;
this.bufferValid = false;
}
public AMQPMessage(long messageFormat, Message message) {
this.messageFormat = messageFormat;
this.protonMessage = (MessageImpl) message;
this.bufferValid = false;
}
public AMQPMessage(Message message) {
this(0, message);
}
public MessageImpl getProtonMessage() {
if (protonMessage == null) {
protonMessage = (MessageImpl) Message.Factory.create();
if (data != null) {
data.readerIndex(0);
protonMessage.decode(data.nioBuffer());
this._header = protonMessage.getHeader();
protonMessage.setHeader(null);
}
}
return protonMessage;
}
private void initalizeObjects() {
if (protonMessage == null) {
if (data == null) {
this.sendFrom = 0;
_header = new Header();
_deliveryAnnotations = new DeliveryAnnotations(new HashMap<>());
_properties = new Properties();
this.applicationProperties = new ApplicationProperties(new HashMap<>());
this.protonMessage = (MessageImpl) Message.Factory.create();
this.protonMessage.setApplicationProperties(applicationProperties);
this.protonMessage.setDeliveryAnnotations(_deliveryAnnotations);
}
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> getApplicationPropertiesMap() {
ApplicationProperties appMap = getApplicationProperties();
Map<String, Object> map = null;
if (appMap != null) {
map = appMap.getValue();
}
if (map == null) {
return Collections.emptyMap();
} else {
return map;
}
}
private ApplicationProperties getApplicationProperties() {
parseHeaders();
if (applicationProperties == null && appLocation >= 0) {
ByteBuffer buffer = getBuffer().nioBuffer();
buffer.position(appLocation);
TLSEncode.getDecoder().setByteBuffer(buffer);
Object section = TLSEncode.getDecoder().readObject();
if (section instanceof ApplicationProperties) {
this.applicationProperties = (ApplicationProperties) section;
}
this.appLocation = -1;
TLSEncode.getDecoder().setByteBuffer(null);
}
return applicationProperties;
}
private void parseHeaders() {
if (!parsedHeaders) {
if (data == null) {
initalizeObjects();
} else {
partialDecode(data.nioBuffer());
}
parsedHeaders = true;
}
}
@Override
public org.apache.activemq.artemis.api.core.Message setConnectionID(String connectionID) {
this.connectionID = connectionID;
return this;
}
@Override
public String getConnectionID() {
return connectionID;
}
public MessageAnnotations getMessageAnnotations() {
parseHeaders();
return _messageAnnotations;
}
public Header getHeader() {
parseHeaders();
return _header;
}
public Properties getProperties() {
parseHeaders();
return _properties;
}
private Object getSymbol(String symbol) {
return getSymbol(Symbol.getSymbol(symbol));
}
private Object getSymbol(Symbol symbol) {
MessageAnnotations annotations = getMessageAnnotations();
Map<Symbol, Object> mapAnnotations = annotations != null ? annotations.getValue() : null;
if (mapAnnotations != null) {
return mapAnnotations.get(symbol);
}
return null;
}
private Object removeSymbol(Symbol symbol) {
MessageAnnotations annotations = getMessageAnnotations();
Map<Symbol, Object> mapAnnotations = annotations != null ? annotations.getValue() : null;
if (mapAnnotations != null) {
return mapAnnotations.remove(symbol);
}
return null;
}
private void setSymbol(String symbol, Object value) {
setSymbol(Symbol.getSymbol(symbol), value);
}
private void setSymbol(Symbol symbol, Object value) {
MessageAnnotations annotations = getMessageAnnotations();
if (annotations == null) {
_messageAnnotations = new MessageAnnotations(new HashMap<>());
annotations = _messageAnnotations;
}
Map<Symbol, Object> mapAnnotations = annotations != null ? annotations.getValue() : null;
if (mapAnnotations != null) {
mapAnnotations.put(symbol, value);
}
}
@Override
public RoutingType getRoutingType() {
Object routingType = getSymbol(AMQPMessageSupport.ROUTING_TYPE);
if (routingType != null) {
return RoutingType.getType((byte) routingType);
} else {
routingType = getSymbol(AMQPMessageSupport.JMS_DEST_TYPE_MSG_ANNOTATION);
if (routingType != null) {
if (AMQPMessageSupport.QUEUE_TYPE == (byte) routingType || AMQPMessageSupport.TEMP_QUEUE_TYPE == (byte) routingType) {
return RoutingType.ANYCAST;
} else if (AMQPMessageSupport.TOPIC_TYPE == (byte) routingType || AMQPMessageSupport.TEMP_TOPIC_TYPE == (byte) routingType) {
return RoutingType.MULTICAST;
}
} else {
return null;
}
return null;
}
}
@Override
public org.apache.activemq.artemis.api.core.Message setRoutingType(RoutingType routingType) {
parseHeaders();
if (routingType == null) {
removeSymbol(AMQPMessageSupport.ROUTING_TYPE);
}
setSymbol(AMQPMessageSupport.ROUTING_TYPE, routingType.getType());
return this;
}
@Override
public SimpleString getGroupID() {
parseHeaders();
if (_properties != null && _properties.getGroupId() != null) {
return SimpleString.toSimpleString(_properties.getGroupId());
} else {
return null;
}
}
@Override
public Long getScheduledDeliveryTime() {
if (scheduledTime < 0) {
Object objscheduledTime = getSymbol("x-opt-delivery-time");
Object objdelay = getSymbol("x-opt-delivery-delay");
if (objscheduledTime != null && objscheduledTime instanceof Number) {
this.scheduledTime = ((Number) objscheduledTime).longValue();
} else if (objdelay != null && objdelay instanceof Number) {
this.scheduledTime = System.currentTimeMillis() + ((Number) objdelay).longValue();
} else {
this.scheduledTime = 0;
}
}
return scheduledTime;
}
@Override
public AMQPMessage setScheduledDeliveryTime(Long time) {
parseHeaders();
setSymbol(AMQPMessageSupport.JMS_DELIVERY_TIME, time);
return this;
}
@Override
public Persister<org.apache.activemq.artemis.api.core.Message> getPersister() {
return AMQPMessagePersister.getInstance();
}
@Override
public synchronized boolean acceptsConsumer(long consumer) {
if (rejectedConsumers == null) {
return true;
} else {
return !rejectedConsumers.contains(consumer);
}
}
@Override
public synchronized void rejectConsumer(long consumer) {
if (rejectedConsumers == null) {
rejectedConsumers = new HashSet<>();
}
rejectedConsumers.add(consumer);
}
private synchronized void partialDecode(ByteBuffer buffer) {
DecoderImpl decoder = TLSEncode.getDecoder();
decoder.setByteBuffer(buffer);
buffer.position(0);
_header = null;
_deliveryAnnotations = null;
_messageAnnotations = null;
_properties = null;
applicationProperties = null;
Section section = null;
try {
if (buffer.hasRemaining()) {
section = (Section) decoder.readObject();
}
if (section instanceof Header) {
sendFrom = buffer.position();
_header = (Header) section;
if (_header.getTtl() != null) {
this.expiration = System.currentTimeMillis() + _header.getTtl().intValue();
}
if (buffer.hasRemaining()) {
section = (Section) decoder.readObject();
} else {
section = null;
}
} else {
// meaning there is no header
sendFrom = 0;
}
if (section instanceof DeliveryAnnotations) {
_deliveryAnnotations = (DeliveryAnnotations) section;
sendFrom = buffer.position();
if (buffer.hasRemaining()) {
section = (Section) decoder.readObject();
} else {
section = null;
}
}
if (section instanceof MessageAnnotations) {
_messageAnnotations = (MessageAnnotations) section;
if (buffer.hasRemaining()) {
section = (Section) decoder.readObject();
} else {
section = null;
}
}
if (section instanceof Properties) {
_properties = (Properties) section;
if (_properties.getAbsoluteExpiryTime() != null && _properties.getAbsoluteExpiryTime().getTime() > 0) {
this.expiration = _properties.getAbsoluteExpiryTime().getTime();
}
// We don't read the next section on purpose, as we will parse ApplicationProperties
// lazily
section = null;
}
if (section instanceof ApplicationProperties) {
applicationProperties = (ApplicationProperties) section;
} else {
if (buffer.hasRemaining()) {
this.appLocation = buffer.position();
} else {
this.appLocation = -1;
}
}
} finally {
decoder.setByteBuffer(null);
}
}
public long getMessageFormat() {
return messageFormat;
}
public int getLength() {
return data.array().length;
}
public byte[] getArray() {
return data.array();
}
@Override
public void messageChanged() {
bufferValid = false;
this.data = null;
}
@Override
public ByteBuf getBuffer() {
if (data == null) {
return null;
} else {
return Unpooled.wrappedBuffer(data);
}
}
@Override
public AMQPMessage setBuffer(ByteBuf buffer) {
this.data = null;
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message copy() {
checkBuffer();
byte[] origin = data.array();
byte[] newData = new byte[data.array().length - sendFrom];
for (int i = 0; i < newData.length; i++) {
newData[i] = origin[i + sendFrom];
}
AMQPMessage newEncode = new AMQPMessage(this.messageFormat, newData);
newEncode.setDurable(isDurable());
return newEncode;
}
@Override
public org.apache.activemq.artemis.api.core.Message copy(long newID) {
checkBuffer();
return copy().setMessageID(newID);
}
@Override
public long getMessageID() {
return messageID;
}
@Override
public org.apache.activemq.artemis.api.core.Message setMessageID(long id) {
this.messageID = id;
return this;
}
@Override
public long getExpiration() {
return expiration;
}
@Override
public AMQPMessage setExpiration(long expiration) {
Properties properties = getProperties();
if (properties != null) {
if (expiration <= 0) {
properties.setAbsoluteExpiryTime(null);
} else {
properties.setAbsoluteExpiryTime(new Date(expiration));
}
}
this.expiration = expiration;
return this;
}
@Override
public Object getUserID() {
Properties properties = getProperties();
if (properties != null && properties.getMessageId() != null) {
return properties.getMessageId();
} else {
return null;
}
}
/**
* Before we added AMQP into Artemis / Hornetq, the name getUserID was already taken by JMSMessageID.
* We cannot simply change the names now as it would break the API for existing clients.
*
* This is to return and read the proper AMQP userID.
* @return
*/
public Object getAMQPUserID() {
Properties properties = getProperties();
if (properties != null && properties.getUserId() != null) {
Binary binary = properties.getUserId();
return new String(binary.getArray(), binary.getArrayOffset(), binary.getLength(), StandardCharsets.UTF_8);
} else {
return null;
}
}
@Override
public org.apache.activemq.artemis.api.core.Message setUserID(Object userID) {
return null;
}
@Override
public boolean isDurable() {
if (durable != null) {
return durable;
}
if (getHeader() != null && getHeader().getDurable() != null) {
durable = getHeader().getDurable().booleanValue();
return durable;
} else {
return durable != null ? durable : false;
}
}
@Override
public Object getDuplicateProperty() {
return null;
}
@Override
public org.apache.activemq.artemis.api.core.Message setDurable(boolean durable) {
this.durable = durable;
return this;
}
@Override
public String getAddress() {
if (address == null) {
Properties properties = getProtonMessage().getProperties();
if (properties != null) {
return properties.getTo();
} else {
return null;
}
} else {
return address;
}
}
@Override
public AMQPMessage setAddress(String address) {
this.address = address;
return this;
}
@Override
public AMQPMessage setAddress(SimpleString address) {
return setAddress(address.toString());
}
@Override
public SimpleString getAddressSimpleString() {
return SimpleString.toSimpleString(getAddress());
}
@Override
public long getTimestamp() {
if (getProperties() != null && getProperties().getCreationTime() != null) {
return getProperties().getCreationTime().getTime();
} else {
return 0L;
}
}
@Override
public org.apache.activemq.artemis.api.core.Message setTimestamp(long timestamp) {
getProperties().setCreationTime(new Date(timestamp));
return this;
}
@Override
public byte getPriority() {
if (getHeader() != null && getHeader().getPriority() != null) {
return (byte) Math.min(getHeader().getPriority().intValue(), MAX_MESSAGE_PRIORITY);
} else {
return DEFAULT_MESSAGE_PRIORITY;
}
}
@Override
public org.apache.activemq.artemis.api.core.Message setPriority(byte priority) {
getHeader().setPriority(UnsignedByte.valueOf(priority));
return this;
}
@Override
public void receiveBuffer(ByteBuf buffer) {
}
private synchronized void checkBuffer() {
if (!bufferValid) {
int estimated = Math.max(1500, data != null ? data.capacity() + 1000 : 0);
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.heapBuffer(estimated);
try {
getProtonMessage().encode(new NettyWritable(buffer));
byte[] bytes = new byte[buffer.writerIndex()];
buffer.readBytes(bytes);
this.data = Unpooled.wrappedBuffer(bytes);
} finally {
buffer.release();
}
}
}
@Override
public int getEncodeSize() {
checkBuffer();
// + 20checkBuffer is an estimate for the Header with the deliveryCount
return data.array().length - sendFrom + 20;
}
@Override
public void sendBuffer(ByteBuf buffer, int deliveryCount) {
checkBuffer();
Header header = getHeader();
if (header == null && deliveryCount > 0) {
header = new Header();
header.setDurable(durable);
}
if (header != null) {
synchronized (header) {
header.setDeliveryCount(UnsignedInteger.valueOf(deliveryCount - 1));
TLSEncode.getEncoder().setByteBuffer(new NettyWritable(buffer));
TLSEncode.getEncoder().writeObject(header);
TLSEncode.getEncoder().setByteBuffer((WritableBuffer) null);
}
}
buffer.writeBytes(data, sendFrom, data.writerIndex() - sendFrom);
}
@Override
public org.apache.activemq.artemis.api.core.Message putBooleanProperty(String key, boolean value) {
getApplicationPropertiesMap().put(key, Boolean.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putByteProperty(String key, byte value) {
getApplicationPropertiesMap().put(key, Byte.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putBytesProperty(String key, byte[] value) {
getApplicationPropertiesMap().put(key, value);
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putShortProperty(String key, short value) {
getApplicationPropertiesMap().put(key, Short.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putCharProperty(String key, char value) {
getApplicationPropertiesMap().put(key, Character.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putIntProperty(String key, int value) {
getApplicationPropertiesMap().put(key, Integer.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putLongProperty(String key, long value) {
getApplicationPropertiesMap().put(key, Long.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putFloatProperty(String key, float value) {
getApplicationPropertiesMap().put(key, Float.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putDoubleProperty(String key, double value) {
getApplicationPropertiesMap().put(key, Double.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putBooleanProperty(SimpleString key, boolean value) {
getApplicationPropertiesMap().put(key.toString(), Boolean.valueOf(value));
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putByteProperty(SimpleString key, byte value) {
return putByteProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putBytesProperty(SimpleString key, byte[] value) {
return putBytesProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putShortProperty(SimpleString key, short value) {
return putShortProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putCharProperty(SimpleString key, char value) {
return putCharProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putIntProperty(SimpleString key, int value) {
return putIntProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putLongProperty(SimpleString key, long value) {
return putLongProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putFloatProperty(SimpleString key, float value) {
return putFloatProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putDoubleProperty(SimpleString key, double value) {
return putDoubleProperty(key.toString(), value);
}
@Override
public org.apache.activemq.artemis.api.core.Message putStringProperty(String key, String value) {
getApplicationPropertiesMap().put(key, value);
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putObjectProperty(String key,
Object value) throws ActiveMQPropertyConversionException {
getApplicationPropertiesMap().put(key, value);
return this;
}
@Override
public org.apache.activemq.artemis.api.core.Message putObjectProperty(SimpleString key,
Object value) throws ActiveMQPropertyConversionException {
return putObjectProperty(key.toString(), value);
}
@Override
public Object removeProperty(String key) {
return getApplicationPropertiesMap().remove(key);
}
@Override
public boolean containsProperty(String key) {
return getApplicationPropertiesMap().containsKey(key);
}
@Override
public Boolean getBooleanProperty(String key) throws ActiveMQPropertyConversionException {
return (Boolean) getApplicationPropertiesMap().get(key);
}
@Override
public Byte getByteProperty(String key) throws ActiveMQPropertyConversionException {
return (Byte) getApplicationPropertiesMap().get(key);
}
@Override
public Double getDoubleProperty(String key) throws ActiveMQPropertyConversionException {
return (Double) getApplicationPropertiesMap().get(key);
}
@Override
public Integer getIntProperty(String key) throws ActiveMQPropertyConversionException {
return (Integer) getApplicationPropertiesMap().get(key);
}
@Override
public Long getLongProperty(String key) throws ActiveMQPropertyConversionException {
return (Long) getApplicationPropertiesMap().get(key);
}
@Override
public Object getObjectProperty(String key) {
if (key.equals(MessageUtil.TYPE_HEADER_NAME.toString())) {
return getProperties().getSubject();
} else if (key.equals(MessageUtil.CONNECTION_ID_PROPERTY_NAME.toString())) {
return getConnectionID();
} else {
Object value = getApplicationPropertiesMap().get(key);
if (value instanceof UnsignedInteger ||
value instanceof UnsignedByte ||
value instanceof UnsignedLong ||
value instanceof UnsignedShort) {
return ((Number)value).longValue();
} else {
return value;
}
}
}
@Override
public Short getShortProperty(String key) throws ActiveMQPropertyConversionException {
return (Short) getApplicationPropertiesMap().get(key);
}
@Override
public Float getFloatProperty(String key) throws ActiveMQPropertyConversionException {
return (Float) getApplicationPropertiesMap().get(key);
}
@Override
public String getStringProperty(String key) throws ActiveMQPropertyConversionException {
if (key.equals(MessageUtil.TYPE_HEADER_NAME.toString())) {
return getProperties().getSubject();
} else if (key.equals(MessageUtil.CONNECTION_ID_PROPERTY_NAME.toString())) {
return getConnectionID();
} else {
return (String) getApplicationPropertiesMap().get(key);
}
}
@Override
public Object removeAnnotation(SimpleString key) {
return removeSymbol(Symbol.getSymbol(key.toString()));
}
@Override
public Object getAnnotation(SimpleString key) {
return getSymbol(key.toString());
}
@Override
public AMQPMessage setAnnotation(SimpleString key, Object value) {
setSymbol(key.toString(), value);
return this;
}
@Override
public void reencode() {
if (_deliveryAnnotations != null) getProtonMessage().setDeliveryAnnotations(_deliveryAnnotations);
if (_messageAnnotations != null) getProtonMessage().setMessageAnnotations(_messageAnnotations);
if (applicationProperties != null) getProtonMessage().setApplicationProperties(applicationProperties);
if (_properties != null) getProtonMessage().setProperties(this._properties);
bufferValid = false;
checkBuffer();
}
@Override
public SimpleString getSimpleStringProperty(String key) throws ActiveMQPropertyConversionException {
return SimpleString.toSimpleString((String) getApplicationPropertiesMap().get(key));
}
@Override
public byte[] getBytesProperty(String key) throws ActiveMQPropertyConversionException {
return (byte[]) getApplicationPropertiesMap().get(key);
}
@Override
public Object removeProperty(SimpleString key) {
return removeProperty(key.toString());
}
@Override
public boolean containsProperty(SimpleString key) {
return containsProperty(key.toString());
}
@Override
public Boolean getBooleanProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getBooleanProperty(key.toString());
}
@Override
public Byte getByteProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getByteProperty(key.toString());
}
@Override
public Double getDoubleProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getDoubleProperty(key.toString());
}
@Override
public Integer getIntProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getIntProperty(key.toString());
}
@Override
public Long getLongProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getLongProperty(key.toString());
}
@Override
public Object getObjectProperty(SimpleString key) {
return getObjectProperty(key.toString());
}
@Override
public Short getShortProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getShortProperty(key.toString());
}
@Override
public Float getFloatProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getFloatProperty(key.toString());
}
@Override
public String getStringProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getStringProperty(key.toString());
}
@Override
public SimpleString getSimpleStringProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getSimpleStringProperty(key.toString());
}
@Override
public byte[] getBytesProperty(SimpleString key) throws ActiveMQPropertyConversionException {
return getBytesProperty(key.toString());
}
@Override
public org.apache.activemq.artemis.api.core.Message putStringProperty(SimpleString key, SimpleString value) {
return putStringProperty(key.toString(), value.toString());
}
@Override
public Set<SimpleString> getPropertyNames() {
HashSet<SimpleString> values = new HashSet<>();
for (Object k : getApplicationPropertiesMap().keySet()) {
values.add(SimpleString.toSimpleString(k.toString()));
}
return values;
}
@Override
public int getMemoryEstimate() {
if (memoryEstimate == -1) {
memoryEstimate = memoryOffset + (data != null ? data.capacity() : 0);
}
return memoryEstimate;
}
@Override
public ICoreMessage toCore() {
try {
return AMQPConverter.getInstance().toCore(this);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public SimpleString getReplyTo() {
if (getProperties() != null) {
return SimpleString.toSimpleString(getProperties().getReplyTo());
} else {
return null;
}
}
@Override
public AMQPMessage setReplyTo(SimpleString address) {
if (getProperties() != null) {
getProperties().setReplyTo(address != null ? address.toString() : null);
}
return this;
}
@Override
public int getPersistSize() {
checkBuffer();
return DataConstants.SIZE_INT + internalPersistSize();
}
private int internalPersistSize() {
return data.array().length;
}
@Override
public void persist(ActiveMQBuffer targetRecord) {
checkBuffer();
targetRecord.writeInt(internalPersistSize());
targetRecord.writeBytes(data.array(), 0, data.array().length );
}
@Override
public void reloadPersistence(ActiveMQBuffer record) {
int size = record.readInt();
byte[] recordArray = new byte[size];
record.readBytes(recordArray);
this.sendFrom = 0; // whatever was persisted will be sent
this.data = Unpooled.wrappedBuffer(recordArray);
this.bufferValid = true;
this.durable = true; // it's coming from the journal, so it's durable
parseHeaders();
}
}