diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml
index 2141a6f890c..a3d71577b80 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml
@@ -297,7 +297,41 @@
${carbon.identity.framework.version}
provided
-
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.datasource.commons
+ provided
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.api
+ provided
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.dataservice.commons
+ provided
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.receiver.stub
+ provided
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.stream.stub
+ provided
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.publisher.stub
+ provided
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.stream.persistence.stub
+ provided
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/Attribute.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/Attribute.java
new file mode 100644
index 00000000000..276fea9ee47
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/Attribute.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * This hold the attribute definition.
+ */
+public class Attribute {
+
+ @ApiModelProperty(value = "Event Attribute Name")
+ @JsonProperty("name")
+ private String name;
+ @ApiModelProperty(value = "Event Attribute Type")
+ @JsonProperty("type")
+ private AttributeType type;
+
+ public Attribute() {
+
+ }
+
+ public Attribute(String name, AttributeType attributeType) {
+ this.name = name;
+ this.type = attributeType;
+ }
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public AttributeType getType() {
+ return type;
+ }
+
+ public void setType(AttributeType type) {
+ this.type = type;
+ }
+}
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/AttributeType.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/AttributeType.java
new file mode 100644
index 00000000000..23235612b93
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/AttributeType.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
+
+/**
+ * This hold the definition of the attribute type for the attributes.
+ */
+public enum AttributeType {
+ STRING, LONG, BOOL, INT, FLOAT, DOUBLE;
+
+ @Override
+ public String toString() {
+ return super.toString().toLowerCase();
+ }
+}
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/DeviceTypeEvent.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/DeviceTypeEvent.java
new file mode 100644
index 00000000000..942c0785294
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/DeviceTypeEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * This hold stats data record
+ */
+public class DeviceTypeEvent {
+
+ @ApiModelProperty(value = "Attributes related to device type event")
+ private EventAttributeList eventAttributeList;
+ @ApiModelProperty(value = "Transport to be used for device to server communication.")
+ private TransportType transportType;
+
+
+ public EventAttributeList getEventAttributeList() {
+ return eventAttributeList;
+ }
+
+ public void setEventAttributeList(
+ EventAttributeList eventAttributeList) {
+ this.eventAttributeList = eventAttributeList;
+ }
+
+ public TransportType getTransportType() {
+ return transportType;
+ }
+
+ public void setTransportType(TransportType transportType) {
+ this.transportType = transportType;
+ }
+}
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/EventAttributeList.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/EventAttributeList.java
new file mode 100644
index 00000000000..fe9bd39e032
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/EventAttributeList.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+import org.wso2.carbon.device.mgt.common.Device;
+import org.wso2.carbon.device.mgt.jaxrs.beans.BasePaginatedResult;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This holds event attributes
+ */
+public class EventAttributeList {
+
+ private List attributes = new ArrayList<>();
+
+ @ApiModelProperty(value = "List of Event Attributes")
+ @JsonProperty("attributes")
+ public List getList() {
+ return attributes;
+ }
+
+ public void setList(List attributes) {
+ this.attributes = attributes;
+ }
+
+}
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/EventRecords.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/EventRecords.java
new file mode 100644
index 00000000000..bb3347c1ba3
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/EventRecords.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+import org.wso2.carbon.device.mgt.common.Device;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.wso2.carbon.analytics.datasource.commons.Record;
+import org.wso2.carbon.device.mgt.jaxrs.beans.BasePaginatedResult;
+
+/**
+ * This hold stats data record
+ */
+public class EventRecords extends BasePaginatedResult {
+
+ private List records = new ArrayList<>();
+
+ @ApiModelProperty(value = "List of records returned")
+ @JsonProperty("records")
+ public List getRecord() {
+ return records;
+ }
+
+ public void setList(List records) {
+ this.records = records;
+ setCount(records.size());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{\n");
+
+ sb.append(" count: ").append(getCount()).append(",\n");
+ sb.append(" records: [").append(records).append("\n");
+ sb.append("]}\n");
+ return sb.toString();
+ }
+
+}
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/TransportType.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/TransportType.java
new file mode 100644
index 00000000000..58eae4e6165
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/analytics/TransportType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
+
+/**
+ * This hold the default transport types support by the server.
+ */
+public enum TransportType {
+ HTTP, MQTT;
+}
+
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java
new file mode 100644
index 00000000000..803c91ffce8
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java
@@ -0,0 +1,294 @@
+package org.wso2.carbon.device.mgt.jaxrs.service.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import io.swagger.annotations.Extension;
+import io.swagger.annotations.ExtensionProperty;
+import io.swagger.annotations.Info;
+import io.swagger.annotations.ResponseHeader;
+import io.swagger.annotations.SwaggerDefinition;
+import io.swagger.annotations.Tag;
+import org.wso2.carbon.apimgt.annotations.api.Scope;
+import org.wso2.carbon.apimgt.annotations.api.Scopes;
+import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceTypeList;
+import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.DeviceTypeEvent;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.TransportType;
+import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
+
+import javax.validation.Valid;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@SwaggerDefinition(
+ info = @Info(
+ version = "1.0.0",
+ title = "",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = "name", value = "DeviceEventManagement"),
+ @ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/device-types/events"),
+ })
+ }
+ ),
+ tags = {
+ @Tag(name = "device_management", description = "")
+ }
+)
+@Scopes(
+ scopes = {
+ @Scope(
+ name = "Add or Delete Event Definition for device type",
+ description = "Add or Delete Event Definition for device type",
+ key = "perm:device-types:events",
+ permissions = {"/device-mgt/device-type/add"}
+ ),
+ @Scope(
+ name = "Get Feature Details of a Device Type",
+ description = "Get Feature Details of a Device Type",
+ key = "perm:device-types:events:view",
+ permissions = {"/device-mgt/devices/owning-device/view"}
+ )
+ }
+)
+@Path("/device-types/events")
+@Api(value = "Device Event Management", description = "This API corresponds to all tasks related to device " +
+ "event management")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface DeviceEventManagementService {
+
+ @POST
+ @Path("/{type}")
+ @ApiOperation(
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "POST",
+ value = "Add Event Type Defnition",
+ notes = "Add the event definition for the device.",
+ tags = "Device Event Management",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = Constants.SCOPE, value = "perm:device-types:events")
+ })
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "OK. \n Successfully added the event defintion.",
+ response = DeviceTypeList.class,
+ responseHeaders = {
+ @ResponseHeader(
+ name = "Content-Type",
+ description = "The content type of the body"),
+ @ResponseHeader(
+ name = "ETag",
+ description = "Entity Tag of the response resource.\n" +
+ "Used by caches, or in conditional requests."),
+ @ResponseHeader(
+ name = "Last-Modified",
+ description =
+ "Date and time the resource was last modified.\n" +
+ "Used by caches, or in conditional requests."),
+ }
+ ),
+ @ApiResponse(
+ code = 400,
+ message =
+ "Bad Request. \n"),
+ @ApiResponse(
+ code = 406,
+ message = "Not Acceptable.\n The requested media type is not supported"),
+ @ApiResponse(
+ code = 500,
+ message = "Internal Server Error. \n Server error occurred while fetching the " +
+ "list of supported device types.",
+ response = ErrorResponse.class)
+ }
+ )
+ Response deployDeviceTypeEventDefinition(@ApiParam(name = "type", value = "name of the device type", required = false)
+ @PathParam("type")String deviceType,
+ @ApiParam(name = "deviceTypeEvent", value = "DeviceTypeEvent object with data.", required = true)
+ @Valid DeviceTypeEvent deviceTypeEvent);
+
+ @DELETE
+ @Path("/{type}")
+ @ApiOperation(
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "DELETE",
+ value = "Delete Event Type Defnition",
+ notes = "Delete the event definition for the device.",
+ tags = "Device Event Management",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = Constants.SCOPE, value = "perm:device-types:events")
+ })
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "OK. \n Successfully deleted the event definition.",
+ response = DeviceTypeList.class,
+ responseHeaders = {
+ @ResponseHeader(
+ name = "Content-Type",
+ description = "The content type of the body"),
+ @ResponseHeader(
+ name = "ETag",
+ description = "Entity Tag of the response resource.\n" +
+ "Used by caches, or in conditional requests."),
+ @ResponseHeader(
+ name = "Last-Modified",
+ description =
+ "Date and time the resource was last modified.\n" +
+ "Used by caches, or in conditional requests."),
+ }
+ ),
+ @ApiResponse(
+ code = 400,
+ message =
+ "Bad Request. \n"),
+ @ApiResponse(
+ code = 406,
+ message = "Not Acceptable.\n The requested media type is not supported"),
+ @ApiResponse(
+ code = 500,
+ message = "Internal Server Error. \n Server error occurred while fetching the " +
+ "list of supported device types.",
+ response = ErrorResponse.class)
+ }
+ )
+ Response deleteDeviceTypeEventDefinitions(@ApiParam(name = "type", value = "name of the device type", required = false)
+ @PathParam("type")String deviceType);
+
+ @GET
+ @Path("/{type}/{deviceId}")
+ @ApiOperation(
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "GET",
+ value = "Getting Device Events",
+ notes = "Get the events for the device.",
+ tags = "Device Event Management",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = Constants.SCOPE, value = "perm:device-types:events:view")
+ })
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "OK. \n Successfully fetched the event definition.",
+ response = DeviceTypeList.class,
+ responseHeaders = {
+ @ResponseHeader(
+ name = "Content-Type",
+ description = "The content type of the body"),
+ @ResponseHeader(
+ name = "ETag",
+ description = "Entity Tag of the response resource.\n" +
+ "Used by caches, or in conditional requests."),
+ @ResponseHeader(
+ name = "Last-Modified",
+ description =
+ "Date and time the resource was last modified.\n" +
+ "Used by caches, or in conditional requests."),
+ }
+ ),
+ @ApiResponse(
+ code = 400,
+ message =
+ "Bad Request. \n"),
+ @ApiResponse(
+ code = 406,
+ message = "Not Acceptable.\n The requested media type is not supported"),
+ @ApiResponse(
+ code = 500,
+ message = "Internal Server Error. \n Server error occurred while fetching the " +
+ "list of supported device types.",
+ response = ErrorResponse.class)
+ }
+ )
+ Response getData(@ApiParam(name = "deviceId", value = "id of the device ", required = false)
+ @PathParam("deviceId") String deviceId,
+ @ApiParam(name = "from", value = "unix timestamp to retrieve", required = false)
+ @QueryParam("from") long from,
+ @ApiParam(name = "to", value = "unix time to retrieve", required = false)
+ @QueryParam("to") long to,
+ @ApiParam(name = "type", value = "name of the device type", required = false)
+ @PathParam("type") String deviceType,
+ @ApiParam(name = "offset", value = "offset of the records that needs to be picked up", required = false)
+ @QueryParam("offset") int offset,
+ @ApiParam(name = "limit", value = "limit of the records that needs to be picked up", required = false)
+ @QueryParam("limit") int limit);
+
+ @GET
+ @Path("/{type}")
+ @ApiOperation(
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "GET",
+ value = "Getting Event Type Defnition",
+ notes = "Get the event definition for the device.",
+ tags = "Device Event Management",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = Constants.SCOPE, value = "perm:device-types:events:view")
+ })
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "OK. \n Successfully fetched the event defintion.",
+ response = DeviceTypeList.class,
+ responseHeaders = {
+ @ResponseHeader(
+ name = "Content-Type",
+ description = "The content type of the body"),
+ @ResponseHeader(
+ name = "ETag",
+ description = "Entity Tag of the response resource.\n" +
+ "Used by caches, or in conditional requests."),
+ @ResponseHeader(
+ name = "Last-Modified",
+ description =
+ "Date and time the resource was last modified.\n" +
+ "Used by caches, or in conditional requests."),
+ }
+ ),
+ @ApiResponse(
+ code = 400,
+ message =
+ "Bad Request. \n"),
+ @ApiResponse(
+ code = 406,
+ message = "Not Acceptable.\n The requested media type is not supported"),
+ @ApiResponse(
+ code = 500,
+ message = "Internal Server Error. \n Server error occurred while fetching the " +
+ "list of supported device types.",
+ response = ErrorResponse.class)
+ }
+ )
+ Response getDeviceTypeEventDefinition(@ApiParam(name = "type", value = "name of the device type", required = false)
+ @PathParam("type")String deviceType) ;
+
+}
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java
new file mode 100644
index 00000000000..69ff1e3e0d9
--- /dev/null
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java
@@ -0,0 +1,655 @@
+package org.wso2.carbon.device.mgt.jaxrs.service.impl;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.client.Options;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.axis2.java.security.SSLProtocolSocketFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
+import org.wso2.carbon.analytics.api.AnalyticsDataAPIUtil;
+import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
+import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
+import org.wso2.carbon.analytics.dataservice.commons.SortByField;
+import org.wso2.carbon.analytics.dataservice.commons.SortType;
+import org.wso2.carbon.analytics.stream.persistence.stub
+ .EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException;
+import org.wso2.carbon.analytics.stream.persistence.stub.EventStreamPersistenceAdminServiceStub;
+import org.wso2.carbon.analytics.stream.persistence.stub.dto.AnalyticsTable;
+import org.wso2.carbon.analytics.stream.persistence.stub.dto.AnalyticsTableRecord;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.base.ServerConfiguration;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.core.util.Utils;
+import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
+import org.wso2.carbon.device.mgt.common.DeviceManagementException;
+import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.DeviceTypeEvent;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventRecords;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.Attribute;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.AttributeType;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList;
+import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.TransportType;
+import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceEventManagementService;
+import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
+import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub;
+import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub;
+import org.wso2.carbon.event.receiver.stub.types.BasicInputAdapterPropertyDto;
+import org.wso2.carbon.event.stream.stub.EventStreamAdminServiceStub;
+import org.wso2.carbon.event.stream.stub.types.EventStreamAttributeDto;
+import org.wso2.carbon.event.stream.stub.types.EventStreamDefinitionDto;
+import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
+import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.analytics.datasource.commons.Record;
+import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.CertificateException;
+import javax.validation.Valid;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.RemoteException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * This is used for simple analytics purpose, to create streams and receiver dynamically and a common endpoint
+ * to retrieve data.
+ */
+@Path("/device-types/events")
+public class DeviceEventManagementServiceImpl implements DeviceEventManagementService {
+
+ private static final Log log = LogFactory.getLog(DeviceEventManagementServiceImpl.class);
+
+ private static final String DAS_PORT = "${iot.analytics.https.port}";
+ private static final String DAS_HOST_NAME = "${iot.analytics.host}";
+ private static final String DEFAULT_HTTP_PROTOCOL = "https";
+ private static final String DAS_ADMIN_SERVICE_EP = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME
+ + ":" + DAS_PORT + "/services/EventReceiverAdminService" + "/";
+ private static final String AUTHORIZATION_HEADER = "Authorization";
+ private static final String AUTHORIZATION_HEADER_VALUE = "Bearer";
+ private static final String KEY_STORE_TYPE = "JKS";
+ private static final String TRUST_STORE_TYPE = "JKS";
+ private static final String KEY_MANAGER_TYPE = "SunX509"; //Default Key Manager Type
+ private static final String TRUST_MANAGER_TYPE = "SunX509"; //Default Trust Manager Type
+ private static final String SSLV3 = "SSLv3";
+ private static final String DEFAULT_STREAM_VERSION = "1.0.0";
+ private static final String DEFAULT_EVENT_STORE_NAME = "EVENT_STORE";
+ private static final String DEFAULT_WEBSOCKET_PUBLISHER_ADAPTER_TYPE = "secured-websocket";
+
+ private static KeyStore keyStore;
+ private static KeyStore trustStore;
+ private static char[] keyStorePassword;
+ private static SSLContext sslContext;
+ static {
+ String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password");
+ String trustStorePassword = ServerConfiguration.getInstance().getFirstProperty(
+ "Security.TrustStore.Password");
+ String keyStoreLocation = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Location");
+ String trustStoreLocation = ServerConfiguration.getInstance().getFirstProperty(
+ "Security.TrustStore.Location");
+
+ //Call to load the keystore.
+ try {
+ loadKeyStore(keyStoreLocation, keyStorePassword);
+ //Call to load the TrustStore.
+ loadTrustStore(trustStoreLocation, trustStorePassword);
+ //Create the SSL context with the loaded TrustStore/keystore.
+ initSSLConnection();
+ } catch (KeyStoreException|IOException|CertificateException|NoSuchAlgorithmException
+ | UnrecoverableKeyException | KeyManagementException e) {
+ log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Deploy Event Stream, Receiver, Publisher and Store Configuration.
+ */
+ @POST
+ @Path("/{type}")
+ @Override
+ public Response deployDeviceTypeEventDefinition(@PathParam("type") String deviceType, @Valid DeviceTypeEvent deviceTypeEvent) {
+ TransportType transportType = deviceTypeEvent.getTransportType();
+ EventAttributeList eventAttributes = deviceTypeEvent.getEventAttributeList();
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ boolean superTenantMode = false;
+ try {
+ if (eventAttributes == null || eventAttributes.getList() == null || eventAttributes.getList().size() == 0 ||
+ deviceType == null ||
+ !DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
+ String errorMessage = "Invalid device type";
+ log.error(errorMessage);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ String eventReceiverName = getReceiverName(deviceType, tenantDomain);
+ String streamName = getStreamDefinition(deviceType, tenantDomain);
+ String streamNameWithVersion = streamName + ":" + DEFAULT_STREAM_VERSION;
+ publishStreamDefinitons(streamName, DEFAULT_STREAM_VERSION, deviceType, eventAttributes);
+ publishEventReceivers(eventReceiverName, streamNameWithVersion, transportType, tenantDomain, deviceType);
+ publishEventStore(streamName, DEFAULT_STREAM_VERSION, eventAttributes);
+ publishWebsocketPublisherDefinition(streamNameWithVersion, deviceType);
+ superTenantMode = true;
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
+ MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
+ if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
+ publishStreamDefinitons(streamName, DEFAULT_STREAM_VERSION, deviceType, eventAttributes);
+ publishEventReceivers(eventReceiverName, streamNameWithVersion, transportType, tenantDomain, deviceType);
+ }
+ return Response.ok().build();
+ } catch (AxisFault e) {
+ log.error("failed to create event definitions for tenantDomain:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (RemoteException e) {
+ log.error("Failed to connect with the remote services:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (JWTClientException e) {
+ log.error("Failed to generate jwt token for tenantDomain:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (UserStoreException e) {
+ log.error("Failed to connect with the user store, tenantDomain: " + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (DeviceManagementException e) {
+ log.error("Failed to access device management service, tenantDomain: " + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException e) {
+ log.error("Failed to create event store for, tenantDomain: " + tenantDomain + " deviceType" + deviceType, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } finally {
+ if (superTenantMode) {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+ }
+
+ @DELETE
+ @Path("/{type}")
+ @Override
+ public Response deleteDeviceTypeEventDefinitions(@PathParam("type") String deviceType) {
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ try {
+ if (deviceType == null ||
+ !DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
+ String errorMessage = "Invalid device type";
+ log.error(errorMessage);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ String eventReceiverName = getReceiverName(deviceType, tenantDomain);
+ String eventPublisherName = deviceType.trim().toLowerCase() + "_websocket_publisher";
+ String streamName = getStreamDefinition(deviceType, tenantDomain);
+
+ getEventStreamAdminServiceStub().removeEventStreamDefinition(streamName, DEFAULT_STREAM_VERSION);
+ getEventReceiverAdminServiceStub().undeployActiveEventReceiverConfiguration(eventReceiverName);
+ getEventPublisherAdminServiceStub().undeployActiveEventPublisherConfiguration(eventPublisherName);
+ return Response.ok().build();
+ } catch (AxisFault e) {
+ log.error("failed to create event definitions for tenantDomain:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (RemoteException e) {
+ log.error("Failed to connect with the remote services:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (JWTClientException e) {
+ log.error("Failed to generate jwt token for tenantDomain:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (UserStoreException e) {
+ log.error("Failed to connect with the user store, tenantDomain: " + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (DeviceManagementException e) {
+ log.error("Failed to access device management service, tenantDomain: " + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ @GET
+ @Path("/{type}/{deviceId}")
+ @Override
+ public Response getData(@PathParam("deviceId") String deviceId, @QueryParam("from") long from,
+ @QueryParam("to") long to,@PathParam("type") String deviceType, @QueryParam("offset")
+ int offset, @QueryParam("limit") int limit) {
+ String fromDate = String.valueOf(from);
+ String toDate = String.valueOf(to);
+ String query = "deviceId:" + deviceId + " AND _timestamp : [" + fromDate + " TO " + toDate + "]";
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ String sensorTableName = getTableName(getStreamDefinition(deviceType, tenantDomain));
+ try {
+ if (deviceType == null ||
+ !DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
+ String errorMessage = "Invalid device type";
+ log.error(errorMessage);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
+ new DeviceIdentifier(deviceId, deviceType))) {
+ return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
+ }
+ List sortByFields = new ArrayList<>();
+ SortByField sortByField = new SortByField("_timestamp", SortType.ASC);
+ sortByFields.add(sortByField);
+ EventRecords eventRecords = getAllEventsForDevice(sensorTableName, query, sortByFields, offset, limit);
+ return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build();
+ } catch (AnalyticsException e) {
+ String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
+ log.error(errorMsg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
+ } catch (DeviceAccessAuthorizationException e) {
+ log.error(e.getErrorMessage(), e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (DeviceManagementException e) {
+ String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
+ log.error(errorMsg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
+ }
+ }
+
+ @GET
+ @Path("/{type}")
+ @Override
+ public Response getDeviceTypeEventDefinition(@PathParam("type") String deviceType) {
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ try {
+ if (deviceType == null ||
+ !DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
+ String errorMessage = "Invalid device type";
+ log.error(errorMessage);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ String streamName = getStreamDefinition(deviceType, tenantDomain);
+ EventStreamDefinitionDto eventStreamDefinitionDto = getEventStreamAdminServiceStub().getStreamDefinitionDto(
+ streamName + ":" + DEFAULT_STREAM_VERSION);
+ if (eventStreamDefinitionDto == null) {
+ return Response.status(Response.Status.NO_CONTENT).build();
+ }
+ EventStreamAttributeDto[] eventStreamAttributeDtos = eventStreamDefinitionDto.getPayloadData();
+ EventAttributeList eventAttributeList = new EventAttributeList();
+ List attributes = new ArrayList<>();
+ for (EventStreamAttributeDto eventStreamAttributeDto : eventStreamAttributeDtos) {
+ attributes.add(new Attribute(eventStreamAttributeDto.getAttributeName()
+ , AttributeType.valueOf(eventStreamAttributeDto.getAttributeType().toUpperCase())));
+ }
+ eventAttributeList.setList(attributes);
+ return Response.ok().entity(eventAttributeList).build();
+ } catch (AxisFault e) {
+ log.error("failed to create event definitions for tenantDomain:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (RemoteException e) {
+ log.error("Failed to connect with the remote services:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (JWTClientException e) {
+ log.error("Failed to generate jwt token for tenantDomain:" + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (UserStoreException e) {
+ log.error("Failed to connect with the user store, tenantDomain: " + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (DeviceManagementException e) {
+ log.error("Failed to access device management service, tenantDomain: " + tenantDomain, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+
+ private void publishEventReceivers(String eventRecieverName, String streamNameWithVersion, TransportType transportType
+ , String requestedTenantDomain, String deviceType)
+ throws RemoteException, UserStoreException, JWTClientException {
+ EventReceiverAdminServiceStub receiverAdminServiceStub = getEventReceiverAdminServiceStub();
+ String adapterType = "oauth-mqtt";
+ BasicInputAdapterPropertyDto basicInputAdapterPropertyDtos[];
+ if (transportType == TransportType.MQTT) {
+ basicInputAdapterPropertyDtos = new BasicInputAdapterPropertyDto[4];
+ basicInputAdapterPropertyDtos[0] = getBasicInputAdapterPropertyDto("topic", requestedTenantDomain
+ + "/" + deviceType + "/+/events");
+ basicInputAdapterPropertyDtos[1] = getBasicInputAdapterPropertyDto("contentValidator", "iot-mqtt");
+ basicInputAdapterPropertyDtos[2] = getBasicInputAdapterPropertyDto("cleanSession", "true");
+ basicInputAdapterPropertyDtos[3] = getBasicInputAdapterPropertyDto("clientId", generateUUID());
+ } else {
+ adapterType = "oauth-http";
+ basicInputAdapterPropertyDtos = new BasicInputAdapterPropertyDto[1];
+ basicInputAdapterPropertyDtos[0] = getBasicInputAdapterPropertyDto("contentValidator", "iot-mqtt");
+ }
+ receiverAdminServiceStub.deployJsonEventReceiverConfiguration(eventRecieverName, streamNameWithVersion
+ , adapterType, null, basicInputAdapterPropertyDtos, false);
+ }
+
+ private void publishStreamDefinitons(String streamName, String version, String deviceType
+ , EventAttributeList eventAttributes)
+ throws RemoteException, UserStoreException, JWTClientException {
+ EventStreamAdminServiceStub eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
+ EventStreamDefinitionDto eventStreamDefinitionDto = new EventStreamDefinitionDto();
+ eventStreamDefinitionDto.setName(streamName);
+ eventStreamDefinitionDto.setVersion(version);
+ EventStreamAttributeDto eventStreamAttributeDtos[] = new EventStreamAttributeDto[eventAttributes.getList().size()];
+ int i = 0;
+ for (Attribute attribute : eventAttributes.getList()) {
+ EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
+ eventStreamAttributeDto.setAttributeName(attribute.getName());
+ eventStreamAttributeDto.setAttributeType(attribute.getType().toString());
+ eventStreamAttributeDtos[i] = eventStreamAttributeDto;
+ i++;
+ }
+ EventStreamAttributeDto metaData[] = new EventStreamAttributeDto[1];
+ EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
+ eventStreamAttributeDto.setAttributeName("deviceId");
+ eventStreamAttributeDto.setAttributeType(AttributeType.STRING.toString());
+ metaData[0] = eventStreamAttributeDto;
+ eventStreamDefinitionDto.setMetaData(metaData);
+ eventStreamDefinitionDto.setPayloadData(eventStreamAttributeDtos);
+ String streamId = streamName + ":" + version;
+ if (eventStreamAdminServiceStub.getStreamDefinitionAsString(streamId) != null) {
+ eventStreamAdminServiceStub.editEventStreamDefinitionAsDto(eventStreamDefinitionDto, streamId);
+ } else {
+ eventStreamAdminServiceStub.addEventStreamDefinitionAsDto(eventStreamDefinitionDto);
+ }
+
+ }
+
+ private void publishEventStore(String streamName, String version, EventAttributeList eventAttributes)
+ throws RemoteException, UserStoreException, JWTClientException,
+ EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException {
+ EventStreamPersistenceAdminServiceStub eventStreamAdminServiceStub = getEventStreamPersistenceAdminServiceStub();
+ AnalyticsTable analyticsTable = new AnalyticsTable();
+ analyticsTable.setRecordStoreName(DEFAULT_EVENT_STORE_NAME);
+ analyticsTable.setStreamVersion(version);
+ analyticsTable.setTableName(getTableName(streamName));
+ AnalyticsTableRecord analyticsTableRecords[] = new AnalyticsTableRecord[eventAttributes.getList().size() + 1];
+ int i = 0;
+ for (Attribute attribute : eventAttributes.getList()) {
+ AnalyticsTableRecord analyticsTableRecord = new AnalyticsTableRecord();
+ analyticsTableRecord.setColumnName(attribute.getName());
+ analyticsTableRecord.setColumnType(attribute.getType().toString().toUpperCase());
+ analyticsTableRecord.setFacet(false);
+ analyticsTableRecord.setIndexed(true);
+ analyticsTableRecord.setPersist(true);
+ analyticsTableRecord.setPrimaryKey(false);
+ analyticsTableRecord.setScoreParam(false);
+ analyticsTableRecords[i] = analyticsTableRecord;
+ i++;
+ }
+ AnalyticsTableRecord analyticsTableRecord = new AnalyticsTableRecord();
+ analyticsTableRecord.setColumnName("meta_deviceId");
+ analyticsTableRecord.setColumnType(AttributeType.STRING.toString().toUpperCase());
+ analyticsTableRecord.setFacet(false);
+ analyticsTableRecord.setIndexed(true);
+ analyticsTableRecord.setPersist(true);
+ analyticsTableRecord.setPrimaryKey(false);
+ analyticsTableRecord.setScoreParam(false);
+ analyticsTableRecords[i] = analyticsTableRecord;
+ analyticsTable.setAnalyticsTableRecords(analyticsTableRecords);
+ eventStreamAdminServiceStub.addAnalyticsTable(analyticsTable);
+
+ }
+
+ private void publishWebsocketPublisherDefinition(String streamNameWithVersion, String deviceType)
+ throws RemoteException, UserStoreException, JWTClientException {
+ EventPublisherAdminServiceStub eventPublisherAdminServiceStub = getEventPublisherAdminServiceStub();
+ String eventPublisherName = deviceType.trim().toLowerCase() + "_websocket_publisher";
+ eventPublisherAdminServiceStub.startdeployJsonEventPublisherConfiguration(eventPublisherName
+ , streamNameWithVersion, DEFAULT_WEBSOCKET_PUBLISHER_ADAPTER_TYPE, null, null,null, false, null);
+ }
+
+ private EventStreamAdminServiceStub getEventStreamAdminServiceStub()
+ throws AxisFault, UserStoreException, JWTClientException {
+ EventStreamAdminServiceStub eventStreamAdminServiceStub = new EventStreamAdminServiceStub(
+ Utils.replaceSystemProperty(DAS_ADMIN_SERVICE_EP));
+ Options streamOptions = eventStreamAdminServiceStub._getServiceClient().getOptions();
+ if (streamOptions == null) {
+ streamOptions = new Options();
+ }
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
+ .getRealmConfiguration().getAdminUserName() + "@" + tenantDomain;
+ JWTClient jwtClient = DeviceMgtAPIUtils.getJWTClientManagerService().getJWTClient();
+
+ String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
+ jwtClient.getJwtToken(username).getBytes()));
+
+ List list = new ArrayList<>();
+ Header httpHeader = new Header();
+ httpHeader.setName(AUTHORIZATION_HEADER);
+ httpHeader.setValue(authValue);
+ list.add(httpHeader);//"https"
+ streamOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
+ streamOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
+ , new Protocol(DEFAULT_HTTP_PROTOCOL
+ , (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
+ , Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
+ eventStreamAdminServiceStub._getServiceClient().setOptions(streamOptions);
+ return eventStreamAdminServiceStub;
+ }
+
+ private EventReceiverAdminServiceStub getEventReceiverAdminServiceStub()
+ throws AxisFault, UserStoreException, JWTClientException {
+ EventReceiverAdminServiceStub receiverAdminServiceStub = new EventReceiverAdminServiceStub(
+ Utils.replaceSystemProperty(DAS_ADMIN_SERVICE_EP));
+ Options eventReciverOptions = receiverAdminServiceStub._getServiceClient().getOptions();
+ if (eventReciverOptions == null) {
+ eventReciverOptions = new Options();
+ }
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
+ .getRealmConfiguration().getAdminUserName() + "@" + tenantDomain;
+ JWTClient jwtClient = DeviceMgtAPIUtils.getJWTClientManagerService().getJWTClient();
+
+ String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
+ jwtClient.getJwtToken(username).getBytes()));
+
+ List list = new ArrayList<>();
+ Header httpHeader = new Header();
+ httpHeader.setName(AUTHORIZATION_HEADER);
+ httpHeader.setValue(authValue);
+ list.add(httpHeader);//"https"
+
+ eventReciverOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
+ eventReciverOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
+ , new Protocol(DEFAULT_HTTP_PROTOCOL
+ , (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
+ , Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
+ receiverAdminServiceStub._getServiceClient().setOptions(eventReciverOptions);
+ return receiverAdminServiceStub;
+ }
+
+ private EventPublisherAdminServiceStub getEventPublisherAdminServiceStub()
+ throws AxisFault, UserStoreException, JWTClientException {
+ EventPublisherAdminServiceStub eventPublisherAdminServiceStub = new EventPublisherAdminServiceStub(
+ Utils.replaceSystemProperty(DAS_ADMIN_SERVICE_EP));
+ Options eventReciverOptions = eventPublisherAdminServiceStub._getServiceClient().getOptions();
+ if (eventReciverOptions == null) {
+ eventReciverOptions = new Options();
+ }
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
+ .getRealmConfiguration().getAdminUserName() + "@" + tenantDomain;
+ JWTClient jwtClient = DeviceMgtAPIUtils.getJWTClientManagerService().getJWTClient();
+
+ String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
+ jwtClient.getJwtToken(username).getBytes()));
+
+ List list = new ArrayList<>();
+ Header httpHeader = new Header();
+ httpHeader.setName(AUTHORIZATION_HEADER);
+ httpHeader.setValue(authValue);
+ list.add(httpHeader);//"https"
+
+ eventReciverOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
+ eventReciverOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
+ , new Protocol(DEFAULT_HTTP_PROTOCOL
+ , (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
+ , Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
+ eventPublisherAdminServiceStub._getServiceClient().setOptions(eventReciverOptions);
+ return eventPublisherAdminServiceStub;
+ }
+
+ private EventStreamPersistenceAdminServiceStub getEventStreamPersistenceAdminServiceStub()
+ throws AxisFault, UserStoreException, JWTClientException {
+ EventStreamPersistenceAdminServiceStub eventStreamPersistenceAdminServiceStub
+ = new EventStreamPersistenceAdminServiceStub(
+ Utils.replaceSystemProperty(DAS_ADMIN_SERVICE_EP));
+ Options eventReciverOptions = eventStreamPersistenceAdminServiceStub._getServiceClient().getOptions();
+ if (eventReciverOptions == null) {
+ eventReciverOptions = new Options();
+ }
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
+ .getRealmConfiguration().getAdminUserName() + "@" + tenantDomain;
+ JWTClient jwtClient = DeviceMgtAPIUtils.getJWTClientManagerService().getJWTClient();
+
+ String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
+ jwtClient.getJwtToken(username).getBytes()));
+
+ List list = new ArrayList<>();
+ Header httpHeader = new Header();
+ httpHeader.setName(AUTHORIZATION_HEADER);
+ httpHeader.setValue(authValue);
+ list.add(httpHeader);//"https"
+
+ eventReciverOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
+ eventReciverOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
+ , new Protocol(DEFAULT_HTTP_PROTOCOL
+ , (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
+ , Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
+ eventStreamPersistenceAdminServiceStub._getServiceClient().setOptions(eventReciverOptions);
+ return eventStreamPersistenceAdminServiceStub;
+ }
+
+ /**
+ * Loads the keystore.
+ *
+ * @param keyStorePath - the path of the keystore
+ * @param ksPassword - the keystore password
+ */
+ private static void loadKeyStore(String keyStorePath, String ksPassword)
+ throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+ InputStream fis = null;
+ try {
+ keyStorePassword = ksPassword.toCharArray();
+ keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
+ fis = new FileInputStream(keyStorePath);
+ keyStore.load(fis, keyStorePassword);
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ }
+
+ /**
+ * Loads the trustore
+ *
+ * @param trustStorePath - the trustore path in the filesystem.
+ * @param tsPassword - the truststore password
+ */
+ private static void loadTrustStore(String trustStorePath, String tsPassword)
+ throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+
+ InputStream fis = null;
+ try {
+ trustStore = KeyStore.getInstance(TRUST_STORE_TYPE);
+ fis = new FileInputStream(trustStorePath);
+ trustStore.load(fis, tsPassword.toCharArray());
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ }
+
+ /**
+ * Initializes the SSL Context
+ */
+ private static void initSSLConnection() throws NoSuchAlgorithmException, UnrecoverableKeyException,
+ KeyStoreException, KeyManagementException {
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
+ keyManagerFactory.init(keyStore, keyStorePassword);
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
+ trustManagerFactory.init(trustStore);
+
+ // Create and initialize SSLContext for HTTPS communication
+ sslContext = SSLContext.getInstance(SSLV3);
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ SSLContext.setDefault(sslContext);
+ }
+
+ private BasicInputAdapterPropertyDto getBasicInputAdapterPropertyDto(String key, String value) {
+ BasicInputAdapterPropertyDto basicInputAdapterPropertyDto = new BasicInputAdapterPropertyDto();
+ basicInputAdapterPropertyDto.setKey(key);
+ basicInputAdapterPropertyDto.setValue(value);
+ return basicInputAdapterPropertyDto;
+ }
+
+ private static String generateUUID() {
+ UUID uuid = UUID.randomUUID();
+ long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong();
+ return Long.toString(l, Character.MAX_RADIX);
+ }
+
+ private String getStreamDefinition(String deviceType, String tenantDomain) {
+ return tenantDomain.toLowerCase() + "." + deviceType.toLowerCase();
+ }
+
+ private String getTableName(String streamName) {
+ return streamName.toUpperCase().replace('.', '_');
+ }
+
+ private String getReceiverName(String deviceType, String tenantDomain) {
+ return deviceType.trim().toLowerCase() + "-" + tenantDomain.toLowerCase() + "-receiver";
+ }
+
+ 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;
+ }
+
+ protected static EventRecords getAllEventsForDevice(String tableName, String query, List sortByFields
+ , int offset, int limit) throws AnalyticsException {
+ int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
+ AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
+ int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
+ if (eventCount == 0) {
+ return null;
+ }
+ List resultEntries = analyticsDataAPI.search(tenantId, tableName, query, offset, limit,
+ sortByFields);
+ List recordIds = getRecordIds(resultEntries);
+ AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds);
+ EventRecords eventRecords = new EventRecords();
+ eventRecords.setList(AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response));
+ return eventRecords;
+ }
+
+ private static List getRecordIds(List searchResults) {
+ List ids = new ArrayList<>();
+ for (SearchResultEntry searchResult : searchResults) {
+ ids.add(searchResult.getId());
+ }
+ return ids;
+ }
+
+}
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java
index 4bbbfdb1302..d34a8ee3e4c 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java
@@ -91,7 +91,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@POST
@Override
- public Response addDevice(Device device) {
+ public Response addDevice(@Valid Device device) {
if (device == null) {
String errorMessage = "The payload of the device enrollment is incorrect.";
return Response.status(Response.Status.BAD_REQUEST).entity(errorMessage).build();
@@ -728,7 +728,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@POST
@Path("/{type}/operations")
- public Response addOperation(@PathParam("type") String type, OperationRequest operationRequest) {
+ public Response addOperation(@PathParam("type") String type, @Valid OperationRequest operationRequest) {
try {
if (operationRequest == null || operationRequest.getDeviceIdentifiers() == null) {
String errorMessage = "Device identifier list is empty";
@@ -794,7 +794,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@PUT
@Path("/{type}/{id}/operations")
- public Response updateOperation(@PathParam("type") String type, @PathParam("id") String deviceId, Operation operation) {
+ public Response updateOperation(@PathParam("type") String type, @PathParam("id") String deviceId, @Valid Operation operation) {
try {
if (operation == null) {
String errorMessage = "Device identifier list is empty";
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml
index fd6c5e0309b..77e7023cb3f 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml
@@ -40,7 +40,8 @@
-
+
+
@@ -82,7 +83,8 @@
-
+
+
diff --git a/pom.xml b/pom.xml
index 6afe10b8ee2..494c985a013 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1396,6 +1396,41 @@
org.wso2.carbon.event.output.adapter.core
${carbon.analytics.common.version}
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.receiver.stub
+ ${carbon.analytics.common.version}
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.datasource.commons
+ ${carbon.analytics.version}
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.dataservice.commons
+ ${carbon.analytics.version}
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.stream.stub
+ ${carbon.analytics.common.version}
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.publisher.stub
+ ${carbon.analytics.common.version}
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.api
+ ${carbon.analytics.version}
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.stream.persistence.stub
+ ${carbon.analytics.common.version}
+
org.wso2.carbon.devicemgt
org.wso2.carbon.device.mgt.extensions.device.type.deployer
@@ -1820,6 +1855,8 @@
5.1.3
[5.1.3,6.0.0)
+ 1.3.3
+ [1.3.0,2.0.0)
4.6.0