All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.robypomper.josp.jcp.gws.broker.Broker Maven / Gradle / Ivy

There is a newer version: 2.2.3
Show newest version
/*******************************************************************************
 * The John Cloud Platform is the set of infrastructure and software required to provide
 * the "cloud" to an IoT EcoSystem, like the John Operating System Platform one.
 * Copyright 2021 Roberto Pompermaier
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 ******************************************************************************/

package com.robypomper.josp.jcp.gws.broker;

import com.robypomper.comm.exception.PeerNotConnectedException;
import com.robypomper.comm.exception.PeerStreamException;
import com.robypomper.java.JavaAssertions;
import com.robypomper.java.JavaStructures;
import com.robypomper.java.JavaStructures.Pair;
import com.robypomper.josp.jcp.db.apis.PermissionsDBService;
import com.robypomper.josp.jcp.gws.exceptions.JSLServiceMissingPermissionException;
import com.robypomper.josp.protocol.JOSPPerm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

@SuppressWarnings("RedundantIfStatement")
public class Broker implements BrokerJOD, BrokerJSL, BrokerObjDB {

    // Internal vars

    private static final Logger log = LoggerFactory.getLogger(Broker.class);
    private final Map registeredObjs = new HashMap<>();
    private final Map registeredSrvs = new HashMap<>();
    private final Map registeredObjsDB = new HashMap<>();
    private final BrokerPermissions permissions;


    // Constructors

    public Broker(PermissionsDBService permissionsDBService) {
        this.permissions = new BrokerPermissions(this, permissionsDBService);
    }

    // Getters

    public List getAllObjects() {
        return new ArrayList<>(registeredObjs.values());
    }

    public BrokerClientJOD getObject(String objId) {
        return registeredObjs.get(objId);
    }

    public List getAllServices() {
        return new ArrayList<>(registeredSrvs.values());
    }

    public BrokerClientJSL getService(String srvId) {
        return registeredSrvs.get(srvId);
    }

    public List getAllObjectsDB() {
        return new ArrayList<>(registeredObjsDB.values());
    }

    public BrokerClientObjDB getObjectDB(String objId) {
        return registeredObjsDB.get(objId);
    }


    // Register methods

    @Override
    public void registerObject(BrokerClientObjDB gwObject) {
        synchronized (registeredObjsDB) {
            if (registeredObjsDB.containsKey(gwObject.getId())) {
                log.warn(String.format("Error registering Object (DB) '%s' to GW Broker, object already registered", gwObject.getId()));
                return;
            }

            registeredObjsDB.put(gwObject.getId(), gwObject);
        }
    }

    @Override
    public void deregisterObject(BrokerClientObjDB gwObject) {
        synchronized (registeredObjsDB) {
            if (!registeredObjsDB.containsKey(gwObject.getId())) {
                log.warn(String.format("Error registering Object (DB) '%s' to GW Broker, object NOT registered", gwObject.getId()));
                return;
            }

            registeredObjsDB.remove(gwObject.getId());
        }
    }

    @Override
    public void registerObject(BrokerClientJOD gwObject) {
        synchronized (registeredObjs) {
            if (registeredObjs.containsKey(gwObject.getId())) {
                log.warn(String.format("Error registering Object '%s' to GW Broker, object already registered", gwObject.getId()));
                return;
            }

            registeredObjs.put(gwObject.getId(), gwObject);
        }

        if (registeredObjsDB.containsKey(gwObject.getId()))
            registeredObjsDB.get(gwObject.getId()).pause();
    }

    @Override
    public void deregisterObject(BrokerClientJOD gwObject) {
        send(gwObject, gwObject.getMsgOBJ_DISCONNECTED(), JOSPPerm.Type.Status);

        synchronized (registeredObjs) {
            if (!registeredObjs.containsKey(gwObject.getId())) {
                log.warn(String.format("Error deregistering Object '%s' to GW Broker, object NOT registered", gwObject.getId()));
                return;
            }

            registeredObjs.remove(gwObject.getId());
        }

        if (!registeredObjsDB.containsKey(gwObject.getId())) {
            if (gwObject.getObjDB() != null)
                registeredObjsDB.put(gwObject.getId(), gwObject.getObjDB());
            else {
                JavaAssertions.makeAssertion_Failed("Error deregistering Object '%s' because objDB not available");
                return;
            }
        }

        registeredObjsDB.get(gwObject.getId()).resume();
    }

    @Override
    public void registerService(BrokerClientJSL gwService) {
        synchronized (registeredSrvs) {
            if (registeredSrvs.containsKey(gwService.getId())) {
                log.warn(String.format("Error registering Service '%s' to GW Broker, service already registered", gwService.getId()));
                return;
            }

            registeredSrvs.put(gwService.getId(), gwService);
        }

        Map> allowedObjects;

        allowedObjects = permissions.getServiceAllowedObjects(gwService.getId(), JOSPPerm.Connection.LocalAndCloud, JOSPPerm.Type.Status);
        for (Map.Entry> objAllowed : allowedObjects.entrySet()) {
            BrokerClientJOD obj = registeredObjs.get(objAllowed.getKey());
            if (obj == null)
                obj = registeredObjsDB.get(objAllowed.getKey());
            Pair objPerm = objAllowed.getValue();

            send(obj, gwService.getId(), obj.getMsgOBJ_INFO(), JOSPPerm.Type.Status);
            send(obj, gwService.getId(), obj.getMsgOBJ_STRUCT(), JOSPPerm.Type.Status);
            send(obj, gwService.getId(), obj.getMsgOBJ_PERM(), JOSPPerm.Type.CoOwner);
            send(obj, gwService.getId(), obj.getMsgSERVICE_PERM(objPerm.getFirst(), objPerm.getSecond()), JOSPPerm.Type.None);
            if (obj instanceof BrokerClientObjDB)
                send(obj, gwService.getId(), obj.getMsgOBJ_DISCONNECTED(), JOSPPerm.Type.Status);
        }

        allowedObjects = permissions.getServiceAllowedObjects(gwService.getId(), JOSPPerm.Connection.LocalAndCloud, JOSPPerm.Type.CoOwner);
        for (Map.Entry> objAllowed : allowedObjects.entrySet()) {
            BrokerClientJOD obj = registeredObjs.get(objAllowed.getKey());
            if (obj == null)
                obj = registeredObjsDB.get(objAllowed.getKey());

            send(obj, gwService.getId(), obj.getMsgOBJ_PERM(), JOSPPerm.Type.CoOwner);
        }

        log.info(String.format("Registered service '%s' to broker", gwService.getId()));
        log.trace(String.format("          available objects      [%s]", String.join(", ", registeredObjs.keySet())));
        log.trace(String.format("          available objects (DB) [%s]", String.join(", ", registeredObjsDB.keySet())));
        log.trace(String.format("          allowed objects        [%s]", String.join(", ", allowedObjects.keySet())));
    }

    @Override
    public void deregisterService(BrokerClientJSL gwService) {
        synchronized (registeredSrvs) {
            if (!registeredSrvs.containsKey(gwService.getId())) {
                log.warn(String.format("Error registering Service '%s' to GW Broker, service NOT registered", gwService.getId()));
                return;
            }

            registeredSrvs.remove(gwService.getId());
        }
    }


    // Dispatch Message methods

    @Override
    public void send(BrokerClient gwClientJOD, String data, JOSPPerm.Type minPerm) {
        // from JOD to JSL
        // send to all service with at least 'minPerm' on gwClientJOD
        // send errors (PeerStreamException, PeerNotConnectedException) are only logged

        Set srvIds = permissions.getObjectAllowedServices(gwClientJOD.getId(), JOSPPerm.Connection.LocalAndCloud, minPerm).keySet();
        //System.out.println("\n\t\tSend message " + data.substring(9,data.indexOf(' ',9)) + " from " + gwClientJOD.getId() + " to:");
        //System.out.println(" srvs: " + String.join(", ", srvIds) + "\n");
        for (String srvId : srvIds) {
            BrokerClientJSL srv = registeredSrvs.get(srvId);
            if (srv == null) {
                log.warn(String.format("Error forward data from Object '%s' to Service '%s', service not registered on broker", gwClientJOD.getId(), srvId));
                continue;
            }

            try {
                srv.send(data);

            } catch (PeerStreamException | PeerNotConnectedException e) {
                log.warn(String.format("Error forward data from Object '%s' to Service '%s'", gwClientJOD.getId(), srvId), e);
            }
        }
    }

    @Override
    public void send(BrokerClient gwClientJOD, String srvId, String data, JOSPPerm.Type minPerm) {
        // from JOD to JSL
        // send to 'gwClientJSL' service only if it has at least 'minPerm' on gwClientJOD
        // send errors (JSLServiceMissingPermissionException, PeerStreamException, PeerNotConnectedException) are only logged
        //System.out.println("\n\t\tSend message " + data.substring(9,data.indexOf(' ',9)) + " from " + gwClientJOD.getId() + " to " + srvId + "\n");

        if (minPerm!=JOSPPerm.Type.None && !permissions.checkServicePermissionOnObject(srvId, gwClientJOD.getId(), JOSPPerm.Connection.LocalAndCloud, minPerm)) {
            log.warn(String.format("Error send data from Object '%s' to Service '%s', service missing permission to object ", gwClientJOD.getId(), srvId));
            return;
        }

        BrokerClientJSL srv = registeredSrvs.get(srvId);
        if (srv == null) {
            log.warn(String.format("Error send data from Object '%s' to Service '%s', service not registered on broker", gwClientJOD.getId(), srvId));
            return;
        }

        try {
            srv.send(data);

        } catch (PeerStreamException | PeerNotConnectedException e) {
            log.warn(String.format("Error send data from Object '%s' to Service '%s'", gwClientJOD.getId(), srvId), e);
        }
    }

    @Override
    public void send(BrokerClientJSL gwClientJSL, String objId, String data, JOSPPerm.Type minPerm) throws JSLServiceMissingPermissionException, PeerStreamException, PeerNotConnectedException {
        // from JSL to JOD
        // send to 'objId' object only if 'gwClientJSL' has at least 'minPerm' on destination object
        // send errors (PeerStreamException, PeerNotConnectedException) are throw to caller methods
        //System.out.println("\n\t\tSend message " + data.substring(9,data.indexOf(' ',9)) + " from " + gwClientJSL.getId() + " to " + objId + "\n");

        BrokerClientJOD obj = registeredObjs.get(objId);
        if (obj == null) {
            if (registeredObjsDB.get(objId) == null)
                log.warn(String.format("Error forward data from Service '%s' to Object '%s', object not registered on broker", gwClientJSL.getId(), objId));
            else
                log.warn(String.format("Error forward data from Service '%s' to Object '%s', object not connected to broker", gwClientJSL.getId(), objId));
            return;
        }

        if (!permissions.checkServicePermissionOnObject(gwClientJSL.getId(), obj.getId(), JOSPPerm.Connection.LocalAndCloud, minPerm))
            throw new JSLServiceMissingPermissionException(gwClientJSL.getSrvId(), objId, minPerm, null);

        obj.send(data);
    }


    // Public permissions

    @Override
    public Map> getObjectCloudAllowedServices(String objId) {
        return permissions.getObjectAllowedServices(objId, JOSPPerm.Connection.LocalAndCloud);
    }

    @Override
    public boolean checkServiceCloudPermissionOnObject(String srvId, String objId, JOSPPerm.Type minPerm) {
        return permissions.checkServicePermissionOnObject(srvId, objId, JOSPPerm.Connection.LocalAndCloud, minPerm);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy