/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.inbound.endpoint.protocol.mqtt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import java.util.Properties;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.inbound.endpoint.common.OneTimeTriggerAbstractCallback;
/**
* MQTT Asynchronous call back handler
*/
public class MqttAsyncCallback extends OneTimeTriggerAbstractCallback implements MqttCallback {
private static final Log log = LogFactory.getLog(MqttAsyncCallback.class);
private String name;
private MqttListener asycClient;
private MqttInjectHandler injectHandler;
private MqttConnectionFactory confac;
private MqttAsyncClient mqttAsyncClient;
private Properties mqttProperties;
private MqttConnectOptions connectOptions;
private MqttConnectionConsumer connectionConsumer;
private MqttConnectionListener connectionListener;
public MqttAsyncCallback(MqttAsyncClient mqttAsyncClient, MqttInjectHandler injectHandler,
MqttConnectionFactory confac, MqttConnectOptions connectOptions,
Properties mqttProperties) {
this.injectHandler = injectHandler;
this.mqttAsyncClient = mqttAsyncClient;
this.confac = confac;
this.connectOptions = connectOptions;
this.mqttProperties = mqttProperties;
}
/**
* Handle losing connection with the server. Here we just print it to the test console.
*
* @param throwable Throwable connection lost
*/
@Override
public void connectionLost(Throwable throwable) {
log.info("Connection lost occurred to the remote server.");
try {
super.handleReconnection();
} catch (InterruptedException ex) {
log.error("Unable to suspend the callback reconnection", ex);
}
}
protected void reConnect() {
if (mqttAsyncClient != null) {
try {
connectionListener = new MqttConnectionListener(connectionConsumer);
IMqttToken token = mqttAsyncClient.connect(connectOptions);
token.waitForCompletion();
if (!mqttAsyncClient.isConnected()) {
connectionListener.onFailure();
}
if (mqttAsyncClient.isConnected()) {
int qosLevel = Integer.parseInt(mqttProperties
.getProperty(MqttConstants.MQTT_QOS));
if (confac.getTopic() != null) {
mqttAsyncClient.subscribe(confac.getTopic(), qosLevel);
}
log.info("MQTT inbound endpoint " + name + " re-connected to the broker");
}
} catch (MqttException ex) {
log.error("Error while trying to subscribe to the remote.", ex);
connectionListener.onFailure();
}
}
}
public void messageArrived(String topic, MqttMessage mqttMessage) throws MqttException {
if (log.isDebugEnabled()) {
log.debug("Received Message: Topic:" + topic + " Message: " + mqttMessage);
}
MqttClientManager clientManager = MqttClientManager.getInstance();
String inboundIdentifier = clientManager.buildIdentifier
(mqttAsyncClient.getClientId(), confac.getServerHost(), confac.getServerPort());
if (super.isInboundRunnerMode()) {
//register tenant loading flag for inbound identifier
clientManager.registerInboundTenantLoadingFlag(inboundIdentifier);
//this is a blocking call
super.startInboundTenantLoading(inboundIdentifier);
//un-register tenant loading flag for inbound identifier
clientManager.unRegisterInboundTenantLoadingFlag(inboundIdentifier);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext privilegedCarbonContext =
PrivilegedCarbonContext.getThreadLocalCarbonContext();
privilegedCarbonContext.setTenantDomain(super.tenantDomain, true);
injectHandler.invoke(mqttMessage, name, topic);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
} else {
injectHandler.invoke(mqttMessage, name, topic);
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
public void setMqttConnectionConsumer(MqttConnectionConsumer connectionConsumer) {
this.connectionConsumer = connectionConsumer;
}
public MqttConnectionConsumer getMqttConnectionConsumer() {
return this.connectionConsumer;
}
public MqttConnectOptions getMqttConnectionOptions() {
return this.connectOptions;
}
public void updateInjectHandler(MqttInjectHandler injectHandler) {
this.injectHandler = injectHandler;
}
public void shutdown() {
super.shutdown();
if (connectionListener != null) {
this.connectionListener.shutdown();
}
}
/**
* Set the inbound endpoint name
* @param name
*/
public void setName (String name) {
this.name = name;
}
/**
* get the inbound endpoint name
* @return name
*/
public String getName () {
return this.name;
}
}