org.eclipse.hono.service.monitoring.AbstractMessageSenderConnectionEventProducer.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.hono.service.monitoring.AbstractMessageSenderConnectionEventProducer.java

Source

/**
 * Copyright (c) 2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 1.0 which is available at
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * SPDX-License-Identifier: EPL-1.0
 */
package org.eclipse.hono.service.monitoring;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.function.BiFunction;

import org.eclipse.hono.client.HonoClient;
import org.eclipse.hono.client.MessageSender;
import org.eclipse.hono.service.auth.device.Device;
import org.eclipse.hono.util.EventConstants;
import org.eclipse.hono.util.RegistrationConstants;
import org.springframework.context.MessageSource;

import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.json.JsonObject;

/**
 * A connection event producer based on a {@link MessageSender}.
 */
public abstract class AbstractMessageSenderConnectionEventProducer implements ConnectionEventProducer {

    /**
     * The client to use for contacting the device registry.
     */
    private final HonoClient deviceRegistryClient;

    /**
     * The client to use for sending out events.
     */
    private final HonoClient messageSenderClient;

    /**
     * The function to derive the {@link MessageSource} from the provided <em>Message Sender Client</em>.
     */
    private final BiFunction<HonoClient, String, Future<MessageSender>> messageSenderSource;

    /**
     * A {@link ConnectionEventProducer} which will send events using a provided {@link MessageSender}.
     * 
     * @param deviceRegistryClient The client for contacting the device registry.
     * @param messageSenderClient The client used for sending events.
     * @param messageSenderSource A function to get the {@link MessageSender} of the {@code messageSenderClient} which
     *            should be used for actually sending the events.
     */
    protected AbstractMessageSenderConnectionEventProducer(final HonoClient deviceRegistryClient,
            final HonoClient messageSenderClient,
            final BiFunction<HonoClient, String, Future<MessageSender>> messageSenderSource) {

        Objects.requireNonNull(deviceRegistryClient);
        Objects.requireNonNull(messageSenderClient);
        Objects.requireNonNull(messageSenderSource);

        this.deviceRegistryClient = deviceRegistryClient;
        this.messageSenderClient = messageSenderClient;
        this.messageSenderSource = messageSenderSource;
    }

    @Override
    public Future<?> connected(final String remoteId, final String protocolAdapter,
            final Device authenticatedDevice, final JsonObject data) {
        return sendNotificationEvent(authenticatedDevice, protocolAdapter, remoteId, "connected", data);
    }

    @Override
    public Future<?> disconnected(final String remoteId, final String protocolAdapter,
            final Device authenticatedDevice, final JsonObject data) {
        return sendNotificationEvent(authenticatedDevice, protocolAdapter, remoteId, "disconnected", data);
    }

    private Future<?> sendNotificationEvent(final Device authenticatedDevice, final String protocolAdapter,
            final String remoteId, final String cause, final JsonObject data) {

        if (authenticatedDevice == null) {
            // we only handle authenticated devices
            return Future.succeededFuture();
        }

        // get an assertion

        final Future<String> assertionFuture = this.deviceRegistryClient
                .getOrCreateRegistrationClient(authenticatedDevice.getTenantId()).compose(registrationClient -> {
                    return registrationClient.assertRegistration(authenticatedDevice.getDeviceId())
                            .map(registration -> {
                                return registration.getString(RegistrationConstants.FIELD_ASSERTION);
                            });
                });

        // get a sender

        final Future<MessageSender> senderFuture = getOrCreateSender(authenticatedDevice);

        // send message with assertion and sender

        return CompositeFuture.all(assertionFuture, senderFuture).compose(f -> {
            final String deviceId = authenticatedDevice.getDeviceId();

            final JsonObject payload = new JsonObject();
            payload.put("cause", cause);
            payload.put("remote-id", remoteId);
            payload.put("source", protocolAdapter);

            if (data != null) {
                payload.put("data", data);
            }

            return senderFuture.result().send(deviceId, payload.encode().getBytes(StandardCharsets.UTF_8),
                    EventConstants.EVENT_CONNECTION_NOTIFICATION_CONTENT_TYPE, assertionFuture.result(), v -> {
                    });
        });
    }

    private Future<MessageSender> getOrCreateSender(final Device device) {
        return messageSenderSource.apply(this.messageSenderClient, device.getTenantId());
    }

}