Added Geo Service into Device Mgt Core

merge-requests/1/head
Rasika Perera 8 years ago
parent 7e83b53bb4
commit ea3ed9c444

@ -296,6 +296,16 @@
<artifactId>org.wso2.carbon.application.mgt.stub</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.datasource.commons</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>

@ -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);
}

@ -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<SortByField> 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<SearchResultEntry> searchResults = analyticsDataAPI.search(tenantId, tableName, query,
0,
100,
sortByFields);
List<Event> events = getEventBeans(analyticsDataAPI, tenantId, tableName, new ArrayList<String>(),
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<GeoFence> 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<GeoFence> alerts = geoService.getStationaryAlerts(identifier);
return Response.ok().entity(alerts).build();
} else if (GeoServices.EXECUTION_PLAN_TYPE_TRAFFIC.equals(executionPlanType)) {
List<GeoFence> 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<Event> getEventBeans(AnalyticsDataAPI analyticsDataAPI, int tenantId, String tableName,
List<String> columns,
List<SearchResultEntry> searchResults) throws AnalyticsException {
List<String> ids = getIds(searchResults);
List<String> requiredColumns = (columns == null || columns.isEmpty()) ? null : columns;
AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, requiredColumns, ids);
List<Record> records = AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response);
Map<String, Event> eventBeanMap = getEventBeanKeyedWithIds(records);
return getSortedEventBeans(eventBeanMap, searchResults);
}
private List<Event> getSortedEventBeans(Map<String, Event> eventBeanMap,
List<SearchResultEntry> searchResults) {
List<Event> sortedRecords = new ArrayList<>();
for (SearchResultEntry entry : searchResults) {
sortedRecords.add(eventBeanMap.get(entry.getId()));
}
return sortedRecords;
}
private Map<String, Event> getEventBeanKeyedWithIds(List<Record> records) {
Map<String, Event> eventBeanMap = new HashMap<>();
for (Record record : records) {
Event event = getEventBean(record);
eventBeanMap.put(event.getId(), event);
}
return eventBeanMap;
}
private List<String> getIds(List<SearchResultEntry> searchResults) {
List<String> 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;
}
}

@ -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);

@ -36,6 +36,7 @@
<ref bean="userManagementService"/>
<ref bean="userManagementAdminService"/>
<ref bean="groupManagementService"/>
<ref bean="geoService"/>
<ref bean="groupManagementAdminService"/>
<ref bean="applicationManagementAdminService"/>
<ref bean="deviceTypeManagementAdminService"/>
@ -76,6 +77,7 @@
<bean id="roleManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.RoleManagementServiceImpl"/>
<bean id="userManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.UserManagementServiceImpl"/>
<bean id="groupManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.GroupManagementServiceImpl"/>
<bean id="geoService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.GeoServiceImpl"/>
<bean id="deviceManagementAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.DeviceManagementAdminServiceImpl"/>
<bean id="applicationManagementAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.ApplicationManagementAdminServiceImpl"/>
<bean id="groupManagementAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.GroupManagementAdminServiceImpl"/>

@ -50,6 +50,7 @@
<Import-Package>
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
</Import-Package>
</instructions>
@ -68,6 +69,14 @@
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.api</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.datasource.commons</artifactId>
</dependency>
</dependencies>
</project>

@ -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;
}
}

@ -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);
}
}

@ -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<String, Object> 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<String, Object> 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<String, Object> 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<String> valueList = new ArrayList<>();
for (Map.Entry<String, Object> entry : values.entrySet()) {
valueList.add(entry.getKey() + ":" + entry.getValue());
}
return valueList.toString();
}
}

@ -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 +
"}";
}
}

@ -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<GeoFence> 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<GeoFence> getStationaryAlerts(DeviceIdentifier identifier) throws GeoServiceException;
List<GeoFence> getTrafficAlerts(DeviceIdentifier identifier) throws GeoServiceException;
}

@ -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);
}
}

@ -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
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.core.internal,
@ -262,6 +265,20 @@
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.event-processing</groupId>
<artifactId>org.wso2.carbon.event.processor.stub</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>

@ -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<GeoFence> 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<GeoFence> 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<Map<String, String>>() {
}.getType();
Gson gson = new Gson();
Map<String, String> parseMap = gson.fromJson(alert.getParseData(), type);
Map<String, String> 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<Header> 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<GeoFence> 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<GeoFence> 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<GeoFence> 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<GeoFence> 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<String, String> 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<String, String> 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<String, String> options)
throws GeoServiceException {
try {
Registry registry = getGovernanceRegistry();
Resource newResource = registry.newResource();
newResource.setContent(content);
newResource.setMediaType("application/json");
for (Map.Entry<String, String> 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;
}
}

@ -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();

@ -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;

@ -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;

@ -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;

@ -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

@ -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;

@ -1171,6 +1171,21 @@
<artifactId>org.wso2.carbon.application.mgt.stub</artifactId>
<version>${carbon.commons.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.api</artifactId>
<version>${carbon.analytics.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.datasource.commons</artifactId>
<version>${carbon.analytics.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.event-processing</groupId>
<artifactId>org.wso2.carbon.event.processor.stub</artifactId>
<version>${carbon.event-processing.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.bouncycastle</groupId>
@ -1827,10 +1842,12 @@
<carbon.api.mgt.version>6.1.64</carbon.api.mgt.version>
<carbon.api.mgt.version.range>(6.0.0,7.0.0]</carbon.api.mgt.version.range>
<!-- Carbon Analytics Commons -->
<!-- Carbon Analytics -->
<carbon.analytics.version>1.3.3</carbon.analytics.version>
<carbon.analytics.version.range>[1.3.3, 1.4.0)</carbon.analytics.version.range>
<carbon.analytics.common.version>5.1.3</carbon.analytics.common.version>
<carbon.analytics.common.version.range>[5.1.3,6.0.0)</carbon.analytics.common.version.range>
<carbon.event-processing.version>2.1.10</carbon.event-processing.version>
<!-- Carbon Registry -->
<carbon.registry.version>4.6.0</carbon.registry.version>

Loading…
Cancel
Save