Package org.openremote.manager.mqtt
Class MQTTHandler
java.lang.Object
org.openremote.manager.mqtt.MQTTHandler
- Direct Known Subclasses:
ConnectionMonitorHandler,DefaultMQTTHandler,UserAssetProvisioningMQTTHandler
This allows custom handlers to be discovered by the
MQTTBrokerService during system startup using the
ServiceLoader mechanism. This allows topic(s) can be handled in a custom way. Any instances must
have a no-arg constructor.-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected ClientEventServiceprotected org.apache.activemq.artemis.api.core.client.ClientSessionprotected ExecutorServiceprotected ManagerKeycloakIdentityProviderprotected booleanprotected org.openremote.container.message.MessageBrokerServiceprotected MQTTBrokerServiceprotected org.apache.activemq.artemis.api.core.client.ClientProducerprotected org.openremote.container.timer.TimerServicestatic final Stringstatic final String -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidaddPublishConsumer(String topic) protected voidaddPublishTopicServerConfiguration(org.openremote.model.Container container, org.apache.activemq.artemis.core.config.Configuration serverConfiguration) abstract booleancanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Called to authorise a publish ifhandlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the publish is allowed otherwise return false.abstract booleancanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Called to authorise a subscription ifhandlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the subscription is allowed otherwise return false.booleancheckCanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Checks that authenticated sessions and topic realm matches the authenticated user and also that topic client ID matches the connection client ID.booleancheckCanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Checks that authenticated session and topic realm matches the authenticated user and also that topic client ID matches the connection client ID.protected static Optional<org.openremote.container.security.AuthContext> getAuthContextFromConnection(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) protected static org.openremote.container.security.AuthContextgetAuthContextFromSecurityContext(org.keycloak.KeycloakSecurityContext securityContext) protected abstract LoggergetName()Provides a name to identify this custom handler for logging purposes etc.intGets the priority of this handler which is used to determine the call order; handlers with a lower priority are initialised and started first.Get the set of topics this handler wants to subscribe to for incoming publish messages; messages that match these topics will be passed toonPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.openremote.manager.mqtt.Topic, io.netty.buffer.ByteBuf).protected org.apache.activemq.artemis.core.settings.impl.AddressSettingsgetPublishTopicAddressSettings(org.openremote.model.Container container, String publishTopic) Just enable metrics on the topic by default but allow custom handlers to add more configuration as requiredprotected static org.keycloak.KeycloakSecurityContextgetSecurityContextFromSubject(Subject subject) protected static SubjectgetSubjectFromConnection(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) booleanhandlesTopic(Topic topic) Checks that topic is valid and has at least 3 tokens (generally first two tokens should be {realm}/{clientId} but it is up to thecanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)and/orcanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)methods to validate this).voidinit(org.openremote.model.Container container, org.apache.activemq.artemis.core.config.Configuration serverConfiguration) Called when the system starts to allow for initialisation.voidonConnect(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client connects; if returns false then subsequent handlers will not be calledvoidonConnectionAuthenticated(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Called when an existingRemotingConnectionis authenticated sometime after initially connecting (seeUserAssetProvisioningMQTTHandler); the authenticatedSubjectcan be retrieved usingRemotingConnection.getSubject()voidonConnectionLost(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client loses connectionvoidonDisconnect(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client disconnectsabstract voidonPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, io.netty.buffer.ByteBuf body) Called to handle publish ifcanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true.abstract voidonSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Called to handle subscribe ifcanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true.abstract voidonUnsubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Called to handle unsubscribe ifhandlesTopic(org.openremote.manager.mqtt.Topic)returned true.voidonUserAssetLinksChanged(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, List<org.openremote.model.PersistenceEvent<org.openremote.model.asset.UserAssetLink>> changes) Called whenUserAssetLinks for a restricted user are changed and that user has an active connection (subject can be accessed from the connection).voidpublishMessage(String topic, Object data, io.netty.handler.codec.mqtt.MqttQoS qoS) voidstart(org.openremote.model.Container container) Called when the system starts to allow for initialisation.voidstop()Called when the system stops to allow for any cleanup.static StringtopicClientID(Topic topic) static booleantopicClientIdMatches(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) protected abstract booleantopicMatches(Topic topic) Indicates if this handler will handle the specified topic; independent of whether it is a publish or subscribe.static StringtopicRealm(Topic topic) static booleantopicRealmAllowed(org.keycloak.KeycloakSecurityContext securityContext, Topic topic) static booleantopicTokenCountGreaterThan(Topic topic, int size) static StringtopicTokenIndexToString(Topic topic, int tokenNumber)
-
Field Details
-
TOKEN_MULTI_LEVEL_WILDCARD
- See Also:
-
TOKEN_SINGLE_LEVEL_WILDCARD
- See Also:
-
clientEventService
-
mqttBrokerService
-
messageBrokerService
protected org.openremote.container.message.MessageBrokerService messageBrokerService -
identityProvider
-
executorService
-
timerService
protected org.openremote.container.timer.TimerService timerService -
isKeycloak
protected boolean isKeycloak -
clientSession
protected org.apache.activemq.artemis.api.core.client.ClientSession clientSession -
producer
protected org.apache.activemq.artemis.api.core.client.ClientProducer producer
-
-
Constructor Details
-
MQTTHandler
public MQTTHandler()
-
-
Method Details
-
getPriority
public int getPriority()Gets the priority of this handler which is used to determine the call order; handlers with a lower priority are initialised and started first. -
getName
Provides a name to identify this custom handler for logging purposes etc. -
init
public void init(org.openremote.model.Container container, org.apache.activemq.artemis.core.config.Configuration serverConfiguration) throws Exception Called when the system starts to allow for initialisation.- Throws:
Exception
-
start
Called when the system starts to allow for initialisation.- Throws:
Exception
-
stop
Called when the system stops to allow for any cleanup.- Throws:
Exception
-
addPublishTopicServerConfiguration
protected void addPublishTopicServerConfiguration(org.openremote.model.Container container, org.apache.activemq.artemis.core.config.Configuration serverConfiguration) -
getPublishTopicAddressSettings
protected org.apache.activemq.artemis.core.settings.impl.AddressSettings getPublishTopicAddressSettings(org.openremote.model.Container container, String publishTopic) Just enable metrics on the topic by default but allow custom handlers to add more configuration as required -
addPublishConsumer
- Throws:
Exception
-
onConnect
public void onConnect(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client connects; if returns false then subsequent handlers will not be called -
onDisconnect
public void onDisconnect(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client disconnects -
onConnectionLost
public void onConnectionLost(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client loses connection -
onConnectionAuthenticated
public void onConnectionAuthenticated(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Called when an existingRemotingConnectionis authenticated sometime after initially connecting (seeUserAssetProvisioningMQTTHandler); the authenticatedSubjectcan be retrieved usingRemotingConnection.getSubject() -
handlesTopic
Checks that topic is valid and has at least 3 tokens (generally first two tokens should be {realm}/{clientId} but it is up to thecanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)and/orcanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)methods to validate this). -
checkCanSubscribe
public boolean checkCanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Checks that authenticated session and topic realm matches the authenticated user and also that topic client ID matches the connection client ID. -
checkCanPublish
public boolean checkCanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Checks that authenticated sessions and topic realm matches the authenticated user and also that topic client ID matches the connection client ID. -
onUserAssetLinksChanged
public void onUserAssetLinksChanged(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, List<org.openremote.model.PersistenceEvent<org.openremote.model.asset.UserAssetLink>> changes) Called whenUserAssetLinks for a restricted user are changed and that user has an active connection (subject can be accessed from the connection). -
publishMessage
-
topicMatches
Indicates if this handler will handle the specified topic; independent of whether it is a publish or subscribe. Should generally check the third token onwards unlesshandlesTopic(org.openremote.manager.mqtt.Topic)has been overridden. -
getLogger
-
canSubscribe
public abstract boolean canSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Called to authorise a subscription ifhandlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the subscription is allowed otherwise return false. -
canPublish
public abstract boolean canPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Called to authorise a publish ifhandlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the publish is allowed otherwise return false. -
onSubscribe
public abstract void onSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Called to handle subscribe ifcanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true. -
onUnsubscribe
public abstract void onUnsubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Called to handle unsubscribe ifhandlesTopic(org.openremote.manager.mqtt.Topic)returned true. -
getPublishListenerTopics
Get the set of topics this handler wants to subscribe to for incoming publish messages; messages that match these topics will be passed toonPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.openremote.manager.mqtt.Topic, io.netty.buffer.ByteBuf). -
onPublish
public abstract void onPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, io.netty.buffer.ByteBuf body) Called to handle publish ifcanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true. -
topicRealm
-
topicClientID
-
topicRealmAllowed
public static boolean topicRealmAllowed(org.keycloak.KeycloakSecurityContext securityContext, Topic topic) -
topicClientIdMatches
public static boolean topicClientIdMatches(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) -
topicTokenCountGreaterThan
-
topicTokenIndexToString
-
getSubjectFromConnection
protected static Subject getSubjectFromConnection(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) -
getSecurityContextFromSubject
protected static org.keycloak.KeycloakSecurityContext getSecurityContextFromSubject(Subject subject) -
getAuthContextFromConnection
protected static Optional<org.openremote.container.security.AuthContext> getAuthContextFromConnection(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) -
getAuthContextFromSecurityContext
protected static org.openremote.container.security.AuthContext getAuthContextFromSecurityContext(org.keycloak.KeycloakSecurityContext securityContext)
-