Shabirmean 9 years ago
commit 2b2b659d22

@ -162,7 +162,7 @@ public class DataPublisherService extends Service {
if (!mqttTransportHandler.isConnected()) {
mqttTransportHandler.connect();
}
String topic = "wso2/" + LocalRegistry.getTenantDomain(context) + "/" + SenseConstants
String topic = LocalRegistry.getTenantDomain(context) + "/" + SenseConstants
.DEVICE_TYPE + "/" + deviceId + "/data";
mqttTransportHandler.publishDeviceData(user, deviceId, jsonArray.toString(), topic);
}

@ -77,7 +77,7 @@ public abstract class MQTTTransportHandler implements MqttCallback, TransportHan
String username = LocalRegistry.getUsername(context);
String deviceId = LocalRegistry.getDeviceId(context);
this.clientId = deviceId + ":" + SenseConstants.DEVICE_TYPE;
this.subscribeTopic = "wso2/" + LocalRegistry.getTenantDomain(context)+ "/" + SenseConstants.DEVICE_TYPE + "/" +
this.subscribeTopic = LocalRegistry.getTenantDomain(context)+ "/" + SenseConstants.DEVICE_TYPE + "/" +
deviceId + "/command/#";
this.clientWillTopic = DISCONNECTION_WILL_TOPIC_PREFIX + SenseConstants.DEVICE_TYPE;
this.mqttBrokerEndPoint = LocalRegistry.getMqttEndpoint(context);

@ -17,13 +17,13 @@
~ under the License.
-->
<eventReceiver name="EventReceiver_AndroidSense" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<eventReceiver name="android_sense_mqtt" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt">
<property name="topic">wso2/carbon.super/android_sense/+/data</property>
<property name="topic">carbon.super/android_sense/+/data</property>
<property name="username">admin</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:3</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2</property>
<property name="contentValidation">default</property>
<property name="dcrUrl">https://${server.host}:${mgt.transport.https.port}/dynamic-client-web/register</property>
<property name="dcrUrl">https://localhost:${carbon.https.port}/dynamic-client-web/register</property>
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
<property name="cleanSession">true</property>
</from>

@ -17,6 +17,6 @@
~ under the License.
-->
<artifact name="EventReceiver_AndroidSense" version="1.0.0" type="event/receiver" serverRole="DataAnalyticsServer">
<artifact name="android_sense_mqtt" version="1.0.0" type="event/receiver" serverRole="DataAnalyticsServer">
<file>EventReceiver_AndroidSense.xml</file>
</artifact>

@ -20,7 +20,7 @@
<artifacts>
<artifact name="AndroidSense_CAPP" version="1.0.0" type="carbon/application">
<dependency artifact="EventStream_AndroidSense" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="EventReceiver_AndroidSense" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="android_sense_mqtt" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="EventPublisher_AndroidSense" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="EventExecution_AndroidSense" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
</artifact>

@ -23,17 +23,12 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.analytics.dataservice.commons.SORT;
import org.wso2.carbon.analytics.dataservice.commons.SortByField;
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport.AndroidSenseMQTTConnector;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorRecord;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -45,7 +40,9 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The api for
@ -53,21 +50,22 @@ import java.util.List;
public class AndroidSenseControllerServiceImpl implements AndroidSenseControllerService {
private static Log log = LogFactory.getLog(AndroidSenseControllerServiceImpl.class);
private static AndroidSenseMQTTConnector androidSenseMQTTConnector;
@Path("device/{deviceId}/words")
@POST
public Response sendKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("keywords") String keywords) {
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
AndroidSenseConstants.DEVICE_TYPE))) {
AndroidSenseConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
androidSenseMQTTConnector.publishDeviceData(deviceId, "add", keywords);
Map<String, String> dynamicProperties = new HashMap<>();
String publishTopic = APIUtil.getAuthenticatedUserTenantDomain()
+ "/" + AndroidSenseConstants.DEVICE_TYPE + "/" + deviceId + "/command/words";
dynamicProperties.put(AndroidSenseConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
APIUtil.getOutputEventAdapterService().publish(AndroidSenseConstants.MQTT_ADAPTER_NAME,
dynamicProperties, keywords);
return Response.ok().build();
} catch (TransportHandlerException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
@ -82,11 +80,13 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
AndroidSenseConstants.DEVICE_TYPE), DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
androidSenseMQTTConnector.publishDeviceData(deviceId, "threshold", threshold);
Map<String, String> dynamicProperties = new HashMap<>();
String publishTopic = APIUtil.getAuthenticatedUserTenantDomain()
+ "/" + AndroidSenseConstants.DEVICE_TYPE + "/" + deviceId + "/command/threshold";
dynamicProperties.put(AndroidSenseConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
APIUtil.getOutputEventAdapterService().publish(AndroidSenseConstants.MQTT_ADAPTER_NAME,
dynamicProperties, threshold);
return Response.ok().build();
} catch (TransportHandlerException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
@ -100,11 +100,13 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
AndroidSenseConstants.DEVICE_TYPE), DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
androidSenseMQTTConnector.publishDeviceData(deviceId, "remove", words);
Map<String, String> dynamicProperties = new HashMap<>();
String publishTopic = APIUtil.getAuthenticatedUserTenantDomain()
+ "/" + AndroidSenseConstants.DEVICE_TYPE + "/" + deviceId + "/command/remove";
dynamicProperties.put(AndroidSenseConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
APIUtil.getOutputEventAdapterService().publish(AndroidSenseConstants.MQTT_ADAPTER_NAME,
dynamicProperties, words);
return Response.ok().build();
} catch (TransportHandlerException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
@ -196,58 +198,4 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
return sensorEventTableName;
}
/**
* Fetches the `AndroidSenseMQTTConnector` specific to this Android Sense controller service.
*
* @return the 'AndroidSenseMQTTConnector' instance bound to the 'AndroidSenseMQTTConnector' variable of
* this service.
*/
@SuppressWarnings("Unused")
public AndroidSenseMQTTConnector getAndroidSenseMQTTConnector() {
return androidSenseMQTTConnector;
}
/**
* Sets the `AndroidSenseMQTTConnector` variable of this Android Sense controller service.
*
* @param androidSenseMQTTConnector a 'AndroidSenseMQTTConnector' object that handles all MQTT related
* communications of any connected Android Sense device-type
*/
@SuppressWarnings("Unused")
public void setAndroidSenseMQTTConnector(final AndroidSenseMQTTConnector androidSenseMQTTConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
//The delay is added for the server to starts up.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
AndroidSenseControllerServiceImpl.androidSenseMQTTConnector = androidSenseMQTTConnector;
if (MqttConfig.getInstance().isEnabled()) {
synchronized (androidSenseMQTTConnector) {
androidSenseMQTTConnector.connect();
}
} else {
log.warn("MQTT disabled in 'devicemgt-config.xml'. Hence, VirtualFireAlarmMQTTConnector not started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.start();
}
private boolean waitForServerStartup() {
while (!IoTServerStartupListener.isServerReady()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return true;
}
}
return false;
}
}

@ -26,11 +26,11 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.AndroidConfiguration;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.Constants;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.exception.IoTException;
import org.wso2.carbon.device.mgt.iot.util.IoTUtil;
@ -61,7 +61,7 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) {
AndroidConfiguration androidConfiguration = new AndroidConfiguration();
androidConfiguration.setTenantDomain(APIUtil.getAuthenticatedUserTenantDomain());
String mqttEndpoint = MqttConfig.getInstance().getMqttQueueEndpoint();
String mqttEndpoint = MqttConfig.getInstance().getBrokerEndpoint();
if (mqttEndpoint.contains(Constants.LOCALHOST)) {
mqttEndpoint = mqttEndpoint.replace(Constants.LOCALHOST, IoTUtil.getHostName());
}
@ -84,7 +84,7 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
if (added) {
AndroidConfiguration androidConfiguration = new AndroidConfiguration();
androidConfiguration.setTenantDomain(APIUtil.getAuthenticatedUserTenantDomain());
String mqttEndpoint = MqttConfig.getInstance().getMqttQueueEndpoint();
String mqttEndpoint = MqttConfig.getInstance().getBrokerEndpoint();
if (mqttEndpoint.contains(Constants.LOCALHOST)) {
mqttEndpoint = mqttEndpoint.replace(Constants.LOCALHOST, IoTUtil.getHostName());
}

@ -1,199 +0,0 @@
/*
* 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.device.mgt.iot.androidsense.service.impl.transport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.user.api.UserStoreException;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@SuppressWarnings("no JAX-WS annotation")
public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
private static Log log = LogFactory.getLog(AndroidSenseMQTTConnector.class);
private static String subscribeTopic = AndroidSenseConstants.MQTT_SUBSCRIBE_WORDS_TOPIC;
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
private static final String KEY_TYPE = "PRODUCTION";
private static final String DEFAULT_PASSWORD = "";
private AndroidSenseMQTTConnector() {
super(iotServerSubscriber, AndroidSenseConstants.DEVICE_TYPE,
MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic);
}
@Override
public void connect() {
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
try {
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername);
APIManagementProviderService apiManagementProviderService = APIUtil
.getAPIManagementProviderService();
String[] tags = {AndroidSenseConstants.DEVICE_TYPE};
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
AndroidSenseConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "device_type_" + AndroidSenseConstants.DEVICE_TYPE + " device_mqtt_connector";
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), applicationUsername, scopes);
//create token
String accessToken = accessTokenInfo.getAccessToken();
setUsernameAndPassword(accessToken, DEFAULT_PASSWORD);
connectToQueue();
} catch (TransportHandlerException e) {
log.warn("Connection/Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed");
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException ex) {
log.error("MQTT-Subscriber: Thread Sleep Interrupt Exception.", ex);
}
}catch (JWTClientException e) {
log.error("Failed to retrieve token from JWT Client.", e);
return;
} catch (UserStoreException e) {
log.error("Failed to retrieve the user.", e);
return;
} catch (APIManagerException e) {
log.error("Failed to create an application and generate keys.", e);
return;
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.start();
}
/**
* @throws TransportHandlerException in the event of any exceptions that occur whilst processing the message.
*/
@Override
public void processIncomingMessage() throws TransportHandlerException {
}
/**
* @param message the message (of the type specific to the protocol) received from the device.
* @throws TransportHandlerException
*/
@Override
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
}
@Override
public void publishDeviceData(String... publishData) throws TransportHandlerException {
if (publishData.length != 3) {
String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " +
"Need to be [owner, deviceId, content]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg);
}
String deviceId = publishData[0];
String operation = publishData[1];
String resource = publishData[2];
MqttMessage pushMessage = new MqttMessage();
String publishTopic = "wso2/" + APIUtil.getAuthenticatedUserTenantDomain()
+ "/" + AndroidSenseConstants.DEVICE_TYPE + "/" + deviceId + "/command";
if (operation.equals("add")) {
publishTopic = publishTopic + "/words";
} else if (operation.equals("remove")) {
publishTopic = publishTopic + "/remove";
} else if (operation.equals("threshold")) {
publishTopic = publishTopic + "/threshold";
} else {
return;
}
String actualMessage = resource;
pushMessage.setPayload(actualMessage.getBytes(StandardCharsets.UTF_8));
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
pushMessage.setRetained(false);
publishToQueue(publishTopic, pushMessage);
}
@Override
public void processIncomingMessage(MqttMessage mqttMessage, String... strings) throws TransportHandlerException {
}
/**
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
*/
@Override
public void publishDeviceData() throws TransportHandlerException {
}
/**
* @param publishData the message (of the type specific to the protocol) to be sent to the device.
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
*/
@Override
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
}
@Override
public void disconnect () {
Runnable stopConnection = new Runnable() {
public void run() {
while (isConnected()) {
try {
closeConnection();
} catch (MqttException e) {
if (log.isDebugEnabled()) {
log.warn("Unable to 'STOP' MQTT connection at broker at: " + mqttBrokerEndPoint
+ " for device-type - " + AndroidSenseConstants.DEVICE_TYPE, e);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error("MQTT-Terminator: Thread Sleep Interrupt Exception at device-type - " +
AndroidSenseConstants.DEVICE_TYPE, e1);
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.start();
}
}

@ -14,6 +14,7 @@ import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.util.ArrayList;
@ -166,4 +167,22 @@ public class APIUtil {
}
return deviceAccessAuthorizationService;
}
public static OutputEventAdapterService getOutputEventAdapterService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
OutputEventAdapterService outputEventAdapterService =
(OutputEventAdapterService) ctx.getOSGiService(OutputEventAdapterService.class, null);
if (outputEventAdapterService == null) {
String msg = "Device Authorization service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return outputEventAdapterService;
}
public static String getTenantDomainOftheUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
return threadLocalCarbonContext.getTenantDomain();
}
}

@ -26,7 +26,6 @@
<jaxrs:serviceBeans>
<bean id="AndroidSenseControllerService"
class="org.wso2.carbon.device.mgt.iot.androidsense.service.impl.AndroidSenseControllerServiceImpl">
<property name="androidSenseMQTTConnector" ref="mqttConnectorBean"/>
</bean>
<bean id="AndroidSenseManagerService"
class="org.wso2.carbon.device.mgt.iot.androidsense.service.impl.AndroidSenseManagerServiceImpl"/>
@ -36,19 +35,5 @@
</jaxrs:providers>
</jaxrs:server>
<!--<jaxrs:server id="AndroidSense_Mgt" address="/enrollment/">-->
<!--<jaxrs:serviceBeans>-->
<!--<bean id="AndroidSenseManagerService"-->
<!--class="org.wso2.carbon.device.mgt.iot.androidsense.service.impl.AndroidSenseManagerServiceImpl"/>-->
<!--</jaxrs:serviceBeans>-->
<!--<jaxrs:providers>-->
<!--<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />-->
<!--</jaxrs:providers>-->
<!--</jaxrs:server>-->
<bean id="mqttConnectorBean"
class="org.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport.AndroidSenseMQTTConnector">
</bean>
</beans>

@ -62,7 +62,13 @@
org.wso2.carbon.device.mgt.common,
org.wso2.carbon.device.mgt.iot.*,
org.wso2.carbon.device.mgt.extensions.feature.mgt.*,
org.wso2.carbon.utils.*
org.wso2.carbon.utils.*,
org.wso2.carbon.base,
org.wso2.carbon.context,
org.wso2.carbon.core,
org.wso2.carbon.core.util,
org.wso2.carbon.event.output.adapter.core,
org.wso2.carbon.event.output.adapter.core.exception
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.androidsense.plugin.internal,
@ -103,5 +109,9 @@
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
</dependency>
</dependencies>
</project>

@ -16,6 +16,10 @@
package org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants;
import org.wso2.carbon.utils.CarbonUtils;
import java.io.File;
public class AndroidSenseConstants {
public final static String DEVICE_TYPE = "android_sense";
@ -50,4 +54,27 @@ public class AndroidSenseConstants {
public static final String MQTT_SUBSCRIBE_WORDS_TOPIC = "wso2/+/android_sense/+/data";
public static final String DATA_SOURCE_NAME = "jdbc/AndroidSenseDM_DB";
public final static String DEVICE_TYPE_PROVIDER_DOMAIN = "carbon.super";
//mqtt tranport related constants
public static final String MQTT_ADAPTER_NAME = "android_sense_mqtt";
public static final String MQTT_ADAPTER_TYPE = "oauth-mqtt";
public static final String ADAPTER_TOPIC_PROPERTY = "topic";
public static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
public static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
public static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
public static final String DEFAULT_CARBON_LOCAL_IP_PROPERTY = "carbon.local.ip";
public static final int CARBON_DEFAULT_PORT_OFFSET = 0;
public static final int DEFAULT_MQTT_PORT = 1883;
public static final String USERNAME_PROPERTY_KEY = "username";
public static final String DCR_PROPERTY_KEY = "dcrUrl";
public static final String BROKER_URL_PROPERTY_KEY = "url";
public static final String SCOPES_PROPERTY_KEY = "scopes";
public static final String QOS_PROPERTY_KEY = "qos";
public static final String CLIENT_ID_PROPERTY_KEY = "qos";
public static final String CLEAR_SESSION_PROPERTY_KEY = "clearSession";
public static final String TOPIC = "topic";
public static final String MQTT_CONFIG_LOCATION = CarbonUtils.getEtcCarbonConfigDirPath() + File.separator
+ "mqtt.properties";
}

@ -50,7 +50,7 @@ public class AndroidSenseManagerService implements DeviceManagementService {
@Override
public ProvisioningConfig getProvisioningConfig() {
return new ProvisioningConfig(AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
return new ProvisioningConfig(AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, false);
}
@Override

@ -21,7 +21,7 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.exception.AndroidSenseDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.dao.util.AndroidSenseUtils;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util.AndroidSenseUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;

@ -1,109 +0,0 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.androidsense.plugin.impl.dao.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.exception.AndroidSenseDeviceMgtPluginException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* Contains utility methods used by plugin.
*/
public class AndroidSenseUtils {
private static Log log = LogFactory.getLog(AndroidSenseUtils.class);
public static String getDeviceProperty(List<Device.Property> deviceProperties, String propertyKey) {
String deviceProperty = "";
for(Device.Property property :deviceProperties){
if(propertyKey.equals(property.getName())){
deviceProperty = property.getValue();
}
}
return deviceProperty;
}
public static Device.Property getProperty(String property, String value) {
if (property != null) {
Device.Property prop = new Device.Property();
prop.setName(property);
prop.setValue(value);
return prop;
}
return null;
}
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.warn("Error occurred while closing result set", e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.warn("Error occurred while closing prepared statement", e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.warn("Error occurred while closing database connection", e);
}
}
}
public static void cleanupResources(PreparedStatement stmt, ResultSet rs) {
cleanupResources(null, stmt, rs);
}
/**
* Creates the device management schema.
*/
public static void setupDeviceManagementSchema() throws AndroidSenseDeviceMgtPluginException {
try {
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup(AndroidSenseConstants.DATA_SOURCE_NAME);
DeviceSchemaInitializer initializer =
new DeviceSchemaInitializer(dataSource);
log.info("Initializing device management repository database schema");
initializer.createRegistryDatabase();
} catch (NamingException e) {
log.error("Error while looking up the data source: " + AndroidSenseConstants.DATA_SOURCE_NAME);
} catch (Exception e) {
throw new AndroidSenseDeviceMgtPluginException("Error occurred while initializing Iot Device " +
"Management database schema", e);
}
}
}

@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.androidsense.plugin.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.ServerStartupObserver;
import java.io.IOException;
/**
* Startup listener to create an output adapter after server starts up.
*/
public class AndroidSenseStartupListener implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(AndroidSenseStartupListener.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
try {
AndroidSenseUtils.setupMqttOutputAdapter();
} catch (IOException e) {
log.error("Failed to intilaize the virtual firealarm output adapter", e);
}
}
}

@ -0,0 +1,179 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.androidsense.plugin.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.exception.AndroidSenseDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.internal.AndroidSenseManagementDataHolder;
import org.wso2.carbon.event.output.adapter.core.MessageType;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Contains utility methods used by plugin.
*/
public class AndroidSenseUtils {
private static Log log = LogFactory.getLog(AndroidSenseUtils.class);
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.warn("Error occurred while closing result set", e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.warn("Error occurred while closing prepared statement", e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.warn("Error occurred while closing database connection", e);
}
}
}
public static void cleanupResources(PreparedStatement stmt, ResultSet rs) {
cleanupResources(null, stmt, rs);
}
/**
* Creates the device management schema.
*/
public static void setupDeviceManagementSchema() throws AndroidSenseDeviceMgtPluginException {
try {
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup(AndroidSenseConstants.DATA_SOURCE_NAME);
DeviceSchemaInitializer initializer =
new DeviceSchemaInitializer(dataSource);
log.info("Initializing device management repository database schema");
initializer.createRegistryDatabase();
} catch (NamingException e) {
log.error("Error while looking up the data source: " + AndroidSenseConstants.DATA_SOURCE_NAME);
} catch (Exception e) {
throw new AndroidSenseDeviceMgtPluginException("Error occurred while initializing Iot Device " +
"Management database schema", e);
}
}
public static void setupMqttOutputAdapter() throws IOException {
OutputEventAdapterConfiguration outputEventAdapterConfiguration =
createMqttOutputEventAdapterConfiguration(AndroidSenseConstants.MQTT_ADAPTER_NAME,
AndroidSenseConstants.MQTT_ADAPTER_TYPE, MessageType.TEXT);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
AndroidSenseManagementDataHolder.getInstance().getOutputEventAdapterService()
.create(outputEventAdapterConfiguration);
} catch (OutputEventAdapterException e) {
log.error("Unable to create Output Event Adapter : " + AndroidSenseConstants.MQTT_ADAPTER_NAME, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
/**
* Create Output Event Adapter Configuration for given configuration.
*
* @param name Output Event Adapter name
* @param type Output Event Adapter type
* @param msgFormat Output Event Adapter message format
* @return OutputEventAdapterConfiguration instance for given configuration
*/
private static OutputEventAdapterConfiguration createMqttOutputEventAdapterConfiguration(String name, String type,
String msgFormat) throws IOException {
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
outputEventAdapterConfiguration.setName(name);
outputEventAdapterConfiguration.setType(type);
outputEventAdapterConfiguration.setMessageFormat(msgFormat);
File configFile = new File(AndroidSenseConstants.MQTT_CONFIG_LOCATION);
if (configFile.exists()) {
Map<String, String> mqttAdapterProperties = new HashMap<>();
InputStream propertyStream = configFile.toURI().toURL().openStream();
Properties properties = new Properties();
properties.load(propertyStream);
mqttAdapterProperties.put(AndroidSenseConstants.USERNAME_PROPERTY_KEY, properties.getProperty(
AndroidSenseConstants.USERNAME_PROPERTY_KEY));
mqttAdapterProperties.put(AndroidSenseConstants.DCR_PROPERTY_KEY, Utils.replaceSystemProperty(
properties.getProperty(AndroidSenseConstants.DCR_PROPERTY_KEY)));
mqttAdapterProperties.put(AndroidSenseConstants.BROKER_URL_PROPERTY_KEY, replaceMqttProperty(
properties.getProperty(AndroidSenseConstants.BROKER_URL_PROPERTY_KEY)));
mqttAdapterProperties.put(AndroidSenseConstants.SCOPES_PROPERTY_KEY, properties.getProperty(
AndroidSenseConstants.SCOPES_PROPERTY_KEY));
mqttAdapterProperties.put(AndroidSenseConstants.CLEAR_SESSION_PROPERTY_KEY, properties.getProperty(
AndroidSenseConstants.CLEAR_SESSION_PROPERTY_KEY));
mqttAdapterProperties.put(AndroidSenseConstants.QOS_PROPERTY_KEY, properties.getProperty(
AndroidSenseConstants.QOS_PROPERTY_KEY));
mqttAdapterProperties.put(AndroidSenseConstants.CLIENT_ID_PROPERTY_KEY, "");
outputEventAdapterConfiguration.setStaticProperties(mqttAdapterProperties);
}
return outputEventAdapterConfiguration;
}
public static String replaceMqttProperty(String urlWithPlaceholders) {
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
urlWithPlaceholders = urlWithPlaceholders.replaceAll(AndroidSenseConstants.MQTT_PORT, "" +
(AndroidSenseConstants.DEFAULT_MQTT_PORT + getPortOffset()));
urlWithPlaceholders = urlWithPlaceholders.replaceAll(AndroidSenseConstants.MQTT_BROKER_HOST,
System.getProperty(AndroidSenseConstants.DEFAULT_CARBON_LOCAL_IP_PROPERTY, "localhost"));
return urlWithPlaceholders;
}
private static int getPortOffset() {
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
String portOffset = System.getProperty("portOffset", carbonConfig.getFirstProperty(
AndroidSenseConstants.CARBON_CONFIG_PORT_OFFSET));
try {
if ((portOffset != null)) {
return Integer.parseInt(portOffset.trim());
} else {
return AndroidSenseConstants.CARBON_DEFAULT_PORT_OFFSET;
}
} catch (NumberFormatException e) {
return AndroidSenseConstants.CARBON_DEFAULT_PORT_OFFSET;
}
}
}

@ -0,0 +1,48 @@
/*
* 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.device.mgt.iot.androidsense.plugin.internal;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
/**
* DataHolder class of plugins component.
*/
public class AndroidSenseManagementDataHolder {
private OutputEventAdapterService outputEventAdapterService;
private static AndroidSenseManagementDataHolder thisInstance = new AndroidSenseManagementDataHolder();
private AndroidSenseManagementDataHolder() {
}
public static AndroidSenseManagementDataHolder getInstance() {
return thisInstance;
}
public OutputEventAdapterService getOutputEventAdapterService() {
return outputEventAdapterService;
}
public void setOutputEventAdapterService(
OutputEventAdapterService outputEventAdapterService) {
this.outputEventAdapterService = outputEventAdapterService;
}
}

@ -21,14 +21,23 @@ import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.exception.AndroidSenseDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.AndroidSenseManagerService;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.dao.util.AndroidSenseUtils;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util.AndroidSenseStartupListener;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util.AndroidSenseUtils;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
/**
* @scr.component name="org.wso2.carbon.device.mgt.iot.android.internal.AndroidSenseManagementServiceComponent"
* immediate="true"
* @scr.reference name="event.output.adapter.service"
* interface="org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService"
* cardinality="1..1"
* policy="dynamic"
* bind="setOutputEventAdapterService"
* unbind="unsetOutputEventAdapterService"
*/
public class AndroidSenseManagementServiceComponent {
@ -43,6 +52,8 @@ public class AndroidSenseManagementServiceComponent {
BundleContext bundleContext = ctx.getBundleContext();
androidServiceRegRef =
bundleContext.registerService(DeviceManagementService.class.getName(), new AndroidSenseManagerService(), null);
bundleContext.registerService(ServerStartupObserver.class.getName(), new AndroidSenseStartupListener(),
null);
String setupOption = System.getProperty("setup");
if (setupOption != null) {
if (log.isDebugEnabled()) {
@ -81,4 +92,20 @@ public class AndroidSenseManagementServiceComponent {
log.error("Error occurred while de-activating Android Device Management bundle", e);
}
}
/**
* Initialize the Output EventAdapter Service dependency
*
* @param outputEventAdapterService Output EventAdapter Service reference
*/
protected void setOutputEventAdapterService(OutputEventAdapterService outputEventAdapterService) {
AndroidSenseManagementDataHolder.getInstance().setOutputEventAdapterService(outputEventAdapterService);
}
/**
* De-reference the Output EventAdapter Service dependency.
*/
protected void unsetOutputEventAdapterService(OutputEventAdapterService outputEventAdapterService) {
AndroidSenseManagementDataHolder.getInstance().setOutputEventAdapterService(null);
}
}

@ -0,0 +1,60 @@
/*
* 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.device.mgt.iot.androidsense.plugin.mqtt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util.AndroidSenseUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class MqttConfig {
private static String brokerEndpoint;
private static MqttConfig mqttConfig = new MqttConfig();
private static final Log log = LogFactory.getLog(MqttConfig.class);
private MqttConfig() {
File configFile = new File(AndroidSenseConstants.MQTT_CONFIG_LOCATION);
if (configFile.exists()) {
try {
InputStream propertyStream = configFile.toURI().toURL().openStream();
Properties properties = new Properties();
properties.load(propertyStream);
brokerEndpoint = AndroidSenseUtils.replaceMqttProperty(
properties.getProperty(AndroidSenseConstants.BROKER_URL_PROPERTY_KEY));
} catch (IOException e) {
log.error("Failed to read the mqtt.properties file" + e);
}
}
}
public static MqttConfig getInstance() {
return mqttConfig;
}
public String getBrokerEndpoint() {
return brokerEndpoint;
}
}

@ -55,8 +55,7 @@ public class ArduinoControllerServiceImpl implements ArduinoControllerService {
public Response switchBulb(@PathParam("deviceId") String deviceId, @QueryParam("state") String state) {
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
ArduinoConstants.DEVICE_TYPE),
DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
ArduinoConstants.DEVICE_TYPE), DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
LinkedList<String> deviceControlList = internalControlsQueue.get(deviceId);

@ -32,7 +32,6 @@ import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.iot.arduino.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.arduino.plugin.constants.ArduinoConstants;
import org.wso2.carbon.device.mgt.iot.arduino.service.impl.util.ZipUtil;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.util.ZipArchive;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
@ -172,9 +171,6 @@ public class ArduinoManagerServiceImpl implements ArduinoManagerService {
} catch (APIManagerException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (DeviceControllerException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (IOException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
@ -185,7 +181,7 @@ public class ArduinoManagerServiceImpl implements ArduinoManagerService {
}
private ZipArchive createDownloadFile(String owner, String deviceName)
throws DeviceManagementException, JWTClientException, DeviceControllerException, APIManagerException,
throws DeviceManagementException, JWTClientException, APIManagerException,
UserStoreException {
if (owner == null) {
throw new IllegalArgumentException("Error on createDownloadFile() Owner is null!");

@ -19,8 +19,6 @@
package org.wso2.carbon.device.mgt.iot.arduino.service.impl.util;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.exception.IoTException;
import org.wso2.carbon.device.mgt.iot.util.IoTUtil;
import org.wso2.carbon.device.mgt.iot.util.IotDeviceManagementUtil;

@ -54,7 +54,7 @@ public class ArduinoManagerService implements DeviceManagementService {
@Override
public ProvisioningConfig getProvisioningConfig() {
return new ProvisioningConfig(DEVICE_TYPE_PROVIDER_DOMAIN, true);
return new ProvisioningConfig(DEVICE_TYPE_PROVIDER_DOMAIN, false);
}
@Override

@ -24,7 +24,7 @@
<property name="contentValidation">default</property>
<property name="transports">all</property>
<property name="maximumTotalHttpConnection">100</property>
<property name="tokenValidationEndpointUrl">https://${server.host}:${mgt.transport.https.port}/services/OAuth2TokenValidationService</property>
<property name="tokenValidationEndpointUrl">https://localhost:${carbon.https.port}/services/OAuth2TokenValidationService</property>
<property name="password">admin</property>
</from>
<mapping customMapping="disable" type="json"/>

@ -19,11 +19,11 @@
<eventReceiver name="temperature-mqtt" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt">
<property name="topic">wso2/carbon.super/raspberrypi/+/temperature</property>
<property name="topic">carbon.super/+/+/temperature</property>
<property name="username">admin</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:3</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2</property>
<property name="contentValidation">default</property>
<property name="dcrUrl">https://${server.host}:${mgt.transport.https.port}/dynamic-client-web/register</property>
<property name="dcrUrl">https://localhost:${carbon.https.port}/dynamic-client-web/register</property>
<property name="clientId">temperatureMqttClient</property>
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
<property name="cleanSession">true</property>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iot-base-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Input Adaptor Extensions Module</name>
<description>Provides the back-end functionality of Input adaptor</description>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Export-Package>
org.wso2.carbon.device.mgt.iot.input.adapter.extension.*
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,55 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.extension;
/**
* This is the return type of the ContentValidator.
*/
public class ContentInfo {
/**
* true if the content is valid if not when false then content will not be published.
*/
private boolean isValidContent;
/**
* msgText to be returned. eg: if the content is encrypted then we can decrypt the content and then validate and
* return it.
*/
private Object message;
public ContentInfo(boolean isValidContent, Object message) {
this.isValidContent = isValidContent;
this.message = message;
}
public boolean isValidContent() {
return isValidContent;
}
public void setIsValidContent(boolean isValidContent) {
this.isValidContent = isValidContent;
}
public Object getMessage() {
return message;
}
public void setMessage(Object message) {
this.message = message;
}
}

@ -0,0 +1,17 @@
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
import java.util.Map;
/**
* Content Transformer will be triggered through input adapters
*/
public interface ContentTransformer {
/**
* This is used to transform the receiver content
* @param message message to be format
* @param dynamicProperties related to transport.
* @return transformed message
*/
Object transform(Object message, Map<String, String> dynamicProperties);
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.extension;
import java.util.Map;
/**
* This interface will be triggered to validate the stream content before publishing.
*/
public interface ContentValidator {
/**
* @param contentValidationParams that related to input adapter.
* @param dynamicParameter that message.
* @return ContentInfo.
*/
ContentInfo validate(Object message, Map<String, String> contentValidationParams, Map<String, String> dynamicParameter);
}

@ -0,0 +1,14 @@
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
import java.util.Map;
/**
* This holds the default implementation of ContentTransformer
*/
public class DefaultContentTransformer implements ContentTransformer{
@Override
public Object transform(Object message, Map<String, String> dynamicProperties) {
return message;
}
}

@ -0,0 +1,15 @@
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
import java.util.Map;
/**
* This holds the default implementation of content validator interface.
*/
public class DefaultContentValidator implements ContentValidator {
@Override
public ContentInfo validate(Object message, Map<String, String> params, Map<String, String> dynamicParams) {
return new ContentInfo(true, message);
}
}

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iot-base-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.http</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Input Adaptor Module - Http</name>
<description>Provides the back-end functionality of Input adaptor</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.core</artifactId>
</dependency>
<dependency>
<groupId>commons-pool.wso2</groupId>
<artifactId>commons-pool</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal,
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.*
</Private-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.input.adapter.http.internal,
!org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.*,
org.wso2.carbon.device.mgt.iot.input.adapter.http.*
</Export-Package>
<Import-Package>
org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.*,
javax.xml.namespace; version=0.0.0,
com.jayway.jsonpath.*,
com.nimbusds.jose,
com.nimbusds.jose.crypto,
com.nimbusds.jwt,
org.osgi.framework,
org.osgi.service.component,
javax.servlet,
javax.servlet.http,
org.osgi.service.http,
org.wso2.carbon.user.api,
org.wso2.carbon.user.core.service,
org.wso2.carbon.user.core.tenant,
org.apache.commons.pool,
org.apache.commons.pool.impl
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,213 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.http;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceDataHolder;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import javax.servlet.ServletException;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public final class HTTPEventAdapter implements InputEventAdapter {
private final InputEventAdapterConfiguration eventAdapterConfiguration;
private final Map<String, String> globalProperties;
private InputEventAdapterListener eventAdaptorListener;
private final String id = UUID.randomUUID().toString();
public static ExecutorService executorService;
private static final Log log = LogFactory.getLog(HTTPEventAdapter.class);
private boolean isConnected = false;
public HTTPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init(InputEventAdapterListener eventAdaptorListener) throws InputEventAdapterException {
this.eventAdaptorListener = eventAdaptorListener;
//ThreadPoolExecutor will be assigned if it is null
if (executorService == null) {
int minThread;
int maxThread;
long defaultKeepAliveTime;
int jobQueueSize;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
minThread = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
} else {
minThread = HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
maxThread = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
} else {
maxThread = HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
defaultKeepAliveTime = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
} else {
defaultKeepAliveTime = HTTPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLS;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
jobQueueSize = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
} else {
jobQueueSize = HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE;
}
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
log.error("Exception while adding event to executor queue : " + e.getMessage(), e);
}
}
};
executorService = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(jobQueueSize), rejectedExecutionHandler);
}
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("not-supported");
}
@Override
public void connect() {
registerDynamicEndpoint(eventAdapterConfiguration.getName());
isConnected = true;
}
@Override
public void disconnect() {
if (isConnected){
isConnected = false;
unregisterDynamicEndpoint(eventAdapterConfiguration.getName());
}
}
@Override
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof HTTPEventAdapter))
return false;
HTTPEventAdapter that = (HTTPEventAdapter) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean isEventDuplicatedInCluster() {
return false;
}
@Override
public boolean isPolling() {
return false;
}
private void registerDynamicEndpoint(String adapterName) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
String endpoint;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
} else {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
}
try {
HttpService httpService = InputAdapterServiceDataHolder.getHTTPService();
if (httpService == null) {
throw new InputEventAdapterRuntimeException(
"HttpService not available, Error in registering endpoint " + endpoint);
}
httpService.registerServlet(endpoint, new HTTPMessageServlet(eventAdaptorListener, tenantId,
eventAdapterConfiguration),
new Hashtable(), httpService.createDefaultHttpContext());
} catch (ServletException | NamespaceException e) {
throw new InputEventAdapterRuntimeException("Error in registering endpoint " + endpoint, e);
}
}
private void unregisterDynamicEndpoint(String adapterName) {
HttpService httpService = InputAdapterServiceDataHolder.getHTTPService();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String endpoint;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
} else {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
}
if (httpService != null) {
httpService.unregister(endpoint);
}
}
}

@ -0,0 +1,167 @@
/*
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.http;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.MessageType;
import org.wso2.carbon.event.input.adapter.core.Property;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.utils.CarbonUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
/**
* The http event adapter factory class to create a http input adapter
*/
public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
private ResourceBundle resourceBundle =
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.input.adapter.http.i18n.Resources", Locale.getDefault());
private int httpPort;
private int httpsPort;
public HTTPEventAdapterFactory() {
int portOffset = getPortOffset();
httpPort = HTTPEventAdapterConstants.DEFAULT_HTTP_PORT + portOffset;
httpsPort = HTTPEventAdapterConstants.DEFAULT_HTTPS_PORT + portOffset;
}
@Override
public String getType() {
return HTTPEventAdapterConstants.ADAPTER_TYPE_HTTP;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportInputMessageTypes = new ArrayList<>();
supportInputMessageTypes.add(MessageType.JSON);
supportInputMessageTypes.add(MessageType.TEXT);
supportInputMessageTypes.add(MessageType.XML);
supportInputMessageTypes.add(MessageType.WSO2EVENT);
return supportInputMessageTypes;
}
@Override
public List<Property> getPropertyList() {
List<Property> propertyList = new ArrayList<>();
// Transport Exposed
Property exposedTransportsProperty = new Property(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
exposedTransportsProperty.setRequired(true);
exposedTransportsProperty.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS));
exposedTransportsProperty.setOptions(
new String[]{HTTPEventAdapterConstants.HTTPS, HTTPEventAdapterConstants.HTTP,
HTTPEventAdapterConstants.LOCAL, HTTPEventAdapterConstants.ALL});
exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL);
propertyList.add(exposedTransportsProperty);
// OAUTH validation endpoint admin service username
Property username = new Property(HTTPEventAdapterConstants.USERNAME);
username.setRequired(true);
username.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME));
username.setHint(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME_HINT));
propertyList.add(username);
// OAUTH validation endpoint admin service password
Property password = new Property(HTTPEventAdapterConstants.PASSWORD);
password.setRequired(true);
password.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD));
password.setHint(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD_HINT));
propertyList.add(password);
// OAUTH validation endpoint
Property tokenValidationEndpoint = new Property(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL);
tokenValidationEndpoint.setRequired(true);
tokenValidationEndpoint.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL));
tokenValidationEndpoint.setHint(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL_HINT));
propertyList.add(tokenValidationEndpoint);
Property maximumHttpConnectionPerHost = new Property(HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST);
maximumHttpConnectionPerHost.setRequired(true);
maximumHttpConnectionPerHost.setDisplayName(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST));
maximumHttpConnectionPerHost.setHint(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT));
maximumHttpConnectionPerHost.setDefaultValue(HTTPEventAdapterConstants.MAX_HTTP_CONNECTION);
propertyList.add(maximumHttpConnectionPerHost);
Property maxTotalHttpConnection = new Property(HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION);
maxTotalHttpConnection.setRequired(true);
maxTotalHttpConnection.setDisplayName(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION));
maxTotalHttpConnection.setHint(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION_HINT));
maxTotalHttpConnection.setDefaultValue(HTTPEventAdapterConstants.MAX_TOTAL_HTTP_CONNECTION);
propertyList.add(maxTotalHttpConnection);
//Content Validator details
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
propertyList.add(contentValidator);
//Content Validator Params details
Property contentValidatorParams = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
contentValidatorParams.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(HTTPEventAdapterConstants.HTTP_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
propertyList.add(contentValidatorParams);
//Content Transformer details
Property contentTransformer = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
contentTransformer.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME));
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
contentTransformer.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
propertyList.add(contentTransformer);
return propertyList;
}
@Override
public String getUsageTips() {
return resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_PREFIX) + httpPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID1) + httpsPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID2) + httpPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID3) + httpsPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_POSTFIX);
}
@Override
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new HTTPEventAdapter(eventAdapterConfiguration, globalProperties);
}
private int getPortOffset() {
return CarbonUtils.getPortFromServerConfig(HTTPEventAdapterConstants.CARBON_CONFIG_PORT_OFFSET_NODE) + 1;
}
}

@ -0,0 +1,273 @@
/*
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.http;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.exception.HTTPContentInitializationException;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.jwt.JWTAuthenticator;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.oauth.OAuthAuthenticator;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.AuthenticationInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
* This will act as the event reciver.
*/
public class HTTPMessageServlet extends HttpServlet {
private static final String AUTH_MESSAGE_STORE_AUTHENTICATION_INFO = "AUTH_MESSAGE_STORE_AUTHENTICATION_INFO";
private static final String AUTH_FAILURE_RESPONSE = "_AUTH_FAILURE_";
private static Log log = LogFactory.getLog(HTTPMessageServlet.class);
private static Map<String, String> contentValidationProperties;
private static ContentValidator contentValidator;
private static ContentTransformer contentTransformer;
private InputEventAdapterListener eventAdaptorListener;
private int tenantId;
private String exposedTransports;
private static JWTAuthenticator jwtAuthenticator;
private static OAuthAuthenticator oAuthAuthenticator;
public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
InputEventAdapterConfiguration eventAdapterConfiguration) {
this.eventAdaptorListener = eventAdaptorListener;
this.tenantId = tenantId;
this.exposedTransports = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
HTTPMessageServlet.contentValidationProperties = new HashMap<>();
String contentValidationParams = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
String validationParams[] = contentValidationParams.split(",");
for (String validationParam : validationParams) {
String[] validationProperty = validationParam.split(":");
if (validationProperty.length == 2) {
contentValidationProperties.put(validationProperty[0], validationProperty[1]);
}
}
}
String className = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
if (HTTPEventAdapterConstants.DEFAULT.equals(className)) {
contentValidator = new DefaultContentValidator();
} else {
try {
Class<? extends ContentValidator> contentValidatorClass = Class.forName(className)
.asSubclass(ContentValidator.class);
contentValidator = contentValidatorClass.newInstance();
} catch (ClassNotFoundException e) {
throw new HTTPContentInitializationException(
"Unable to find the class validator: " + className, e);
} catch (InstantiationException e) {
throw new HTTPContentInitializationException(
"Unable to create an instance of :" + className, e);
} catch (IllegalAccessException e) {
throw new HTTPContentInitializationException("Access of the instance in not allowed.", e);
}
}
String contentTransformerClassName = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
if (contentTransformerClassName != null && contentTransformerClassName.equals(HTTPEventAdapterConstants.DEFAULT)) {
contentTransformer = new DefaultContentTransformer();
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
try {
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName)
.asSubclass(ContentTransformer.class);
contentTransformer = contentTransformerClass.newInstance();
} catch (ClassNotFoundException e) {
throw new HTTPContentInitializationException(
"Unable to find the class transformer: " + contentTransformerClassName, e);
} catch (InstantiationException e) {
throw new HTTPContentInitializationException(
"Unable to create an instance of :" + contentTransformerClassName, e);
} catch (IllegalAccessException e) {
throw new HTTPContentInitializationException("Access of the instance in not allowed.", e);
}
}
jwtAuthenticator = new JWTAuthenticator();
oAuthAuthenticator = new OAuthAuthenticator(eventAdapterConfiguration);
}
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse res) throws IOException {
String data = this.inputStreamToString(req.getInputStream());
if (data == null) {
log.warn("Event Object is empty/null");
return;
}
AuthenticationInfo authenticationInfo = null;
if (exposedTransports.equalsIgnoreCase(HTTPEventAdapterConstants.HTTPS)) {
if (!req.isSecure()) {
res.setStatus(403);
log.error("Only Secured endpoint is enabled for requests");
return;
} else {
authenticationInfo = this.checkAuthentication(req);
int tenantId = authenticationInfo != null ? authenticationInfo.getTenantId() : -1;
if (tenantId == -1) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
} else if (tenantId != this.tenantId) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
}
}
} else if (exposedTransports.equalsIgnoreCase(HTTPEventAdapterConstants.HTTP)) {
if (req.isSecure()) {
res.setStatus(403);
log.error("Only unsecured endpoint is enabled for requests");
return;
}
} else {
authenticationInfo = this.checkAuthentication(req);
int tenantId = authenticationInfo != null ? authenticationInfo.getTenantId() : -1;
if (tenantId == -1) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
} else if (tenantId != this.tenantId) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
}
}
if (log.isDebugEnabled()) {
log.debug("Message : " + data);
}
if (authenticationInfo != null) {
Map<String, String> paramMap = new HashMap<>();
Enumeration<String> reqParameterNames = req.getParameterNames();
while (reqParameterNames.hasMoreElements()) {
String paramterName = reqParameterNames.nextElement();
paramMap.put(paramterName, req.getParameter(paramterName));
}
paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername());
paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain());
if (contentValidator != null && contentTransformer != null) {
data = (String) contentTransformer.transform(data, paramMap);
ContentInfo contentInfo = contentValidator.validate(data, contentValidationProperties, paramMap);
if (contentInfo != null && contentInfo.isValidContent()) {
HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener,
(String) contentInfo.getMessage(), tenantId));
}
}
}
}
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse res) throws IOException {
doPost(req, res);
}
public class HTTPRequestProcessor implements Runnable {
private InputEventAdapterListener inputEventAdapterListener;
private String payload;
private int tenantId;
public HTTPRequestProcessor(InputEventAdapterListener inputEventAdapterListener, String payload, int tenantId) {
this.inputEventAdapterListener = inputEventAdapterListener;
this.payload = payload;
this.tenantId = tenantId;
}
public void run() {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
if (log.isDebugEnabled()) {
log.debug("Event received in HTTP Event Adapter - " + payload);
}
if (payload != null) {
inputEventAdapterListener.onEvent(payload);
} else {
log.warn("Dropping the empty/null event received through http adapter");
}
} catch (Exception e) {
log.error("Error while parsing http request for processing: " + e.getMessage(), e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
private AuthenticationInfo checkAuthentication(HttpServletRequest req) {
AuthenticationInfo authenticationInfo = (AuthenticationInfo) req.getSession().getAttribute(
AUTH_MESSAGE_STORE_AUTHENTICATION_INFO);
if (authenticationInfo != null) {
return authenticationInfo;
}
if (jwtAuthenticator.isJWTHeaderExist(req)) {
authenticationInfo = jwtAuthenticator.authenticate(req);
} else {
authenticationInfo = oAuthAuthenticator.authenticate(req);
}
if (authenticationInfo != null) {
boolean success = authenticationInfo.isAuthenticated();
if (success) {
req.getSession().setAttribute(AUTH_MESSAGE_STORE_AUTHENTICATION_INFO, authenticationInfo);
}
}
return authenticationInfo;
}
private String inputStreamToString(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int i;
while ((i = in.read(buff)) > 0) {
out.write(buff, 0, i);
}
out.close();
return out.toString();
}
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.http.exception;
/**
* This exception will thrown when content validator is failed to intialiaze.
*/
public class HTTPContentInitializationException extends RuntimeException {
private String errMessage;
public HTTPContentInitializationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public HTTPContentInitializationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public HTTPContentInitializationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public HTTPContentInitializationException() {
super();
}
public HTTPContentInitializationException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errMessage;
}
public void setErrorMessage(String errMessage) {
this.errMessage = errMessage;
}
}

@ -0,0 +1,70 @@
/*
* 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.device.mgt.iot.input.adapter.http.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.HTTPEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component name="input.iot.http.AdapterService.component" immediate="true"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
* @scr.reference name="http.service" interface="org.osgi.service.http.HttpService"
* cardinality="1..1" policy="dynamic" bind="setHttpService" unbind="unsetHttpService"
*/
public class InputAdapterServiceComponent {
private static final Log log = LogFactory.getLog(
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceComponent.class);
protected void activate(ComponentContext context) {
try {
InputEventAdapterFactory httpEventEventAdapterFactory = new HTTPEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
httpEventEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the input adapter service");
}
} catch (RuntimeException e) {
log.error("Can not create the input adapter service ", e);
}
}
protected void setRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(realmService);
}
protected void unsetRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(null);
}
protected void setHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(httpService);
}
protected void unsetHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(null);
}
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.http.internal;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.user.core.service.RealmService;
/**
* common place to hold some OSGI service references.
*/
public final class InputAdapterServiceDataHolder {
private static RealmService realmService;
private static HttpService httpService;
private InputAdapterServiceDataHolder() {
}
public static void registerRealmService(
RealmService realmService) {
InputAdapterServiceDataHolder.realmService = realmService;
}
public static RealmService getRealmService() {
return realmService;
}
public static void registerHTTPService(
HttpService httpService) {
InputAdapterServiceDataHolder.httpService = httpService;
}
public static HttpService getHTTPService() {
return httpService;
}
}

@ -0,0 +1,120 @@
/*
* 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.device.mgt.iot.input.adapter.http.jwt;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.SignedJWT;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceDataHolder;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.AuthenticationInfo;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.servlet.http.HttpServletRequest;
import java.security.interfaces.RSAPublicKey;
import java.text.ParseException;
/**
* This authenticator authenticates HTTP requests using JWT header.
*/
public class JWTAuthenticator {
private static final Log log = LogFactory.getLog(JWTAuthenticator.class);
public static final String SIGNED_JWT_AUTH_USERNAME = "Username";
private static final String JWT_ASSERTION_HEADER = "X-JWT-Assertion";
public boolean isJWTHeaderExist(HttpServletRequest request) {
String authorizationHeader = request.getHeader(JWT_ASSERTION_HEADER);
if((authorizationHeader != null) && !authorizationHeader.isEmpty()){
return true;
}
return false;
}
public AuthenticationInfo authenticate(HttpServletRequest request) {
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
//Get the filesystem keystore default primary certificate
KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID);
try {
keyStoreManager.getDefaultPrimaryCertificate();
String authorizationHeader = request.getHeader(HTTPConstants.HEADER_AUTHORIZATION);
String headerData = decodeAuthorizationHeader(authorizationHeader);
JWSVerifier verifier =
new RSASSAVerifier((RSAPublicKey) keyStoreManager.getDefaultPublicKey());
SignedJWT jwsObject = SignedJWT.parse(headerData);
if (jwsObject.verify(verifier)) {
String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME);
String tenantDomain = MultitenantUtils.getTenantDomain(username);
username = MultitenantUtils.getTenantAwareUsername(username);
TenantManager tenantManager = InputAdapterServiceDataHolder.getRealmService().
getTenantManager();
int tenantId = tenantManager.getTenantId(tenantDomain);
if (tenantId == -1) {
log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " +
": " + tenantDomain);
} else {
UserStoreManager userStore = InputAdapterServiceDataHolder.getRealmService().
getTenantUserRealm(tenantId).getUserStoreManager();
if (userStore.isExistingUser(username)) {
authenticationInfo.setTenantId(tenantId);
authenticationInfo.setUsername(username);
authenticationInfo.setTenantDomain(tenantDomain);
authenticationInfo.setAuthenticated(true);
}
}
}
} catch (UserStoreException e) {
log.error("Error occurred while obtaining the user.", e);
} catch (ParseException e) {
log.error("Error occurred while parsing the JWT header.", e);
} catch (JOSEException e) {
log.error("Error occurred while verifying the JWT header.", e);
} catch (Exception e) {
log.error("Error occurred while verifying the JWT header.", e);
}
return authenticationInfo;
}
private String decodeAuthorizationHeader(String authorizationHeader) {
if(authorizationHeader == null) {
return null;
}
String[] splitValues = authorizationHeader.trim().split(" ");
byte[] decodedBytes = Base64Utils.decode(splitValues[1].trim());
if (decodedBytes != null) {
return new String(decodedBytes);
} else {
if (log.isDebugEnabled()) {
log.debug("Error decoding authorization header.");
}
return null;
}
}
}

@ -0,0 +1,174 @@
/*
* 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.device.mgt.iot.input.adapter.http.oauth;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceDataHolder;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.AuthenticationInfo;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.servlet.http.HttpServletRequest;
import java.rmi.RemoteException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Authenticate use oauth validator
*/
public class OAuthAuthenticator {
private static String cookie;
private GenericObjectPool stubs;
private static final Pattern PATTERN = Pattern.compile("[B|b]earer\\s");
private static final String TOKEN_TYPE = "bearer";
private static final String AUTHORIZATION_HEADER = "Authorization";
private static Log log = LogFactory.getLog(OAuthAuthenticator.class);
public OAuthAuthenticator(InputEventAdapterConfiguration eventAdapterConfiguration) {
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(eventAdapterConfiguration));
}
public AuthenticationInfo authenticate(HttpServletRequest req) {
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
String bearerToken = getBearerToken(req);
if (bearerToken == null) {
return authenticationInfo;
}
try {
authenticationInfo = validateToken(bearerToken);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("checkAuthentication() fail: " + e.getMessage(), e);
}
}
return authenticationInfo;
}
private String getBearerToken(HttpServletRequest request) {
String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);
if (authorizationHeader != null) {
Matcher matcher = PATTERN.matcher(authorizationHeader);
if (matcher.find()) {
authorizationHeader = authorizationHeader.substring(matcher.end());
}
}
return authorizationHeader;
}
/**
* This creates an AuthenticationInfo object that is used for authorization. This method will validate the token
* and
* sets the required parameters to the object.
*
* @param token that needs to be validated.
* @param tokenValidationServiceStub stub that is used to call the external service.
* @return AuthenticationInfo This contains the information related to authenticated client.
* @throws RemoteException that triggers when failing to call the external service..
*/
private AuthenticationInfo getAuthenticationInfo(String token,
OAuth2TokenValidationServiceStub tokenValidationServiceStub)
throws RemoteException, UserStoreException {
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO();
OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken =
new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
accessToken.setTokenType(TOKEN_TYPE);
accessToken.setIdentifier(token);
validationRequest.setAccessToken(accessToken);
boolean authenticated;
OAuth2TokenValidationResponseDTO tokenValidationResponse;
tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest);
if (tokenValidationResponse == null) {
authenticationInfo.setAuthenticated(false);
return authenticationInfo;
}
authenticated = tokenValidationResponse.getValid();
if (authenticated) {
String authorizedUser = tokenValidationResponse.getAuthorizedUser();
String username = MultitenantUtils.getTenantAwareUsername(authorizedUser);
String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
authenticationInfo.setUsername(username);
authenticationInfo.setTenantDomain(tenantDomain);
RealmService realmService = InputAdapterServiceDataHolder.getRealmService();
int tenantId = realmService.getTenantManager().getTenantId(authenticationInfo.getTenantDomain());
authenticationInfo.setTenantId(tenantId);
} else {
if (log.isDebugEnabled()) {
log.debug("Token validation failed for token: " + token);
}
}
ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient()
.getLastOperationContext().getServiceContext();
cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);
authenticationInfo.setAuthenticated(authenticated);
return authenticationInfo;
}
/**
* This method gets a string accessToken and validates it
*
* @param token which need to be validated.
* @return AuthenticationInfo with the validated results.
*/
private AuthenticationInfo validateToken(String token) {
OAuth2TokenValidationServiceStub tokenValidationServiceStub = null;
try {
Object stub = this.stubs.borrowObject();
if (stub != null) {
tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub;
if (cookie != null) {
tokenValidationServiceStub._getServiceClient().getOptions().setProperty(
HTTPConstants.COOKIE_STRING, cookie);
}
return getAuthenticationInfo(token, tokenValidationServiceStub);
} else {
log.warn("Stub initialization failed.");
}
} catch (RemoteException e) {
log.error("Error on connecting with the validation endpoint.", e);
} catch (Exception e) {
log.error("Error occurred in borrowing an validation stub from the pool.", e);
} finally {
try {
if (tokenValidationServiceStub != null) {
this.stubs.returnObject(tokenValidationServiceStub);
}
} catch (Exception e) {
log.warn("Error occurred while returning the object back to the oauth token validation service " +
"stub pool.", e);
}
}
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
authenticationInfo.setAuthenticated(false);
authenticationInfo.setTenantId(-1);
return authenticationInfo;
}
}

@ -0,0 +1,181 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.http.oauth;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.log4j.Logger;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.oauth.exception.OAuthTokenValidationException;
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
/**
* This follows object pool pattern to manage the stub for oauth validation service.
*/
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
private HttpClient httpClient;
InputEventAdapterConfiguration eventAdapterConfiguration;
public OAuthTokenValidaterStubFactory(InputEventAdapterConfiguration eventAdapterConfiguration) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.httpClient = createHttpClient();
}
/**
* This creates a OAuth2TokenValidationServiceStub object to the pool.
*
* @return an OAuthValidationStub object
* @throws Exception thrown when creating the object.
*/
@Override
public Object makeObject() throws Exception {
return this.generateStub();
}
/**
* This is used to clean up the OAuth validation stub and releases to the object pool.
*
* @param o object that needs to be released.
* @throws Exception throws when failed to release to the pool
*/
@Override
public void passivateObject(Object o) throws Exception {
if (o instanceof OAuth2TokenValidationServiceStub) {
OAuth2TokenValidationServiceStub stub = (OAuth2TokenValidationServiceStub) o;
stub._getServiceClient().cleanupTransport();
}
}
/**
* This is used to create a stub which will be triggered through object pool factory, which will create an
* instance of it.
*
* @return OAuth2TokenValidationServiceStub stub that is used to call an external service.
* @throws OAuthTokenValidationException will be thrown when initialization failed.
*/
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
OAuth2TokenValidationServiceStub stub;
try {
URL hostURL = new URL(Utils.replaceSystemProperty(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
if (hostURL != null) {
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
if (stub != null) {
ServiceClient client = stub._getServiceClient();
client.getServiceContext().getConfigurationContext().setProperty(
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
HttpTransportProperties.Authenticator auth =
new HttpTransportProperties.Authenticator();
auth.setPreemptiveAuthentication(true);
String username = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.USERNAME);
String password = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.PASSWORD);
auth.setPassword(username);
auth.setUsername(password);
Options options = client.getOptions();
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
client.setOptions(options);
if (hostURL.getProtocol().equals("https")) {
// set up ssl factory since axis2 https transport is used.
EasySSLProtocolSocketFactory sslProtocolSocketFactory =
createProtocolSocketFactory();
Protocol authhttps = new Protocol(hostURL.getProtocol(),
(ProtocolSocketFactory) sslProtocolSocketFactory,
hostURL.getPort());
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
}
} else {
String errorMsg = "OAuth Validation instanization failed.";
throw new OAuthTokenValidationException(errorMsg);
}
} else {
String errorMsg = "host url is invalid";
throw new OAuthTokenValidationException(errorMsg);
}
} catch (AxisFault axisFault) {
throw new OAuthTokenValidationException(
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
} catch (MalformedURLException e) {
throw new OAuthTokenValidationException(
"Error occurred while parsing token endpoint URL", e);
}
return stub;
}
/**
* This is required to create a trusted connection with the external entity.
* Have to manually configure it since we use CommonHTTPTransport(axis2 transport) in axis2.
*
* @return an EasySSLProtocolSocketFactory for SSL communication.
*/
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
try {
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
return easySSLPSFactory;
} catch (IOException e) {
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
throw new OAuthTokenValidationException(errorMsg, e);
} catch (GeneralSecurityException e) {
String errorMsg = "Failed to set the key material in easy ssl factory.";
throw new OAuthTokenValidationException(errorMsg, e);
}
}
/**
* This created httpclient pool that can be used to connect to external entity. This connection can be configured
* via broker.xml by setting up the required http connection parameters.
*
* @return an instance of HttpClient that is configured with MultiThreadedHttpConnectionManager
*/
private HttpClient createHttpClient() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params);
return new HttpClient(connectionManager);
}
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.http.oauth.exception;
/**
* This Exception will be thrown, when there any interference with token validation flow.
*/
public class OAuthTokenValidationException extends Exception {
private String errMessage;
public OAuthTokenValidationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public OAuthTokenValidationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public OAuthTokenValidationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public OAuthTokenValidationException() {
super();
}
public OAuthTokenValidationException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errMessage;
}
public void setErrorMessage(String errMessage) {
this.errMessage = errMessage;
}
}

@ -0,0 +1,69 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.http.util;
/**
* This will be return after authentication and this will consist of the authenticated user info.
*/
public class AuthenticationInfo {
/**
* this variable is used to check whether the client is authenticated.
*/
private boolean authenticated;
private String username;
private String tenantDomain;
private int tenantId;
/**
* returns whether the client is authenticated
*/
public boolean isAuthenticated() {
return authenticated;
}
public void setAuthenticated(boolean authenticated) {
this.authenticated = authenticated;
}
/**
* returns the authenticated client username
*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* return the authenticated client tenant domain
*/
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
}

@ -0,0 +1,77 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.http.util;
import com.jayway.jsonpath.JsonPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
import java.util.Map;
public class HTTPContentValidator implements ContentValidator {
private static final Log log = LogFactory.getLog(HTTPContentValidator.class);
private static String JSON_ARRAY_START_CHAR = "[";
@Override
public ContentInfo validate(Object msgPayload, Map<String, String> contentValidationParams,
Map<String, String> dynamicParams) {
String deviceId = dynamicParams.get("deviceId");
String msg = (String) msgPayload;
String deviceIdJsonPath = contentValidationParams.get(HTTPEventAdapterConstants.DEVICE_ID_JSON_PATH);
boolean status;
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(msg, deviceId, deviceIdJsonPath);
} else {
status = processSingleEvent(msg, deviceId, deviceIdJsonPath);
}
return new ContentInfo(status, msg);
}
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
Object res = JsonPath.read(msg, deviceIdJsonPath);
String deviceIdFromContent = (res != null) ? res.toString() : "";
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
return true;
}
return false;
}
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
try {
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
boolean status = false;
for (int i = 0; i < jsonArray.size(); i++) {
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
if (!status) {
return status;
}
}
return status;
} catch (ParseException e) {
log.error("Invalid input " + msg, e);
return false;
}
}
}

@ -0,0 +1,75 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.http.util;
/**
* This holds the constants related to HTTP event adapter.
*/
public final class HTTPEventAdapterConstants {
private HTTPEventAdapterConstants() {
}
public static final String ADAPTER_TYPE_HTTP = "oauth-http";
public static final String ADAPTER_USAGE_TIPS_PREFIX = "http.usage.tips_prefix";
public static final String ADAPTER_USAGE_TIPS_MID1 = "http.usage.tips_mid1";
public static final String ADAPTER_USAGE_TIPS_MID2 = "http.usage.tips_mid2";
public static final String ADAPTER_USAGE_TIPS_MID3 = "http.usage.tips_mid3";
public static final String ADAPTER_USAGE_TIPS_POSTFIX = "http.usage.tips_postfix";
public static final int ADAPTER_MIN_THREAD_POOL_SIZE = 8;
public static final int ADAPTER_MAX_THREAD_POOL_SIZE = 100;
public static final int ADAPTER_EXECUTOR_JOB_QUEUE_SIZE = 10000;
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLS = 20000;
public static final String ENDPOINT_PREFIX = "/endpoints/";
public static final String ENDPOINT_URL_SEPARATOR = "/";
public static final String ENDPOINT_TENANT_KEY = "t";
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
public static final String EXPOSED_TRANSPORTS = "transports";
public static final String HTTPS = "https";
public static final String HTTP = "http";
public static final String LOCAL = "local";
public static final String ALL = "all";
public static final String CARBON_CONFIG_PORT_OFFSET_NODE = "Ports.Offset";
public static final int DEFAULT_HTTP_PORT = 9763;
public static final int DEFAULT_HTTPS_PORT = 9443;
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION_HINT = "maximumTotalHttpConnection.hint";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT = "maximumHttpConnectionPerHost.hint";
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpointUrl";
public static final String TOKEN_VALIDATION_ENDPOINT_URL_HINT = "tokenValidationEndpointUrl.hint";
public static final String USERNAME = "username";
public static final String USERNAME_HINT = "username.hint";
public static final String PASSWORD = "password";
public static final String PASSWORD_HINT = "password.hint";
public static final String DEFAULT_STRING = "default";
public static final String MAX_HTTP_CONNECTION = "2";
public static final String MAX_TOTAL_HTTP_CONNECTION = "100";
public static final String TENANT_DOMAIN_TAG = "tenantDomain";
public static final String USERNAME_TAG = "username";
public static final String PAYLOAD_TAG = "payload";
public static final String DEVICE_ID_JSON_PATH = "device_id_json_path";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
public static final String DEFAULT = "default";
public static final String HTTP_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME = "contentTransformer";
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT = "contentTransformer.hint";
}

@ -0,0 +1,40 @@
#
# Copyright (c) 2005-2014, 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.
#
transports=Transport(s)
http.usage.tips_prefix=Following url formats are used to receive events</br>For super tenants:</br>&nbsp;&nbsp;<i>http://localhost:
http.usage.tips_mid1=/endpoints/&lt;event_receiver_name&gt</i></br>&nbsp;&nbsp;<i>https://localhost:
http.usage.tips_mid2=/endpoints/&lt;event_receiver_name&gt;</i></br></br>For other tenants:</br>&nbsp;&nbsp;<i>http://localhost:
http.usage.tips_mid3=/endpoints/t/&lt;tenant_domain&gt;/&lt;event_receiver_name&gt;</i></br>&nbsp;&nbsp;<i>https://localhost:
http.usage.tips_postfix=/endpoints/t/&lt;tenant_domain&gt;/&lt;event_receiver_name&gt;</i>
tokenValidationEndpointUrl=tokenEndpointUrl
tokenValidationEndpointUrl.hint=OAUTH Token Validation Endpoint
username=username
username.hint=username of the user to connect to the admin services
password=password
password.hint=password of the user to connect to the admin services.
maximumTotalHttpConnection=maximumTotalHttpConnection
maximumTotalHttpConnection.hint=Maximum Total connection to be made with the endpoint
maximumHttpConnectionPerHost=maximumHttpConnectionPerHost
maximumHttpConnectionPerHost.hint=Maximum Http connection per host.
contentValidation=contentValidation
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentValidationParams=contentValidationParams
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
contentTransformer=contentTransformer
contentTransformer.hint=Class Name of the content transformer or 'default' to set default class, required to implement (if required)

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iot-base-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.mqtt</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Input Adaptor Module - MQTT</name>
<description>Provides the back-end functionality of Input adaptor</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.wso2</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal,
org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal.*
</Private-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal,
!org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal.*,
org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.*
</Export-Package>
<Import-Package>
org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.*,
javax.xml.namespace; version=0.0.0,
org.eclipse.paho.client.mqttv3.*,
org.apache.http;version="${httpclient.version.range}",
org.apache.http.message;version="${httpclient.version.range}",
org.apache.http.client;version="${httpclient.version.range}",
org.apache.http.impl;version="${httpclient.version.range}",
org.apache.http.conn.*;version="${httpclient.version.range}",
org.apache.http.util;version="${httpclient.version.range}",
org.apache.http.client.entity;version="${httpclient.version.range}",
org.apache.http.client.methods;version="${httpclient.version.range}",
org.apache.http.impl.client;version="${httpclient.version.range}",
org.json.simple.*,
org.wso2.carbon.identity.jwt.client.extension.*,
com.jayway.jsonpath.*
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,166 @@
/*
* 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.device.mgt.iot.input.adapter.mqtt;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTBrokerConnectionConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTAdapterListener;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTEventAdapterConstants;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Input XMPPEventAdapter will be used to receive events with MQTT protocol using specified broker and topic.
*/
public class MQTTEventAdapter implements InputEventAdapter {
private final InputEventAdapterConfiguration eventAdapterConfiguration;
private final Map<String, String> globalProperties;
private InputEventAdapterListener eventAdapterListener;
private final String id = UUID.randomUUID().toString();
private MQTTAdapterListener mqttAdapterListener;
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
public MQTTEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
this.eventAdapterListener = eventAdapterListener;
try {
int keepAlive;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
} else {
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
}
String contentValidationParams = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
Map<String, String> paramsMap = new HashMap<>();
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
String params[] = contentValidationParams.split(",");
for (String param : params) {
String paramsKeyAndValue[] = splitOnFirst(param, ':');
if (paramsKeyAndValue.length != 2) {
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
}
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
}
}
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION),
keepAlive,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
paramsMap,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
);
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID),
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
} catch (Throwable t) {
throw new InputEventAdapterException(t.getMessage(), t);
}
}
private String[] splitOnFirst(String str, char c) {
int idx = str.indexOf(c);
String head = str.substring(0, idx);
String tail = str.substring(idx + 1);
return new String[] { head, tail} ;
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("not-supported");
}
@Override
public void connect() {
mqttAdapterListener.createConnection();
}
@Override
public void disconnect() {
//when mqtt and this feature both together then this method becomes a blocking method, Therefore
// have used a thread to skip it.
try {
Thread thread = new Thread(new Runnable() {
public void run() {
if (mqttAdapterListener != null) {
mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
}
}
});
thread.start();
thread.join(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MQTTEventAdapter)) return false;
MQTTEventAdapter that = (MQTTEventAdapter) o;
if (!id.equals(that.id)) return false;
return true;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean isEventDuplicatedInCluster() {
return true;
}
@Override
public boolean isPolling() {
return true;
}
}

@ -0,0 +1,148 @@
/*
* 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.device.mgt.iot.input.adapter.mqtt;
import org.wso2.carbon.event.input.adapter.core.*;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTEventAdapterConstants;
import java.util.*;
/**
* The mqtt event adapter factory class to create a mqtt input adapter
*/
public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
private ResourceBundle resourceBundle = ResourceBundle.getBundle
("org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.i18n.Resources", Locale.getDefault());
@Override
public String getType() {
return MQTTEventAdapterConstants.ADAPTER_TYPE_MQTT;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportInputMessageTypes = new ArrayList<String>();
supportInputMessageTypes.add(MessageType.JSON);
supportInputMessageTypes.add(MessageType.TEXT);
supportInputMessageTypes.add(MessageType.XML);
supportInputMessageTypes.add(MessageType.WSO2EVENT);
return supportInputMessageTypes;
}
@Override
public List<Property> getPropertyList() {
List<Property> propertyList = new ArrayList<Property>();
// set topic
Property topicProperty = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
topicProperty.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC));
topicProperty.setRequired(true);
topicProperty.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC_HINT));
propertyList.add(topicProperty);
//Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
brokerUrl.setRequired(true);
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
propertyList.add(brokerUrl);
//DCR endpoint details
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
dcrUrl.setRequired(false);
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
propertyList.add(dcrUrl);
//Content Validator details
Property contentValidator = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
propertyList.add(contentValidator);
//Content Validator Params details
Property contentValidatorParams = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
contentValidatorParams.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(MQTTEventAdapterConstants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
propertyList.add(contentValidatorParams);
//Broker Username
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(false);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
propertyList.add(userName);
//Broker Required Scopes.
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
scopes.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES));
scopes.setRequired(false);
scopes.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES_HINT));
propertyList.add(scopes);
//Broker clear session
Property clearSession = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION);
clearSession.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
clearSession.setRequired(false);
clearSession.setOptions(new String[]{"true", "false"});
clearSession.setDefaultValue("true");
clearSession.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION_HINT));
propertyList.add(clearSession);
//Content Transformer details
Property contentTransformer = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
contentTransformer.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME));
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
contentTransformer.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
propertyList.add(contentTransformer);
// set clientId
Property clientId = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
clientId.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID));
clientId.setRequired(false);
clientId.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID_HINT));
propertyList.add(clientId);
return propertyList;
}
@Override
public String getUsageTips() {
return null;
}
@Override
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new MQTTEventAdapter(eventAdapterConfiguration, globalProperties);
}
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.mqtt.exception;
/**
* This exception will thrown when content validator is failed to intialiaze.
*/
public class MQTTContentInitializationException extends RuntimeException {
private String errMessage;
public MQTTContentInitializationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public MQTTContentInitializationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public MQTTContentInitializationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public MQTTContentInitializationException() {
super();
}
public MQTTContentInitializationException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errMessage;
}
public void setErrorMessage(String errMessage) {
this.errMessage = errMessage;
}
}

@ -0,0 +1,67 @@
/*
* 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.device.mgt.iot.input.adapter.mqtt.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.MQTTEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component name="input.iot.mqtt.AdapterService.component" immediate="true"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
*/
public class InputAdapterServiceComponent {
private static final Log log = LogFactory.getLog(InputAdapterServiceComponent.class);
protected void activate(ComponentContext context) {
try {
InputEventAdapterFactory mqttEventAdapterFactory = new MQTTEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
mqttEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the input adapter service");
}
} catch (RuntimeException e) {
log.error("Can not create the input adapter service ", e);
}
}
protected void setRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(realmService);
}
protected void unsetRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(null);
}
protected void setHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(httpService);
}
protected void unsetHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(null);
}
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.mqtt.internal;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.user.core.service.RealmService;
/**
* common place to hold some OSGI service references.
*/
public final class InputAdapterServiceDataHolder {
private static RealmService realmService;
private static HttpService httpService;
private InputAdapterServiceDataHolder() {
}
public static void registerRealmService(
RealmService realmService) {
InputAdapterServiceDataHolder.realmService = realmService;
}
public static RealmService getRealmService() {
return realmService;
}
public static void registerHTTPService(
HttpService httpService) {
InputAdapterServiceDataHolder.httpService = httpService;
}
public static HttpService getHTTPService() {
return httpService;
}
}

@ -0,0 +1,285 @@
/*
* 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.device.mgt.iot.input.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStatus;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentValidator;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.exception.MQTTContentInitializationException;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
public class MQTTAdapterListener implements MqttCallback, Runnable {
private static final Log log = LogFactory.getLog(MQTTAdapterListener.class);
private MqttClient mqttClient;
private MqttConnectOptions connectionOptions;
private boolean cleanSession;
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
private String topic;
private int tenantId;
private boolean connectionSucceeded = false;
ContentValidator contentValidator;
Map<String, String> contentValidationParams;
ContentTransformer contentTransformer;
private InputEventAdapterListener eventAdapterListener = null;
public MQTTAdapterListener(MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration,
String topic, String mqttClientId,
InputEventAdapterListener inputEventAdapterListener, int tenantId) {
if(mqttClientId == null || mqttClientId.trim().isEmpty()){
mqttClientId = MqttClient.generateClientId();
}
this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
this.cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
int keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
this.topic = topic;
this.eventAdapterListener = inputEventAdapterListener;
this.tenantId = tenantId;
//SORTING messages until the server fetches them
String temp_directory = System.getProperty("java.io.tmpdir");
MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(temp_directory);
try {
connectionOptions = new MqttConnectOptions();
connectionOptions.setCleanSession(cleanSession);
connectionOptions.setKeepAliveInterval(keepAlive);
// Construct an MQTT blocking mode client
mqttClient = new MqttClient(this.mqttBrokerConnectionConfiguration.getBrokerUrl(), mqttClientId,
dataStore);
// Set this wrapper as the callback handler
mqttClient.setCallback(this);
String contentValidatorClassName = this.mqttBrokerConnectionConfiguration.getContentValidatorClassName();
if (contentValidatorClassName != null && contentValidatorClassName.equals(MQTTEventAdapterConstants.DEFAULT)) {
contentValidator = new DefaultContentValidator();
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
try {
Class<? extends ContentValidator> contentValidatorClass = Class.forName(contentValidatorClassName)
.asSubclass(ContentValidator.class);
contentValidator = contentValidatorClass.newInstance();
} catch (ClassNotFoundException e) {
throw new MQTTContentInitializationException(
"Unable to find the class validator: " + contentValidatorClassName, e);
} catch (InstantiationException e) {
throw new MQTTContentInitializationException(
"Unable to create an instance of :" + contentValidatorClassName, e);
} catch (IllegalAccessException e) {
throw new MQTTContentInitializationException("Access of the instance in not allowed.", e);
}
}
contentValidationParams = mqttBrokerConnectionConfiguration.getContentValidatorParams();
String contentTransformerClassName = this.mqttBrokerConnectionConfiguration.getContentTransformerClassName();
if (contentTransformerClassName != null && contentTransformerClassName.equals(MQTTEventAdapterConstants.DEFAULT)) {
contentTransformer = new DefaultContentTransformer();
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
try {
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName)
.asSubclass(ContentTransformer.class);
contentTransformer = contentTransformerClass.newInstance();
} catch (ClassNotFoundException e) {
throw new MQTTContentInitializationException(
"Unable to find the class transfoer: " + contentTransformerClassName, e);
} catch (InstantiationException e) {
throw new MQTTContentInitializationException(
"Unable to create an instance of :" + contentTransformerClassName, e);
} catch (IllegalAccessException e) {
throw new MQTTContentInitializationException("Access of the instance in not allowed.", e);
}
}
} catch (MqttException e) {
log.error("Exception occurred while subscribing to MQTT broker at "
+ mqttBrokerConnectionConfiguration.getBrokerUrl());
throw new InputEventAdapterRuntimeException(e);
}
}
public void startListener() throws MqttException {
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null &&
this.mqttBrokerConnectionConfiguration.getDcrUrl() != null) {
String username = this.mqttBrokerConnectionConfiguration.getBrokerUsername();
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
//getJWT Client Parameters.
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
try {
URL dcrUrl = new URL(dcrUrlString);
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
HttpPost postMethod = new HttpPost(dcrUrlString);
RegistrationProfile registrationProfile = new RegistrationProfile();
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.EMPTY_STRING);
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
registrationProfile.setClientName(username + "_" + tenantId);
String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity);
HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse);
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
clientId, clientSecret, username, scopes);
connectionOptions.setUserName(accessTokenInfo.getAccessToken());
} catch (ParseException e) {
String msg = "error occurred while parsing client credential payload";
log.error(msg, e);
} catch (JWTClientException e) {
String msg = "error occurred while parsing the response from JWT Client";
log.error(msg, e);
}
} catch (MalformedURLException e) {
log.error("Invalid dcrUrl : " + dcrUrlString);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
log.error("Failed to create an https connection.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
mqttClient.connect(connectionOptions);
mqttClient.subscribe(topic);
}
public void stopListener(String adapterName) {
if (connectionSucceeded) {
try {
if (!ServerStatus.getCurrentStatus().equals(ServerStatus.STATUS_SHUTTING_DOWN) || cleanSession) {
mqttClient.unsubscribe(topic);
}
mqttClient.disconnect(3000);
} catch (MqttException e) {
log.error("Can not unsubscribe from the destination " + topic +
" with the event adapter " + adapterName, e);
}
}
connectionSucceeded = true;
}
@Override
public void connectionLost(Throwable throwable) {
log.warn("MQTT connection not reachable " + throwable);
connectionSucceeded = false;
new Thread(this).start();
}
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
try {
String msgText = mqttMessage.toString();
if (log.isDebugEnabled()) {
log.debug(msgText);
}
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
if (log.isDebugEnabled()) {
log.debug("Event received in MQTT Event Adapter - " + msgText);
}
if (contentValidator != null && contentTransformer != null) {
ContentInfo contentInfo;
Map<String, String> dynamicProperties = new HashMap<>();
dynamicProperties.put(MQTTEventAdapterConstants.TOPIC, topic);
msgText = (String) contentTransformer.transform(msgText, dynamicProperties);
contentInfo = contentValidator.validate(msgText,contentValidationParams, dynamicProperties);
if (contentInfo != null && contentInfo.isValidContent()) {
eventAdapterListener.onEvent(contentInfo.getMessage());
}
} else {
eventAdapterListener.onEvent(msgText);
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
@Override
public void run() {
while (!connectionSucceeded) {
try {
MQTTEventAdapterConstants.initialReconnectDuration = MQTTEventAdapterConstants.initialReconnectDuration
* MQTTEventAdapterConstants.reconnectionProgressionFactor;
Thread.sleep(MQTTEventAdapterConstants.initialReconnectDuration);
startListener();
connectionSucceeded = true;
log.info("MQTT Connection successful");
} catch (InterruptedException e) {
log.error("Interruption occurred while waiting for reconnection", e);
} catch (MqttException e) {
log.error("MQTT Exception occurred when starting listener", e);
}
}
}
public void createConnection() {
new Thread(this).start();
}
}

@ -0,0 +1,94 @@
/*
* 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.device.mgt.iot.input.adapter.mqtt.util;
import java.util.Map;
/**
* This holds the configurations related to MQTT Broker.
*/
public class MQTTBrokerConnectionConfiguration {
private String brokerUsername = null;
private String brokerScopes = null;
private boolean cleanSession = true;
private int keepAlive;
private String brokerUrl;
private String dcrUrl;
private String contentValidatorClassName;
private Map<String, String> contentValidatorParams;
private String contentTransformerClassName;
public String getBrokerScopes() {
return brokerScopes;
}
public String getBrokerUsername() {
return brokerUsername;
}
public boolean isCleanSession() {
return cleanSession;
}
public String getBrokerUrl() {
return brokerUrl;
}
public String getDcrUrl() {
return dcrUrl;
}
public int getKeepAlive() {
return keepAlive;
}
public String getContentValidatorClassName() {
return contentValidatorClassName;
}
public Map<String, String> getContentValidatorParams() {
return contentValidatorParams;
}
public String getContentTransformerClassName() {
return contentTransformerClassName;
}
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes,
String dcrUrl, String cleanSession, int keepAlive,
String contentValidatorClassName, Map<String, String> contentValidatorParams,
String contentTransformerClassName) {
this.brokerUsername = brokerUsername;
this.brokerScopes = brokerScopes;
if (brokerScopes == null) {
this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING;
}
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl);
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl);
this.contentValidatorClassName = contentValidatorClassName;
if (cleanSession != null) {
this.cleanSession = Boolean.parseBoolean(cleanSession);
}
this.keepAlive = keepAlive;
if (contentValidatorParams != null) {
this.contentValidatorParams = contentValidatorParams;
}
this.contentTransformerClassName = contentTransformerClassName;
}
}

@ -0,0 +1,85 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.mqtt.util;
import com.jayway.jsonpath.JsonPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
import java.util.Map;
public class MQTTContentValidator implements ContentValidator {
private static final String JSON_ARRAY_START_CHAR = "[";
private static final Log log = LogFactory.getLog(MQTTContentValidator.class);
@Override
public ContentInfo validate(Object msgPayload, Map<String, String> contentValidationParams,
Map<String, String> dynamicParams) {
String topic = dynamicParams.get(MQTTEventAdapterConstants.TOPIC);
String topics[] = topic.split("/");
String deviceIdJsonPath = contentValidationParams.get(MQTTEventAdapterConstants.DEVICE_ID_JSON_PATH);
String deviceIdInTopicHierarchyLevel = contentValidationParams.get(
MQTTEventAdapterConstants.DEVICE_ID_TOPIC_HIERARCHY_INDEX);
int deviceIdInTopicHierarchyLevelIndex = 0;
if (deviceIdInTopicHierarchyLevel != null && !deviceIdInTopicHierarchyLevel.isEmpty()) {
deviceIdInTopicHierarchyLevelIndex = Integer.parseInt(deviceIdInTopicHierarchyLevel);
}
String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex];
boolean status;
String message = (String) msgPayload;
if (message.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(message, deviceIdFromTopic, deviceIdJsonPath);
} else {
status = processSingleEvent(message, deviceIdFromTopic, deviceIdJsonPath);
}
return new ContentInfo(status, msgPayload);
}
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
Object res = JsonPath.read(msg, deviceIdJsonPath);
String deviceIdFromContent = (res != null) ? res.toString() : "";
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
return true;
}
return false;
}
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
try {
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
boolean status = false;
for (int i = 0; i < jsonArray.size(); i++) {
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
if (!status) {
return false;
}
}
return status;
} catch (ParseException e) {
log.error("Invalid input " + msg, e);
return false;
}
}
}

@ -0,0 +1,66 @@
/*
* 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.device.mgt.iot.input.adapter.mqtt.util;
/**
* This holds the constants related to mqtt event adapter.
*/
public class MQTTEventAdapterConstants {
public static final String ADAPTER_TYPE_MQTT = "oauth-mqtt";
public static final String ADAPTER_CONF_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_SCOPES = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME = "contentTransformer";
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT = "contentTransformer.hint";
public static final String ADAPTER_MESSAGE_TOPIC = "topic";
public static final String ADAPTER_MESSAGE_TOPIC_HINT = "topic.hint";
public static final String ADAPTER_CONF_CLIENTID = "clientId";
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
public static final String ADAPTER_CONF_CLEAN_SESSION = "cleanSession";
public static final String ADAPTER_CONF_CLEAN_SESSION_HINT = "cleanSession.hint";
public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
public static int initialReconnectDuration = 10000;
public static final int reconnectionProgressionFactor = 2;
public static final String EMPTY_STRING = "";
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
public static final String TOKEN_SCOPE = "production";
public static final String APPLICATION_TYPE = "device";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String CLIENT_NAME = "client_name";
public static final String DEFAULT = "default";
public static final String MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
public static final String TOPIC = "topic";
public static final String PAYLOAD = "payload";
public static final String DEVICE_ID_JSON_PATH = "device_id_json_path";
public static final String DEVICE_ID_TOPIC_HIERARCHY_INDEX = "device_id_topic_hierarchy_index";
}

@ -0,0 +1,99 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
/**
* This is the utility class that is used for MQTT input adapater.
*/
public class MQTTUtil {
private static final String HTTPS_PROTOCOL = "https";
private static final Log log = LogFactory.getLog(MQTTUtil.class);
/**
* Return a http client instance
*
* @param protocol- service endpoint protocol http/https
* @return
*/
public static HttpClient getHttpClient(String protocol)
throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpClient httpclient;
if (HTTPS_PROTOCOL.equals(protocol)) {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
} else {
httpclient = HttpClients.createDefault();
}
return httpclient;
}
public static String getResponseString(HttpResponse httpResponse) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String readLine;
String response = "";
while (((readLine = br.readLine()) != null)) {
response += readLine;
}
return response;
} finally {
EntityUtils.consumeQuietly(httpResponse.getEntity());
if (br != null) {
try {
br.close();
} catch (IOException e) {
log.warn("Error while closing the connection! " + e.getMessage());
}
}
}
}
public static JWTClientManagerService getJWTClientManagerService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService =
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
if (jwtClientManagerService == null) {
String msg = "JWT management service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return jwtClientManagerService;
}
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.mqtt.util;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.core.util.Utils;
public class PropertyUtils {
private static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
private static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
private static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
private static final String DEFAULT_CARBON_LOCAL_IP_PROPERTY = "carbon.local.ip";
private static final int CARBON_DEFAULT_PORT_OFFSET = 0;
private static final int DEFAULT_MQTT_PORT = 1883;
//This method is only used if the mb features are within DAS.
public static String replaceMqttProperty (String urlWithPlaceholders) {
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
urlWithPlaceholders = urlWithPlaceholders.replaceAll(MQTT_PORT, "" + (DEFAULT_MQTT_PORT + getPortOffset()));
urlWithPlaceholders = urlWithPlaceholders.replaceAll(MQTT_BROKER_HOST, System.getProperty(
DEFAULT_CARBON_LOCAL_IP_PROPERTY, "localhost"));
return urlWithPlaceholders;
}
private static int getPortOffset() {
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
String portOffset = System.getProperty("portOffset", carbonConfig.getFirstProperty(CARBON_CONFIG_PORT_OFFSET));
try {
if ((portOffset != null)) {
return Integer.parseInt(portOffset.trim());
} else {
return CARBON_DEFAULT_PORT_OFFSET;
}
} catch (NumberFormatException e) {
return CARBON_DEFAULT_PORT_OFFSET;
}
}
}

@ -0,0 +1,73 @@
package org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
private String callbackUrl;
private String clientName;
private String tokenScope;
private String owner;
private String grantType;
private String applicationType;
private static final String TAG = RegistrationProfile.class.getSimpleName();
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
public String toJSON() {
String jsonString =
"{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName + "\", \"tokenScope\": " +
"\"" + tokenScope + "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
"\", \"saasApp\" :false }\n";
return jsonString;
}
}

@ -0,0 +1,40 @@
#
# 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.
#
topic=Topic
topic.hint=Topic subscribed
clientId=Client Id
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.
url=Broker Url
username=Username
username.hint=Username of the broker (if required)
scopes=Scopes
scopes.hint=Scopes required to connect to broker (if required)
dcrUrl=dcrUrl
dcrUrl.hint=dynamic client registration endpoint URL to create application (if required) eg: https://localhost:9443/dynamic-client-web/register
contentValidation=contentValidation
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentValidationParams=contentValidationParams
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
url.hint=MQTT broker url tcp://localhost:1883
cleanSession=Clean Session
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
keepAlive=Keep Alive (In seconds)
events.duplicated.in.cluster=Is events duplicated in cluster
contentTransformer=contentTransformer
contentTransformer.hint=Class Name of the content transformer or 'default' to set default class, required to implement (if required)

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iot-base-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.xmpp</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Input Adaptor Module - XMPP</name>
<description>Provides the back-end functionality of Input adaptor</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal,
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.*
</Private-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal,
!org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal.*,
org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.*
</Export-Package>
<Import-Package>
org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.*,
javax.xml.namespace; version=0.0.0,
org.jivesoftware.smack.*,
org.apache.log4j,
org.wso2.carbon.base,
org.wso2.carbon.core.util
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,163 @@
/*
* 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.device.mgt.iot.input.adapter.xmpp;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPAdapterListener;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPServerConnectionConfiguration;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPEventAdapterConstants;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Input XMPPEventAdapter will be used to receive events with XMPP protocol using specified broker and topic.
*/
public class XMPPEventAdapter implements InputEventAdapter {
private final InputEventAdapterConfiguration eventAdapterConfiguration;
private final Map<String, String> globalProperties;
private InputEventAdapterListener eventAdapterListener;
private final String id = UUID.randomUUID().toString();
private XMPPAdapterListener xmppAdapterListener;
private XMPPServerConnectionConfiguration xmppServerConnectionConfiguration;
public XMPPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
this.eventAdapterListener = eventAdapterListener;
try {
String contentValidationParams = eventAdapterConfiguration.getProperties().get(
XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
Map<String, String> paramsMap = new HashMap<>();
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
String params[] = contentValidationParams.split(",");
for (String param : params) {
String paramsKeyAndValue[] = splitOnFirst(param, ':');
if (paramsKeyAndValue.length != 2) {
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
}
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
}
}
int xmppPort = XMPPEventAdapterConstants.DEFAULT_XMPP_PORT;
String xmppPortString = eventAdapterConfiguration.getProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
if (xmppPortString != null && !xmppPortString.trim().isEmpty()) {
xmppPort = Integer.parseInt(xmppPortString);
}
int timeoutInterval = XMPPEventAdapterConstants.DEFAULT_TIMEOUT_INTERVAL;
String timeoutIntervalString = eventAdapterConfiguration.getProperties().get(
XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
if (timeoutIntervalString != null && !timeoutIntervalString.trim().isEmpty()) {
timeoutInterval = Integer.parseInt(timeoutIntervalString);
}
xmppServerConnectionConfiguration =
new XMPPServerConnectionConfiguration(eventAdapterConfiguration.getProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_HOST),
xmppPort,
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME),
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD),
timeoutInterval,
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE),
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants
.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
paramsMap,
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID),
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants
.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
);
xmppAdapterListener = new XMPPAdapterListener(xmppServerConnectionConfiguration,
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true));
} catch (Throwable t) {
throw new InputEventAdapterException(t.getMessage(), t);
}
}
private String[] splitOnFirst(String str, char c) {
int idx = str.indexOf(c);
String head = str.substring(0, idx);
String tail = str.substring(idx + 1);
return new String[] { head, tail} ;
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("not-supported");
}
@Override
public void connect() {
xmppAdapterListener.createConnection();
}
@Override
public void disconnect() {
if (xmppAdapterListener != null) {
xmppAdapterListener.stopListener(eventAdapterConfiguration.getName());
}
}
@Override
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof XMPPEventAdapter)) return false;
XMPPEventAdapter that = (XMPPEventAdapter) o;
if (!id.equals(that.id)) return false;
return true;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean isEventDuplicatedInCluster() {
return true;
}
@Override
public boolean isPolling() {
return true;
}
}

@ -0,0 +1,150 @@
/*
* 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.device.mgt.iot.input.adapter.xmpp;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPEventAdapterConstants;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.MessageType;
import org.wso2.carbon.event.input.adapter.core.Property;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
/**
* The xmpp event adapter factory class to create a xmpp input adapter
*/
public class XMPPEventAdapterFactory extends InputEventAdapterFactory {
private ResourceBundle resourceBundle = ResourceBundle.getBundle
("org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.i18n.Resources", Locale.getDefault());
@Override
public String getType() {
return XMPPEventAdapterConstants.ADAPTER_TYPE_XMPP;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportInputMessageTypes = new ArrayList<String>();
supportInputMessageTypes.add(MessageType.JSON);
supportInputMessageTypes.add(MessageType.TEXT);
supportInputMessageTypes.add(MessageType.XML);
supportInputMessageTypes.add(MessageType.WSO2EVENT);
return supportInputMessageTypes;
}
@Override
public List<Property> getPropertyList() {
List<Property> propertyList = new ArrayList<Property>();
// Url
Property host = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_HOST);
host.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST));
host.setRequired(true);
host.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST_HINT));
// Host Port
Property port = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
port.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT));
port.setRequired(true);
port.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT_HINT));
//Broker Username
Property userName = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(true);
userName.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
//Broker Password
Property password = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD);
password.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD));
password.setRequired(true);
password.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
//Timeout Interval
Property timooutInterval = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
timooutInterval.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
timooutInterval.setRequired(false);
timooutInterval.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
//Resource
Property resource = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE);
resource.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE));
resource.setRequired(false);
resource.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE_HINT));
//Content Validator details
Property contentValidator = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(XMPPEventAdapterConstants.DEFAULT);
//Content Validator Params details
Property contentValidatorParams = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
contentValidatorParams.setDisplayName(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(XMPPEventAdapterConstants.XMPP_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
Property jid = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID);
jid.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID));
jid.setRequired(true);
jid.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID_HINT));
//Content Transformer details
Property contentTransformer = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
contentTransformer.setDisplayName(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME));
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
contentTransformer.setDefaultValue(XMPPEventAdapterConstants.DEFAULT);
propertyList.add(host);
propertyList.add(port);
propertyList.add(userName);
propertyList.add(password);
propertyList.add(timooutInterval);
propertyList.add(resource);
propertyList.add(contentValidator);
propertyList.add(contentValidatorParams);
propertyList.add(jid);
propertyList.add(contentTransformer);
return propertyList;
}
@Override
public String getUsageTips() {
return null;
}
@Override
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new XMPPEventAdapter(eventAdapterConfiguration, globalProperties);
}
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.input.adapter.xmpp.exception;
/**
* This exception will thrown when content validator is failed to intialiaze.
*/
public class XMPPContentInitializationException extends RuntimeException {
private String errMessage;
public XMPPContentInitializationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public XMPPContentInitializationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public XMPPContentInitializationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public XMPPContentInitializationException() {
super();
}
public XMPPContentInitializationException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errMessage;
}
public void setErrorMessage(String errMessage) {
this.errMessage = errMessage;
}
}

@ -0,0 +1,67 @@
/*
* 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.device.mgt.iot.input.adapter.xmpp.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.XMPPEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component name="input.iot.xmpp.AdapterService.component" immediate="true"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
*/
public class InputAdapterServiceComponent {
private static final Log log = LogFactory.getLog(InputAdapterServiceComponent.class);
protected void activate(ComponentContext context) {
try {
InputEventAdapterFactory xmppEventEventAdapterFactory = new XMPPEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
xmppEventEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the input adapter service");
}
} catch (RuntimeException e) {
log.error("Can not create the input adapter service ", e);
}
}
protected void setRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(realmService);
}
protected void unsetRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(null);
}
protected void setHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(httpService);
}
protected void unsetHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(null);
}
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.device.mgt.iot.input.adapter.xmpp.internal;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.user.core.service.RealmService;
/**
* common place to hold some OSGI service references.
*/
public final class InputAdapterServiceDataHolder {
private static RealmService realmService;
private static HttpService httpService;
private InputAdapterServiceDataHolder() {
}
public static void registerRealmService(
RealmService realmService) {
InputAdapterServiceDataHolder.realmService = realmService;
}
public static RealmService getRealmService() {
return realmService;
}
public static void registerHTTPService(
HttpService httpService) {
InputAdapterServiceDataHolder.httpService = httpService;
}
public static HttpService getHTTPService() {
return httpService;
}
}

@ -0,0 +1,224 @@
/*
* 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.device.mgt.iot.input.adapter.xmpp.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.filter.ToContainsFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStatus;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.exception.XMPPContentInitializationException;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
import java.util.HashMap;
import java.util.Map;
public class XMPPAdapterListener implements Runnable {
private static final Log log = LogFactory.getLog(XMPPAdapterListener.class);
private XMPPConnection xmppConnection;
private XMPPServerConnectionConfiguration xmppServerConnectionConfiguration;
private int tenantId;
private boolean connectionSucceeded = false;
private ContentValidator contentValidator;
private Map<String, String> contentValidationParams;
private ContentTransformer contentTransformer;
private PacketListener packetListener;
private InputEventAdapterListener eventAdapterListener = null;
public XMPPAdapterListener(XMPPServerConnectionConfiguration xmppServerConnectionConfiguration,
InputEventAdapterListener inputEventAdapterListener, int tenantId) {
this.xmppServerConnectionConfiguration = xmppServerConnectionConfiguration;
this.eventAdapterListener = inputEventAdapterListener;
this.tenantId = tenantId;
try {
String contentValidatorClassName = this.xmppServerConnectionConfiguration.getContentValidatorClassName();
if (contentValidatorClassName != null && contentValidatorClassName.equals(XMPPEventAdapterConstants.DEFAULT)) {
contentValidator = new DefaultContentValidator();
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
try {
Class<? extends ContentValidator> contentValidatorClass = Class.forName(contentValidatorClassName)
.asSubclass(ContentValidator.class);
contentValidator = contentValidatorClass.newInstance();
} catch (ClassNotFoundException e) {
throw new XMPPContentInitializationException(
"Unable to find the class validator: " + contentValidatorClassName, e);
} catch (InstantiationException e) {
throw new XMPPContentInitializationException(
"Unable to create an instance of :" + contentValidatorClassName, e);
} catch (IllegalAccessException e) {
throw new XMPPContentInitializationException("Access of the instance in not allowed.", e);
}
}
contentValidationParams = xmppServerConnectionConfiguration.getContentValidatorParams();
String contentTransformerClassName = this.xmppServerConnectionConfiguration.getContentTransformerClassName();
if (contentTransformerClassName != null && contentTransformerClassName.equals(XMPPEventAdapterConstants.DEFAULT)) {
contentTransformer = new DefaultContentTransformer();
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
try {
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName)
.asSubclass(ContentTransformer.class);
contentTransformer = contentTransformerClass.newInstance();
} catch (ClassNotFoundException e) {
throw new XMPPContentInitializationException(
"Unable to find the class transformer: " + contentTransformerClassName, e);
} catch (InstantiationException e) {
throw new XMPPContentInitializationException(
"Unable to create an instance of :" + contentTransformerClassName, e);
} catch (IllegalAccessException e) {
throw new XMPPContentInitializationException("Access of the instance in not allowed.", e);
}
}
} catch (Throwable e) {
log.error("Exception occurred while subscribing to MQTT broker at "
+ xmppServerConnectionConfiguration.getHost());
throw new InputEventAdapterRuntimeException(e);
}
}
public void startListener() throws XMPPException {
SmackConfiguration.setPacketReplyTimeout(xmppServerConnectionConfiguration.getTimeoutInterval());
ConnectionConfiguration config = new ConnectionConfiguration(xmppServerConnectionConfiguration.getHost(),
xmppServerConnectionConfiguration.getPort());
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
xmppConnection = new XMPPConnection(config);
xmppConnection.connect();
String resource = xmppServerConnectionConfiguration.getResource();
String username = xmppServerConnectionConfiguration.getUsername();
String password = xmppServerConnectionConfiguration.getPassword();
try {
if (resource == null || resource.trim().isEmpty()) {
xmppConnection.login(username, password);
} else {
xmppConnection.login(username, password, resource);
}
setFilterOnReceiver(xmppServerConnectionConfiguration.getJid());
} catch (XMPPException e) {
String errorMsg = "Login attempt to the XMPP Server with username - " + username + " failed.";
log.info(errorMsg);
throw new InputEventAdapterRuntimeException(errorMsg, e);
}
}
public void stopListener(String adapterName) {
if (connectionSucceeded) {
// Un-subscribe accordingly and disconnect from the MQTT server.
if (!ServerStatus.getCurrentStatus().equals(ServerStatus.STATUS_SHUTTING_DOWN)) {
xmppConnection.removePacketListener(packetListener);
}
xmppConnection.disconnect();
}
//This is to stop all running reconnection threads
connectionSucceeded = true;
}
protected void setFilterOnReceiver(String receiverJID) {
PacketFilter packetFilter = new AndFilter(new PacketTypeFilter(Message.class), new ToContainsFilter(
receiverJID));
packetListener = new PacketListener() {
@Override
public void processPacket(Packet packet) {
if (packet instanceof Message) {
final Message xmppMessage = (Message) packet;
Thread msgProcessThread = new Thread() {
public void run() {
processIncomingMessage(xmppMessage);
}
};
msgProcessThread.start();
}
}
};
xmppConnection.addPacketListener(packetListener, packetFilter);
}
public void processIncomingMessage(Message xmppMessage) {
try {
String from = xmppMessage.getFrom();
String subject = xmppMessage.getSubject();
String message = xmppMessage.getBody();
if (log.isDebugEnabled()) {
log.debug(message);
}
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
if (log.isDebugEnabled()) {
log.debug("Event received in MQTT Event Adapter - " + message);
}
if (contentValidator != null && contentTransformer != null) {
Map<String, String> dynamicParmaters = new HashMap<>();
dynamicParmaters.put(XMPPEventAdapterConstants.FROM_KEY, from);
dynamicParmaters.put(XMPPEventAdapterConstants.SUBJECT_KEY, subject);
message = (String) contentTransformer.transform(message, dynamicParmaters);
ContentInfo contentInfo = contentValidator.validate(message, contentValidationParams, dynamicParmaters);
if (contentInfo != null && contentInfo.isValidContent()) {
eventAdapterListener.onEvent(contentInfo.getMessage());
}
} else {
eventAdapterListener.onEvent(message);
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
@Override
public void run() {
while (!connectionSucceeded) {
try {
XMPPEventAdapterConstants.initialReconnectDuration = XMPPEventAdapterConstants.initialReconnectDuration
* XMPPEventAdapterConstants.reconnectionProgressionFactor;
Thread.sleep(XMPPEventAdapterConstants.initialReconnectDuration);
startListener();
connectionSucceeded = true;
log.info("XMPP Connection successful");
} catch (InterruptedException e) {
log.error("Interruption occurred while waiting for reconnection", e);
} catch (XMPPException e) {
log.error("XMPP Exception occurred when starting listener", e);
}
}
}
public void createConnection() {
new Thread(this).start();
}
}

@ -0,0 +1,60 @@
/*
* 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.device.mgt.iot.input.adapter.xmpp.util;
/**
* This holds the constants related to xmpp event adapter.
*/
public class XMPPEventAdapterConstants {
public static final String ADAPTER_TYPE_XMPP = "xmpp";
//static properties
public static final String ADAPTER_CONF_HOST = "host";
public static final String ADAPTER_CONF_HOST_HINT = "host.hint";
public static final String ADAPTER_CONF_PORT = "port";
public static final String ADAPTER_CONF_PORT_HINT = "port.hint";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_PASSWORD = "password";
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
public static final String ADAPTER_CONF_RESOURCE = "resource";
public static final String ADAPTER_CONF_RESOURCE_HINT = "resource.hint";
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL = "timeoutInterval";
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL_HINT = "timeoutInterval.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME = "contentTransformer";
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT = "contentTransformer.hint";
public static final String ADAPTER_CONF_RECIEVER_JID = "jid";
public static final String ADAPTER_CONF_RECIEVER_JID_HINT = "jid.hint";
public static final int DEFAULT_XMPP_PORT = 5222;
public static final int DEFAULT_TIMEOUT_INTERVAL = 5000;
public static int initialReconnectDuration = 10000;
public static final int reconnectionProgressionFactor = 2;
public static final String DEFAULT = "default";
public static final String XMPP_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
public static final String FROM_KEY = "from";
public static final String SUBJECT_KEY = "subject";
}

@ -0,0 +1,96 @@
/*
* 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.device.mgt.iot.input.adapter.xmpp.util;
import java.util.Map;
/**
* This holds the configurations related to MQTT Broker.
*/
public class XMPPServerConnectionConfiguration {
private String host;
private int port;
private String username;
private String password;
private int timeoutInterval;
private String resource;
private String jid;
private String contentValidatorClassName;
private Map<String, String> contentValidatorParams;
private String contentTransformerClassName;
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public int getTimeoutInterval() {
return timeoutInterval;
}
public String getResource() {
return resource;
}
public String getContentValidatorClassName() {
return contentValidatorClassName;
}
public Map<String, String> getContentValidatorParams() {
return contentValidatorParams;
}
public String getJid() {
return jid;
}
public String getContentTransformerClassName() {
return contentTransformerClassName;
}
public XMPPServerConnectionConfiguration(String host, int port, String username, String password,
int timeoutInterval, String resource, String contentValidatorClassName,
Map<String, String> contentValidatorParams, String jid,
String contentTransformerClassName) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.timeoutInterval = timeoutInterval;
this.resource = resource;
this.contentValidatorClassName = contentValidatorClassName;
if (contentValidatorParams != null) {
this.contentValidatorParams = contentValidatorParams;
}
this.contentTransformerClassName = contentTransformerClassName;
this.jid = jid;
}
}

@ -0,0 +1,38 @@
#
# 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.
#
host=Server Url
host.hint=XMPP Server url
port=Server Port
port.hint=Server Port Number
username=Username
username.hint=Username of the broker
password=Password
password.hint=Password to connect to the server.
timeoutInterval=Time out Interval
timeoutInterval.hint=used by listeners to the server and for reconnection schedules.
resource=Resource
resource.hint=specific to the XMPP-Account to which the login is made to.
contentValidation=contentValidation
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentValidationParams=contentValidationParams
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
jid=jid
jid.hint=JID - XMPP Account Name.
contentTransformer=contentTransformer
contentTransformer.hint=Class Name of the content transformer or 'default' to set default class, required to implement (if required)

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iot-base-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.output.adapter.mqtt</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Output MQTT Adaptor Module</name>
<description>org.wso2.carbon.device.mgt.iot.output.adapter.mqtt provides the back-end functionality of mqtt adaptor
</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.wso2</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal,
org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal.*
</Private-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal,
!org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal.*,
org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.*,
</Export-Package>
<Import-Package>
org.wso2.carbon.event.output.adapter.core,
org.wso2.carbon.event.output.adapter.core.*,
javax.net.ssl,
org.apache.commons.logging,
org.apache.http,
org.apache.http.client,
org.apache.http.client.methods,
org.apache.http.conn.socket,
org.apache.http.conn.ssl,
org.apache.http.entity,
org.apache.http.impl.client,
org.apache.http.util,
org.eclipse.paho.client.mqttv3,
org.eclipse.paho.client.mqttv3.persist,
org.json.simple,
org.json.simple.parser,
org.osgi.framework,
org.osgi.service.component,
org.wso2.carbon.context,
org.wso2.carbon.identity.jwt.client.extension.*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,204 @@
/*
* 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.device.mgt.iot.output.adapter.mqtt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTAdapterPublisher;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTEventAdapterConstants;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTBrokerConnectionConfiguration;
import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Output MQTTEventAdapter will be used to publish events with MQTT protocol to specified broker and topic.
*/
public class MQTTEventAdapter implements OutputEventAdapter {
private OutputEventAdapterConfiguration eventAdapterConfiguration;
private Map<String, String> globalProperties;
private MQTTAdapterPublisher mqttAdapterPublisher;
private int connectionKeepAliveInterval;
private String qos;
private static ThreadPoolExecutor threadPoolExecutor;
private static final Log log = LogFactory.getLog(MQTTEventAdapter.class);
private int tenantId;
public MQTTEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
Object keeAliveInternal = globalProperties.get(MQTTEventAdapterConstants.CONNECTION_KEEP_ALIVE_INTERVAL);
if (keeAliveInternal != null) {
try {
connectionKeepAliveInterval = Integer.parseInt(keeAliveInternal.toString());
} catch (NumberFormatException e) {
log.error("Error when configuring user specified connection keep alive time, using default value", e);
connectionKeepAliveInterval = MQTTEventAdapterConstants.DEFAULT_CONNECTION_KEEP_ALIVE_INTERVAL;
}
} else {
connectionKeepAliveInterval = MQTTEventAdapterConstants.DEFAULT_CONNECTION_KEEP_ALIVE_INTERVAL;
}
}
@Override
public void init() throws OutputEventAdapterException {
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
//ThreadPoolExecutor will be assigned if it is null
if (threadPoolExecutor == null) {
int minThread;
int maxThread;
int jobQueSize;
long defaultKeepAliveTime;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
minThread = Integer.parseInt(globalProperties.get(
MQTTEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
} else {
minThread = MQTTEventAdapterConstants.DEFAULT_MIN_THREAD_POOL_SIZE;
}
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
maxThread = Integer.parseInt(globalProperties.get(
MQTTEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
} else {
maxThread = MQTTEventAdapterConstants.DEFAULT_MAX_THREAD_POOL_SIZE;
}
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
defaultKeepAliveTime = Integer.parseInt(globalProperties.get(
MQTTEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
} else {
defaultKeepAliveTime = MQTTEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS;
}
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
jobQueSize = Integer.parseInt(globalProperties.get(
MQTTEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
} else {
jobQueSize = MQTTEventAdapterConstants.DEFAULT_EXECUTOR_JOB_QUEUE_SIZE;
}
threadPoolExecutor = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(
jobQueSize));
}
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("Test connection is not available");
}
@Override
public void connect() {
MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration =
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
connectionKeepAliveInterval,
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION)
);
String clientId = eventAdapterConfiguration.getStaticProperties().get(
MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
qos = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);
mqttAdapterPublisher = new MQTTAdapterPublisher(mqttBrokerConnectionConfiguration, clientId);
}
@Override
public void publish(Object message, Map<String, String> dynamicProperties) {
String topic = dynamicProperties.get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
try {
threadPoolExecutor.submit(new MQTTSender(topic, message));
} catch (RejectedExecutionException e) {
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, "Job queue is full", e, log,
tenantId);
}
}
@Override
public void disconnect() {
try {
if (mqttAdapterPublisher != null) {
mqttAdapterPublisher.close();
mqttAdapterPublisher = null;
}
} catch (OutputEventAdapterException e) {
log.error("Exception when closing the mqtt publisher connection on Output MQTT Adapter '" +
eventAdapterConfiguration.getName() + "'", e);
}
}
@Override
public void destroy() {
//not required
}
@Override
public boolean isPolled() {
return false;
}
class MQTTSender implements Runnable {
String topic;
Object message;
MQTTSender(String topic, Object message) {
this.topic = topic;
this.message = message;
}
@Override
public void run() {
try {
if (!mqttAdapterPublisher.isConnected()) {
synchronized (MQTTEventAdapter.class) {
if (!mqttAdapterPublisher.isConnected()) {
mqttAdapterPublisher.connect();
}
}
}
if (qos == null || qos.trim().isEmpty()) {
mqttAdapterPublisher.publish(message.toString(), topic);
} else {
mqttAdapterPublisher.publish(Integer.parseInt(qos), message.toString(), topic);
}
} catch (Throwable t) {
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, null, t, log, tenantId);
}
}
}
}

@ -0,0 +1,126 @@
/*
* 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.device.mgt.iot.output.adapter.mqtt;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTEventAdapterConstants;
import org.wso2.carbon.event.output.adapter.core.*;
import java.util.*;
/**
* The mqtt event adapter factory class to create a mqtt output adapter
*/
public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
private ResourceBundle resourceBundle =
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.i18n.Resources", Locale.getDefault());
@Override
public String getType() {
return MQTTEventAdapterConstants.ADAPTER_TYPE_MQTT;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportedMessageFormats = new ArrayList<String>();
supportedMessageFormats.add(MessageType.XML);
supportedMessageFormats.add(MessageType.JSON);
supportedMessageFormats.add(MessageType.TEXT);
return supportedMessageFormats;
}
@Override
public List<Property> getStaticPropertyList() {
List<Property> staticPropertyList = new ArrayList<Property>();
//Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
brokerUrl.setRequired(true);
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
//Broker Username
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(true);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
//Broker dcr URL
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
dcrUrl.setRequired(true);
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
//Broker Connection Scopes
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
scopes.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES));
scopes.setRequired(true);
scopes.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES_HINT));
// set clientId
Property clientId = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
clientId.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID));
clientId.setRequired(false);
clientId.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID_HINT));
staticPropertyList.add(clientId);
//Broker clear session
Property clearSession = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION);
clearSession.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
clearSession.setRequired(false);
clearSession.setOptions(new String[]{"true", "false"});
clearSession.setDefaultValue("true");
clearSession.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION_HINT));
// set Quality of Service
Property qos = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);
qos.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS));
qos.setRequired(true);
qos.setOptions(new String[]{"0", "1", "2"});
qos.setDefaultValue("1");
staticPropertyList.add(brokerUrl);
staticPropertyList.add(userName);
staticPropertyList.add(dcrUrl);
staticPropertyList.add(scopes);
staticPropertyList.add(clearSession);
staticPropertyList.add(qos);
return staticPropertyList;
}
@Override
public List<Property> getDynamicPropertyList() {
List<Property> dynamicPropertyList = new ArrayList<Property>();
// set topic
Property topicProperty = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
topicProperty.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC));
topicProperty.setRequired(true);
dynamicPropertyList.add(topicProperty);
return dynamicPropertyList;
}
@Override
public String getUsageTips() {
return null;
}
@Override
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new MQTTEventAdapter(eventAdapterConfiguration, globalProperties);
}
}

@ -0,0 +1,51 @@
/*
* 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.device.mgt.iot.output.adapter.mqtt.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.MQTTEventAdapterFactory;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;
/**
* @scr.component component.name="output.Mqtt.AdapterService.component" immediate="true"
*/
public class MQTTEventAdapterServiceComponent {
private static final Log log = LogFactory.getLog(MQTTEventAdapterServiceComponent.class);
/**
* Deployment of the MQTT event adapter service will be done.
* @param context bundle context where service is registered
*/
protected void activate(ComponentContext context) {
try {
OutputEventAdapterFactory mqttEventAdapterFactory = new MQTTEventAdapterFactory();
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(),
mqttEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("The MQTT publisher service has been deployed successfully");
}
} catch (RuntimeException e) {
log.error("Exception occurred when deploying MQTT publisher service", e);
}
}
}

@ -0,0 +1,186 @@
/*
* 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.device.mgt.iot.output.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.output.adapter.core.exception.ConnectionUnavailableException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
/**
* MQTT publisher related configuration initialization and publishing capabilties are implemented here.
*/
public class MQTTAdapterPublisher {
private static final Log log = LogFactory.getLog(MQTTAdapterPublisher.class);
private MqttClient mqttClient;
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
String clientId;
public MQTTAdapterPublisher(MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration, String clientId) {
if (clientId == null || clientId.trim().isEmpty()) {
this.clientId = MqttClient.generateClientId();
}
this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
connect();
}
public void connect() {
if (clientId == null || clientId.trim().isEmpty()) {
clientId = MqttClient.generateClientId();
}
boolean cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
int keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
String temp_directory = System.getProperty(MQTTEventAdapterConstants.ADAPTER_TEMP_DIRECTORY_NAME);
MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(temp_directory);
try {
MqttConnectOptions connectionOptions = new MqttConnectOptions();
connectionOptions.setCleanSession(cleanSession);
connectionOptions.setKeepAliveInterval(keepAlive);
if (mqttBrokerConnectionConfiguration.getBrokerUsername() != null) {
connectionOptions.setUserName(getToken(mqttBrokerConnectionConfiguration.getBrokerUsername(),
mqttBrokerConnectionConfiguration.getDcrUrl(),
mqttBrokerConnectionConfiguration.getScopes()));
connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray());
}
// Construct an MQTT blocking mode client
mqttClient = new MqttClient(mqttBrokerConnectionConfiguration.getBrokerUrl(), clientId, dataStore);
mqttClient.connect(connectionOptions);
} catch (MqttException e) {
log.error("Error occurred when constructing MQTT client for broker url : "
+ mqttBrokerConnectionConfiguration.getBrokerUrl(), e);
handleException(e);
}
}
public boolean isConnected() {
return mqttClient.isConnected();
}
public void publish(int qos, String payload, String topic) {
try {
// Create and configure a message
MqttMessage message = new MqttMessage(payload.getBytes());
message.setQos(qos);
mqttClient.publish(topic, message);
} catch (MqttException e) {
log.error("Error occurred when publishing message for MQTT server : " + mqttClient.getServerURI(), e);
handleException(e);
}
}
public void publish(String payload, String topic) {
try {
// Create and configure a message
MqttMessage message = new MqttMessage(payload.getBytes());
mqttClient.publish(topic, message);
} catch (MqttException e) {
log.error("Error occurred when publishing message for MQTT server : " + mqttClient.getServerURI(), e);
handleException(e);
}
}
public void close() throws OutputEventAdapterException {
try {
mqttClient.disconnect(1000);
mqttClient.close();
} catch (MqttException e) {
throw new OutputEventAdapterException(e);
}
}
private void handleException(MqttException e) {
//Check for Client not connected exception code and throw ConnectionUnavailableException
if (e.getReasonCode() == 32104) {
throw new ConnectionUnavailableException(e);
} else {
throw new OutputEventAdapterRuntimeException(e);
}
}
private String getToken(String username, String dcrUrlString, String scopes) {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
try {
URL dcrUrl = new URL(dcrUrlString);
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
HttpPost postMethod = new HttpPost(dcrUrlString);
RegistrationProfile registrationProfile = new RegistrationProfile();
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.DEFAULT_CALLBACK);
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
registrationProfile.setClientName(username + "_" + tenantId);
String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity);
HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse);
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
clientId, clientSecret, username, scopes);
return accessTokenInfo.getAccessToken();
} catch (ParseException e) {
String msg = "error occurred while parsing client credential payload";
throw new OutputEventAdapterRuntimeException(msg, e);
} catch (JWTClientException e) {
String msg = "error occurred while parsing the response from JWT Client";
throw new OutputEventAdapterRuntimeException(msg, e);
}
} catch (MalformedURLException e) {
throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
throw new OutputEventAdapterRuntimeException("Failed to create an https connection.", e);
}
}
throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher");
}
}

@ -0,0 +1,65 @@
/*
* 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.device.mgt.iot.output.adapter.mqtt.util;
public class MQTTBrokerConnectionConfiguration {
private String brokerUsername;
private String dcrUrl;
private String scopes;
private String brokerUrl;
private boolean cleanSession = true;
private int keepAlive;
public String getDcrUrl() {
return dcrUrl;
}
public String getScopes() {
return scopes;
}
public String getBrokerUsername() {
return brokerUsername;
}
public boolean isCleanSession() {
return cleanSession;
}
public String getBrokerUrl() {
return brokerUrl;
}
public int getKeepAlive() {
return keepAlive;
}
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername,
String dcrUrl, String scopes, int keepAlive, String cleanSession) {
this.brokerUsername = brokerUsername;
this.dcrUrl = dcrUrl;
this.scopes = scopes;
this.brokerUrl = brokerUrl;
this.keepAlive = keepAlive;
if (cleanSession != null) {
this.cleanSession = Boolean.parseBoolean(cleanSession);
}
}
}

@ -0,0 +1,61 @@
/*
* 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.device.mgt.iot.output.adapter.mqtt.util;
public final class MQTTEventAdapterConstants {
private MQTTEventAdapterConstants() {
}
public static final String ADAPTER_TYPE_MQTT = "oauth-mqtt";
public static final String ADAPTER_CONF_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
public static final String ADAPTER_CONF_SCOPES = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
public static final String ADAPTER_MESSAGE_TOPIC = "topic";
public static final String ADAPTER_MESSAGE_QOS = "qos";
public static final String ADAPTER_CONF_CLEAN_SESSION = "cleanSession";
public static final String ADAPTER_CONF_CLEAN_SESSION_HINT = "cleanSession.hint";
public static final String CONNECTION_KEEP_ALIVE_INTERVAL = "connectionKeepAliveInterval";
public static final int DEFAULT_CONNECTION_KEEP_ALIVE_INTERVAL = 60;
public static final String ADAPTER_TEMP_DIRECTORY_NAME = "java.io.tmpdir";
public static final String ADAPTER_CONF_CLIENTID = "clientId";
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
public static final int DEFAULT_MIN_THREAD_POOL_SIZE = 8;
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100;
public static final int DEFAULT_EXECUTOR_JOB_QUEUE_SIZE = 2000;
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS = 20000;
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
public static final String DEFAULT_CALLBACK = "";
public static final String DEFAULT_PASSWORD = "";
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
public static final String TOKEN_SCOPE = "production";
public static final String APPLICATION_TYPE = "device";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
}

@ -0,0 +1,99 @@
/*
* Copyright (c) 2016, 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.device.mgt.iot.output.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
/**
* This is the utility class that is used for MQTT input adapter.
*/
public class MQTTUtil {
private static final String HTTPS_PROTOCOL = "https";
private static final Log log = LogFactory.getLog(MQTTUtil.class);
/**
* Return a http client instance
* @param protocol- service endpoint protocol http/https
* @return
*/
public static HttpClient getHttpClient(String protocol)
throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpClient httpclient;
if (HTTPS_PROTOCOL.equals(protocol)) {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
} else {
httpclient = HttpClients.createDefault();
}
return httpclient;
}
public static String getResponseString(HttpResponse httpResponse) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String readLine;
String response = "";
while (((readLine = br.readLine()) != null)) {
response += readLine;
}
return response;
} finally {
EntityUtils.consumeQuietly(httpResponse.getEntity());
if (br != null) {
try {
br.close();
} catch (IOException e) {
log.warn("Error while closing the connection! " + e.getMessage());
}
}
}
}
public static JWTClientManagerService getJWTClientManagerService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService =
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
if (jwtClientManagerService == null) {
String msg = "JWT management service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return jwtClientManagerService;
}
}

@ -0,0 +1,73 @@
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
private String callbackUrl;
private String clientName;
private String tokenScope;
private String owner;
private String grantType;
private String applicationType;
private static final String TAG = RegistrationProfile.class.getSimpleName();
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
public String toJSON() {
String jsonString =
"{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName + "\", \"tokenScope\": " +
"\"" + tokenScope + "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
"\", \"saasApp\" :false }\n";
return jsonString;
}
}

@ -0,0 +1,33 @@
#
# 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.
#
topic=Topic
url=Broker Url
username=Username
username.hint=Username of the broker
dcrUrl=dcrUrl
dcrUrl.hint=Dynamic Client Registration Url
scopes=scopes
scopes.hint=Scopes that required to connect with the broker.
url.hint=MQTT broker url
cleanSession=Clean Session
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
keepAlive=Keep Alive (In seconds)
qos=Quality of Service
clientId=Client Id
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iot-base-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.output.adapter.xmpp</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Output MQTT Adaptor Module</name>
<description>org.wso2.carbon.device.mgt.iot.output.adapter.xmpp provides the back-end functionality of xmpp adaptor
</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal,
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal.*
</Private-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal,
!org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal.*,
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.*,
</Export-Package>
<Import-Package>
org.wso2.carbon.event.output.adapter.core,
org.wso2.carbon.event.output.adapter.core.*,
org.jivesoftware.smack.*,
org.apache.commons.logging,
org.osgi.framework,
org.osgi.service.component,
org.wso2.carbon.context
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,200 @@
/*
* 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.device.mgt.iot.output.adapter.xmpp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPEventAdapterConstants;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPAdapterPublisher;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPServerConnectionConfiguration;
import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Output XMPPEventAdapter will be used to publish events with MQTT protocol to specified broker and topic.
*/
public class XMPPEventAdapter implements OutputEventAdapter {
private OutputEventAdapterConfiguration eventAdapterConfiguration;
private Map<String, String> globalProperties;
private XMPPAdapterPublisher xmppAdapterPublisher;
private static ThreadPoolExecutor threadPoolExecutor;
private static final Log log = LogFactory.getLog(XMPPEventAdapter.class);
private int tenantId;
public XMPPEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init() throws OutputEventAdapterException {
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
//ThreadPoolExecutor will be assigned if it is null
if (threadPoolExecutor == null) {
int minThread;
int maxThread;
int jobQueSize;
long defaultKeepAliveTime;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
minThread = Integer.parseInt(globalProperties.get(
XMPPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
} else {
minThread = XMPPEventAdapterConstants.DEFAULT_MIN_THREAD_POOL_SIZE;
}
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
maxThread = Integer.parseInt(globalProperties.get(
XMPPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
} else {
maxThread = XMPPEventAdapterConstants.DEFAULT_MAX_THREAD_POOL_SIZE;
}
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
defaultKeepAliveTime = Integer.parseInt(globalProperties.get(
XMPPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
} else {
defaultKeepAliveTime = XMPPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS;
}
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
jobQueSize = Integer.parseInt(globalProperties.get(
XMPPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
} else {
jobQueSize = XMPPEventAdapterConstants.DEFAULT_EXECUTOR_JOB_QUEUE_SIZE;
}
threadPoolExecutor = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(
jobQueSize));
}
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("Test connection is not available");
}
@Override
public void connect() {
int xmppPort = XMPPEventAdapterConstants.DEFAULT_XMPP_PORT;
String xmppPortString = eventAdapterConfiguration.getStaticProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
if (xmppPortString != null && !xmppPortString.trim().isEmpty()) {
xmppPort = Integer.parseInt(xmppPortString);
}
int timeoutInterval = XMPPEventAdapterConstants.DEFAULT_TIMEOUT_INTERVAL;
String timeoutIntervalString = eventAdapterConfiguration.getStaticProperties().get(
XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
if (timeoutIntervalString != null && !timeoutIntervalString.trim().isEmpty()) {
timeoutInterval = Integer.parseInt(timeoutIntervalString);
}
XMPPServerConnectionConfiguration xmppServerConnectionConfiguration =
new XMPPServerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_HOST),
xmppPort,
eventAdapterConfiguration.getStaticProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME),
eventAdapterConfiguration.getStaticProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD),
timeoutInterval,
eventAdapterConfiguration.getStaticProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE)
);
xmppAdapterPublisher = new XMPPAdapterPublisher(xmppServerConnectionConfiguration);
}
@Override
public void publish(Object message, Map<String, String> dynamicProperties) {
String jid = dynamicProperties.get(XMPPEventAdapterConstants.ADAPTER_CONF_JID);
String subject = dynamicProperties.get(XMPPEventAdapterConstants.ADAPTER_CONF_SUBJECT);
String messageType = dynamicProperties.get(XMPPEventAdapterConstants.ADAPTER_CONF_MESSAGETYPE);
try {
threadPoolExecutor.submit(new XMPPSender(jid, subject, (String)message, messageType));
} catch (RejectedExecutionException e) {
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, "Job queue is full", e, log,
tenantId);
}
}
@Override
public void disconnect() {
try {
if (xmppAdapterPublisher != null) {
xmppAdapterPublisher.close();
xmppAdapterPublisher = null;
}
} catch (OutputEventAdapterException e) {
log.error("Exception when closing the mqtt publisher connection on Output MQTT Adapter '" +
eventAdapterConfiguration.getName() + "'", e);
}
}
@Override
public void destroy() {
//not required
}
@Override
public boolean isPolled() {
return false;
}
class XMPPSender implements Runnable {
String jid;
String subject;
String message;
String messageType;
XMPPSender(String jid, String subject, String message, String messageType) {
this.jid = jid;
this.message = message;
this.subject = subject;
this.messageType = messageType;
}
@Override
public void run() {
try {
if (!xmppAdapterPublisher.isConnected()) {
synchronized (XMPPEventAdapter.class) {
if (!xmppAdapterPublisher.isConnected()) {
xmppAdapterPublisher.connect();
}
}
}
xmppAdapterPublisher.publish(jid, subject, message, messageType);
} catch (Throwable t) {
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, null, t, log, tenantId);
}
}
}
}

@ -0,0 +1,132 @@
/*
* 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.device.mgt.iot.output.adapter.xmpp;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPEventAdapterConstants;
import org.wso2.carbon.event.output.adapter.core.*;
import java.util.*;
/**
* The xmpp event adapter factory class to create a xmpp output adapter
*/
public class XMPPEventAdapterFactory extends OutputEventAdapterFactory {
private ResourceBundle resourceBundle =
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.Resources", Locale.getDefault());
@Override
public String getType() {
return XMPPEventAdapterConstants.ADAPTER_TYPE_XMPP;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportedMessageFormats = new ArrayList<String>();
supportedMessageFormats.add(MessageType.XML);
supportedMessageFormats.add(MessageType.JSON);
supportedMessageFormats.add(MessageType.TEXT);
return supportedMessageFormats;
}
@Override
public List<Property> getStaticPropertyList() {
List<Property> staticPropertyList = new ArrayList<Property>();
// Url
Property host = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_HOST);
host.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST));
host.setRequired(true);
host.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST_HINT));
// Host Port
Property port = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
port.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT));
port.setRequired(true);
port.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT_HINT));
//Broker Username
Property userName = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(true);
userName.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
//Broker Password
Property password = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD);
password.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD));
password.setRequired(true);
password.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
//Timeout Interval
Property timooutInterval = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
timooutInterval.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
timooutInterval.setRequired(false);
timooutInterval.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
//Resource
Property resource = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE);
resource.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE));
resource.setRequired(false);
resource.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE_HINT));
staticPropertyList.add(host);
staticPropertyList.add(port);
staticPropertyList.add(userName);
staticPropertyList.add(password);
staticPropertyList.add(timooutInterval);
staticPropertyList.add(resource);
return staticPropertyList;
}
@Override
public List<Property> getDynamicPropertyList() {
List<Property> dynamicPropertyList = new ArrayList<Property>();
// set topic
Property jidProperty = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_JID);
jidProperty.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_JID_HINT));
jidProperty.setRequired(true);
Property subjectProperty = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_SUBJECT);
subjectProperty.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_SUBJECT_HINT));
subjectProperty.setRequired(false);
Property messageType = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_MESSAGETYPE);
messageType.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_MESSAGETYPE_HINT));
messageType.setRequired(true);
messageType.setOptions(
new String[]{XMPPEventAdapterConstants.MessageType.CHAT, XMPPEventAdapterConstants.MessageType.ERROR,
XMPPEventAdapterConstants.MessageType.GROUP_CHAT, XMPPEventAdapterConstants.MessageType.NORMAL,
XMPPEventAdapterConstants.MessageType.HEADLINE});
messageType.setDefaultValue(XMPPEventAdapterConstants.MessageType.NORMAL);
dynamicPropertyList.add(jidProperty);
dynamicPropertyList.add(subjectProperty);
dynamicPropertyList.add(messageType);
return dynamicPropertyList;
}
@Override
public String getUsageTips() {
return null;
}
@Override
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new XMPPEventAdapter(eventAdapterConfiguration, globalProperties);
}
}

@ -0,0 +1,51 @@
/*
* 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.device.mgt.iot.output.adapter.xmpp.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.XMPPEventAdapterFactory;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;
/**
* @scr.component component.name="output.XMPP.AdapterService.component" immediate="true"
*/
public class XMPPEventAdapterServiceComponent {
private static final Log log = LogFactory.getLog(XMPPEventAdapterServiceComponent.class);
/**
* Deployment of the XMPP event adapter service will be done.
* @param context bundle context where service is registered
*/
protected void activate(ComponentContext context) {
try {
OutputEventAdapterFactory xmppEventAdapterFactory = new XMPPEventAdapterFactory();
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(),
xmppEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("The XMPP publisher service has been deployed successfully");
}
} catch (RuntimeException e) {
log.error("Exception occurred when deploying XMPP publisher service", e);
}
}
}

@ -0,0 +1,106 @@
/*
* 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.device.mgt.iot.output.adapter.xmpp.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException;
/**
* XMPP publisher related configuration initialization and publishing capabilties are implemented here.
*/
public class XMPPAdapterPublisher {
private static final Log log = LogFactory.getLog(XMPPAdapterPublisher.class);
private XMPPServerConnectionConfiguration xmppServerConnectionConfiguration;
XMPPConnection xmppConnection;
public XMPPAdapterPublisher(XMPPServerConnectionConfiguration xmppServerConnectionConfiguration) {
this.xmppServerConnectionConfiguration = xmppServerConnectionConfiguration;
connect();
}
public void connect() {
SmackConfiguration.setPacketReplyTimeout(xmppServerConnectionConfiguration.getTimeoutInterval());
ConnectionConfiguration config = new ConnectionConfiguration(xmppServerConnectionConfiguration.getHost(),
xmppServerConnectionConfiguration.getPort());
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
xmppConnection = new XMPPConnection(config);
String resource = xmppServerConnectionConfiguration.getResource();
String username = xmppServerConnectionConfiguration.getUsername();
String password = xmppServerConnectionConfiguration.getPassword();
try {
xmppConnection.connect();
if (resource == null || resource.trim().isEmpty()) {
xmppConnection.login(username, password);
} else {
xmppConnection.login(username, password, resource);
}
} catch (XMPPException e) {
String errorMsg = "Login attempt to the XMPP Server with username - " + username + " failed.";
log.info(errorMsg);
throw new OutputEventAdapterRuntimeException(errorMsg, e);
}
}
public boolean isConnected() {
return xmppConnection.isConnected();
}
public void publish(String JID, String subject, String message, String messageType) {
Message xmppMessage = new Message();
xmppMessage.setTo(JID);
xmppMessage.setSubject(subject);
xmppMessage.setBody(message);
if (messageType != null) {
switch (messageType) {
case XMPPEventAdapterConstants.MessageType.CHAT:
xmppMessage.setType(Message.Type.chat);
break;
case XMPPEventAdapterConstants.MessageType.GROUP_CHAT:
xmppMessage.setType(Message.Type.groupchat);
break;
case XMPPEventAdapterConstants.MessageType.ERROR:
xmppMessage.setType(Message.Type.error);
break;
case XMPPEventAdapterConstants.MessageType.HEADLINE:
xmppMessage.setType(Message.Type.headline);
break;
default:
xmppMessage.setType(Message.Type.normal);
}
} else {
xmppMessage.setType(Message.Type.normal);
}
xmppConnection.sendPacket(xmppMessage);
}
public void close() throws OutputEventAdapterException {
if (xmppConnection != null && isConnected()) {
xmppConnection.disconnect();
}
}
}

@ -0,0 +1,71 @@
/*
* 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.device.mgt.iot.output.adapter.xmpp.util;
public final class XMPPEventAdapterConstants {
private XMPPEventAdapterConstants() {
}
public static final String ADAPTER_TYPE_XMPP = "xmpp";
//dynamic properties
public static final String ADAPTER_CONF_JID = "jid";
public static final String ADAPTER_CONF_JID_HINT = "jid.hint";
public static final String ADAPTER_CONF_SUBJECT = "subject";
public static final String ADAPTER_CONF_SUBJECT_HINT = "subject.hint";
public static final String ADAPTER_CONF_MESSAGETYPE = "messageType";
public static final String ADAPTER_CONF_MESSAGETYPE_HINT = "messageType.hint";
//static properties
public static final String ADAPTER_CONF_HOST = "host";
public static final String ADAPTER_CONF_HOST_HINT = "host.hint";
public static final String ADAPTER_CONF_PORT = "port";
public static final String ADAPTER_CONF_PORT_HINT = "port.hint";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_PASSWORD = "password";
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
public static final String ADAPTER_CONF_RESOURCE = "resource";
public static final String ADAPTER_CONF_RESOURCE_HINT = "resource.hint";
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL = "timeoutInterval";
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL_HINT = "timeoutInterval.hint";
public static final int DEFAULT_XMPP_PORT = 5222;
public static final int DEFAULT_TIMEOUT_INTERVAL = 5000;
//global properties
public static final int DEFAULT_MIN_THREAD_POOL_SIZE = 8;
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100;
public static final int DEFAULT_EXECUTOR_JOB_QUEUE_SIZE = 2000;
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS = 20000;
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
public static final class MessageType {
public static final String NORMAL = "normal";
public static final String CHAT = "chat";
public static final String GROUP_CHAT = "groupchat";
public static final String HEADLINE = "headline";
public static final String ERROR = "error";
}
}

@ -0,0 +1,63 @@
/*
* 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.device.mgt.iot.output.adapter.xmpp.util;
public class XMPPServerConnectionConfiguration {
private String host;
private int port;
private String username;
private String password;
private int timeoutInterval;
private String resource;
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public int getTimeoutInterval() {
return timeoutInterval;
}
public String getResource() {
return resource;
}
public XMPPServerConnectionConfiguration(String host, int port, String username, String password,
int timeoutInterval, String resource) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.timeoutInterval = timeoutInterval;
this.resource = resource;
}
}

@ -0,0 +1,36 @@
#
# 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.
#
host=Server Url
host.hint=XMPP Server url
port=Server Port
port.hint=Server Port Number
username=Username
username.hint=Username of the broker
password=Password
password.hint=Password to connect to the server.
timeoutInterval=Time out Interval
timeoutInterval.hint=used by listeners to the server and for reconnection schedules.
resource=Resource
resource.hint=specific to the XMPP-Account to which the login is made to.
jid=JID
jid.hint=the JID (XMPP Account ID) to which the message is to be sent to.
subject=Subject
subject.hint=Subject of the message.
messageType=Message Type
messageType.hint=Type of the XMPP Message (chat, groupchat, error, headline, normal)

@ -1,5 +1,5 @@
{
"version": "1.0.0",
"index": 29,
"extends": "mdm.unit.ui.header.logo"
"extends": "cdmf.unit.ui.header.logo"
}

@ -63,28 +63,15 @@
<Bundle-Description>IoT Server Impl Bundle</Bundle-Description>
<Private-Package>org.wso2.carbon.device.mgt.iot.internal</Private-Package>
<Import-Package>
org.jivesoftware.smack.*,
javax.xml.namespace;resolution:=optional,
javax.xml.validation;resolution:=optional,
org.apache.commons.codec.binary,
org.apache.http.*,
org.apache.commons.io.*,
org.apache.commons.logging.*,
org.json;version="${commons-json.version}",
org.wso2.carbon.base.*,
org.osgi.framework,
org.osgi.service.component,
javax.xml.bind.*;resolution:=optional,
javax.xml.parsers.*;resolution:=optional,
javax.crypto,
org.apache.tomcat.util.codec.binary,
org.w3c.dom;resolution:=optional,
org.wso2.carbon.core;version="${carbon.kernel.version.range}",
org.wso2.carbon.utils.*;version="${carbon.kernel.version.range}",
org.wso2.carbon.device.mgt.common.*,
org.eclipse.paho.client.mqttv3.*;version="${eclipse.paho.version}",
javax.xml;resolution:=optional,
javax.net.ssl;resolution:=optional
org.apache.axis2.context,
org.apache.commons.io,
org.apache.commons.logging,
org.wso2.carbon.core,
org.wso2.carbon.device.mgt.common,
org.wso2.carbon.utils
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.internal,

@ -1,118 +0,0 @@
/*
* 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.device.mgt.iot.config.server;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.device.mgt.iot.config.server.datasource.ControlQueue;
import org.wso2.carbon.device.mgt.iot.config.server.datasource.DeviceManagementConfiguration;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.util.IotDeviceManagementUtil;
import org.wso2.carbon.utils.CarbonUtils;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.File;
import java.util.List;
/**
* Class responsible for the iot device manager configuration initialization.
*/
public class DeviceManagementConfigurationManager {
private static final Log log = LogFactory.getLog(DeviceManagementConfigurationManager.class);
private static final String DEVICE_MGT_CONFIG_XML_NAME = "devicemgt-config.xml";
private static final String DEVICE_MGT_ROOT_DIRECTORY = "iot";
private final String XMLCONFIGS_FILE_LOCATION =
CarbonUtils.getCarbonConfigDirPath() + File.separator +
DEVICE_MGT_ROOT_DIRECTORY + File.separator + DEVICE_MGT_CONFIG_XML_NAME;
private static final String IOT_DEVICE_CONFIG_XSD_NAME = "devicemgt-config.xsd";
private final String XSDCONFIGS_FILE_LOCATION =
CarbonUtils.getCarbonConfigDirPath() + File.separator +
DEVICE_MGT_ROOT_DIRECTORY + File.separator + IOT_DEVICE_CONFIG_XSD_NAME;
private DeviceManagementConfiguration currentDeviceManagementConfiguration;
private static DeviceManagementConfigurationManager deviceConfigurationManager =
new DeviceManagementConfigurationManager();
private DeviceManagementConfigurationManager() {
}
public static DeviceManagementConfigurationManager getInstance() {
return deviceConfigurationManager;
}
public void initConfig() throws DeviceControllerException {
try {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File(XSDCONFIGS_FILE_LOCATION));
File deviceCloudMgtConfig = new File(XMLCONFIGS_FILE_LOCATION);
Document doc = IotDeviceManagementUtil.convertToDocument(deviceCloudMgtConfig);
JAXBContext deviceCloudContext = JAXBContext.newInstance(DeviceManagementConfiguration.class);
Unmarshaller unmarshaller = deviceCloudContext.createUnmarshaller();
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(new IotConfigValidationEventHandler());
this.currentDeviceManagementConfiguration = (DeviceManagementConfiguration) unmarshaller.unmarshal(doc);
} catch (Exception e) {
String error = "Error occurred while initializing DeviceController configurations";
log.error(error);
throw new DeviceControllerException(error, e);
}
}
public DeviceManagementConfiguration getDeviceCloudMgtConfig() {
return currentDeviceManagementConfiguration;
}
public ControlQueue getControlQueue(String name) {
List<ControlQueue> controlQueues = currentDeviceManagementConfiguration.getControlQueues().getControlQueue();
if (controlQueues != null) {
for (ControlQueue controlQueue : controlQueues) {
if (controlQueue.getName().equals(name)) {
return controlQueue;
}
}
}
return null;
}
private class IotConfigValidationEventHandler implements ValidationEventHandler {
@Override
public boolean handleEvent(ValidationEvent event) {
String error = "\nEVENT" + "\nSEVERITY: " + event.getSeverity()
+ "\n MESSAGE: " + event.getMessage()
+ "\n LINKED EXCEPTION: " + event.getLinkedException()
+ "\n LOCATOR"
+ "\n LINE NUMBER: " + event.getLocator().getLineNumber()
+ "\n COLUMN NUMBER: " + event.getLocator().getColumnNumber()
+ "\n OFFSET: " + event.getLocator().getOffset()
+ "\n OBJECT: " + event.getLocator().getObject()
+ "\n NODE: " + event.getLocator().getNode()
+ "\n URL: " + event.getLocator().getURL();
log.error(error);
return true;
}
}
}

@ -1,229 +0,0 @@
/*
* 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.device.mgt.iot.config.server.datasource;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for ControlQueue complex type.
* <p/>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p/>
* <pre>
* &lt;complexType name="ControlQueue">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="Enabled" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
* &lt;element name="ControlClass" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="Protocol" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="ServerURL" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="Port" type="{http://www.w3.org/2001/XMLSchema}short"/>
* &lt;element name="Username" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="Password" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ControlQueue", propOrder = {
"name",
"enabled",
"controlClass",
"protocol",
"serverURL",
"port",
"username",
"password"
})
public class ControlQueue {
@XmlElement(name = "Name", required = true)
protected String name;
@XmlElement(name = "Enabled")
protected boolean enabled;
@XmlElement(name = "ControlClass", required = true)
protected String controlClass;
@XmlElement(name = "Protocol", required = true)
protected String protocol;
@XmlElement(name = "ServerURL", required = true)
protected String serverURL;
@XmlElement(name = "Port")
protected short port;
@XmlElement(name = "Username", required = true)
protected String username;
@XmlElement(name = "Password", required = true)
protected String password;
/**
* Gets the value of the name property.
*
* @return possible object is
* {@link String }
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value allowed object is
* {@link String }
*/
public void setName(String value) {
this.name = value;
}
/**
* Gets the value of the enabled property.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Sets the value of the enabled property.
*/
public void setEnabled(boolean value) {
this.enabled = value;
}
/**
* Gets the value of the controlClass property.
*
* @return possible object is
* {@link String }
*/
public String getControlClass() {
return controlClass;
}
/**
* Sets the value of the controlClass property.
*
* @param value allowed object is
* {@link String }
*/
public void setControlClass(String value) {
this.controlClass = value;
}
/**
* Gets the value of the protocol property.
*
* @return possible object is
* {@link String }
*/
public String getProtocol() {
return protocol;
}
/**
* Sets the value of the protocol property.
*
* @param value allowed object is
* {@link String }
*/
public void setProtocol(String value) {
this.protocol = value;
}
/**
* Gets the value of the serverURL property.
*
* @return possible object is
* {@link String }
*/
public String getServerURL() {
return serverURL;
}
/**
* Sets the value of the serverURL property.
*
* @param value allowed object is
* {@link String }
*/
public void setServerURL(String value) {
this.serverURL = value;
}
/**
* Gets the value of the port property.
*/
public short getPort() {
return port;
}
/**
* Sets the value of the port property.
*/
public void setPort(short value) {
this.port = value;
}
/**
* Gets the value of the username property.
*
* @return possible object is
* {@link String }
*/
public String getUsername() {
return username;
}
/**
* Sets the value of the username property.
*
* @param value allowed object is
* {@link String }
*/
public void setUsername(String value) {
this.username = value;
}
/**
* Gets the value of the password property.
*
* @return possible object is
* {@link String }
*/
public String getPassword() {
return password;
}
/**
* Sets the value of the password property.
*
* @param value allowed object is
* {@link String }
*/
public void setPassword(String value) {
this.password = value;
}
}

@ -1,82 +0,0 @@
/*
* 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.device.mgt.iot.config.server.datasource;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for ControlQueuesConfig complex type.
* <p/>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p/>
* <pre>
* &lt;complexType name="ControlQueuesConfig">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="ControlQueue" type="{}ControlQueue" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ControlQueuesConfig", propOrder = {
"controlQueue"
})
public class ControlQueuesConfig {
@XmlElement(name = "ControlQueue")
protected List<ControlQueue> controlQueue;
/**
* Gets the value of the controlQueue property.
* <p/>
* <p/>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the controlQueue property.
* <p/>
* <p/>
* For example, to add a new item, do as follows:
* <pre>
* getControlQueue().add(newItem);
* </pre>
* <p/>
* <p/>
* <p/>
* Objects of the following type(s) are allowed in the list
* {@link ControlQueue }
*/
public List<ControlQueue> getControlQueue() {
if (controlQueue == null) {
controlQueue = new ArrayList<ControlQueue>();
}
return this.controlQueue;
}
}

@ -1,74 +0,0 @@
/*
* 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.device.mgt.iot.config.server.datasource;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for DeviceCloudConfig complex type.
* <p/>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p/>
* <pre>
* &lt;complexType name="DeviceManagementConfigurations">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="ControlQueues" type="{}ControlQueuesConfig"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "DeviceManagementConfigurations", propOrder = {
"controlQueues"
})
@XmlRootElement(name = "DeviceManagementConfigurations")
public class DeviceManagementConfiguration {
@XmlElement(name = "ControlQueues", required = true)
protected ControlQueuesConfig controlQueues;
/**
* Gets the value of the controlQueues property.
*
* @return possible object is
* {@link ControlQueuesConfig }
*/
public ControlQueuesConfig getControlQueues() {
return controlQueues;
}
/**
* Sets the value of the controlQueues property.
*
* @param value allowed object is
* {@link ControlQueuesConfig }
*/
public void setControlQueues(ControlQueuesConfig value) {
this.controlQueues = value;
}
}

@ -1,69 +0,0 @@
/*
* 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.device.mgt.iot.config.server.datasource;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the org.wso2.carbon.device.mgt.iot.common.config.server.configs package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*/
@XmlRegistry
public class ObjectFactory {
private final static QName _DeviceCloudConfiguration_QNAME = new QName("", "DeviceManagementConfigurations");
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
* org.wso2.carbon.device.mgt.iot.common.config.server.configs
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link DeviceManagementConfiguration }
*/
public DeviceManagementConfiguration createDeviceCloudConfig() {
return new DeviceManagementConfiguration();
}
/**
* Create an instance of {@link JAXBElement }{@code <}{@link DeviceManagementConfiguration }{@code >}}
*/
@XmlElementDecl(namespace = "", name = "DeviceManagementConfigurations")
public JAXBElement<DeviceManagementConfiguration> createDeviceCloudConfiguration(
DeviceManagementConfiguration value) {
return new JAXBElement<DeviceManagementConfiguration>(_DeviceCloudConfiguration_QNAME,
DeviceManagementConfiguration.class, null, value);
}
}

@ -1,81 +0,0 @@
/*
* 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.device.mgt.iot.controlqueue.mqtt;
import org.wso2.carbon.device.mgt.iot.config.server.DeviceManagementConfigurationManager;
import org.wso2.carbon.device.mgt.iot.config.server.datasource.ControlQueue;
public class MqttConfig {
private String mqttQueueEndpoint;
private String mqttQueueUsername;
private String mqttQueuePassword;
private boolean isEnabled;
private static final String MQTT_QUEUE_CONFIG_NAME = "MQTT";
private static final String LOCALHOST = "localhost";
private static final String PORT_OFFSET_PROPERTY = "portOffset";
private ControlQueue mqttControlQueue;
private static MqttConfig mqttConfig = new MqttConfig();
public String getMqttQueueEndpoint() {
return mqttQueueEndpoint;
}
public String getMqttQueueUsername() {
return mqttQueueUsername;
}
public String getMqttQueuePassword() {
return mqttQueuePassword;
}
public ControlQueue getMqttControlQueue() {
return mqttControlQueue;
}
public boolean isEnabled() {
return isEnabled;
}
public static String getMqttQueueConfigName() {
return MQTT_QUEUE_CONFIG_NAME;
}
private MqttConfig() {
mqttControlQueue = DeviceManagementConfigurationManager.getInstance().getControlQueue(MQTT_QUEUE_CONFIG_NAME);
int portOffset = Integer.parseInt(System.getProperty(PORT_OFFSET_PROPERTY));
String brokerURL = mqttControlQueue.getServerURL();
if (portOffset != 0 && brokerURL.contains(LOCALHOST)) {
// if using the internal MB (meaning URL is localhost and there is a portOffset)
// then increment port accordingly
int mqttPort = mqttControlQueue.getPort();
mqttPort = mqttPort + portOffset;
mqttQueueEndpoint = mqttControlQueue.getServerURL() + ":" + mqttPort;
} else {
mqttQueueEndpoint = mqttControlQueue.getServerURL() + ":" + mqttControlQueue.getPort();
}
mqttQueueUsername = mqttControlQueue.getUsername();
mqttQueuePassword = mqttControlQueue.getPassword();
isEnabled = mqttControlQueue.isEnabled();
}
public static MqttConfig getInstance() {
return mqttConfig;
}
}

@ -1,93 +0,0 @@
/*
* 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.device.mgt.iot.controlqueue.xmpp;
import org.wso2.carbon.device.mgt.iot.config.server.DeviceManagementConfigurationManager;
import org.wso2.carbon.device.mgt.iot.config.server.datasource.ControlQueue;
public class XmppConfig {
private String xmppServerIP;
private int xmppServerPort;
private String xmppEndpoint;
private String xmppUsername;
private String xmppPassword;
private boolean isEnabled;
private static final String XMPP_QUEUE_CONFIG_NAME = "XMPP";
private final int SERVER_CONNECTION_PORT = 5222;
private ControlQueue xmppControlQueue;
private static XmppConfig xmppConfig = new XmppConfig();
public String getXmppServerIP() {
return xmppServerIP;
}
public int getXmppServerPort() {
return xmppServerPort;
}
public String getXmppEndpoint() {
return xmppEndpoint;
}
public String getXmppUsername() {
return xmppUsername;
}
public String getXmppPassword() {
return xmppPassword;
}
public ControlQueue getXmppControlQueue() {
return xmppControlQueue;
}
public boolean isEnabled() {
return isEnabled;
}
public static String getXmppQueueConfigName() {
return XMPP_QUEUE_CONFIG_NAME;
}
private XmppConfig() {
xmppControlQueue = DeviceManagementConfigurationManager.getInstance().getControlQueue(
XMPP_QUEUE_CONFIG_NAME);
xmppServerIP = xmppControlQueue.getServerURL();
int indexOfChar = xmppServerIP.lastIndexOf('/');
if (indexOfChar != -1) {
xmppServerIP = xmppServerIP.substring((indexOfChar + 1), xmppServerIP.length());
}
xmppServerPort = xmppControlQueue.getPort();
xmppEndpoint = xmppControlQueue.getServerURL() + ":" + xmppServerPort;
xmppUsername = xmppControlQueue.getUsername();
xmppPassword = xmppControlQueue.getPassword();
isEnabled = xmppControlQueue.isEnabled();
}
public static XmppConfig getInstance() {
return xmppConfig;
}
public int getSERVER_CONNECTION_PORT() {
return SERVER_CONNECTION_PORT;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save