From ea3ed9c44408658e15ea621c803bac5752d73e8a Mon Sep 17 00:00:00 2001 From: Rasika Perera Date: Mon, 29 May 2017 11:51:41 +0530 Subject: [PATCH] Added Geo Service into Device Mgt Core --- .../org.wso2.carbon.device.mgt.api/pom.xml | 10 + .../mgt/jaxrs/service/api/GeoService.java | 404 +++++++++++ .../jaxrs/service/impl/GeoServiceImpl.java | 315 +++++++++ .../mgt/jaxrs/util/DeviceMgtAPIUtils.java | 23 + .../src/main/webapp/WEB-INF/cxf-servlet.xml | 2 + .../org.wso2.carbon.device.mgt.common/pom.xml | 9 + .../mgt/common/DeviceManagementConstants.java | 30 + .../device/mgt/common/geo/service/Alert.java | 180 +++++ .../device/mgt/common/geo/service/Event.java | 135 ++++ .../mgt/common/geo/service/GeoFence.java | 114 +++ .../mgt/common/geo/service/GeoService.java | 49 ++ .../geo/service/GeoServiceException.java | 60 ++ .../org.wso2.carbon.device.mgt.core/pom.xml | 19 +- .../geo/service/GeoServcieManagerImpl.java | 668 ++++++++++++++++++ .../DeviceManagementServiceComponent.java | 6 + ...Geo-ExecutionPlan-Proximity_alert.siddhiql | 140 ++++ .../Geo-ExecutionPlan-Speed_alert.siddhiql | 20 + ...eo-ExecutionPlan-Stationery_alert.siddhiql | 89 +++ .../Geo-ExecutionPlan-Traffic_alert.siddhiql | 17 + .../Geo-ExecutionPlan-Within_alert.siddhiql | 20 + pom.xml | 21 +- 21 files changed, 2328 insertions(+), 3 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoService.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoServiceImpl.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Alert.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Event.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFence.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoService.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoServiceException.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoServcieManagerImpl.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql 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 8de7832bba..9b17a27634 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 @@ -296,6 +296,16 @@ org.wso2.carbon.application.mgt.stub provided + + org.wso2.carbon.analytics + org.wso2.carbon.analytics.api + provided + + + org.wso2.carbon.analytics + org.wso2.carbon.analytics.datasource.commons + provided + org.wso2.carbon.devicemgt org.wso2.carbon.identity.jwt.client.extension diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoService.java new file mode 100644 index 0000000000..52fa8fbf01 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoService.java @@ -0,0 +1,404 @@ +/* + * 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.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.common.geo.service.Alert; +import org.wso2.carbon.device.mgt.jaxrs.util.Constants; + +import javax.validation.Valid; +import javax.validation.constraints.Size; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +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.Response; + +@SwaggerDefinition( + info = @Info( + version = "1.0.0", + title = "", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "name", value = "geo_services"), + @ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/geo-services"), + }) + } + ), + tags = { + @Tag(name = "device_management", description = "") + } +) +@Scopes( + scopes = { + @Scope( + name = "View Analytics", + description = "", + key = "perm:geo-service:analytics", + permissions = {"/device-mgt/devices/owning-device/analytics"} + ) + } +) +@Path("/geo-services") +@Api(value = "Geo Service", + description = "This carries all the resources related to the geo service functionalities.") +public interface GeoService { + /** + * Retrieve Analytics for the device type + */ + @GET + @Path("stats/{deviceType}/{deviceId}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Retrieve Analytics for the device type", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @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 Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response getGeoDeviceStats( + @ApiParam( + name = "deviceId", + value = "The registered device Id.", + required = true) + @PathParam("deviceId") String deviceId, + @ApiParam( + name = "device-type", + value = "The device type, such as ios, android or windows.", + required = true) + @PathParam("deviceType") + @Size(max = 45) + String deviceType, + @ApiParam( + name = "from", + value = "Get stats from what time", + required = true) + @QueryParam("from") long from, + @ApiParam( + name = "to", + value = "Get stats up to what time", + required = true) + @QueryParam("to") long to); + + /** + * Create Geo alerts + */ + @POST + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Create Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response createGeoAlerts( + @ApiParam( + name = "alert", + value = "The alert object", + required = true) + @Valid Alert alert, + @ApiParam( + name = "deviceId", + value = "The registered device Id.", + required = true) + @PathParam("deviceId") String deviceId, + @ApiParam( + name = "device-type", + value = "The device type, such as ios, android or windows.", + required = true) + @PathParam("deviceType") + @Size(max = 45) + String deviceType, + @ApiParam( + name = "executionPlanType", + value = "The execution plan type, such as Within, Speed, Stationary", + required = true) + @PathParam("executionPlanType") String executionPlanType); + + /** + * Update Geo alerts + */ + @PUT + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Update Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response updateGeoAlerts( + @ApiParam( + name = "alert", + value = "The alert object", + required = true) + @Valid Alert alert, + @ApiParam( + name = "deviceId", + value = "The registered device Id.", + required = true) + @PathParam("deviceId") String deviceId, + @ApiParam( + name = "device-type", + value = "The device type, such as ios, android or windows.", + required = true) + @PathParam("deviceType") + @Size(max = 45) + String deviceType, + @ApiParam( + name = "executionPlanType", + value = "The execution plan type, such as Within, Speed, Stationary", + required = true) + @PathParam("executionPlanType") String executionPlanType); + + /** + * Retrieve Geo alerts + */ + @GET + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Retrieve Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @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 Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response getGeoAlerts( + @ApiParam( + name = "deviceId", + value = "The registered device Id.", + required = true) + @PathParam("deviceId") String deviceId, + @ApiParam( + name = "device-type", + value = "The device type, such as ios, android or windows.", + required = true) + @PathParam("deviceType") + @Size(max = 45) + String deviceType, + @ApiParam( + name = "executionPlanType", + value = "The execution plan type, such as Within, Speed, Stationary", + required = true) + @PathParam("executionPlanType") String executionPlanType); + + + @DELETE + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "DELETE", + value = "Create Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response removeGeoAlerts( + @ApiParam( + name = "deviceId", + value = "The registered device Id.", + required = true) + @PathParam("deviceId") String deviceId, + @ApiParam( + name = "deviceType", + value = "The device type, such as ios, android or windows.", + required = true) + @PathParam("deviceType") String deviceType, + @ApiParam( + name = "executionPlanType", + value = "The execution plan type, such as Within, Speed, Stationary", + required = true) + @PathParam("executionPlanType") String executionPlanType, + @ApiParam( + name = "queryName", + value = "The query name.", + required = true) + @QueryParam("queryName") String queryName); +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoServiceImpl.java new file mode 100644 index 0000000000..91ef644bab --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoServiceImpl.java @@ -0,0 +1,315 @@ +/* + * 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.service.impl; + +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.datasource.commons.Record; +import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices; +import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException; +import org.wso2.carbon.device.mgt.common.geo.service.Alert; +import org.wso2.carbon.device.mgt.common.geo.service.Event; +import org.wso2.carbon.device.mgt.common.geo.service.GeoFence; +import org.wso2.carbon.device.mgt.common.geo.service.GeoServiceException; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants; +import org.wso2.carbon.device.mgt.jaxrs.service.api.GeoService; +import org.wso2.carbon.device.mgt.jaxrs.util.Constants; +import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; +import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtUtil; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +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.Response; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The api for + */ +public class GeoServiceImpl implements GeoService { + + private static Log log = LogFactory.getLog(GeoServiceImpl.class); + + @Path("stats/{deviceType}/{deviceId}") + @GET + @Consumes("application/json") + @Produces("application/json") + public Response getGeoDeviceStats(@PathParam("deviceId") String deviceId, + @PathParam("deviceType") String deviceType, + @QueryParam("from") long from, @QueryParam("to") long to) { + String tableName = "ORG_WSO2_GEO_FUSEDSPATIALEVENT"; + String fromDate = String.valueOf(from); + String toDate = String.valueOf(to); + String query = "id:" + deviceId + " AND type:" + deviceType; + if (from != 0 || to != 0) { + query += " AND timeStamp : [" + fromDate + " TO " + toDate + "]"; + } + try { + if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized( + new DeviceIdentifier(deviceId, deviceType), + DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) { + return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); + } + List sortByFields = new ArrayList<>(); + SortByField sortByField = new SortByField("timeStamp", SortType.ASC); + sortByFields.add(sortByField); + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername()); + + try { + String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser); + int tenantId = DeviceMgtAPIUtils.getRealmService().getTenantManager().getTenantId(tenantDomain); + AnalyticsDataAPI analyticsDataAPI = DeviceMgtAPIUtils.getAnalyticsDataAPI(); + List searchResults = analyticsDataAPI.search(tenantId, tableName, query, + 0, + 100, + sortByFields); + List events = getEventBeans(analyticsDataAPI, tenantId, tableName, new ArrayList(), + searchResults); + return Response.ok().entity(events).build(); + } catch (AnalyticsException | UserStoreException e) { + log.error("Failed to perform search on table: " + tableName + " : " + e.getMessage(), e); + throw DeviceMgtUtil.buildBadRequestException( + Constants.ErrorMessages.STATUS_BAD_REQUEST_MESSAGE_DEFAULT); + } + } catch (DeviceAccessAuthorizationException e) { + log.error(e.getErrorMessage()); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); + } + } + + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @POST + @Consumes("application/json") + @Produces("application/json") + public Response createGeoAlerts(Alert alert, @PathParam("deviceId") String deviceId, + @PathParam("deviceType") String deviceType, + @PathParam("executionPlanType") String executionPlanType) { + try { + if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized( + new DeviceIdentifier(deviceId, deviceType), + DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) { + return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); + } + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + DeviceIdentifier identifier = new DeviceIdentifier(); + identifier.setId(deviceId); + identifier.setType(deviceType); + + org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.createGeoAlert(alert, identifier, executionPlanType); + return Response.ok().build(); + } catch (DeviceAccessAuthorizationException | GeoServiceException e) { + String error = "Error occurred while creating the geo alert for " + deviceType + " with id: " + deviceId; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @PUT + @Consumes("application/json") + @Produces("application/json") + public Response updateGeoAlerts(Alert alert, @PathParam("deviceId") String deviceId, + @PathParam("deviceType") String deviceType, + @PathParam("executionPlanType") String executionPlanType) { + try { + if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized( + new DeviceIdentifier(deviceId, deviceType), + DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) { + return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); + } + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + DeviceIdentifier identifier = new DeviceIdentifier(); + identifier.setId(deviceId); + identifier.setType(deviceType); + + org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.updateGeoAlert(alert, identifier, executionPlanType); + return Response.ok().build(); + } catch (DeviceAccessAuthorizationException | GeoServiceException e) { + String error = "Error occurred while creating the geo alert for " + deviceType + " with id: " + deviceId; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @DELETE + @Consumes("application/json") + @Produces("application/json") + public Response removeGeoAlerts(@PathParam("deviceId") String deviceId, + @PathParam("deviceType") String deviceType, + @PathParam("executionPlanType") String executionPlanType, + @QueryParam("queryName") String queryName) { + try { + if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized( + new DeviceIdentifier(deviceId, deviceType), + DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) { + return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); + } + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + DeviceIdentifier identifier = new DeviceIdentifier(); + identifier.setId(deviceId); + identifier.setType(deviceType); + + org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.removeGeoAlert(executionPlanType, identifier, queryName); + return Response.ok().build(); + } catch (DeviceAccessAuthorizationException | GeoServiceException e) { + String error = "Error occurred while removing the geo alert for " + deviceType + " with id: " + deviceId; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + + @Path("alerts/{executionPlanType}/{deviceType}/{deviceId}") + @GET + @Consumes("application/json") + @Produces("application/json") + public Response getGeoAlerts(@PathParam("deviceId") String deviceId, + @PathParam("deviceType") String deviceType, + @PathParam("executionPlanType") String executionPlanType) { + try { + if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized( + new DeviceIdentifier(deviceId, deviceType), + DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) { + return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); + } + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + DeviceIdentifier identifier = new DeviceIdentifier(); + identifier.setId(deviceId); + identifier.setType(deviceType); + + org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService(); + + if (GeoServices.EXECUTION_PLAN_TYPE_WITHIN.equals(executionPlanType)) { + List alerts = geoService.getWithinAlerts(identifier); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.EXECUTION_PLAN_TYPE_SPEED.equals(executionPlanType)) { + String result = geoService.getSpeedAlerts(identifier); + return Response.ok().entity(result).build(); + } else if (GeoServices.EXECUTION_PLAN_TYPE_PROXIMITY.equals(executionPlanType)) { + String result = geoService.getProximityAlerts(identifier); + return Response.ok().entity(result).build(); + } else if (GeoServices.EXECUTION_PLAN_TYPE_STATIONARY.equals(executionPlanType)) { + List alerts = geoService.getStationaryAlerts(identifier); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.EXECUTION_PLAN_TYPE_TRAFFIC.equals(executionPlanType)) { + List alerts = geoService.getTrafficAlerts(identifier); + return Response.ok().entity(alerts).build(); + } + return null; + } catch (DeviceAccessAuthorizationException | GeoServiceException e) { + String error = "Error occurred while getting the geo alerts for " + deviceType + " with id: " + deviceId; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + + private List getEventBeans(AnalyticsDataAPI analyticsDataAPI, int tenantId, String tableName, + List columns, + List searchResults) throws AnalyticsException { + List ids = getIds(searchResults); + List requiredColumns = (columns == null || columns.isEmpty()) ? null : columns; + AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, requiredColumns, ids); + List records = AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response); + Map eventBeanMap = getEventBeanKeyedWithIds(records); + return getSortedEventBeans(eventBeanMap, searchResults); + } + + private List getSortedEventBeans(Map eventBeanMap, + List searchResults) { + List sortedRecords = new ArrayList<>(); + for (SearchResultEntry entry : searchResults) { + sortedRecords.add(eventBeanMap.get(entry.getId())); + } + return sortedRecords; + } + + private Map getEventBeanKeyedWithIds(List records) { + Map eventBeanMap = new HashMap<>(); + for (Record record : records) { + Event event = getEventBean(record); + eventBeanMap.put(event.getId(), event); + } + return eventBeanMap; + } + + private List getIds(List searchResults) { + List ids = new ArrayList<>(); + if (searchResults != null) { + for (SearchResultEntry resultEntry : searchResults) { + ids.add(resultEntry.getId()); + } + } + return ids; + } + + private static Event getEventBean(Record record) { + Event eventBean = new Event(); + eventBean.setId(record.getId()); + eventBean.setTableName(record.getTableName()); + eventBean.setTimestamp(record.getTimestamp()); + eventBean.setValues(record.getValues()); + return eventBean; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index 888b1c42ee..d1e3ba234c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.analytics.api.AnalyticsDataAPI; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.analytics.dashboard.GadgetDataService; @@ -28,6 +29,7 @@ import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorization import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; +import org.wso2.carbon.device.mgt.common.geo.service.GeoService; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; @@ -320,6 +322,27 @@ public class DeviceMgtAPIUtils { return gadgetDataService; } + public static GeoService getGeoService() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + GeoService geoService = (GeoService) ctx.getOSGiService(GeoService.class, null); + if (geoService == null) { + throw new IllegalStateException("Geo Service has not been initialized."); + } + return geoService; + } + + 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 int getTenantId(String tenantDomain) throws DeviceManagementException { RealmService realmService = (RealmService) PrivilegedCarbonContext.getThreadLocalCarbonContext().getOSGiService(RealmService.class, null); 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 e33d1beb26..6e37d0256b 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 @@ -36,6 +36,7 @@ + @@ -76,6 +77,7 @@ + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml index 611fe6c150..15f98b812a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml @@ -50,6 +50,7 @@ javax.xml.bind.annotation; version="${javax.xml.bind.imp.pkg.version}", com.fasterxml.jackson.annotation;version="${jackson-annotations.version}", + org.wso2.carbon.analytics.datasource.commons;version="${carbon.analytics.version.range}", io.swagger.annotations; version="${swagger.annotations.version}"; resolution:=optional @@ -68,6 +69,14 @@ org.wso2.orbit.com.fasterxml.jackson.core jackson-annotations + + org.wso2.carbon.analytics + org.wso2.carbon.analytics.api + + + org.wso2.carbon.analytics + org.wso2.carbon.analytics.datasource.commons + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java index ba0d3d59ed..a3d50e2d12 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java @@ -61,6 +61,7 @@ public final class DeviceManagementConstants { private LicenseProperties() { throw new AssertionError(); } + public static final String PROVIDER = "overview_provider"; public static final String NAME = "overview_name"; public static final String LANGUAGE = "overview_language"; @@ -76,6 +77,7 @@ public final class DeviceManagementConstants { private NotificationProperties() { throw new AssertionError(); } + public static final String NOTIFICATION_CONFIG_FILE = "notification-messages.xml"; } @@ -83,6 +85,7 @@ public final class DeviceManagementConstants { private DataBaseTypes() { throw new AssertionError(); } + public static final String DB_TYPE_MYSQL = "MySQL"; public static final String DB_TYPE_ORACLE = "Oracle"; public static final String DB_TYPE_MSSQL = "Microsoft SQL Server"; @@ -91,4 +94,31 @@ public final class DeviceManagementConstants { public static final String DB_TYPE_POSTGRESQL = "PostgreSQL"; } + public static final class GeoServices { + private GeoServices() { + throw new AssertionError(); + } + + public static final String EXECUTION_PLAN_TYPE_SPEED = "Speed"; + public static final String EXECUTION_PLAN_TYPE_WITHIN = "Within"; + public static final String EXECUTION_PLAN_TYPE_PROXIMITY = "Proximity"; + public static final String EXECUTION_PLAN_TYPE_STATIONARY = "Stationery"; + public static final String EXECUTION_PLAN_TYPE_TRAFFIC = "Traffic"; + public static final String REGISTRY_PATH_FOR_ALERTS = "/_system/governance/geo/alerts/"; + public static final String PROXIMITY_DISTANCE = "proximityDistance"; + public static final String PROXIMITY_TIME = "proximityTime"; + public static final String STATIONARY_NAME = "stationeryName"; + public static final String STATIONARY_TIME = "stationeryTime"; + public static final String FLUCTUATION_RADIUS = "fluctuationRadius"; + public static final String QUERY_NAME = "queryName"; + public static final String AREA_NAME = "areaName"; + + public static final String GEO_FENCE_GEO_JSON = "geoFenceGeoJSON"; + public static final String SPEED_ALERT_VALUE = "speedAlertValue"; + + public static final String DAS_PORT = "${iot.analytics.https.port}"; + public static final String DAS_HOST_NAME = "${iot.analytics.host}"; + public static final String DEFAULT_HTTP_PROTOCOL = "https"; + public static final String DAS_URL = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME + ":" + DAS_PORT; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Alert.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Alert.java new file mode 100644 index 0000000000..f43c319567 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Alert.java @@ -0,0 +1,180 @@ +/* + * 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.common.geo.service; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * The Class Alert Bean. + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "alert") +public class Alert { + + /** + * The parse data. + */ + @XmlElement(required = true, name = "parseData") + private String parseData; + + /** + * The execution plan name. + */ + @XmlElement(required = true, name = "executionPlan") + private String executionPlan; + + /** + * The custom name. + */ + @XmlElement(required = false, nillable = true, name = "customName") + private String customName; + + /** + * The query name. + */ + @XmlElementWrapper(required = true, name = "queryName") + private String queryName; + + /** + * The CEP action. + */ + @XmlElementWrapper(required = true, name = "cepAction") + private String cepAction; + + /** + * The device id. + */ + @XmlElementWrapper(required = true, name = "deviceId") + private String deviceId; + + /** + * The stationery time. + */ + @XmlElementWrapper(required = false, nillable = true, name = "stationeryTime") + private String stationeryTime; + + /** + * The fluctuation radius. + */ + @XmlElementWrapper(required = false, nillable = true, name = "fluctuationRadius") + private String fluctuationRadius; + + /** + * The proximity distance. + */ + @XmlElementWrapper(required = false, nillable = true, name = "proximityDistance") + private String proximityDistance; + + /** + * The proximity time. + */ + @XmlElementWrapper(required = false, nillable = true, name = "proximityTime") + private String proximityTime; + + public String getParseData() { + return parseData; + } + + public void setParseData(String parseData) { + this.parseData = parseData; + } + + public String getExecutionPlan() { + return executionPlan; + } + + public void setExecutionPlan(String executionPlan) { + this.executionPlan = executionPlan; + } + + public String getCustomName() { + return customName; + } + + public void setCustomName(String customName) { + this.customName = customName; + } + + public String getQueryName() { + return queryName; + } + + public void setQueryName(String queryName) { + this.queryName = queryName; + } + + public String getCepAction() { + return cepAction; + } + + public void setCepAction(String cepAction) { + this.cepAction = cepAction; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getStationeryTime() { + return stationeryTime; + } + + public void setStationeryTime(String stationeryTime) { + this.stationeryTime = stationeryTime; + } + + public String getFluctuationRadius() { + return fluctuationRadius; + } + + public void setFluctuationRadius(String fluctuationRadius) { + this.fluctuationRadius = fluctuationRadius; + } + + public String getProximityDistance() { + return proximityDistance; + } + + public void setProximityDistance(String proximityDistance) { + this.proximityDistance = proximityDistance; + } + + public String getProximityTime() { + return proximityTime; + } + + public void setProximityTime(String proximityTime) { + this.proximityTime = proximityTime; + } + + @Override + public String toString() { + return String.format( + "{\"queryName\" : %s,\"customName\" : %s,\"cepAction\" : %s,\"deviceId\" : %s }", + queryName, customName, cepAction, deviceId); + } +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Event.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Event.java new file mode 100644 index 0000000000..8c79475a37 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/Event.java @@ -0,0 +1,135 @@ +/* + * 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.common.geo.service; + + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +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; + +/** + * The Class RecordBean. + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "event") +public class Event { + + /** The id. */ + @XmlElement(required = false, name = "id") + private String id; + + /** The table name. */ + @XmlElement(required = false, name = "tableName") + private String tableName; + + /** The timestamp. */ + @XmlElement(required = false, nillable = true, name = "timestamp") + private long timestamp; + + /** The values. */ + @XmlElementWrapper(required = true, name = "values") + private Map values; + + /** + * Sets the table name. + * @param tableName the new table name + */ + public void setTableName(String tableName) { + this.tableName = tableName; + } + + /** + * Sets the values. + * @param values the values + */ + public void setValues(Map values) { + this.values = values; + } + + /** + * Sets the timestamp. + * @param timestamp the new timestamp + */ + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + /** + * 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; + } + /** + * Gets the table name. + * @return the table name + */ + public String getTableName() { + return tableName; + } + + /** + * Gets the values. + * @return the values + */ + public Map getValues() { + return values; + } + + /** + * Gets the value. + * @param name + * the name + * @return the value + */ + public Object getValue(String name) { + return this.values.get(name); + } + + /** + * Gets the timestamp. + * @return the timestamp + */ + public long getTimestamp() { + return timestamp; + } + + @Override + public String toString(){ + List valueList = new ArrayList<>(); + for (Map.Entry entry : values.entrySet()) { + valueList.add(entry.getKey() + ":" + entry.getValue()); + } + return valueList.toString(); + } +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFence.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFence.java new file mode 100644 index 0000000000..359264dadb --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFence.java @@ -0,0 +1,114 @@ +/* + * 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.common.geo.service; + + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * The Class GeoFence. + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "fence") +public class GeoFence { + + /** The geoJson. */ + @XmlElement(required = false, name = "geoJson") + private String geoJson; + + /** The queryName. */ + @XmlElement(required = false, name = "queryName") + private String queryName; + + /** The areaName. */ + @XmlElement(required = false, name = "areaName") + private String areaName; + + /** The createdTime. */ + @XmlElement(required = false, nillable = true, name = "createdTime") + private long createdTime; + + /** The stationaryTime. */ + @XmlElement(required = false, name = "stationaryTime") + private String stationaryTime; + + /** The fluctuationRadius. */ + @XmlElement(required = false, name = "fluctuationRadius") + private String fluctuationRadius; + + public String getGeoJson() { + return geoJson; + } + + public void setGeoJson(String geoJson) { + this.geoJson = geoJson; + } + + public String getQueryName() { + return queryName; + } + + public void setQueryName(String queryName) { + this.queryName = queryName; + } + + public String getAreaName() { + return areaName; + } + + public void setAreaName(String areaName) { + this.areaName = areaName; + } + + public long getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(long createdTime) { + this.createdTime = createdTime; + } + + public void setStationaryTime(String stationaryTime) { + this.stationaryTime = stationaryTime; + } + + public String getStationaryTime() { + return stationaryTime; + } + + public void setFluctuationRadius(String fluctuationRadius) { + this.fluctuationRadius = fluctuationRadius; + } + + public String getFluctuationRadius() { + return fluctuationRadius; + } + + @Override + public String toString() { + return "{\"geoJson\": " + geoJson + + ",\"queryName\": " + queryName + + ",\"areaName\":" + areaName + + ",\"createdTime\":" + createdTime + + "}"; + } +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoService.java new file mode 100644 index 0000000000..1cc28e95f5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoService.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.geo.service; + +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; + +import java.util.List; + +/** + * This represents the Geo service functionality which should be implemented by + * required GeoServiceManagers. + */ +public interface GeoService { + + List getWithinAlerts(DeviceIdentifier identifier) throws GeoServiceException; + + boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String executionPlanType) + throws GeoServiceException; + + boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String executionPlanType) + throws GeoServiceException; + + boolean removeGeoAlert(String executionPlanType, DeviceIdentifier identifier, String queryName) + throws GeoServiceException; + + String getSpeedAlerts(DeviceIdentifier identifier) throws GeoServiceException; + + String getProximityAlerts(DeviceIdentifier identifier) throws GeoServiceException; + + List getStationaryAlerts(DeviceIdentifier identifier) throws GeoServiceException; + + List getTrafficAlerts(DeviceIdentifier identifier) throws GeoServiceException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoServiceException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoServiceException.java new file mode 100644 index 0000000000..91154e03e2 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoServiceException.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.common.geo.service; + +/** + * Custom exception class of Geo Service related operations. + */ +public class GeoServiceException extends Exception { + + private static final long serialVersionUID = -7151990041029070298L; + + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public GeoServiceException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public GeoServiceException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public GeoServiceException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public GeoServiceException() { + super(); + } + + public GeoServiceException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml index a5d2e2afea..bfef6dc4ed 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml @@ -86,7 +86,10 @@ io.swagger.annotations.*;resolution:=optional, org.wso2.carbon, org.wso2.carbon.base, - org.scannotation.* + org.scannotation.*, + org.wso2.carbon.event.processor.stub, + org.wso2.carbon.identity.jwt.client.extension.service, + org.apache.commons.codec.binary !org.wso2.carbon.device.mgt.core.internal, @@ -262,6 +265,20 @@ org.wso2.carbon.devicemgt org.wso2.carbon.apimgt.annotations + + org.wso2.carbon.event-processing + org.wso2.carbon.event.processor.stub + + + org.wso2.carbon.devicemgt + org.wso2.carbon.identity.jwt.client.extension + provided + + + commons-codec.wso2 + commons-codec + provided + javax.ws.rs diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoServcieManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoServcieManagerImpl.java new file mode 100644 index 0000000000..8ff4ceb8dd --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoServcieManagerImpl.java @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.core.geo.service; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import org.apache.axis2.AxisFault; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.Stub; +import org.apache.axis2.java.security.SSLProtocolSocketFactory; +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.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.base.ServerConfiguration; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.core.util.Utils; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices; +import org.wso2.carbon.device.mgt.common.geo.service.Alert; +import org.wso2.carbon.device.mgt.common.geo.service.GeoFence; +import org.wso2.carbon.device.mgt.common.geo.service.GeoService; +import org.wso2.carbon.device.mgt.common.geo.service.GeoServiceException; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub; +import org.wso2.carbon.identity.jwt.client.extension.JWTClient; +import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; +import org.wso2.carbon.registry.api.Registry; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.api.Resource; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import static org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices.DAS_PORT; +import static org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices.DEFAULT_HTTP_PROTOCOL; + +/** + * This class will read events, set alerts, read alerts related to geo-fencing and it will + * use Registry as the persistence storage. + */ +public class GeoServcieManagerImpl implements GeoService { + + private static Log log = LogFactory.getLog(GeoServcieManagerImpl.class); + + /** + * required soap header for authorization + */ + private static final String AUTHORIZATION_HEADER = "Authorization"; + /** + * required soap header value for mutualSSL + */ + private static final String AUTHORIZATION_HEADER_VALUE = "Bearer"; + /** + * Default keystore type of the client + */ + private static final String KEY_STORE_TYPE = "JKS"; + /** + * Default truststore type of the client + */ + private static final String TRUST_STORE_TYPE = "JKS"; + /** + * Default keymanager type of the client + */ + private static final String KEY_MANAGER_TYPE = "SunX509"; //Default Key Manager Type + /** + * Default trustmanager type of the client + */ + private static final String TRUST_MANAGER_TYPE = "SunX509"; //Default Trust Manager Type + + private static final String SSLV3 = "SSLv3"; + + @Override + public List getWithinAlerts(DeviceIdentifier identifier) throws GeoServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.EXECUTION_PLAN_TYPE_WITHIN + "/" + identifier.getId() + "/"; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + Gson gson = new Gson(); + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List areaNameObj = (List) props.get(GeoServices.AREA_NAME); + geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoServiceException( + "Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " + + identifier.getId(), e); + } + } + + @Override + public boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String executionPlanType) + throws GeoServiceException { + return saveGeoAlert(alert, identifier, executionPlanType, false); + } + + @Override + public boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String executionPlanType) + throws GeoServiceException { + return saveGeoAlert(alert, identifier, executionPlanType, true); + } + + public boolean saveGeoAlert(Alert alert, DeviceIdentifier identifier, String executionPlanType, boolean isUpdate) + throws GeoServiceException { + + Type type = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + Map parseMap = gson.fromJson(alert.getParseData(), type); + + Map options = new HashMap<>(); + Object content = null; + + if (GeoServices.EXECUTION_PLAN_TYPE_WITHIN.equals(executionPlanType)) { + options.put(GeoServices.QUERY_NAME, alert.getQueryName()); + options.put(GeoServices.AREA_NAME, alert.getCustomName()); + content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON); + + } else if (GeoServices.EXECUTION_PLAN_TYPE_SPEED.equals(executionPlanType)) { + content = parseMap.get(GeoServices.SPEED_ALERT_VALUE); + + } else if (GeoServices.EXECUTION_PLAN_TYPE_PROXIMITY.equals(executionPlanType)) { + options.put(GeoServices.PROXIMITY_DISTANCE, alert.getProximityDistance()); + options.put(GeoServices.PROXIMITY_TIME, alert.getProximityTime()); + content = alert.getParseData(); + + } else if (GeoServices.EXECUTION_PLAN_TYPE_STATIONARY.equals(executionPlanType)) { + options.put(GeoServices.QUERY_NAME, alert.getQueryName()); + options.put(GeoServices.AREA_NAME, alert.getCustomName()); + options.put(GeoServices.STATIONARY_TIME, alert.getStationeryTime()); + options.put(GeoServices.FLUCTUATION_RADIUS, alert.getFluctuationRadius()); + content = alert.getParseData(); + + } else if (GeoServices.EXECUTION_PLAN_TYPE_TRAFFIC.equals(executionPlanType)) { + content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON); + } else { + throw new GeoServiceException( + "Unrecognized execution plan type: " + executionPlanType + " while creating geo alert"); + } + + //persist alert in registry + updateRegistry(getRegistryPath(executionPlanType, identifier, alert.getQueryName()), identifier, content, + options); + + //deploy alert into event processor + EventProcessorAdminServiceStub eventprocessorStub = null; + String action = (isUpdate ? "updating" : "creating"); + try { + eventprocessorStub = getEventProcessorAdminServiceStub(); + String parsedTemplate = parseTemplate(executionPlanType, parseMap); + String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); + if (validationResponse.equals("success")) { + if (isUpdate) { + String executionPlanName = getExecutionPlanName(executionPlanType, alert.getQueryName(), + identifier.getId()); + eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); + } else { + eventprocessorStub.deployExecutionPlan(parsedTemplate); + } + } else { + log.error("Execution plan validation failed: " + validationResponse); + throw new GeoServiceException( + "Error occurred while " + action + " geo " + executionPlanType + " alert for " + + identifier.getType() + " with id: " + identifier.getId()); + } + return true; + } catch (AxisFault axisFault) { + throw new GeoServiceException( + "Event processor admin service stub initialization failed while " + action + " geo alert '" + + executionPlanType + "' for " + identifier.getType() + " " + + "device with id: " + identifier.getId(), axisFault + ); + } catch (IOException e) { + throw new GeoServiceException( + "Event processor admin service stub invocation failed while " + action + " geo alert '" + + executionPlanType + "' for " + identifier.getType() + " " + + "device with id: " + identifier.getId(), e); + } catch (JWTClientException e) { + throw new GeoServiceException( + "JWT token creation failed while " + action + " geo alert '" + executionPlanType + "' for " + + identifier.getType() + " device with id:" + identifier.getId(), e); + } finally { + cleanup(eventprocessorStub); + } + } + + private String getRegistryPath(String executionPlanType, DeviceIdentifier identifier, String queryName) + throws GeoServiceException { + String path = ""; + if (GeoServices.EXECUTION_PLAN_TYPE_WITHIN.equals(executionPlanType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.EXECUTION_PLAN_TYPE_WITHIN + + "/" + identifier.getId() + "/" + queryName; + } else if (GeoServices.EXECUTION_PLAN_TYPE_SPEED.equals(executionPlanType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.EXECUTION_PLAN_TYPE_SPEED + + "/" + identifier.getId(); + } else if (GeoServices.EXECUTION_PLAN_TYPE_PROXIMITY.equals(executionPlanType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.EXECUTION_PLAN_TYPE_PROXIMITY + + "/" + identifier.getId() + "/" + queryName; + } else if (GeoServices.EXECUTION_PLAN_TYPE_STATIONARY.equals(executionPlanType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.EXECUTION_PLAN_TYPE_STATIONARY + + "/" + identifier.getId() + "/" + queryName; + } else if (GeoServices.EXECUTION_PLAN_TYPE_TRAFFIC.equals(executionPlanType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.EXECUTION_PLAN_TYPE_TRAFFIC + + "/" + identifier.getId() + "/" + queryName; + } else { + throw new GeoServiceException( + "Unrecognized execution plan type: " + executionPlanType); + } + return path; + } + + private String getExecutionPlanName(String executionPlanType, String queryName, String deviceId) { + if ("Traffic".equals(executionPlanType)) { + return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert"; + } else { + return "Geo-ExecutionPlan-" + executionPlanType + "_" + queryName + "---_" + deviceId + "_alert"; + } + } + + @Override + public boolean removeGeoAlert(String executionPlanType, DeviceIdentifier identifier, String queryName) + throws GeoServiceException { + removeFromRegistry(executionPlanType, identifier, queryName); + String executionPlanName = getExecutionPlanName(executionPlanType, queryName, identifier.getId()); + EventProcessorAdminServiceStub eventprocessorStub = null; + try { + eventprocessorStub = getEventProcessorAdminServiceStub(); + eventprocessorStub.undeployActiveExecutionPlan(executionPlanName); + return true; + } catch (IOException e) { + throw new GeoServiceException( + "Event processor admin service stub invocation failed while removing geo alert '" + + executionPlanType + + "': " + executionPlanName + " for " + + identifier.getType() + " device with id:" + identifier.getId(), e + ); + } catch (JWTClientException e) { + throw new GeoServiceException( + "JWT token creation failed while removing geo alert '" + executionPlanType + "': " + + executionPlanName + " for " + + identifier.getType() + " device with id:" + identifier.getId(), e + ); + } finally { + cleanup(eventprocessorStub); + } + } + + private void removeFromRegistry(String executionPlanType, DeviceIdentifier identifier, String queryName) + throws GeoServiceException { + String path = "unknown"; + try { + path = getRegistryPath(executionPlanType, identifier, queryName); + getGovernanceRegistry().delete(path); + } catch (RegistryException e) { + throw new GeoServiceException( + "Error occurred while removing " + executionPlanType + " alert for " + identifier.getType() + + " device with id:" + identifier.getId() + " from the path: " + path); + } + } + + private EventProcessorAdminServiceStub getEventProcessorAdminServiceStub() throws JWTClientException { + //send alert to event-processing + String eventProcessorAdminServiceWSUrl = Utils.replaceSystemProperty(GeoServices.DAS_URL) + + "/services/EventProcessorAdminService"; + + //Getting the tenant Domain + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + String tenantAdminUser = username + "@" + tenantDomain; + + try { + //Create the SSL context with the loaded TrustStore/keystore. + SSLContext sslContext = initSSLConnection(tenantAdminUser); + JWTClient jwtClient = getJWTClientManagerService().getJWTClient(); + + String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64( + jwtClient.getJwtToken(tenantAdminUser).getBytes())); + + EventProcessorAdminServiceStub eventprocessorStub = new EventProcessorAdminServiceStub( + eventProcessorAdminServiceWSUrl); + + Options eventProcessorOption = eventprocessorStub._getServiceClient().getOptions(); + if (eventProcessorOption == null) { + eventProcessorOption = new Options(); + } + + List
list = new ArrayList<>(); + Header httpHeader = new Header(); + httpHeader.setName(AUTHORIZATION_HEADER); + httpHeader.setValue(authValue); + list.add(httpHeader);//"https" + + eventProcessorOption.setProperty(HTTPConstants.HTTP_HEADERS, list); + eventProcessorOption.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER + , new Protocol(DEFAULT_HTTP_PROTOCOL + , (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext) + , Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT)))); + eventprocessorStub._getServiceClient().setOptions(eventProcessorOption); + + return eventprocessorStub; + } catch (CertificateException | NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException | + KeyManagementException | IOException e) { + throw new JWTClientException("JWT token creation failed for the Event Processor Stub", e); + } + } + + @Override + public String getSpeedAlerts(DeviceIdentifier identifier) throws GeoServiceException { + try { + Registry registry = getGovernanceRegistry(); + Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.EXECUTION_PLAN_TYPE_SPEED + "/" + identifier.getId()); + if (resource == null) { + return "{'content': false}"; + } + InputStream inputStream = resource.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + return "{'speedLimit':" + writer.toString() + "}"; + } catch (RegistryException | IOException e) { + return "{'content': false}"; + } + } + + @Override + public String getProximityAlerts(DeviceIdentifier identifier) throws GeoServiceException { + try { + Registry registry = getGovernanceRegistry(); + Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.EXECUTION_PLAN_TYPE_PROXIMITY + + "/" + identifier.getId()); + if (resource != null) { + Properties props = resource.getProperties(); + + List proxDisObj = (List) props.get(GeoServices.PROXIMITY_DISTANCE); + List proxTimeObj = (List) props.get(GeoServices.PROXIMITY_TIME); + + return String.format("{proximityDistance:\"%s\", proximityTime:\"%s\"}", + proxDisObj != null ? proxDisObj.get(0).toString() : "", + proxTimeObj != null ? proxTimeObj.get(0).toString() : ""); + } else { + return "{'content': false}"; + } + } catch (RegistryException e) { + return "{'content': false}"; + } + } + + @Override + public List getStationaryAlerts(DeviceIdentifier identifier) throws GeoServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.EXECUTION_PLAN_TYPE_STATIONARY + "/" + identifier.getId() + "/"; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + Gson gson = new Gson(); + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List areaNameObj = (List) props.get(GeoServices.AREA_NAME); + geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null); + List sTimeObj = (List) props.get(GeoServices.STATIONARY_TIME); + geoFence.setStationaryTime(sTimeObj != null ? sTimeObj.get(0).toString() : null); + List fluctRadiusObj = (List) props.get(GeoServices.FLUCTUATION_RADIUS); + geoFence.setFluctuationRadius(fluctRadiusObj != null ? fluctRadiusObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoServiceException( + "Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " + + identifier.getId(), e); + } + } + + @Override + public List getTrafficAlerts(DeviceIdentifier identifier) throws GeoServiceException { + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.EXECUTION_PLAN_TYPE_STATIONARY + "/" + identifier.getId() + "/"; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + Gson gson = new Gson(); + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List sNameObj = (List) props.get(GeoServices.STATIONARY_NAME); + geoFence.setAreaName(sNameObj != null ? sNameObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoServiceException( + "Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " + + identifier.getId(), e); + } + } + + private Registry getGovernanceRegistry() throws GeoServiceException { + try { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + return DeviceManagementDataHolder.getInstance().getRegistryService() + .getGovernanceSystemRegistry( + tenantId); + } catch (RegistryException e) { + throw new GeoServiceException( + "Error in retrieving governance registry instance: " + + e.getMessage(), e); + } + } + + private String parseTemplate(String executionPlan, Map parseMap) throws GeoServiceException { + String templatePath = "alerts/Geo-ExecutionPlan-" + executionPlan + "_alert.siddhiql"; + InputStream resource = getClass().getClassLoader().getResourceAsStream(templatePath); + if (resource == null) { + throw new GeoServiceException("Could not find template in path : " + templatePath); + } + try { + //Read template + String template = IOUtils.toString(resource, StandardCharsets.UTF_8.toString()); + //Replace variables + for (Map.Entry parseEntry : parseMap.entrySet()) { + String find = "\\$" + parseEntry.getKey(); + template = template.replaceAll(find, parseEntry.getValue()); + } + return template; + } catch (IOException e) { + throw new GeoServiceException( + "Error occurred while populating the template for the Within Alert", e); + } + } + + private void updateRegistry(String path, DeviceIdentifier identifier, Object content, Map options) + throws GeoServiceException { + try { + + Registry registry = getGovernanceRegistry(); + Resource newResource = registry.newResource(); + newResource.setContent(content); + newResource.setMediaType("application/json"); + for (Map.Entry option : options.entrySet()) { + newResource.addProperty(option.getKey(), option.getValue()); + } + registry.put(path, newResource); + } catch (RegistryException e) { + throw new GeoServiceException( + "Error occurred while setting the Within Alert for " + identifier.getType() + " with id: " + + identifier.getId(), e); + } + } + + /** + * Loads the keystore. + * + * @param keyStorePath - the path of the keystore + * @param keyStorePassword - the keystore password + */ + private KeyStore loadKeyStore(String keyStorePath, char[] keyStorePassword) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { + InputStream fis = null; + try { + KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE); + fis = new FileInputStream(keyStorePath); + keyStore.load(fis, keyStorePassword); + return keyStore; + } finally { + if (fis != null) { + fis.close(); + } + } + } + + /** + * Loads the trustore + * + * @param trustStorePath - the trustore path in the filesystem. + * @param tsPassword - the truststore password + */ + private KeyStore loadTrustStore(String trustStorePath, char[] tsPassword) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { + + InputStream fis = null; + try { + KeyStore trustStore = KeyStore.getInstance(TRUST_STORE_TYPE); + fis = new FileInputStream(trustStorePath); + trustStore.load(fis, tsPassword); + return trustStore; + } finally { + if (fis != null) { + fis.close(); + } + } + } + + /** + * Initializes the SSL Context + */ + private SSLContext initSSLConnection(String tenantAdminUser) + throws NoSuchAlgorithmException, UnrecoverableKeyException, + KeyStoreException, KeyManagementException, IOException, CertificateException { + 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. + KeyStore keyStore = loadKeyStore(keyStoreLocation, keyStorePassword.toCharArray()); + //Call to load the TrustStore. + KeyStore trustStore = loadTrustStore(trustStoreLocation, trustStorePassword.toCharArray()); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE); + keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE); + trustManagerFactory.init(trustStore); + + // Create and initialize SSLContext for HTTPS communication + + SSLContext sslContext = SSLContext.getInstance(SSLV3); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + SSLContext.setDefault(sslContext); + return sslContext; + } + + private void cleanup(Stub stub) { + if (stub != null) { + try { + stub.cleanup(); + } catch (AxisFault axisFault) { + //do nothing + } + } + } + + public static JWTClientManagerService getJWTClientManagerService() { + JWTClientManagerService jwtClientManagerService; + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + jwtClientManagerService = (JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null); + if (jwtClientManagerService == null) { + String msg = "jwtClientManagerServicehas not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return jwtClientManagerService; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java index 0c1a62471d..db8167d282 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -25,6 +25,7 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; +import org.wso2.carbon.device.mgt.common.geo.service.GeoService; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager; @@ -42,6 +43,7 @@ import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig; import org.wso2.carbon.device.mgt.core.config.tenant.PlatformConfigurationManagementServiceImpl; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.geo.service.GeoServcieManagerImpl; import org.wso2.carbon.device.mgt.core.notification.mgt.NotificationManagementServiceImpl; import org.wso2.carbon.device.mgt.core.notification.mgt.dao.NotificationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.OperationManagerImpl; @@ -260,6 +262,10 @@ public class DeviceManagementServiceComponent { bundleContext.registerService(DeviceAccessAuthorizationService.class.getName(), deviceAccessAuthorizationService, null); + /* Registering Geo Service */ + GeoService geoService = new GeoServcieManagerImpl(); + bundleContext.registerService(GeoService.class.getName(), geoService, null); + /* Registering App Management service */ try { AppManagementConfigurationManager.getInstance().initConfig(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql new file mode 100644 index 0000000000..fb64720391 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql @@ -0,0 +1,140 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('Geo-ExecutionPlan-Proximity_alert') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string ); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut ( id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string ); + +@IndexBy('id') +define table ProximityTable(id string, timeStamp long); + +@IndexBy('id') +define table AlertsTable(id string , proximityWith string, eventId string); + +from dataIn#geodashboard:subscribe() +select id, latitude, longitude, timeStamp, type, speed, heading, eventId +insert into initialStream; + +from initialStream[type == 'STOP'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from initialStream[type != 'STOP'] +select * +insert into objectInitialStream; + +from objectInitialStream#geo:proximity(id,longitude,latitude, $proximityDistance) +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith +insert into proxymityStream; + +from proxymityStream[AlertsTable.id == proxymityStream.id in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable +insert into innerStreamOne; + +from proxymityStream[not(AlertsTable.id == proxymityStream.id in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable +insert into innerStreamOne; + +from proxymityStream[AlertsTable.id == proxymityStream.proximityWith in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable +insert into innerStreamSeven; + +from proxymityStream[not(AlertsTable.id == proxymityStream.proximityWith in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable +insert into innerStreamSeven; + +from innerStreamOne[inCloseProximity == true AND not(inAlertTable)] +select id,str:concat(",",proximityWith) as proximityWith , eventId +insert into AlertsTable; + +from innerStreamSeven[inCloseProximity == true AND not(inAlertTable)] +select proximityWith as id,str:concat(",",id) as proximityWith , eventId +insert into AlertsTable; + +from innerStreamOne[innerStreamOne.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamOne.id == AlertsTable.id +select innerStreamOne.id as id, str:concat(",", innerStreamOne.proximityWith, AlertsTable.proximityWith) as proximityWith, innerStreamOne.eventId as eventId +insert into updateStream; + +from innerStreamSeven[innerStreamSeven.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamSeven.proximityWith == AlertsTable.id +select innerStreamSeven.proximityWith as id, str:concat(",", innerStreamSeven.id, AlertsTable.proximityWith) as proximityWith, innerStreamSeven.eventId as eventId +insert into updateStream; + +from innerStreamOne[innerStreamOne.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamOne.id == AlertsTable.id +select innerStreamOne.id as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamOne.proximityWith), "") as proximityWith, innerStreamOne.eventId as eventId +insert into updateStream; + +from innerStreamSeven[innerStreamSeven.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamSeven.proximityWith == AlertsTable.id +select innerStreamSeven.proximityWith as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamSeven.id), "") as proximityWith, innerStreamSeven.eventId as eventId +insert into updateStream; + +from updateStream +select * +update AlertsTable + on id== AlertsTable.id; + +from updateStream[proximityWith == ""] +delete AlertsTable + on id== AlertsTable.id; + +from objectInitialStream[AlertsTable.id == objectInitialStream.id in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId, true as inAlertTable +insert into publishStream; + +from objectInitialStream[not(AlertsTable.id == objectInitialStream.id in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId, false as inAlertTable +insert into publishStream; + +from publishStream[inAlertTable == true]#window.length(0) join AlertsTable +on publishStream.id== AlertsTable.id +select publishStream.id as id, publishStream.latitude as latitude, publishStream.longitude as longitude, publishStream.timeStamp as timeStamp, publishStream.type as type, publishStream.speed as speed, publishStream.heading as heading, publishStream.eventId as eventId, AlertsTable.proximityWith as proximityInfo +insert into innerStreamTwo; + +from publishStream[inAlertTable == false] +delete ProximityTable on ProximityTable.id==id; + +from publishStream[inAlertTable == false] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from innerStreamTwo[ProximityTable.id == innerStreamTwo.id in ProximityTable] +insert into innerStreamThree; + +from innerStreamThree#window.length(0) join ProximityTable +on innerStreamThree.id == ProximityTable.id +select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId, ProximityTable.timeStamp as storedTime, innerStreamThree.proximityInfo as proximityInfo +insert into innerStreamFour; + +from innerStreamFour[(timeStamp - storedTime) >= $proximityTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,proximityInfo,"true" as isProximity +insert into dataOutStream; + +from innerStreamFour[(timeStamp - storedTime) < $proximityTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)] +select innerStreamTwo.id, innerStreamTwo.timeStamp +insert into ProximityTable; + +from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from dataOutStream[isProximity == 'true'] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,"WARNING" as state,str:concat("Proximity with "," ",proximityInfo) as information +insert into dataOut; + +from dataOutStream[isProximity == 'false'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql new file mode 100644 index 0000000000..65dad468d5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql @@ -0,0 +1,20 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('Geo-ExecutionPlan-Speed---$deviceId_alert') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string); + +from dataIn[speed >= $speedAlertValue and id == "$deviceId"]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information +insert into dataOut; +from dataIn[speed < $speedAlertValue and id == "$deviceId"] +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information +insert into dataOut; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql new file mode 100644 index 0000000000..46bfbfe2e3 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql @@ -0,0 +1,89 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +@IndexBy('id') +define table StationeryTable(id string, timeStamp long); + +@IndexBy('id') +define table AlertsTable(id string, stationary bool); + +from dataIn#geodashboard:subscribe() +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin +insert into innerStreamOne; + +from innerStreamOne[isWithin == false] +delete StationeryTable on StationeryTable.id==id; + +from innerStreamOne[isWithin == false] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius) +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary +insert into innerStreamTwo; + +from innerStreamTwo[innerStreamTwo.stationary == true] +select innerStreamTwo.id, innerStreamTwo.stationary +insert into AlertsTable; + +from innerStreamTwo[innerStreamTwo.stationary == false] +delete AlertsTable on AlertsTable.id==id; + +from innerStreamTwo[innerStreamTwo.stationary == false] +delete StationeryTable on StationeryTable.id==id; + +from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable] +insert into innerStreamThree; + +from innerStreamThree#window.length(0) join AlertsTable +on innerStreamThree.id == AlertsTable.id +select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId +insert into innerStreamFour; + +from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)] +select innerStreamFour.id, innerStreamFour.timeStamp +insert into StationeryTable; + +from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable] +insert into innerStreamFive; + +from innerStreamFive#window.length(0) join StationeryTable +on innerStreamFive.id == StationeryTable.id +select innerStreamFive.id , innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime +insert into innerStreamSix; + +from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true" as isStationary +insert into dataOutStream; + +from innerStreamSix[(timeStamp - storedTime) < $stationeryTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false" as isStationary +insert into dataOutStream; + +from dataOutStream[isStationary == 'true'] +select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information +insert into dataOut; + +from dataOutStream[isStationary == 'false'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql new file mode 100644 index 0000000000..5e6bb5b1a8 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql @@ -0,0 +1,17 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('rawGeoStream:1.0.0') +define stream dataIn (id string, timeStamp long, geometry string, state string, information string); + +@Export('AlertsNotifications:1.0.0') +define stream dataOut (id string, state string, information string, timeStamp long, latitude double, longitude double); + +from dataIn[geo:intersects(geometry, "$geoFenceGeoJSON")==true and geodashboard:needToNotify(id, str:concat(information, state), "sendFirst") == true and id == $deviceId] +select id, state, str:concat("Traffic alert in $areaName. State: ", state, " ", information) as information, timeStamp, 0.0 as latitude, 0.0 as longitude +insert into dataOut \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql new file mode 100644 index 0000000000..b58fd59e33 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql @@ -0,0 +1,20 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true and id == "$deviceId"]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information +insert into dataOut; +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true and id == "$deviceId"] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information +insert into dataOut; diff --git a/pom.xml b/pom.xml index 809b90d159..f3bb3f2103 100644 --- a/pom.xml +++ b/pom.xml @@ -1171,6 +1171,21 @@ org.wso2.carbon.application.mgt.stub ${carbon.commons.version} + + org.wso2.carbon.analytics + org.wso2.carbon.analytics.api + ${carbon.analytics.version} + + + org.wso2.carbon.analytics + org.wso2.carbon.analytics.datasource.commons + ${carbon.analytics.version} + + + org.wso2.carbon.event-processing + org.wso2.carbon.event.processor.stub + ${carbon.event-processing.version} + org.wso2.orbit.org.bouncycastle @@ -1827,10 +1842,12 @@ 6.1.64 (6.0.0,7.0.0] - + + 1.3.3 + [1.3.3, 1.4.0) 5.1.3 [5.1.3,6.0.0) - + 2.1.10 4.6.0