diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/pom.xml b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/pom.xml
index d9cff3eee8..52489251bb 100644
--- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/pom.xml
+++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/pom.xml
@@ -179,6 +179,11 @@
org.wso2.carbon.apimgt.webapp.publisher
provided
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.api
+ provided
+
diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseControllerServiceImpl.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseControllerServiceImpl.java
index 3d0dfa7f30..312a9d9aa3 100644
--- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseControllerServiceImpl.java
+++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseControllerServiceImpl.java
@@ -20,26 +20,26 @@ package org.wso2.carbon.device.mgt.iot.androidsense.service.impl;
import org.apache.commons.logging.Log;
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.analytics.data.publisher.AnalyticsDataRecord;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
-import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DeviceManagementAnalyticsException;
-import org.wso2.carbon.device.mgt.analytics.data.publisher.service.DeviceAnalyticsService;
+import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
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.DeviceData;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorData;
+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.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager;
-import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord;
import org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
/**
@@ -100,8 +100,8 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response addSensorData(DeviceData dataMsg) {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
- DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
- .getOSGiService(DeviceAnalyticsService.class, null);
+ EventsPublisherService deviceAnalyticsService = (EventsPublisherService) ctx
+ .getOSGiService(EventsPublisherService.class, null);
SensorData[] sensorData = dataMsg.values;
String streamDef = null;
Object payloadData[] = null;
@@ -202,7 +202,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response getLightData(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_LIGHT);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -212,7 +212,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response getBattery(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_BATTERY);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -222,7 +222,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response getGPS(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_GPS);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -232,7 +232,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readMagnetic(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_MAGNETIC);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -242,7 +242,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readAccelerometer(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_ACCELEROMETER);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -252,7 +252,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readRotation(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_ROTATION);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -262,7 +262,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readProximity(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_PROXIMITY);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -272,7 +272,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readGyroscope(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_GYROSCOPE);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -282,7 +282,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readPressure(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_PRESSURE);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -292,7 +292,7 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response readGravity(String deviceId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_GRAVITY);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
@@ -302,8 +302,8 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
public Response getWords(String deviceId, String sessionId) {
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
- AndroidSenseConstants.SENSOR_WORDCOUNT);
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
+ AndroidSenseConstants.SENSOR_WORDCOUNT);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
@@ -344,55 +344,27 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
String fromDate = String.valueOf(from);
String toDate = String.valueOf(to);
String user = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
- List sensorDatas = new ArrayList<>();
- PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
- DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
- .getOSGiService(DeviceAnalyticsService.class, null);
String query = "owner:" + user + " AND deviceId:" + deviceId + " AND deviceType:" +
AndroidSenseConstants.DEVICE_TYPE + " AND time : [" + fromDate + " TO " + toDate + "]";
if (sensor.equals(AndroidSenseConstants.SENSOR_WORDCOUNT)) {
query = "owner:" + user + " AND deviceId:" + deviceId;
}
String sensorTableName = getSensorEventTableName(sensor);
+ List sensorDatas;
try {
- List records = deviceAnalyticsService.getAllEventsForDevice(sensorTableName, query);
if (sensor.equals(AndroidSenseConstants.SENSOR_WORDCOUNT)) {
- for (AnalyticsDataRecord record : records) {
- SensorData sensorData = new SensorData();
- sensorData.setKey((String) record.getValue("word"));
- sensorData.setTime((long) record.getValue("occurence"));
- sensorData.setValue((String) record.getValue("sessionId"));
- sensorDatas.add(sensorData);
- }
+ List sortByFields = new ArrayList<>();
+ SortByField sortByField = new SortByField("time", SORT.ASC, false);
+ sortByFields.add(sortByField);
+ sensorDatas = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields);
} else {
- Collections.sort(records, new Comparator() {
- @Override
- public int compare(AnalyticsDataRecord o1, AnalyticsDataRecord o2) {
- long t1 = (Long) o1.getValue("time");
- long t2 = (Long) o2.getValue("time");
- if (t1 < t2) {
- return -1;
- } else if (t1 > t2) {
- return 1;
- } else {
- return 0;
- }
- }
- });
- for (AnalyticsDataRecord record : records) {
- SensorData sensorData = new SensorData();
- sensorData.setTime((long) record.getValue("time"));
- sensorData.setValue("" + (float) record.getValue(sensor));
- sensorDatas.add(sensorData);
- }
+ sensorDatas = APIUtil.getAllEventsForDevice(sensorTableName, query, null);
}
- SensorData[] sensorDetails = sensorDatas.toArray(new SensorData[sensorDatas.size()]);
- return Response.ok().entity(sensorDetails).build();
- } catch (DeviceManagementAnalyticsException e) {
+ return Response.ok().entity(sensorDatas).build();
+ } catch (AnalyticsException e) {
String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
log.error(errorMsg);
- SensorData[] senserDetails = sensorDatas.toArray(new SensorData[sensorDatas.size()]);
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(senserDetails).build();
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
}
}
diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/transport/AndroidSenseMQTTConnector.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/transport/AndroidSenseMQTTConnector.java
index 0b8f30e224..bd86bca260 100644
--- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/transport/AndroidSenseMQTTConnector.java
+++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/transport/AndroidSenseMQTTConnector.java
@@ -26,7 +26,7 @@ import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
-import org.wso2.carbon.device.mgt.analytics.data.publisher.service.DeviceAnalyticsService;
+import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
@@ -289,8 +289,8 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
if (device != null) {
String owner = device.getEnrolmentInfo().getOwner();
ctx.setTenantDomain(MultitenantUtils.getTenantDomain(owner), true);
- DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
- .getOSGiService(DeviceAnalyticsService.class, null);
+ EventsPublisherService deviceAnalyticsService = (EventsPublisherService) ctx
+ .getOSGiService(EventsPublisherService.class, null);
if (deviceAnalyticsService != null) {
Object metaData[] = {owner, AndroidSenseConstants.DEVICE_TYPE, deviceId, time};
if (streamDefinition != null && payloadData != null && payloadData.length > 0) {
diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/APIUtil.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/APIUtil.java
index 73287696e4..c8d90a1c17 100644
--- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/APIUtil.java
+++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/APIUtil.java
@@ -2,9 +2,23 @@ package org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
+import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
+import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDrillDownRequest;
+import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
+import org.wso2.carbon.analytics.dataservice.commons.SortByField;
+import org.wso2.carbon.analytics.dataservice.core.AnalyticsDataServiceUtils;
+import org.wso2.carbon.analytics.datasource.commons.Record;
+import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
+import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* This class provides utility functions used by REST-API.
*/
@@ -33,4 +47,84 @@ public class APIUtil {
}
return deviceManagementProviderService;
}
+
+ public static AnalyticsDataAPI getAnalyticsDataAPI() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ AnalyticsDataAPI analyticsDataAPI =
+ (AnalyticsDataAPI) ctx.getOSGiService(AnalyticsDataAPI.class, null);
+ if (analyticsDataAPI == null) {
+ String msg = "Analytics api service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return analyticsDataAPI;
+ }
+
+ public static List getAllEventsForDevice(String tableName, String query, List sortByFields) throws AnalyticsException {
+ int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
+ AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
+ int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
+ if (eventCount == 0) {
+ return null;
+ }
+ AnalyticsDrillDownRequest drillDownRequest = new AnalyticsDrillDownRequest();
+ drillDownRequest.setQuery(query);
+ drillDownRequest.setTableName(tableName);
+ drillDownRequest.setRecordCount(eventCount);
+ if (sortByFields != null) {
+ drillDownRequest.setSortByFields(sortByFields);
+ }
+ List resultEntries = analyticsDataAPI.drillDownSearch(tenantId, drillDownRequest);
+ List recordIds = getRecordIds(resultEntries);
+ AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds);
+ Map sensorDatas = createSensorData(AnalyticsDataServiceUtils.listRecords(
+ analyticsDataAPI, response));
+ List sortedSensorData = getSortedSensorData(sensorDatas, resultEntries);
+ return sortedSensorData;
+ }
+
+ private static List getRecordIds(List searchResults) {
+ List ids = new ArrayList<>();
+ for (SearchResultEntry searchResult : searchResults) {
+ ids.add(searchResult.getId());
+ }
+ return ids;
+ }
+
+ public static List getSortedSensorData(Map sensorDatas,
+ List searchResults) {
+ List sortedRecords = new ArrayList<>();
+ for (SearchResultEntry searchResultEntry : searchResults) {
+ sortedRecords.add(sensorDatas.get(searchResultEntry.getId()));
+ }
+ return sortedRecords;
+ }
+
+ /**
+ * Creates the SensorDatas from records.
+ *
+ * @param records the records
+ * @return the Map of SensorRecord
+ */
+ public static Map createSensorData(List records) {
+ Map sensorDatas = new HashMap<>();
+ for (Record record : records) {
+ SensorRecord sensorData = createSensorData(record);
+ sensorDatas.put(sensorData.getId(), sensorData);
+ }
+ return sensorDatas;
+ }
+
+ /**
+ * Create a SensorRecord object out of a Record object
+ *
+ * @param record the record object
+ * @return SensorRecord object
+ */
+ public static SensorRecord createSensorData(Record record) {
+ SensorRecord recordBean = new SensorRecord();
+ recordBean.setId(record.getId());
+ recordBean.setValues(record.getValues());
+ return recordBean;
+ }
}
diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorData.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorData.java
index becd170856..67890f2f0f 100644
--- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorData.java
+++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorData.java
@@ -12,33 +12,32 @@ import javax.xml.bind.annotation.XmlRootElement;
@JsonIgnoreProperties(ignoreUnknown = true)
public class SensorData {
- @XmlElement public Long time;
- @XmlElement public String key;
+ @XmlElement public Long time;
+ @XmlElement public String key;
+ @XmlElement public String value;
- public String getValue() {
- return value;
- }
+ public String getValue() {
+ return value;
+ }
- public void setValue(String value) {
- this.value = value;
- }
+ public void setValue(String value) {
+ this.value = value;
+ }
- public String getKey() {
- return key;
- }
+ public String getKey() {
+ return key;
+ }
- public void setKey(String key) {
- this.key = key;
- }
+ public void setKey(String key) {
+ this.key = key;
+ }
- public Long getTime() {
- return time;
- }
+ public Long getTime() {
+ return time;
+ }
- public void setTime(Long time) {
- this.time = time;
- }
-
- @XmlElement public String value;
+ public void setTime(Long time) {
+ this.time = time;
+ }
}
diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorRecord.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorRecord.java
new file mode 100644
index 0000000000..2159a0830a
--- /dev/null
+++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/util/SensorRecord.java
@@ -0,0 +1,68 @@
+package org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
+
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@XmlRootElement
+/**
+ * This stores sensor event data for android sense.
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SensorRecord {
+
+ @XmlElementWrapper(required = true, name = "values")
+ private Map values;
+
+ /** The id. */
+ @XmlElement(required = false, name = "id")
+ private String id;
+
+ /**
+ * Gets the values.
+ * @return the values
+ */
+ public Map getValues() {
+ return values;
+ }
+
+ /**
+ * Sets the values.
+ * @param values the values
+ */
+ public void setValues(Map values) {
+ this.values = values;
+ }
+
+ /**
+ * Sets the id.
+ * @param id the new id
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the id.
+ * @return the id
+ */
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString(){
+ List valueList = new ArrayList();
+ for (Map.Entry entry : values.entrySet()) {
+ valueList.add(entry.getKey() + ":" + entry.getValue());
+ }
+ return valueList.toString();
+
+ }
+
+}
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/pom.xml b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/pom.xml
index 7d698874aa..77142701b7 100644
--- a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/pom.xml
+++ b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/pom.xml
@@ -160,6 +160,11 @@
org.wso2.carbon.apimgt.webapp.publisher
provided
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.api
+ provided
+
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoControllerServiceImpl.java b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoControllerServiceImpl.java
index 0b7de4e640..98ae9de0ea 100644
--- a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoControllerServiceImpl.java
+++ b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoControllerServiceImpl.java
@@ -20,23 +20,21 @@ package org.wso2.carbon.device.mgt.iot.arduino.service.impl;
import org.apache.commons.logging.Log;
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.analytics.data.publisher.AnalyticsDataRecord;
-import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DeviceManagementAnalyticsException;
-import org.wso2.carbon.device.mgt.analytics.data.publisher.service.DeviceAnalyticsService;
import org.wso2.carbon.device.mgt.iot.arduino.service.impl.dto.DeviceData;
-import org.wso2.carbon.device.mgt.iot.arduino.service.impl.dto.SensorData;
+import org.wso2.carbon.device.mgt.iot.arduino.service.impl.dto.SensorRecord;
+import org.wso2.carbon.device.mgt.iot.arduino.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.arduino.service.impl.util.ArduinoServiceUtils;
import org.wso2.carbon.device.mgt.iot.arduino.plugin.constants.ArduinoConstants;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager;
-import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -83,10 +81,9 @@ public class ArduinoControllerServiceImpl implements ArduinoControllerService {
@Override
public Response requestTemperature(String deviceId, String protocol) {
-
try {
- SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
- ArduinoConstants.SENSOR_TEMPERATURE);
+ org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord sensorRecord =
+ SensorDataManager.getInstance().getSensorRecord(deviceId, ArduinoConstants.SENSOR_TEMPERATURE);
return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
@@ -157,43 +154,19 @@ public class ArduinoControllerServiceImpl implements ArduinoControllerService {
public Response getArduinoTemperatureStats(String deviceId, long from, long to) {
String fromDate = String.valueOf(from);
String toDate = String.valueOf(to);
- List sensorDatas = new ArrayList<>();
- PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
- DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
- .getOSGiService(DeviceAnalyticsService.class, null);
String query = "deviceId:" + deviceId + " AND deviceType:" +
ArduinoConstants.DEVICE_TYPE + " AND time : [" + fromDate + " TO " + toDate + "]";
String sensorTableName = ArduinoConstants.TEMPERATURE_EVENT_TABLE;
- SensorData[] sensorDetails;
try {
- List records = deviceAnalyticsService.getAllEventsForDevice(sensorTableName, query);
- Collections.sort(records, new Comparator() {
- @Override
- public int compare(AnalyticsDataRecord o1, AnalyticsDataRecord o2) {
- long t1 = (Long) o1.getValue("time");
- long t2 = (Long) o2.getValue("time");
- if (t1 < t2) {
- return -1;
- } else if (t1 > t2) {
- return 1;
- } else {
- return 0;
- }
- }
- });
- for (AnalyticsDataRecord record : records) {
- SensorData sensorData = new SensorData();
- sensorData.setTime((long) record.getValue("time"));
- sensorData.setValue("" + (float) record.getValue(ArduinoConstants.SENSOR_TEMPERATURE));
- sensorDatas.add(sensorData);
- }
- sensorDetails = sensorDatas.toArray(new SensorData[sensorDatas.size()]);
- return Response.status(Response.Status.OK.getStatusCode()).entity(sensorDetails).build();
- } catch (DeviceManagementAnalyticsException e) {
+ List sortByFields = new ArrayList<>();
+ SortByField sortByField = new SortByField("time", SORT.ASC, false);
+ sortByFields.add(sortByField);
+ List sensorRecords = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields);
+ return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecords).build();
+ } catch (AnalyticsException e) {
String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
log.error(errorMsg);
- sensorDetails = sensorDatas.toArray(new SensorData[sensorDatas.size()]);
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(sensorDetails).build();
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
}
}
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoManagerServiceImpl.java b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoManagerServiceImpl.java
index 3ef8971287..fa7566b228 100644
--- a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoManagerServiceImpl.java
+++ b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/ArduinoManagerServiceImpl.java
@@ -34,7 +34,6 @@ import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.util.ZipArchive;
import org.wso2.carbon.device.mgt.iot.util.ZipUtil;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
-import org.wso2.carbon.identity.jwt.client.extension.JWTClientManager;
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;
@@ -184,14 +183,14 @@ public class ArduinoManagerServiceImpl implements ArduinoManagerService {
apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
ArduinoConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
}
- JWTClient jwtClient = JWTClientManager.getInstance().getJWTClient();
+ JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "device_type_" + ArduinoConstants.DEVICE_TYPE + " device_" + deviceId;
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), owner,
scopes);
//create token
- String accessToken = accessTokenInfo.getAccess_token();
- String refreshToken = accessTokenInfo.getRefresh_token();
+ String accessToken = accessTokenInfo.getAccessToken();
+ String refreshToken = accessTokenInfo.getRefreshToken();
//Register the device with CDMF
boolean status = register(deviceId, deviceName);
if (!status) {
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/dto/SensorData.java b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/dto/SensorData.java
deleted file mode 100644
index 9e46a7cad1..0000000000
--- a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/dto/SensorData.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.wso2.carbon.device.mgt.iot.arduino.service.impl.dto;
-
-import org.codehaus.jackson.annotate.JsonIgnoreProperties;
-
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
-@XmlRootElement
-/**
- * This stores sensor event data for the device type.
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class SensorData {
-
- @XmlElement public Long time;
- @XmlElement public String key;
-
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- public String getKey() {
- return key;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
-
- public Long getTime() {
- return time;
- }
-
- public void setTime(Long time) {
- this.time = time;
- }
-
- @XmlElement public String value;
-
-}
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/dto/SensorRecord.java b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/dto/SensorRecord.java
new file mode 100644
index 0000000000..2593ed83b2
--- /dev/null
+++ b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/dto/SensorRecord.java
@@ -0,0 +1,68 @@
+package org.wso2.carbon.device.mgt.iot.arduino.service.impl.dto;
+
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@XmlRootElement
+/**
+ * This stores sensor event data for android sense.
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SensorRecord {
+
+ @XmlElementWrapper(required = true, name = "values")
+ private Map values;
+
+ /** The id. */
+ @XmlElement(required = false, name = "id")
+ private String id;
+
+ /**
+ * Gets the values.
+ * @return the values
+ */
+ public Map getValues() {
+ return values;
+ }
+
+ /**
+ * Sets the values.
+ * @param values the values
+ */
+ public void setValues(Map values) {
+ this.values = values;
+ }
+
+ /**
+ * Sets the id.
+ * @param id the new id
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the id.
+ * @return the id
+ */
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString(){
+ List valueList = new ArrayList();
+ for (Map.Entry entry : values.entrySet()) {
+ valueList.add(entry.getKey() + ":" + entry.getValue());
+ }
+ return valueList.toString();
+
+ }
+
+}
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/APIUtil.java b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/APIUtil.java
index fb759f25a3..44ce396e58 100644
--- a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/APIUtil.java
+++ b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/APIUtil.java
@@ -2,9 +2,25 @@ package org.wso2.carbon.device.mgt.iot.arduino.service.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
+import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
+import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDrillDownRequest;
+import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
+import org.wso2.carbon.analytics.dataservice.commons.SortByField;
+import org.wso2.carbon.analytics.dataservice.core.AnalyticsDataServiceUtils;
+import org.wso2.carbon.analytics.datasource.commons.Record;
+import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
+import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
+import org.wso2.carbon.device.mgt.iot.arduino.service.impl.dto.SensorRecord;
+import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* This class provides utility functions used by REST-API.
@@ -23,12 +39,6 @@ public class APIUtil {
return username;
}
- public static String getTenantDomainOftheUser() {
- PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
- String tenantDomain = threadLocalCarbonContext.getTenantDomain();
- return tenantDomain;
- }
-
public static DeviceManagementProviderService getDeviceManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
@@ -41,6 +51,86 @@ public class APIUtil {
return deviceManagementProviderService;
}
+ public static AnalyticsDataAPI getAnalyticsDataAPI() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ AnalyticsDataAPI analyticsDataAPI =
+ (AnalyticsDataAPI) ctx.getOSGiService(AnalyticsDataAPI.class, null);
+ if (analyticsDataAPI == null) {
+ String msg = "Analytics api service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return analyticsDataAPI;
+ }
+
+ public static List getAllEventsForDevice(String tableName, String query, List sortByFields) throws AnalyticsException {
+ int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
+ AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
+ int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
+ if (eventCount == 0) {
+ return null;
+ }
+ AnalyticsDrillDownRequest drillDownRequest = new AnalyticsDrillDownRequest();
+ drillDownRequest.setQuery(query);
+ drillDownRequest.setTableName(tableName);
+ drillDownRequest.setRecordCount(eventCount);
+ if (sortByFields != null) {
+ drillDownRequest.setSortByFields(sortByFields);
+ }
+ List resultEntries = analyticsDataAPI.drillDownSearch(tenantId, drillDownRequest);
+ List recordIds = getRecordIds(resultEntries);
+ AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds);
+ Map sensorDatas = createSensorData(AnalyticsDataServiceUtils.listRecords(
+ analyticsDataAPI, response));
+ List sortedSensorData = getSortedSensorData(sensorDatas, resultEntries);
+ return sortedSensorData;
+ }
+
+ private static List getRecordIds(List searchResults) {
+ List ids = new ArrayList<>();
+ for (SearchResultEntry searchResult : searchResults) {
+ ids.add(searchResult.getId());
+ }
+ return ids;
+ }
+
+ public static List getSortedSensorData(Map sensorDatas,
+ List searchResults) {
+ List sortedRecords = new ArrayList<>();
+ for (SearchResultEntry searchResultEntry : searchResults) {
+ sortedRecords.add(sensorDatas.get(searchResultEntry.getId()));
+ }
+ return sortedRecords;
+ }
+
+ /**
+ * Creates the SensorDatas from records.
+ *
+ * @param records the records
+ * @return the Map of SensorRecord
+ */
+ public static Map createSensorData(List records) {
+ Map sensorDatas = new HashMap<>();
+ for (Record record : records) {
+ SensorRecord sensorData = createSensorData(record);
+ sensorDatas.put(sensorData.getId(), sensorData);
+ }
+ return sensorDatas;
+ }
+
+ /**
+ * Create a SensorRecord object out of a Record object
+ *
+ * @param record the record object
+ * @return SensorRecord object
+ */
+ public static SensorRecord createSensorData(Record record) {
+ SensorRecord recordBean = new SensorRecord();
+ recordBean.setId(record.getId());
+ recordBean.setValues(record.getValues());
+ return recordBean;
+ }
+
public static APIManagementProviderService getAPIManagementProviderService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
APIManagementProviderService apiManagementProviderService =
@@ -52,4 +142,21 @@ public class APIUtil {
}
return apiManagementProviderService;
}
+
+ public static JWTClientManagerService getJWTClientManagerService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ JWTClientManagerService jwtClientManagerService =
+ (JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
+ if (jwtClientManagerService == null) {
+ String msg = "JWT Client manager service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return jwtClientManagerService;
+ }
+
+ public static String getTenantDomainOftheUser() {
+ PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ return threadLocalCarbonContext.getTenantDomain();
+ }
}
diff --git a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/ArduinoServiceUtils.java b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/ArduinoServiceUtils.java
index 421541c41c..fcf49a80eb 100644
--- a/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/ArduinoServiceUtils.java
+++ b/components/iot-plugins/arduino-plugin/org.wso2.carbon.device.mgt.iot.arduino.api/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/impl/util/ArduinoServiceUtils.java
@@ -27,7 +27,7 @@ import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
-import org.wso2.carbon.device.mgt.analytics.data.publisher.service.DeviceAnalyticsService;
+import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.arduino.plugin.constants.ArduinoConstants;
import javax.ws.rs.HttpMethod;
@@ -193,8 +193,8 @@ public class ArduinoServiceUtils {
String owner = ctx.getUsername();
Object metdaData[] = {owner, ArduinoConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()};
Object payloadData[] = {temperature};
- DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
- .getOSGiService(DeviceAnalyticsService.class, null);
+ EventsPublisherService deviceAnalyticsService = (EventsPublisherService) ctx
+ .getOSGiService(EventsPublisherService.class, null);
if (deviceAnalyticsService != null) {
try {
deviceAnalyticsService.publishEvent(TEMPERATURE_STREAM_DEFINITION, "1.0.0", metdaData,
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/pom.xml b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/pom.xml
new file mode 100644
index 0000000000..1c27e77a1d
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/pom.xml
@@ -0,0 +1,165 @@
+
+
+
+
+ das-extensions
+ org.wso2.carbon.devicemgt-plugins
+ 2.1.0-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+
+ org.wso2.carbon.event.input.adapter.extensions
+ bundle
+ WSO2 Carbon - Event Input MQTT Adapter Module
+ This provides the capability of connecting to existing broker that supports OAUTH
+ http://wso2.org
+
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.input.adapter.core
+
+
+ org.wso2.carbon
+ org.wso2.carbon.logging
+
+
+ org.wso2.carbon
+ org.wso2.carbon.core
+
+
+ org.eclipse.paho
+ org.eclipse.paho.client.mqttv3
+
+
+ org.apache.httpcomponents.wso2
+ httpcore
+
+
+ org.wso2.orbit.org.apache.httpcomponents
+ httpclient
+
+
+ com.googlecode.json-simple.wso2
+ json-simple
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.identity.jwt.client.extension
+
+
+ com.jayway.jsonpath.wso2
+ json-path
+
+
+ org.wso2.carbon.identity
+ org.wso2.carbon.identity.oauth.stub
+
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ generate-scr-descriptor
+
+ scr
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+
+ org.wso2.carbon.event.input.adapter.extensions.internal,
+ org.wso2.carbon.event.input.adapter.extensions.internal.*
+
+
+ !org.wso2.carbon.event.input.adapter.extensions.internal,
+ !org.wso2.carbon.event.input.adapter.extensions.internal.*,
+ org.wso2.carbon.event.input.adapter.extensions.*
+
+
+ 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.*,
+ javax.net.ssl,
+ org.apache.commons.logging,
+ org.apache.http.entity,
+ org.osgi.framework,
+ org.osgi.service.component,
+ org.wso2.carbon.context,
+ org.wso2.carbon.core,
+ javax.servlet,
+ javax.servlet.http,
+ org.apache.axiom.om.util,
+ org.osgi.service.http,
+ org.wso2.carbon.user.api,
+ org.wso2.carbon.user.core.service,
+ org.wso2.carbon.user.core.tenant,
+ org.wso2.carbon.utils,
+ org.wso2.carbon.utils.multitenancy,
+ org.wso2.carbon.identity.oauth2.stub;version="${carbon.identity.version.range}",
+ org.wso2.carbon.identity.oauth2.stub.dto;version="${carbon.identity.version.range}",
+ org.apache.axis2,
+ org.apache.axis2.client,
+ org.apache.axis2.context,
+ org.apache.axis2.transport.http,
+ org.apache.commons.httpclient,
+ org.apache.commons.httpclient.contrib.ssl,
+ org.apache.commons.httpclient.params,
+ org.apache.commons.httpclient.protocol,
+ org.apache.commons.pool,
+ org.apache.commons.pool.impl,
+ org.apache.log4j
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/ContentInfo.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/ContentInfo.java
new file mode 100644
index 0000000000..0cd60b993d
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/ContentInfo.java
@@ -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.event.input.adapter.extensions;
+
+/**
+ * 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 String msgText;
+
+ public ContentInfo(boolean isValidContent, String msgText) {
+ this.isValidContent = isValidContent;
+ this.msgText = msgText;
+ }
+
+ public boolean isValidContent() {
+ return isValidContent;
+ }
+
+ public void setIsValidContent(boolean isValidContent) {
+ this.isValidContent = isValidContent;
+ }
+
+ public String getMsgText() {
+ return msgText;
+ }
+
+ public void setMsgText(String msgText) {
+ this.msgText = msgText;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/ContentValidator.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/ContentValidator.java
new file mode 100644
index 0000000000..8a0ca50ad4
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/ContentValidator.java
@@ -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.event.input.adapter.extensions;
+
+import java.util.Map;
+
+/**
+ * This interface will be triggered to validate the stream content before publishing.
+ */
+public interface ContentValidator {
+ /**
+ *
+ * @param params that related to input adapter to identify the client and the content
+ * @return
+ */
+ ContentInfo validate(Map params);
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPEventAdapter.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPEventAdapter.java
new file mode 100644
index 0000000000..1c8c7f3314
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPEventAdapter.java
@@ -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.event.input.adapter.extensions.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.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.event.input.adapter.extensions.http.util.HTTPEventAdapterConstants;
+import org.wso2.carbon.event.input.adapter.extensions.internal.EventAdapterServiceDataHolder;
+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 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 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(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 = EventAdapterServiceDataHolder.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 = EventAdapterServiceDataHolder.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);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPEventAdapterFactory.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPEventAdapterFactory.java
new file mode 100644
index 0000000000..4a810d7d60
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPEventAdapterFactory.java
@@ -0,0 +1,160 @@
+/*
+ * 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.event.input.adapter.extensions.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.event.input.adapter.extensions.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.event.input.adapter.extensions.http.i18n.Resources", Locale.getDefault());
+ private int httpPort;
+ private int httpsPort;
+ private int portOffset;
+
+ public HTTPEventAdapterFactory() {
+ 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 getSupportedMessageFormats() {
+ List supportInputMessageTypes = new ArrayList();
+ supportInputMessageTypes.add(MessageType.XML);
+ supportInputMessageTypes.add(MessageType.JSON);
+ supportInputMessageTypes.add(MessageType.TEXT);
+ return supportInputMessageTypes;
+ }
+
+ @Override
+ public List getPropertyList() {
+
+ List 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));
+ propertyList.add(contentValidator);
+ 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));
+ propertyList.add(contentValidatorParams);
+ contentValidatorParams.setDefaultValue(HTTPEventAdapterConstants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
+ propertyList.add(contentValidatorParams);
+ 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 globalProperties) {
+ return new HTTPEventAdapter(eventAdapterConfiguration, globalProperties);
+ }
+
+ private int getPortOffset() {
+ return CarbonUtils.getPortFromServerConfig(HTTPEventAdapterConstants.CARBON_CONFIG_PORT_OFFSET_NODE) + 1;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPMessageServlet.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPMessageServlet.java
new file mode 100644
index 0000000000..4220ec7734
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/HTTPMessageServlet.java
@@ -0,0 +1,339 @@
+/*
+ * 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.event.input.adapter.extensions.http;
+
+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.context.PrivilegedCarbonContext;
+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.extensions.ContentInfo;
+import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
+import org.wso2.carbon.event.input.adapter.extensions.http.oauth.OAuthTokenValidaterStubFactory;
+import org.wso2.carbon.event.input.adapter.extensions.http.util.AuthenticationInfo;
+import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPContentValidator;
+import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPEventAdapterConstants;
+import org.wso2.carbon.event.input.adapter.extensions.internal.EventAdapterServiceDataHolder;
+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.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.rmi.RemoteException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class HTTPMessageServlet extends HttpServlet {
+
+ private static final String AUTHORIZATION_HEADER = "Authorization";
+ 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 final Pattern PATTERN = Pattern.compile("[B|b]earer\\s");
+ private static final String TOKEN_TYPE = "bearer";
+ private static String cookie;
+ private static Log log = LogFactory.getLog(HTTPMessageServlet.class);
+ private GenericObjectPool stubs;
+
+ private InputEventAdapterListener eventAdaptorListener;
+ private int tenantId;
+ private String exposedTransports;
+
+ public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
+ InputEventAdapterConfiguration eventAdapterConfiguration) {
+ this.eventAdaptorListener = eventAdaptorListener;
+ this.tenantId = tenantId;
+ this.exposedTransports = eventAdapterConfiguration.getProperties().get(
+ HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
+ this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(eventAdapterConfiguration));
+ }
+
+ 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;
+ }
+
+ private AuthenticationInfo checkAuthentication(HttpServletRequest req) {
+ AuthenticationInfo authenticationInfo = (AuthenticationInfo) req.getSession().getAttribute(
+ AUTH_MESSAGE_STORE_AUTHENTICATION_INFO);
+ if (authenticationInfo != null) {
+ return authenticationInfo;
+ }
+ String bearerToken = getBearerToken(req);
+ if (bearerToken == null) {
+ return authenticationInfo;
+ }
+
+ RealmService realmService = EventAdapterServiceDataHolder.getRealmService();
+ try {
+ authenticationInfo = validateToken(bearerToken);
+ boolean success = authenticationInfo.isAuthenticated();
+ if (success) {
+ req.getSession().setAttribute(AUTH_MESSAGE_STORE_AUTHENTICATION_INFO, authenticationInfo);
+ }
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.debug("checkAuthentication() fail: " + e.getMessage(), e);
+ }
+ }
+ 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;
+ }
+
+ /**
+ * 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 = EventAdapterServiceDataHolder.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;
+ }
+
+
+ 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();
+ }
+
+ @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 {
+ if (req.isSecure()) {
+ 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 paramMap = new HashMap<>();
+ Enumeration reqParameterNames = req.getParameterNames();
+ while (reqParameterNames.hasMoreElements()) {
+ paramMap.put(reqParameterNames.nextElement(), req.getParameter(reqParameterNames.nextElement()));
+ }
+ paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername());
+ paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain());
+ paramMap.put(HTTPEventAdapterConstants.PAYLOAD_TAG, data);
+ ContentValidator contentValidator = new HTTPContentValidator();
+ ContentInfo contentInfo = contentValidator.validate(paramMap);
+ if (contentInfo != null && contentInfo.isValidContent()) {
+ HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener,
+ contentInfo.getMsgText(), 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);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Event received in HTTP Event Adapter - " + payload);
+ }
+
+ if (payload.trim() != 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();
+ }
+ }
+
+ }
+
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/oauth/OAuthTokenValidaterStubFactory.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/oauth/OAuthTokenValidaterStubFactory.java
new file mode 100644
index 0000000000..57962f007e
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/oauth/OAuthTokenValidaterStubFactory.java
@@ -0,0 +1,180 @@
+/*
+ * 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.event.input.adapter.extensions.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.event.input.adapter.core.InputEventAdapterConfiguration;
+import org.wso2.carbon.event.input.adapter.extensions.http.oauth.exception.OAuthTokenValidationException;
+import org.wso2.carbon.event.input.adapter.extensions.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(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);
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/oauth/exception/OAuthTokenValidationException.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/oauth/exception/OAuthTokenValidationException.java
new file mode 100644
index 0000000000..d7b7b5797f
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/oauth/exception/OAuthTokenValidationException.java
@@ -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.event.input.adapter.extensions.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;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/AuthenticationInfo.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/AuthenticationInfo.java
new file mode 100644
index 0000000000..7e64cd36e0
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/AuthenticationInfo.java
@@ -0,0 +1,52 @@
+package org.wso2.carbon.event.input.adapter.extensions.http.util;
+
+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;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/HTTPContentValidator.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/HTTPContentValidator.java
new file mode 100644
index 0000000000..d6a163e87a
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/HTTPContentValidator.java
@@ -0,0 +1,45 @@
+/*
+* 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.event.input.adapter.extensions.http.util;
+
+import com.jayway.jsonpath.JsonPath;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.event.input.adapter.extensions.ContentInfo;
+import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
+
+import java.util.Map;
+
+public class HTTPContentValidator implements ContentValidator {
+ private static final Log log = LogFactory.getLog(HTTPContentValidator.class);
+
+ @Override
+ public ContentInfo validate(Map paramMap) {
+ String deviceId = paramMap.get("deviceId");
+
+ String msg = paramMap.get(HTTPEventAdapterConstants.PAYLOAD_TAG);
+ String deviceIdJsonPath = paramMap.get(HTTPEventAdapterConstants.DEVICE_ID_JSON_PATH);
+ Object res = JsonPath.read(msg, deviceIdJsonPath);
+ String deviceIdFromContent = (res != null) ? res.toString() : "";
+ if (deviceIdFromContent.equals(deviceId)) {
+ return new ContentInfo(true, msg);
+ }
+ return new ContentInfo(false, msg);
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/HTTPEventAdapterConstants.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/HTTPEventAdapterConstants.java
new file mode 100644
index 0000000000..a03112c77d
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/http/util/HTTPEventAdapterConstants.java
@@ -0,0 +1,72 @@
+/*
+ * 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.event.input.adapter.extensions.http.util;
+
+
+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 MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS =
+ "device_id_json_path:meta_deviceId";
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/internal/EventAdapterServiceComponent.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/internal/EventAdapterServiceComponent.java
new file mode 100644
index 0000000000..397487ab54
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/internal/EventAdapterServiceComponent.java
@@ -0,0 +1,77 @@
+/*
+* 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.event.input.adapter.extensions.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.event.input.adapter.core.InputEventAdapterFactory;
+import org.wso2.carbon.event.input.adapter.extensions.http.HTTPEventAdapterFactory;
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.MQTTEventAdapterFactory;
+import org.wso2.carbon.user.core.service.RealmService;
+
+/**
+ * @scr.component component.name="input.iot.Mqtt.AdapterService.component" immediate="true"
+ */
+
+/**
+ * @scr.component name="org.wso2.carbon.event.input.adapter.extension.EventAdapterServiceComponent" 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 EventAdapterServiceComponent {
+
+ private static final Log log = LogFactory.getLog(EventAdapterServiceComponent.class);
+
+ protected void activate(ComponentContext context) {
+ try {
+ InputEventAdapterFactory mqttEventAdapterFactory = new MQTTEventAdapterFactory();
+ context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
+ mqttEventAdapterFactory, null);
+ InputEventAdapterFactory httpEventEventAdapterFactory = new HTTPEventAdapterFactory();
+ context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
+ httpEventEventAdapterFactory, null);
+ if (log.isDebugEnabled()) {
+ log.debug("Successfully deployed the input IoT-MQTT adapter service");
+ }
+ } catch (RuntimeException e) {
+ log.error("Can not create the input IoT-MQTT adapter service ", e);
+ }
+ }
+
+ protected void setRealmService(RealmService realmService) {
+ EventAdapterServiceDataHolder.registerRealmService(realmService);
+ }
+
+ protected void unsetRealmService(RealmService realmService) {
+ EventAdapterServiceDataHolder.registerRealmService(null);
+ }
+
+ protected void setHttpService(HttpService httpService) {
+ EventAdapterServiceDataHolder.registerHTTPService(httpService);
+ }
+
+ protected void unsetHttpService(HttpService httpService) {
+ EventAdapterServiceDataHolder.registerHTTPService(null);
+ }
+
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/internal/EventAdapterServiceDataHolder.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/internal/EventAdapterServiceDataHolder.java
new file mode 100644
index 0000000000..324196bf9b
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/internal/EventAdapterServiceDataHolder.java
@@ -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.event.input.adapter.extensions.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 EventAdapterServiceDataHolder {
+
+ private static RealmService realmService;
+ private static HttpService httpService;
+
+ private EventAdapterServiceDataHolder() {
+ }
+
+ public static void registerRealmService(
+ RealmService realmService) {
+ EventAdapterServiceDataHolder.realmService = realmService;
+ }
+
+ public static RealmService getRealmService() {
+ return realmService;
+ }
+
+ public static void registerHTTPService(
+ HttpService httpService) {
+ EventAdapterServiceDataHolder.httpService = httpService;
+ }
+
+ public static HttpService getHTTPService() {
+ return httpService;
+ }
+
+
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/Constants.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/Constants.java
new file mode 100644
index 0000000000..284397cb12
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/Constants.java
@@ -0,0 +1,38 @@
+/*
+ * 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.event.input.adapter.extensions.mqtt;
+
+/**
+ * This holds the constants related to MQTT input adapter.
+ */
+public class Constants {
+ 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 =
+ "device_id_json_path:meta_deviceId,device_id_topic_hierarchy_index:2";
+ 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";
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/MQTTEventAdapter.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/MQTTEventAdapter.java
new file mode 100644
index 0000000000..c273e5af03
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/MQTTEventAdapter.java
@@ -0,0 +1,147 @@
+/*
+* 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.event.input.adapter.extensions.mqtt;
+
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+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.event.input.adapter.extensions.mqtt.util.MQTTAdapterListener;
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.util.MQTTBrokerConnectionConfiguration;
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.util.MQTTEventAdapterConstants;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Input MQTTEventAdapter 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 globalProperties;
+ private InputEventAdapterListener eventAdapterListener;
+ private final String id = UUID.randomUUID().toString();
+ private MQTTAdapterListener mqttAdapterListener;
+ private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
+
+
+ public MQTTEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
+ Map 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);
+ String params[] = contentValidationParams.split(",");
+ Map paramsMap = new HashMap<>();
+ for (String param: params) {
+ String paramsKeyAndValue[] = param.split("/_(.+)?/");
+ 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
+ );
+
+
+ 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);
+ }
+ }
+
+ @Override
+ public void testConnect() throws TestConnectionNotSupportedException {
+ throw new TestConnectionNotSupportedException("not-supported");
+ }
+
+ @Override
+ public void connect() {
+ mqttAdapterListener.createConnection();
+ }
+
+ @Override
+ public void disconnect() {
+ if (mqttAdapterListener != null) {
+ mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
+ }
+ }
+
+ @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;
+ }
+
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/MQTTEventAdapterFactory.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/MQTTEventAdapterFactory.java
new file mode 100644
index 0000000000..be1111bce2
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/MQTTEventAdapterFactory.java
@@ -0,0 +1,153 @@
+/*
+* 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.event.input.adapter.extensions.mqtt;
+
+import org.wso2.carbon.event.input.adapter.core.*;
+import org.wso2.carbon.event.input.adapter.extensions.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.event.input.adapter.extensions.mqtt.i18n.Resources", Locale.getDefault());
+
+ @Override
+ public String getType() {
+ return MQTTEventAdapterConstants.ADAPTER_TYPE_MQTT;
+ }
+
+ @Override
+ public List getSupportedMessageFormats() {
+ List supportInputMessageTypes = new ArrayList();
+
+ supportInputMessageTypes.add(MessageType.TEXT);
+ supportInputMessageTypes.add(MessageType.JSON);
+ supportInputMessageTypes.add(MessageType.XML);
+
+ return supportInputMessageTypes;
+ }
+
+ @Override
+ public List getPropertyList() {
+ List propertyList = new ArrayList();
+
+ // 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));
+ propertyList.add(contentValidator);
+ contentValidator.setDefaultValue(Constants.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));
+ propertyList.add(contentValidatorParams);
+ contentValidatorParams.setDefaultValue(Constants.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);
+ 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);
+
+ // 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 globalProperties) {
+ return new MQTTEventAdapter(eventAdapterConfiguration, globalProperties);
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/exception/MQTTContentValidatorInitializationException.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/exception/MQTTContentValidatorInitializationException.java
new file mode 100644
index 0000000000..a03cde2f98
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/exception/MQTTContentValidatorInitializationException.java
@@ -0,0 +1,53 @@
+/*
+ * 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.event.input.adapter.extensions.mqtt.exception;
+
+public class MQTTContentValidatorInitializationException extends RuntimeException {
+ private String errMessage;
+
+ public MQTTContentValidatorInitializationException(String msg, Exception nestedEx) {
+ super(msg, nestedEx);
+ setErrorMessage(msg);
+ }
+
+ public MQTTContentValidatorInitializationException(String message, Throwable cause) {
+ super(message, cause);
+ setErrorMessage(message);
+ }
+
+ public MQTTContentValidatorInitializationException(String msg) {
+ super(msg);
+ setErrorMessage(msg);
+ }
+
+ public MQTTContentValidatorInitializationException() {
+ super();
+ }
+
+ public MQTTContentValidatorInitializationException(Throwable cause) {
+ super(cause);
+ }
+
+ public String getErrorMessage() {
+ return errMessage;
+ }
+
+ public void setErrorMessage(String errMessage) {
+ this.errMessage = errMessage;
+ }
+}
\ No newline at end of file
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTAdapterListener.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTAdapterListener.java
new file mode 100644
index 0000000000..0da5ee21d5
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTAdapterListener.java
@@ -0,0 +1,280 @@
+/*
+* 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.event.input.adapter.extensions.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.event.input.adapter.core.InputEventAdapterListener;
+import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
+import org.wso2.carbon.event.input.adapter.extensions.ContentInfo;
+import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.Constants;
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.exception.MQTTContentValidatorInitializationException;
+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.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 int keepAlive;
+
+ private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
+ private String mqttClientId;
+ private String topic;
+ private int tenantId;
+ private boolean connectionSucceeded = false;
+ ContentValidator contentValidator;
+ Map contentValidationParams;
+
+ 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.mqttClientId = mqttClientId;
+ this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
+ this.cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
+ this.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 {
+ // Construct the connection options object that contains connection parameters
+ // such as cleanSession and LWT
+ connectionOptions = new MqttConnectOptions();
+ connectionOptions.setCleanSession(cleanSession);
+ connectionOptions.setKeepAliveInterval(keepAlive);
+
+ // Construct an MQTT blocking mode client
+ mqttClient = new MqttClient(this.mqttBrokerConnectionConfiguration.getBrokerUrl(), this.mqttClientId,
+ dataStore);
+
+ // Set this wrapper as the callback handler
+ mqttClient.setCallback(this);
+ String contentValidatorClassName = this.mqttBrokerConnectionConfiguration.getContentValidatorClassName();
+
+ if (contentValidatorClassName != null && contentValidatorClassName.equals(Constants.DEFAULT)) {
+ contentValidator = new MQTTContentValidator();
+ } 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 MQTTContentValidatorInitializationException(
+ "Unable to find the class authorizer: " + contentValidatorClassName, e);
+ } catch (InstantiationException e) {
+ throw new MQTTContentValidatorInitializationException(
+ "Unable to create an instance of :" + contentValidatorClassName, e);
+ } catch (IllegalAccessException e) {
+ throw new MQTTContentValidatorInitializationException("Access of the instance in not allowed.", e);
+ }
+ }
+
+ contentValidationParams = mqttBrokerConnectionConfiguration.getContentValidatorParams();
+
+ } catch (MqttException e) {
+ log.error("Exception occurred while subscribing to MQTT broker at "
+ + mqttBrokerConnectionConfiguration.getBrokerUrl());
+ throw new InputEventAdapterRuntimeException(e);
+ } catch (Throwable 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()) {
+ try {
+ URL dcrUrl = new URL(dcrUrlString);
+ HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
+ HttpPost postMethod = new HttpPost(dcrUrlString);
+ RegistrationProfile registrationProfile = new RegistrationProfile();
+ registrationProfile.setCallbackUrl(Constants.EMPTY_STRING);
+ registrationProfile.setGrantType(Constants.GRANT_TYPE);
+ registrationProfile.setOwner(username);
+ registrationProfile.setTokenScope(Constants.TOKEN_SCOPE);
+ registrationProfile.setApplicationType(Constants.APPLICATION_TYPE);
+ int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
+ 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(Constants.CLIENT_ID);
+ String clientSecret = (String) jsonPayload.get(Constants.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);
+ }
+ }
+ }
+ // Connect to the MQTT server
+ mqttClient.connect(connectionOptions);
+
+ // Subscribe to the requested topic
+ // The QoS specified is the maximum level that messages will be sent to the client at.
+ // For instance if QoS 1 is specified, any messages originally published at QoS 2 will
+ // be downgraded to 1 when delivering to the client but messages published at 1 and 0
+ // will be received at the same level they were published at.
+ mqttClient.subscribe(topic);
+ }
+
+ public void stopListener(String adapterName) {
+ if (connectionSucceeded) {
+ try {
+ // Un-subscribe accordingly and disconnect from the MQTT server.
+ 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);
+ }
+ }
+ //This is to stop all running reconnection threads
+ 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);
+ }
+ ContentInfo contentInfo;
+ synchronized (contentValidationParams) {
+ contentValidationParams.put(Constants.TOPIC, topic);
+ contentValidationParams.put(Constants.PAYLOAD, msgText);
+ contentInfo = contentValidator.validate(contentValidationParams);
+ contentValidationParams.remove(Constants.TOPIC);
+ contentValidationParams.remove(Constants.PAYLOAD);
+ }
+ if (contentValidator != null) {
+ if (contentInfo != null && contentInfo.isValidContent()) {
+ eventAdapterListener.onEvent(contentInfo.getMsgText());
+ }
+ } 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();
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTBrokerConnectionConfiguration.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTBrokerConnectionConfiguration.java
new file mode 100644
index 0000000000..504d46ff61
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTBrokerConnectionConfiguration.java
@@ -0,0 +1,119 @@
+/*
+* 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.event.input.adapter.extensions.mqtt.util;
+
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.Constants;
+
+import java.util.Map;
+
+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 contentValidatorParams;
+
+ public String getBrokerScopes() {
+ return brokerScopes;
+ }
+
+ public void setBrokerScopes(String brokerScopes) {
+ this.brokerScopes = brokerScopes;
+ }
+
+ public String getBrokerUsername() {
+ return brokerUsername;
+ }
+
+ public void setBrokerUsername(String brokerUsername) {
+ this.brokerUsername = brokerUsername;
+ }
+
+ public void setCleanSession(boolean cleanSession) {
+ this.cleanSession = cleanSession;
+ }
+
+
+ public boolean isCleanSession() {
+ return cleanSession;
+ }
+
+ public String getBrokerUrl() {
+ return brokerUrl;
+ }
+
+ public void setBrokerUrl(String brokerUrl) {
+ this.brokerUrl = brokerUrl;
+ }
+
+ public String getDcrUrl() {
+ return dcrUrl;
+ }
+
+ public void setDcrUrl(String dcrUrl) {
+ this.dcrUrl = dcrUrl;
+ }
+
+ public int getKeepAlive() {
+ return keepAlive;
+ }
+
+ public void setKeepAlive(int keepAlive) {
+ this.keepAlive = keepAlive;
+ }
+
+ public String getContentValidatorClassName() {
+ return contentValidatorClassName;
+ }
+
+ public void setContentValidatorClassName(String contentValidatorClassName) {
+ this.contentValidatorClassName = contentValidatorClassName;
+ }
+
+ public Map getContentValidatorParams() {
+ return contentValidatorParams;
+ }
+
+ public void setContentValidatorParams(Map contentValidatorParams) {
+ this.contentValidatorParams = contentValidatorParams;
+ }
+
+ public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes,
+ String dcrUrl, String cleanSession, int keepAlive,
+ String contentValidatorClassName, Map contentValidatorParams) {
+ this.brokerUsername = brokerUsername;
+ this.brokerScopes = brokerScopes;
+ if (brokerScopes == null) {
+ this.brokerScopes = Constants.EMPTY_STRING;
+ }
+ this.brokerUrl = brokerUrl;
+ this.dcrUrl = dcrUrl;
+ this.contentValidatorClassName = contentValidatorClassName;
+ if (cleanSession != null) {
+ this.cleanSession = Boolean.parseBoolean(cleanSession);
+ }
+ this.keepAlive = keepAlive;
+ if (contentValidatorParams != null) {
+ this.contentValidatorParams = contentValidatorParams;
+ }
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTContentValidator.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTContentValidator.java
new file mode 100644
index 0000000000..96c1eee167
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTContentValidator.java
@@ -0,0 +1,53 @@
+/*
+* 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.event.input.adapter.extensions.mqtt.util;
+
+import com.jayway.jsonpath.JsonPath;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.event.input.adapter.extensions.ContentInfo;
+import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
+import org.wso2.carbon.event.input.adapter.extensions.mqtt.Constants;
+
+import java.util.Map;
+
+public class MQTTContentValidator implements ContentValidator {
+ private static final Log log = LogFactory.getLog(MQTTContentValidator.class);
+
+ @Override
+ public ContentInfo validate(Map params) {
+ String topic = params.get(Constants.TOPIC);
+ String topics[] = topic.split("/");
+
+ String msg = params.get(Constants.PAYLOAD);
+ String deviceIdJsonPath = params.get(Constants.DEVICE_ID_JSON_PATH);
+ String deviceIdInTopicHierarchyLevel = params.get(Constants.DEVICE_ID_TOPIC_HIERARCHY_INDEX);
+ int deviceIdInTopicHierarchyLevelIndex = 0;
+ if (deviceIdInTopicHierarchyLevel != null && !deviceIdInTopicHierarchyLevel.isEmpty()) {
+ deviceIdInTopicHierarchyLevelIndex = Integer.parseInt(deviceIdInTopicHierarchyLevel);
+ }
+ String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex];
+ Object res = JsonPath.read(msg, deviceIdJsonPath);
+ String deviceIdFromContent = (res != null) ? res.toString() : "";
+ if (deviceIdFromContent.equals(deviceIdFromTopic)) {
+ return new ContentInfo(true, msg);
+ }
+ return new ContentInfo(false, msg);
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTEventAdapterConstants.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTEventAdapterConstants.java
new file mode 100644
index 0000000000..d9a564d96c
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTEventAdapterConstants.java
@@ -0,0 +1,46 @@
+/*
+* 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.event.input.adapter.extensions.mqtt.util;
+
+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_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;
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTUtil.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTUtil.java
new file mode 100644
index 0000000000..29bae3583b
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/MQTTUtil.java
@@ -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.event.input.adapter.extensions.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;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/RegistrationProfile.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/RegistrationProfile.java
new file mode 100644
index 0000000000..fec69d61b6
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/java/org/wso2/carbon/event/input/adapter/extensions/mqtt/util/RegistrationProfile.java
@@ -0,0 +1,73 @@
+package org.wso2.carbon.event.input.adapter.extensions.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;
+ }
+}
\ No newline at end of file
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/resources/org/wso2/carbon/event/input/adapter/extensions/http/i18n/Resources.properties b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/resources/org/wso2/carbon/event/input/adapter/extensions/http/i18n/Resources.properties
new file mode 100644
index 0000000000..de84fc0124
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/resources/org/wso2/carbon/event/input/adapter/extensions/http/i18n/Resources.properties
@@ -0,0 +1,38 @@
+#
+# 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 eventsFor super tenants: http://localhost:
+http.usage.tips_mid1=/endpoints/<event_receiver_name> https://localhost:
+http.usage.tips_mid2=/endpoints/<event_receiver_name>For other tenants: http://localhost:
+http.usage.tips_mid3=/endpoints/t/<tenant_domain>/<event_receiver_name> https://localhost:
+http.usage.tips_postfix=/endpoints/t/<tenant_domain>/<event_receiver_name>
+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)
\ No newline at end of file
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/resources/org/wso2/carbon/event/input/adapter/extensions/mqtt/i18n/Resources.properties b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/resources/org/wso2/carbon/event/input/adapter/extensions/mqtt/i18n/Resources.properties
new file mode 100644
index 0000000000..70d4019e42
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.input.adapter.extensions/src/main/resources/org/wso2/carbon/event/input/adapter/extensions/mqtt/i18n/Resources.properties
@@ -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.
+#
+
+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
\ No newline at end of file
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/pom.xml b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/pom.xml
new file mode 100644
index 0000000000..466120b71e
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/pom.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+ das-extensions
+ org.wso2.carbon.devicemgt-plugins
+ 2.1.0-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.event.output.adapter.extensions.ui.endpoint
+ war
+ WSO2 Carbon UI Webapp - Webapp for UI Output Event Adapter
+ http://wso2.org
+
+
+
+ junit
+ junit
+ test
+
+
+ org.apache.tomcat
+ tomcat-websocket-api
+
+
+ org.wso2.carbon.devicemgt-plugins
+ org.wso2.carbon.event.output.adapter.extensions.ui
+ provided
+
+
+ org.apache.httpcomponents.wso2
+ httpcore
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+ org.apache.cxf
+ cxf-rt-frontend-jaxrs
+
+
+ org.apache.httpcomponents.wso2
+ httpcore
+ provided
+
+
+ org.wso2.orbit.org.apache.httpcomponents
+ httpclient
+ provided
+
+
+ org.wso2.carbon.identity
+ org.wso2.carbon.identity.oauth.stub
+ provided
+
+
+
+
+ secured-outputui
+
+
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/SubscriptionEndpoint.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/SubscriptionEndpoint.java
new file mode 100644
index 0000000000..d6e0e49092
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/SubscriptionEndpoint.java
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+import oauth.OAuthTokenValdiator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.servlet.ServiceHolder;
+
+import javax.websocket.CloseReason;
+import javax.websocket.Session;
+
+/**
+ * Interface for subscription and un-subscription for web socket
+ */
+
+public class SubscriptionEndpoint {
+
+ private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class);
+
+ public SubscriptionEndpoint() {
+
+ }
+
+ /**
+ * Web socket onClose - Remove the registered sessions
+ *
+ * @param session - Users registered session.
+ * @param reason - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ public void onClose(Session session, CloseReason reason, String streamName, String version) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing a WebSocket due to " + reason.getReasonPhrase() + ", for session ID:" + session.getId
+ () +
+ ", for request URI - " + session.getRequestURI());
+ }
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().unsubscribeWebsocket(streamName, version,
+ session);
+ }
+
+ /**
+ * Web socket onError - Remove the registered sessions
+ *
+ * @param session - Users registered session.
+ * @param throwable - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ public void onError(Session session, Throwable throwable, String streamName, String version) {
+ log.error(
+ "Error occurred in session ID: " + session.getId() + ", for request URI - " + session.getRequestURI() +
+ ", " + throwable.getMessage(), throwable);
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().unsubscribeWebsocket(streamName, version,
+ session);
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java
new file mode 100644
index 0000000000..674b32447f
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+import oauth.OAuthTokenValdiator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.servlet.ServiceHolder;
+import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
+import util.AuthenticationInfo;
+
+import javax.websocket.CloseReason;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+
+/**
+ * Connect to web socket with Super tenant
+ */
+
+@ServerEndpoint(value = "/{streamname}/{version}")
+public class SuperTenantSubscriptionEndpoint extends SubscriptionEndpoint {
+
+ private static final Log log = LogFactory.getLog(SuperTenantSubscriptionEndpoint.class);
+
+ /**
+ * Web socket onOpen - When client sends a message
+ *
+ * @param session - Users registered session.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ @OnOpen
+ public void onOpen(Session session, @PathParam("streamname") String streamName,
+ @PathParam("version") String version) {
+ if (log.isDebugEnabled()) {
+ log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName);
+ }
+ AuthenticationInfo authenticationInfo = OAuthTokenValdiator.getInstance().validateToken(session);
+ //TODO Authorization
+ if (authenticationInfo != null && authenticationInfo.isAuthenticated()) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().subscribeWebsocket(streamName,
+ version,
+ session);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+ }
+
+ /**
+ * Web socket onMessage - When client sens a message
+ *
+ * @param session - Users registered session.
+ * @param message - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ */
+ @OnMessage
+ public void onMessage(Session session, String message, @PathParam("streamname") String streamName) {
+ if (log.isDebugEnabled()) {
+ log.debug("Received and dropped message from client. Message: " + message + ", " +
+ "for Session id: " + session.getId() + ", for the Stream:" + streamName);
+ }
+ }
+
+ /**
+ * Web socket onClose - Remove the registered sessions
+ *
+ * @param session - Users registered session.
+ * @param reason - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ @OnClose
+ public void onClose(Session session, CloseReason reason, @PathParam("streamname") String streamName,
+ @PathParam("version") String version) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+ super.onClose(session, reason, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+ /**
+ * Web socket onError - Remove the registered sessions
+ *
+ * @param session - Users registered session.
+ * @param throwable - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ @OnError
+ public void onError(Session session, Throwable throwable, @PathParam("streamname") String streamName,
+ @PathParam("version") String version) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+ super.onError(session, throwable, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java
new file mode 100644
index 0000000000..640fb0de17
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+import oauth.OAuthTokenValdiator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.servlet.ServiceHolder;
+import util.AuthenticationInfo;
+
+import javax.websocket.CloseReason;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+
+/**
+ * Connect to web socket with a tenant
+ */
+
+@ServerEndpoint(value = "/t/{tdomain}/{streamname}/{version}")
+public class TenantSubscriptionEndpoint extends SubscriptionEndpoint {
+
+ private static final Log log = LogFactory.getLog(TenantSubscriptionEndpoint.class);
+
+ /**
+ * Web socket onOpen - When client sends a message
+ *
+ * @param session - Users registered session.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ * @param tdomain - Tenant domain extracted from ws url.
+ */
+ @OnOpen
+ public void onOpen (Session session, @PathParam("streamname") String streamName ,
+ @PathParam("version") String version, @PathParam("tdomain") String tdomain) {
+ if (log.isDebugEnabled()) {
+ log.debug("WebSocket opened, for Session id: "+session.getId()+", for the Stream:"+streamName);
+ }
+ AuthenticationInfo authenticationInfo = OAuthTokenValdiator.getInstance().validateToken(session);
+ //TODO Authorization
+ if (authenticationInfo != null && authenticationInfo.isAuthenticated()) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true);
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().subscribeWebsocket(streamName,
+ version, session);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+ }
+
+ /**
+ * Web socket onMessage - When client sens a message
+ *
+ * @param session - Users registered session.
+ * @param message - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ */
+ @OnMessage
+ public void onMessage (Session session, String message, @PathParam("streamname") String streamName, @PathParam("tdomain") String tdomain) {
+ if (log.isDebugEnabled()) {
+ log.debug("Received and dropped message from client. Message: " + message+", for Session id: "+session.getId()+", for tenant domain"+tdomain+", for the Adaptor:"+streamName);
+ }
+ }
+
+ /**
+ * Web socket onClose - Remove the registered sessions
+ *
+ * @param session - Users registered session.
+ * @param reason - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ @OnClose
+ public void onClose (Session session, CloseReason reason, @PathParam("streamname") String streamName,
+ @PathParam("version") String version, @PathParam("tdomain") String tdomain) {
+
+ try {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain,true);
+ super.onClose(session, reason, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow();
+ }
+ }
+
+ /**
+ * Web socket onError - Remove the registered sessions
+ *
+ * @param session - Users registered session.
+ * @param throwable - Status code for web-socket close.
+ * @param streamName - StreamName extracted from the ws url.
+ * @param version - Version extracted from the ws url.
+ */
+ @OnError
+ public void onError (Session session, Throwable throwable, @PathParam("streamname") String streamName,
+ @PathParam("version") String version, @PathParam("tdomain") String tdomain) {
+
+ try {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true);
+ super.onError(session, throwable, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow();
+ }
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java
new file mode 100644
index 0000000000..1abe5f1792
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java
@@ -0,0 +1,174 @@
+package 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.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.utils.CarbonUtils;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
+import util.AuthenticationInfo;
+
+import javax.websocket.Session;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+public class OAuthTokenValdiator {
+
+ private static String cookie;
+ private GenericObjectPool stubs;
+ private static Log log = LogFactory.getLog(OAuthTokenValdiator.class);
+ private static final String WEBSOCKET_CONFIG_LOCATION =
+ CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.properties";
+ private static final String QUERY_STRING_SEPERATOR = "&";
+ private static final String QUERY_KEY_VALUE_SEPERATOR = "=";
+ private static final String TOKEN_TYPE = "bearer";
+ private static final String TOKEN_IDENTIFIER = "token";
+ private static OAuthTokenValdiator oAuthTokenValdiator = new OAuthTokenValdiator();
+
+ public static OAuthTokenValdiator getInstance() {
+ return oAuthTokenValdiator;
+ }
+
+ private OAuthTokenValdiator() {
+ Properties properties = null;
+ try {
+ properties = getWebSocketConfig();
+ this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(properties));
+ } catch (IOException e) {
+ log.error("Failed to parse the web socket config file " + WEBSOCKET_CONFIG_LOCATION);
+ }
+ }
+
+ /**
+ * This method gets a string accessToken and validates it
+ *
+ * @param session which need to be validated.
+ * @return AuthenticationInfo with the validated results.
+ */
+ public AuthenticationInfo validateToken(Session session) {
+ String token = getTokenFromSession(session);
+ if (token == null) {
+ AuthenticationInfo authenticationInfo = new AuthenticationInfo();
+ authenticationInfo.setAuthenticated(false);
+ return authenticationInfo;
+ }
+ 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);
+ return authenticationInfo;
+ }
+
+ /**
+ * 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);
+ } 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;
+ }
+
+ /**
+ * Retrieve JWT configs from registry.
+ */
+ private Properties getWebSocketConfig() throws IOException {
+ Properties properties = new Properties();
+ InputStream inputStream = getClass().getClassLoader().getResourceAsStream(WEBSOCKET_CONFIG_LOCATION);
+ if (inputStream != null) {
+ properties.load(inputStream);
+ }
+ return properties;
+ }
+
+ private String getTokenFromSession(Session session) {
+ String queryString = session.getQueryString();
+ if (queryString != null) {
+ String[] allQueryParamPairs = queryString.split(QUERY_STRING_SEPERATOR);
+
+ for (String keyValuePair : allQueryParamPairs) {
+ String[] queryParamPair = keyValuePair.split(QUERY_KEY_VALUE_SEPERATOR);
+
+ if (queryParamPair.length != 2) {
+ log.warn("Invalid query string [" + queryString + "] passed in.");
+ break;
+ }
+ if (queryParamPair[0].equals(TOKEN_IDENTIFIER)) {
+ return queryParamPair[1];
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java
new file mode 100644
index 0000000000..a43f874729
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java
@@ -0,0 +1,177 @@
+/*
+ * 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 oauth;
+
+import oauth.exception.OAuthTokenValidationException;
+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.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
+import util.UIConstants;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.Properties;
+
+/**
+ * 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;
+ Properties tokenValidationProperties;
+
+
+ public OAuthTokenValidaterStubFactory(Properties tokenValidationProperties) {
+ this.tokenValidationProperties = tokenValidationProperties;
+ 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(tokenValidationProperties.getProperty((UIConstants.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 = tokenValidationProperties.getProperty(UIConstants.USERNAME);
+ String password = tokenValidationProperties.getProperty(UIConstants.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(tokenValidationProperties.getProperty(
+ UIConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
+ params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.getProperty(
+ UIConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
+ HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+ connectionManager.setParams(params);
+ return new HttpClient(connectionManager);
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java
new file mode 100644
index 0000000000..3f54c5244c
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java
@@ -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 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;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/ServiceHolder.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/ServiceHolder.java
new file mode 100644
index 0000000000..08d07a44c6
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/ServiceHolder.java
@@ -0,0 +1,28 @@
+package org.wso2.carbon.servlet;
+
+
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.event.output.adapter.extensions.ui.UIOutputCallbackControllerService;
+
+public class ServiceHolder {
+
+ private static ServiceHolder instance;
+ private UIOutputCallbackControllerService uiOutputCallbackControllerService;
+
+ private ServiceHolder(){
+ uiOutputCallbackControllerService = (UIOutputCallbackControllerService) PrivilegedCarbonContext
+ .getThreadLocalCarbonContext()
+ .getOSGiService(UIOutputCallbackControllerService.class,null);
+ }
+
+ public synchronized static ServiceHolder getInstance(){
+ if (instance==null){
+ instance= new ServiceHolder();
+ }
+ return instance;
+ }
+
+ public UIOutputCallbackControllerService getUiOutputCallbackControllerService() {
+ return uiOutputCallbackControllerService;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/SuperTenantEventRetrievalEndpoint.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/SuperTenantEventRetrievalEndpoint.java
new file mode 100644
index 0000000000..41a0d8b33a
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/SuperTenantEventRetrievalEndpoint.java
@@ -0,0 +1,85 @@
+package org.wso2.carbon.servlet;/*
+ *
+ * Copyright (c) 2014-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.
+ *
+ */
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
+import util.UIConstants;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Getting events for HTTP request for super tenant
+ */
+
+@Path("/")
+public class SuperTenantEventRetrievalEndpoint{
+
+ public SuperTenantEventRetrievalEndpoint() {
+ }
+
+ /**
+ * Retrieve events when polling
+ *
+ * @param streamName - StreamName extracted from the http url.
+ * @param version - Version extracted from the http url.
+ * @param lastUpdatedTime - Last event's dispatched name.
+ * @return respnse
+ */
+ @GET
+ @Path("/{streamname}/{version}")
+ public Response retrieveEvents(@PathParam("streamname") String streamName, @PathParam("version") String version,
+ @QueryParam("lastUpdatedTime") String lastUpdatedTime) {
+ String streamId;
+ JsonObject eventDetails;
+ String jsonString;
+
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+ streamId = streamName + UIConstants.ADAPTER_UI_COLON + version;
+
+ eventDetails = ServiceHolder.getInstance().getUiOutputCallbackControllerService().retrieveEvents(streamName, version,
+ lastUpdatedTime);
+
+ } finally {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow();
+ }
+
+ if(eventDetails == null){
+ JsonObject errorData = new JsonObject();
+ errorData.addProperty("error","StreamId: " + streamId + " is not registered to receive events.");
+ jsonString = new Gson().toJson(errorData);
+ return Response.status(Response.Status.NOT_FOUND).entity(jsonString).header
+ ("Access-Control-Allow-Origin","*").build();
+ } else{
+ jsonString = new Gson().toJson(eventDetails);
+ return Response.ok(jsonString, MediaType.APPLICATION_JSON).header("Access-Control-Allow-Origin",
+ "*").build();
+ }
+ }
+
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/TenantEventRetrievalEndpoint.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/TenantEventRetrievalEndpoint.java
new file mode 100644
index 0000000000..ec14e57221
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/org/wso2/carbon/servlet/TenantEventRetrievalEndpoint.java
@@ -0,0 +1,89 @@
+package org.wso2.carbon.servlet;
+/*
+ *
+ * Copyright (c) 2014-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.
+ *
+ */
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import util.UIConstants;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Getting events for HTTP request from a tenant
+ */
+
+@Path("/t/{tdomain}/")
+public class TenantEventRetrievalEndpoint {
+
+ private static final Log log = LogFactory.getLog(SuperTenantEventRetrievalEndpoint.class);
+
+ public TenantEventRetrievalEndpoint() {
+
+ }
+
+ /**
+ * Retrieve events when polling
+ *
+ * @param streamName - StreamName extracted from the http url.
+ * @param version - Version extracted from the http url.
+ * @param lastUpdatedTime - Last event's dispatched name.
+ * @param tdomain - Tenant domain extracted from http url
+ * @return response
+ */
+ @GET
+ @Path("/{streamname}/{version}")
+ public Response retrieveEvents(@PathParam("streamname") String streamName, @PathParam("version") String version,
+ @QueryParam("lastUpdatedTime") String lastUpdatedTime,
+ @PathParam("tdomain") String tdomain) {
+
+ String streamId;
+ JsonObject eventDetails;
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true);
+ streamId = streamName + UIConstants.ADAPTER_UI_COLON + version;
+ eventDetails = ServiceHolder.getInstance().getUiOutputCallbackControllerService().retrieveEvents
+ (streamName, version, lastUpdatedTime);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+
+ String jsonString;
+ if (eventDetails == null) {
+ JsonObject errorData = new JsonObject();
+ errorData.addProperty("error", "StreamId: " + streamId + " is not registered to receive events.");
+ jsonString = new Gson().toJson(errorData);
+ return Response.status(Response.Status.NOT_FOUND).entity(jsonString).header
+ ("Access-Control-Allow-Origin", "*").build();
+ } else {
+ jsonString = new Gson().toJson(eventDetails);
+ return Response.ok(jsonString, MediaType.APPLICATION_JSON).header("Access-Control-Allow-Origin",
+ "*").build();
+ }
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/util/AuthenticationInfo.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/util/AuthenticationInfo.java
new file mode 100644
index 0000000000..2bac34e68f
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/util/AuthenticationInfo.java
@@ -0,0 +1,43 @@
+package util;
+
+public class AuthenticationInfo {
+
+ /**
+ * this variable is used to check whether the client is authenticated.
+ */
+ private boolean authenticated;
+ private String username;
+ private String tenantDomain;
+ /**
+ * 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;
+ }
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/util/UIConstants.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/util/UIConstants.java
new file mode 100644
index 0000000000..52f61f0201
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/java/util/UIConstants.java
@@ -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.
+ * *
+ *
+ */
+
+package util;
+
+/**
+ * This class contains the constants related to ui client.
+ */
+public class UIConstants {
+
+ private UIConstants() {
+ }
+ public static final String ADAPTER_UI_COLON = ":";
+ public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
+ public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
+ public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpointUrl";
+ public static final String USERNAME = "username";
+ public static final String PASSWORD = "password";
+}
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/webapp/WEB-INF/web.xml b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..4c01cc52c2
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui.endpoint/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ Output WebSocket
+
+ JAXServlet
+
+ org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
+
+
+ jaxrs.serviceClasses
+ org.wso2.carbon.servlet.TenantEventRetrievalEndpoint org.wso2.carbon.servlet.SuperTenantEventRetrievalEndpoint
+
+ 1
+
+
+
+
+ JAXServlet
+ /*
+
+
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui/pom.xml b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui/pom.xml
new file mode 100644
index 0000000000..0dee07435a
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui/pom.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+ das-extensions
+ org.wso2.carbon.devicemgt-plugins
+ 2.1.0-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.event.output.adapter.extensions.ui
+ bundle
+ WSO2 Carbon - Event Output UI Adapter Module
+ org.wso2.carbon.event.output.adapter.ui provides the back-end functionality of
+ ui event adapter
+
+ http://wso2.org
+
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.output.adapter.core
+
+
+ org.wso2.carbon
+ org.wso2.carbon.logging
+
+
+ org.wso2.carbon
+ org.wso2.carbon.core
+
+
+ javax.websocket
+ javax.websocket-api
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.databridge.commons
+
+
+ com.google.code.gson
+ gson
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.stream.core
+
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ generate-scr-descriptor
+
+ scr
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+
+ org.wso2.carbon.event.output.adapter.extensions.ui.internal,
+ org.wso2.carbon.event.output.adapter.extensions.ui.internal.*
+
+
+ !org.wso2.carbon.event.output.adapter.extensions.ui.internal,
+ !org.wso2.carbon.event.output.adapter.extensions.ui.internal.*,
+ org.wso2.carbon.event.output.adapter.extensions.ui.*
+
+
+ org.wso2.carbon.event.output.adapter.core.*,
+ javax.xml.namespace; version=0.0.0,
+ org.apache.axis2,
+ org.apache.axis2.client,
+ org.apache.axis2.context,
+ org.apache.axis2.transport.http,
+ org.apache.commons.httpclient,
+ org.apache.commons.httpclient.contrib.ssl,
+ org.apache.commons.httpclient.params,
+ org.apache.commons.httpclient.protocol,
+ org.apache.commons.pool,
+ org.apache.commons.pool.impl,
+ org.apache.log4j,
+ com.google.gson,
+ javax.websocket,
+ org.apache.commons.logging,
+ org.osgi.framework,
+ org.osgi.service.component,
+ org.wso2.carbon.context,
+ org.wso2.carbon.databridge.commons,
+ org.wso2.carbon.event.stream.core,
+ org.wso2.carbon.event.stream.core.exception,
+ org.wso2.carbon.utils
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui/src/main/java/org/wso2/carbon/event/output/adapter/extensions/ui/UIEventAdapter.java b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui/src/main/java/org/wso2/carbon/event/output/adapter/extensions/ui/UIEventAdapter.java
new file mode 100644
index 0000000000..f34ee03df5
--- /dev/null
+++ b/components/iot-plugins/das-extensions/org.wso2.carbon.event.output.adapter.extensions.ui/src/main/java/org/wso2/carbon/event/output/adapter/extensions/ui/UIEventAdapter.java
@@ -0,0 +1,459 @@
+/*
+ *
+ * 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.event.output.adapter.extensions.ui;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.databridge.commons.Attribute;
+import org.wso2.carbon.databridge.commons.Event;
+import org.wso2.carbon.databridge.commons.StreamDefinition;
+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.OutputEventAdapterRuntimeException;
+import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException;
+import org.wso2.carbon.event.output.adapter.extensions.ui.internal.ds.OutputAdaptorEventStreamServiceValueHolder;
+import org.wso2.carbon.event.output.adapter.extensions.ui.internal.util.UIEventAdapterConstants;
+import org.wso2.carbon.event.output.adapter.extensions.ui.internal.UIOutputCallbackControllerServiceImpl;
+import org.wso2.carbon.event.output.adapter.extensions.ui.internal.ds.UIEventAdaptorServiceInternalValueHolder;
+import org.wso2.carbon.event.output.adapter.extensions.ui.internal.util.CEPWebSocketSession;
+import org.wso2.carbon.event.stream.core.EventStreamService;
+import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Contains the life cycle of executions regarding the UI Adapter
+ */
+
+public class UIEventAdapter implements OutputEventAdapter {
+
+ private static final Log log = LogFactory.getLog(UIEventAdapter.class);
+ private OutputEventAdapterConfiguration eventAdapterConfiguration;
+ private Map globalProperties;
+ private int queueSize;
+ private LinkedBlockingDeque