use of org.eclipse.hono.client.util.DownstreamMessageProperties in project hono by eclipse.
the class DownstreamAmqpMessageFactory method newMessage.
/**
* Creates a new AMQP 1.0 message.
* <p>
* This method creates a new {@code Message} and sets
* <ul>
* <li>its <em>to</em> property to the address consisting of the target's endpoint and tenant</li>
* <li>its <em>creation-time</em> to the current system time,</li>
* <li>its <em>content-type</em> to the given value,</li>
* <li>its payload as an AMQP <em>Data</em> section</li>
* </ul>
*
* In addition, this method
* <ul>
* <li>augments the message with the given message properties.</li>
* <li>augments the message with missing (application) properties corresponding to the default properties
* registered at the tenant and device level. Default properties defined at the device level take precedence
* over properties with the same name defined at the tenant level.</li>
* <li>optionally adds JMS vendor properties.</li>
* <li>sets the message's <em>content-type</em> to the {@linkplain MessageHelper#CONTENT_TYPE_OCTET_STREAM fall
* back content type}, if the payload is not {@code null} but the given content type is {@code null} and the
* default properties do not contain a content type property.</li>
* <li>sets the message's <em>ttl</em> header field based on the (device provided) <em>time-to-live</em> duration
* as specified by the <a href="https://www.eclipse.org/hono/docs/api/tenant/#resource-limits-configuration-format">
* Tenant API</a>.</li>
* </ul>
*
* @param target The target address of the message. The target address is used to determine if the message
* represents an event or not.
* @param contentType The content type describing the message's payload. If {@code null}, the message's
* <em>content-type</em> property will either be derived from the given properties or
* deviceDefaultProperties (if set there) or it will be set to the
* {@linkplain MessageHelper#CONTENT_TYPE_OCTET_STREAM default content type} if the
* given payload isn't {@code null}.
* @param payload The message payload or {@code null} if the message has no payload.
* @param tenant The information registered for the tenant that the device belongs to or {@code null}
* if no information about the tenant is available.
* @param tenantLevelDefaults The default properties registered at the tenant level or {@code null}
* if no default properties are registered for the tenant.
* @param deviceLevelDefaults The device's default properties registered at the device level or {@code null}
* if no default properties are registered for the device.
* @param messageProperties Additional message properties or {@code null} if the message has no additional properties.
* @param addJmsVendorProps {@code true} if
* <a href="https://www.oasis-open.org/committees/download.php/60574/amqp-bindmap-jms-v1.0-wd09.pdf">
* JMS Vendor Properties</a> should be added to the message.
*
* @return The newly created message.
* @throws NullPointerException if target is {@code null}.
*/
public static Message newMessage(final ResourceIdentifier target, final String contentType, final Buffer payload, final TenantObject tenant, final Map<String, Object> tenantLevelDefaults, final Map<String, Object> deviceLevelDefaults, final Map<String, Object> messageProperties, final boolean addJmsVendorProps) {
Objects.requireNonNull(target);
final Message message = ProtonHelper.message();
MessageHelper.setCreationTime(message);
message.setAddress(target.getBasePath());
MessageHelper.annotate(message, target);
Optional.ofNullable(payload).map(Buffer::getBytes).map(Binary::new).map(Data::new).ifPresent(message::setBody);
final Map<String, Object> effectiveMessageProperties = Optional.ofNullable(messageProperties).map(HashMap::new).orElseGet(HashMap::new);
Optional.ofNullable(contentType).ifPresent(ct -> effectiveMessageProperties.put(MessageHelper.SYS_PROPERTY_CONTENT_TYPE, ct));
final DownstreamMessageProperties props = new DownstreamMessageProperties(target.getEndpoint(), tenantLevelDefaults, deviceLevelDefaults, effectiveMessageProperties, Optional.ofNullable(tenant).map(TenantObject::getResourceLimits).orElse(null));
addDefaults(message, props.asMap());
// and message payload isn't null
if (Strings.isNullOrEmpty(message.getContentType()) && message.getBody() != null) {
message.setContentType(MessageHelper.CONTENT_TYPE_OCTET_STREAM);
}
if (addJmsVendorProps) {
addJmsVendorProperties(message);
}
return message;
}
use of org.eclipse.hono.client.util.DownstreamMessageProperties in project hono by eclipse.
the class ProtonBasedCommandResponseSender method createDownstreamMessage.
private Message createDownstreamMessage(final CommandResponse response, final TenantObject tenant, final RegistrationAssertion device, final Map<String, Object> properties) {
final var props = new DownstreamMessageProperties(CommandConstants.NORTHBOUND_COMMAND_RESPONSE_ENDPOINT, tenant.getDefaults().getMap(), device.getDefaults(), properties, tenant.getResourceLimits()).asMap();
final Message msg = ProtonHelper.message();
DownstreamAmqpMessageFactory.addDefaults(msg, props);
MessageHelper.setCreationTime(msg);
msg.setCorrelationId(response.getCorrelationId());
MessageHelper.setPayload(msg, response.getContentType(), response.getPayload());
MessageHelper.addStatus(msg, response.getStatus());
msg.setAddress(AddressHelper.getTargetAddress(CommandConstants.NORTHBOUND_COMMAND_RESPONSE_ENDPOINT, response.getTenantId(), response.getReplyToId(), null));
MessageHelper.addTenantId(msg, response.getTenantId());
MessageHelper.addDeviceId(msg, response.getDeviceId());
if (jmsVendorPropsEnabled) {
DownstreamAmqpMessageFactory.addJmsVendorProperties(msg);
}
return msg;
}
use of org.eclipse.hono.client.util.DownstreamMessageProperties in project hono by eclipse.
the class AbstractKafkaBasedDownstreamSender method addDefaults.
/**
* Adds default properties defined either at the device or tenant level are added to the message headers.
*
* @param endpointName The endpoint that the message is targeted at.
* @param tenant The tenant that the device belongs to.
* @param device The registration assertion for the device that the data originates from.
* @param qos The delivery semantics to use for sending the data.
* @param contentType The content type of the data. If {@code null}, the content type will be determined
* from the following sources (in that order, the first one that is present is used):
* <ol>
* <li>the <em>contentType</em> parameter</li>
* <li>the property with key {@value org.eclipse.hono.util.MessageHelper#SYS_PROPERTY_CONTENT_TYPE} in the
* <em>properties</em> parameter</li>
* <li>the device default</li>
* <li>the tenant default</li>
* <li>the default content type ({@value org.eclipse.hono.util.MessageHelper#CONTENT_TYPE_OCTET_STREAM}
* if payload is not {@code null}</li>
* </ol>
* @param payload The data to send in the message or {@code null}.
* @param properties Additional meta data that should be included in the downstream message.
* @return The augmented properties.
* @throws NullPointerException if endpoint name, tenant, device or qos are {@code null}.
*/
protected final Map<String, Object> addDefaults(final String endpointName, final TenantObject tenant, final RegistrationAssertion device, final QoS qos, final String contentType, final Buffer payload, final Map<String, Object> properties) {
Objects.requireNonNull(endpointName);
Objects.requireNonNull(tenant);
Objects.requireNonNull(device);
Objects.requireNonNull(qos);
final Map<String, Object> messageProperties = Optional.ofNullable(properties).map(HashMap::new).orElseGet(HashMap::new);
messageProperties.put(MessageHelper.APP_PROPERTY_DEVICE_ID, device.getDeviceId());
messageProperties.put(MessageHelper.APP_PROPERTY_QOS, qos.ordinal());
final var propsWithDefaults = new DownstreamMessageProperties(endpointName, isDefaultsEnabled ? tenant.getDefaults().getMap() : null, isDefaultsEnabled ? device.getDefaults() : null, messageProperties, tenant.getResourceLimits()).asMap();
if (contentType != null) {
propsWithDefaults.put(MessageHelper.SYS_PROPERTY_CONTENT_TYPE, contentType);
} else if (payload != null) {
propsWithDefaults.putIfAbsent(MessageHelper.SYS_PROPERTY_CONTENT_TYPE, MessageHelper.CONTENT_TYPE_OCTET_STREAM);
}
return propsWithDefaults;
}
use of org.eclipse.hono.client.util.DownstreamMessageProperties in project hono by eclipse.
the class KafkaBasedCommandResponseSender method getHeaders.
private Map<String, Object> getHeaders(final CommandResponse response, final TenantObject tenant, final RegistrationAssertion device) {
final var headers = new DownstreamMessageProperties(CommandConstants.NORTHBOUND_COMMAND_RESPONSE_ENDPOINT, tenant.getDefaults().getMap(), device.getDefaults(), response.getAdditionalProperties(), tenant.getResourceLimits()).asMap();
headers.put(MessageHelper.SYS_PROPERTY_CORRELATION_ID, response.getCorrelationId());
headers.put(MessageHelper.APP_PROPERTY_TENANT_ID, response.getTenantId());
headers.put(MessageHelper.APP_PROPERTY_DEVICE_ID, response.getDeviceId());
headers.put(MessageHelper.APP_PROPERTY_STATUS, response.getStatus());
if (response.getContentType() != null) {
headers.put(MessageHelper.SYS_PROPERTY_CONTENT_TYPE, response.getContentType());
} else if (response.getPayload() != null) {
headers.put(MessageHelper.SYS_PROPERTY_CONTENT_TYPE, MessageHelper.CONTENT_TYPE_OCTET_STREAM);
}
return headers;
}
Aggregations