package org.openamq.framing; import org.apache.mina.common.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BasicContentHeaderProperties implements ContentHeaderProperties { private static final Logger _logger = LoggerFactory.getLogger(BasicContentHeaderProperties.class); /** * We store the encoded form when we decode the content header so that if we need to * write it out without modifying it we can do so without incurring the expense of * reencoding it */ private byte[] _encodedForm; /** * Flag indicating whether the entire content header has been decoded yet */ private boolean _decoded = true; /** * We have some optimisations for partial decoding for maximum performance. The headers are used in the broker * for routing in some cases so we can decode that separately. */ private boolean _decodedHeaders = true; /** * We have some optimisations for partial decoding for maximum performance. The content type is used by all * clients to determine the message type */ private boolean _decodedContentType = true; private String _contentType; private String _encoding; private FieldTable _headers; private byte _deliveryMode; private byte _priority; private String _correlationId; private String _replyTo; private long _expiration; private String _messageId; private long _timestamp; private String _type; private String _userId; private String _appId; private String _clusterId; private int _propertyFlags = 0; public BasicContentHeaderProperties() { } public int getPropertyListSize() { if (_encodedForm != null) { return _encodedForm.length; } else { int size = 0; if ((_propertyFlags & (1 << 15)) > 0) { size += EncodingUtils.encodedShortStringLength(_contentType); } if ((_propertyFlags & (1 << 14)) > 0) { size += EncodingUtils.encodedShortStringLength(_encoding); } if ((_propertyFlags & (1 << 13)) > 0) { size += EncodingUtils.encodedFieldTableLength(_headers); } if ((_propertyFlags & (1 << 12)) > 0) { size += 1; } if ((_propertyFlags & (1 << 11)) > 0) { size += 1; } if ((_propertyFlags & (1 << 10)) > 0) { size += EncodingUtils.encodedShortStringLength(_correlationId); } if ((_propertyFlags & (1 << 9)) > 0) { size += EncodingUtils.encodedShortStringLength(_replyTo); } if ((_propertyFlags & (1 << 8)) > 0) { size += EncodingUtils.encodedShortStringLength(String.valueOf(_expiration)); } if ((_propertyFlags & (1 << 7)) > 0) { size += EncodingUtils.encodedShortStringLength(_messageId); } if ((_propertyFlags & (1 << 6)) > 0) { size += 8; } if ((_propertyFlags & (1 << 5)) > 0) { size += EncodingUtils.encodedShortStringLength(_type); } if ((_propertyFlags & (1 << 4)) > 0) { size += EncodingUtils.encodedShortStringLength(_userId); } if ((_propertyFlags & (1 << 3)) > 0) { size += EncodingUtils.encodedShortStringLength(_appId); } if ((_propertyFlags & (1 << 2)) > 0) { size += EncodingUtils.encodedShortStringLength(_clusterId); } return size; } } private void clearEncodedForm() { if (!_decoded && _encodedForm != null) { //decode(); } _encodedForm = null; } public void setPropertyFlags(int propertyFlags) { clearEncodedForm(); _propertyFlags = propertyFlags; } public int getPropertyFlags() { return _propertyFlags; } public void writePropertyListPayload(ByteBuffer buffer) { if (_encodedForm != null) { buffer.put(_encodedForm); } else { if ((_propertyFlags & (1 << 15)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _contentType); } if ((_propertyFlags & (1 << 14)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _encoding); } if ((_propertyFlags & (1 << 13)) > 0) { EncodingUtils.writeFieldTableBytes(buffer, _headers); } if ((_propertyFlags & (1 << 12)) > 0) { buffer.put(_deliveryMode); } if ((_propertyFlags & (1 << 11)) > 0) { buffer.put(_priority); } if ((_propertyFlags & (1 << 10)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _correlationId); } if ((_propertyFlags & (1 << 9)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _replyTo); } if ((_propertyFlags & (1 << 8)) > 0) { EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration)); } if ((_propertyFlags & (1 << 7)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _messageId); } if ((_propertyFlags & (1 << 6)) > 0) { EncodingUtils.writeUnsignedInteger(buffer, 0/*timestamp msb*/); EncodingUtils.writeUnsignedInteger(buffer, _timestamp); } if ((_propertyFlags & (1 << 5)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _type); } if ((_propertyFlags & (1 << 4)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _userId); } if ((_propertyFlags & (1 << 3)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _appId); } if ((_propertyFlags & (1 << 2)) > 0) { EncodingUtils.writeShortStringBytes(buffer, _clusterId); } } } public void populatePropertiesFromBuffer(ByteBuffer buffer, int propertyFlags, int size) throws AMQFrameDecodingException { _propertyFlags = propertyFlags; if (_logger.isDebugEnabled()) { _logger.debug("Property flags: " + _propertyFlags); } decode(buffer); /*_encodedForm = new byte[size]; buffer.get(_encodedForm, 0, size); _decoded = false; _decodedHeaders = false; _decodedContentType = false;*/ } private void decode(ByteBuffer buffer) { //ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); int pos = buffer.position(); try { if ((_propertyFlags & (1 << 15)) > 0) { _contentType = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 14)) > 0) { _encoding = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 13)) > 0) { _headers = EncodingUtils.readFieldTable(buffer); } if ((_propertyFlags & (1 << 12)) > 0) { _deliveryMode = buffer.get(); } if ((_propertyFlags & (1 << 11)) > 0) { _priority = buffer.get(); } if ((_propertyFlags & (1 << 10)) > 0) { _correlationId = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 9)) > 0) { _replyTo = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 8)) > 0) { _expiration = Long.valueOf(EncodingUtils.readShortString(buffer)).longValue(); } if ((_propertyFlags & (1 << 7)) > 0) { _messageId = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 6)) > 0) { // Discard msb from AMQ timestamp buffer.getUnsignedInt(); _timestamp = buffer.getUnsignedInt(); } if ((_propertyFlags & (1 << 5)) > 0) { _type = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 4)) > 0) { _userId = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 3)) > 0) { _appId = EncodingUtils.readShortString(buffer); } if ((_propertyFlags & (1 << 2)) > 0) { _clusterId = EncodingUtils.readShortString(buffer); } } catch (AMQFrameDecodingException e) { throw new RuntimeException("Error in content header data: " + e); } final int endPos = buffer.position(); buffer.position(pos); final int len = endPos - pos; _encodedForm = new byte[len]; final int limit = buffer.limit(); buffer.limit(endPos); buffer.get(_encodedForm, 0, len); buffer.limit(limit); buffer.position(endPos); _decoded = true; } private void decodeUpToHeaders() { ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); try { if ((_propertyFlags & (1 << 15)) > 0) { byte length = buffer.get(); buffer.skip(length); } if ((_propertyFlags & (1 << 14)) > 0) { byte length = buffer.get(); buffer.skip(length); } if ((_propertyFlags & (1 << 13)) > 0) { _headers = EncodingUtils.readFieldTable(buffer); } _decodedHeaders = true; } catch (AMQFrameDecodingException e) { throw new RuntimeException("Error in content header data: " + e); } } private void decodeUpToContentType() { ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); if ((_propertyFlags & (1 << 15)) > 0) { _contentType = EncodingUtils.readShortString(buffer); } _decodedContentType = true; } private void decodeIfNecessary() { if (!_decoded) { //decode(); } } private void decodeHeadersIfNecessary() { if (!_decoded && !_decodedHeaders) { decodeUpToHeaders(); } } private void decodeContentTypeIfNecessary() { if (!_decoded && !_decodedContentType) { decodeUpToContentType(); } } public String getContentType() { decodeContentTypeIfNecessary(); return _contentType; } public void setContentType(String contentType) { clearEncodedForm(); _propertyFlags |= (1 << 15); _contentType = contentType; } public String getEncoding() { decodeIfNecessary(); return _encoding; } public void setEncoding(String encoding) { clearEncodedForm(); _propertyFlags |= (1 << 14); _encoding = encoding; } public FieldTable getHeaders() { decodeHeadersIfNecessary(); return _headers; } public void setHeaders(FieldTable headers) { clearEncodedForm(); _propertyFlags |= (1 << 13); _headers = headers; } public byte getDeliveryMode() { decodeIfNecessary(); return _deliveryMode; } public void setDeliveryMode(byte deliveryMode) { clearEncodedForm(); _propertyFlags |= (1 << 12); _deliveryMode = deliveryMode; } public byte getPriority() { decodeIfNecessary(); return _priority; } public void setPriority(byte priority) { clearEncodedForm(); _propertyFlags |= (1 << 11); _priority = priority; } public String getCorrelationId() { decodeIfNecessary(); return _correlationId; } public void setCorrelationId(String correlationId) { clearEncodedForm(); _propertyFlags |= (1 << 10); _correlationId = correlationId; } public String getReplyTo() { decodeIfNecessary(); return _replyTo; } public void setReplyTo(String replyTo) { clearEncodedForm(); _propertyFlags |= (1 << 9); _replyTo = replyTo; } public long getExpiration() { decodeIfNecessary(); return _expiration; } public void setExpiration(long expiration) { clearEncodedForm(); _propertyFlags |= (1 << 8); _expiration = expiration; } public String getMessageId() { decodeIfNecessary(); return _messageId; } public void setMessageId(String messageId) { clearEncodedForm(); _propertyFlags |= (1 << 7); _messageId = messageId; } public long getTimestamp() { decodeIfNecessary(); return _timestamp; } public void setTimestamp(long timestamp) { clearEncodedForm(); _propertyFlags |= (1 << 6); _timestamp = timestamp; } public String getType() { decodeIfNecessary(); return _type; } public void setType(String type) { clearEncodedForm(); _propertyFlags |= (1 << 5); _type = type; } public String getUserId() { decodeIfNecessary(); return _userId; } public void setUserId(String userId) { clearEncodedForm(); _propertyFlags |= (1 << 4); _userId = userId; } public String getAppId() { decodeIfNecessary(); return _appId; } public void setAppId(String appId) { clearEncodedForm(); _propertyFlags |= (1 << 3); _appId = appId; } public String getClusterId() { decodeIfNecessary(); return _clusterId; } public void setClusterId(String clusterId) { clearEncodedForm(); _propertyFlags |= (1 << 2); _clusterId = clusterId; } }