diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/EventAction.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/EventAction.java new file mode 100644 index 00000000000..61f58704830 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/EventAction.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.jaxrs.beans; + +import io.swagger.annotations.ApiModelProperty; + +public class EventAction { + + @ApiModelProperty( + name = "actionType", + value = "Type of the event action to be triggered in the device level", + required = true) + private String actionType; + + @ApiModelProperty( + name = "payload", + value = "Payload of the event action", + required = true) + private Object payload; + + public String getActionType() { + return actionType; + } + + public void setActionType(String actionType) { + this.actionType = actionType; + } + + public Object getPayload() { + return payload; + } + + public void setPayload(Object payload) { + this.payload = payload; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/EventConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/EventConfig.java new file mode 100644 index 00000000000..2d1ba340052 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/EventConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.jaxrs.beans; + +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +public class EventConfig { + + @ApiModelProperty( + name = "id", + value = "id of the event entry") + private int id; + + @ApiModelProperty( + name = "eventLogic", + value = "Logic of the event should be handled at the device level", + required = true) + private String eventLogic; + + @ApiModelProperty( + name = "actions", + value = "List of actions to be triggered according to the logic", + required = true) + private List actions; + + public String getEventLogic() { + return eventLogic; + } + + public void setEventLogic(String eventLogic) { + this.eventLogic = eventLogic; + } + + public List getActions() { + return actions; + } + + public void setActions(List actions) { + this.actions = actions; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/GeofenceWrapper.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/GeofenceWrapper.java index 533775b73b4..e97323fd232 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/GeofenceWrapper.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/GeofenceWrapper.java @@ -20,6 +20,9 @@ package org.wso2.carbon.device.mgt.jaxrs.beans; import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.Map; + public class GeofenceWrapper { @ApiModelProperty( @@ -35,8 +38,7 @@ public class GeofenceWrapper { @ApiModelProperty( name = "description", - value = "Description of the geo fence", - required = true) + value = "Description of the geo fence") private String description; @ApiModelProperty( @@ -61,9 +63,24 @@ public class GeofenceWrapper { @ApiModelProperty( name = "fenceShape", - value = "Shape of the fence") + value = "Shape of the fence", + required = true) private String fenceShape; + @ApiModelProperty( + name = "eventConfig", + value = "Event configuration of the geofence", + required = true) + private List eventConfig; + + @ApiModelProperty( + name = "groupIds", + value = "Group ids to add geo fences", + required = true) + private List groupIds; + + private Map groupNames; + public int getId() { return id; } @@ -127,4 +144,28 @@ public class GeofenceWrapper { public void setFenceShape(String fenceShape) { this.fenceShape = fenceShape; } + + public List getEventConfig() { + return eventConfig; + } + + public void setEventConfig(List eventConfig) { + this.eventConfig = eventConfig; + } + + public List getGroupIds() { + return groupIds; + } + + public void setGroupIds(List groupIds) { + this.groupIds = groupIds; + } + + public Map getGroupNames() { + return groupNames; + } + + public void setGroupNames(Map groupNames) { + this.groupNames = groupNames; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java index a8358ad8317..5e55acdc775 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java @@ -33,6 +33,7 @@ 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.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.GeofenceWrapper; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -50,6 +51,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.util.ArrayList; @SwaggerDefinition( info = @Info( @@ -872,14 +874,15 @@ public interface GeoLocationBasedService { @ApiResponse( code = 400, message = "Bad Request. \n Invalid Geofence data found.", - response = Response.class), + response = ErrorResponse.class), @ApiResponse( code = 401, - message = "Unauthorized. \n Unauthorized request."), + message = "Unauthorized. \n Unauthorized request.", + response = ErrorResponse.class), @ApiResponse( code = 500, message = "Internal Server Error. \n Error on retrieving stats", - response = Response.class) + response = ErrorResponse.class) }) Response createGeofence(@ApiParam(name = "fence", value = "Geo fence data")GeofenceWrapper geofenceWrapper); @@ -927,7 +930,11 @@ public interface GeoLocationBasedService { name = "fenceId", value = "Id of the fence", required = true) - @PathParam("fenceId") int fenceId); + @PathParam("fenceId") int fenceId, + @ApiParam( + name = "requireEventData", + value = "Require geofence event data") + @QueryParam("requireEventData") boolean requireEventData); @GET @@ -976,7 +983,11 @@ public interface GeoLocationBasedService { @ApiParam( name = "name", value = "Geo Fence name") - @QueryParam("name") String name); + @QueryParam("name") String name, + @ApiParam( + name = "requireEventData", + value = "Require geofence event data") + @QueryParam("requireEventData") boolean requireEventData); @DELETE @@ -1067,11 +1078,13 @@ public interface GeoLocationBasedService { response = Response.class) }) Response updateGeofence( - @ApiParam(name = "fence", value = "Geo fence data")GeofenceWrapper geofenceWrapper, + @ApiParam(name = "fence", value = "Geo fence data") + GeofenceWrapper geofenceWrapper, @ApiParam( name = "fenceId", value = "Id of the fence", required = true) - @PathParam("fenceId") int fenceId); + @PathParam("fenceId") int fenceId, + @ApiParam(name = "eventIds", value = "Event id list to be removed") @QueryParam("eventIds") int[] eventIds); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 144b1228b7e..be5592b3404 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -18,8 +18,13 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.google.gson.Gson; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpStatus; import org.wso2.carbon.analytics.api.AnalyticsDataAPI; import org.wso2.carbon.analytics.api.AnalyticsDataAPIUtil; import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse; @@ -35,6 +40,8 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException; import org.wso2.carbon.device.mgt.common.geo.service.*; @@ -45,8 +52,11 @@ import org.wso2.carbon.device.mgt.core.geo.geoHash.geoHashStrategy.GeoHashLength import org.wso2.carbon.device.mgt.core.geo.geoHash.geoHashStrategy.ZoomGeoHashLengthStrategy; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; +import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.jaxrs.beans.EventAction; import org.wso2.carbon.device.mgt.jaxrs.beans.GeofenceWrapper; import org.wso2.carbon.device.mgt.jaxrs.service.api.GeoLocationBasedService; +import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; @@ -56,6 +66,7 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import javax.ws.rs.*; import javax.ws.rs.core.Response; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -589,35 +600,53 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { @Produces("application/json") public Response createGeofence(GeofenceWrapper geofenceWrapper) { RequestValidationUtil.validateGeofenceData(geofenceWrapper); + RequestValidationUtil.validateEventConfigurationData(geofenceWrapper.getEventConfig()); try { - GeofenceData geofenceData = new GeofenceData(); - geofenceData.setFenceName(geofenceWrapper.getFenceName()); - geofenceData.setDescription(geofenceWrapper.getDescription()); - geofenceData.setLatitude(geofenceWrapper.getLatitude()); - geofenceData.setLongitude(geofenceWrapper.getLongitude()); - geofenceData.setRadius(geofenceWrapper.getRadius()); - geofenceData.setGeoJson(geofenceWrapper.getGeoJson()); - geofenceData.setFenceShape(geofenceWrapper.getFenceShape()); - + GeofenceData geofenceData = mapRequestGeofenceData(geofenceWrapper); GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); if (!geoService.createGeofence(geofenceData)) { String msg = "Failed to create geofence"; log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); } - return Response.status(Response.Status.CREATED).build(); + return Response.status(Response.Status.CREATED).entity("Geo Fence record created successfully").build(); } catch (GeoLocationBasedServiceException e) { String msg = "Failed to create geofence"; log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } catch (EventConfigurationException e) { + String msg = "Failed to create event configuration for Geo Fence"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + + private List mapRequestEvent(List eventConfig) { + List savingEventList = new ArrayList<>(); + for (org.wso2.carbon.device.mgt.jaxrs.beans.EventConfig event : eventConfig) { + EventConfig savingConfig = new EventConfig(); + if (event.getId() > 0) { + savingConfig.setEventId(event.getId()); + } else { + savingConfig.setEventId(-1); + } + savingConfig.setEventLogic(event.getEventLogic()); + String eventJson = new Gson().toJson(event.getActions()); + savingConfig.setActions(eventJson); + savingEventList.add(savingConfig); } + return savingEventList; } @Path("/geo-fence/{fenceId}") @GET @Consumes("application/json") @Produces("application/json") - public Response getGeofence(@PathParam("fenceId") int fenceId) { + public Response getGeofence(@PathParam("fenceId") int fenceId, + @QueryParam("requireEventData") boolean requireEventData) { try { GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); GeofenceData geofenceData = geoService.getGeoFences(fenceId); @@ -625,6 +654,10 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { String msg = "No valid Geofence found for ID " + fenceId; return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); } + if (requireEventData) { + List eventsOfGeoFence = geoService.getEventsOfGeoFence(geofenceData.getId()); + geofenceData.setEventConfig(eventsOfGeoFence); + } return Response.status(Response.Status.OK).entity(getMappedResponseBean(geofenceData)).build(); } catch (GeoLocationBasedServiceException e) { String msg = "Server error occurred while retrieving Geofence for Id " + fenceId; @@ -647,16 +680,48 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { geofenceWrapper.setRadius(geofenceData.getRadius()); geofenceWrapper.setGeoJson(geofenceData.getGeoJson()); geofenceWrapper.setFenceShape(geofenceData.getFenceShape()); + if (geofenceData.getGroupIds() != null && !geofenceData.getGroupIds().isEmpty()) { + geofenceWrapper.setGroupIds(geofenceData.getGroupIds()); + } + if (geofenceData.getGroupData() != null && !geofenceData.getGroupData().isEmpty()) { + geofenceWrapper.setGroupNames(geofenceData.getGroupData()); + } + if (geofenceData.getEventConfig() != null) { + geofenceWrapper.setEventConfig(getEventConfigBean(geofenceData.getEventConfig())); + } return geofenceWrapper; } + private List getEventConfigBean(List eventConfig) { + List eventList = new ArrayList<>(); + org.wso2.carbon.device.mgt.jaxrs.beans.EventConfig eventData; + for (EventConfig event : eventConfig) { + eventData = new org.wso2.carbon.device.mgt.jaxrs.beans.EventConfig(); + eventData.setId(event.getEventId()); + eventData.setEventLogic(event.getEventLogic()); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + try { + List eventActions = mapper.readValue(event.getActions(), mapper.getTypeFactory(). + constructCollectionType(List.class, EventAction.class)); + eventData.setActions(eventActions); + } catch (IOException e) { + log.error("Error occurred while parsing event actions of the event with ID " + event.getEventId()); + } + eventList.add(eventData); + } + return eventList; + } + @Path("/geo-fence") @GET @Consumes("application/json") @Produces("application/json") public Response getGeofence(@QueryParam("offset") int offset, @QueryParam("limit") int limit, - @QueryParam("name") String name) { + @QueryParam("name") String name, + @QueryParam("requireEventData") boolean requireEventData) { try { GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); if (offset >= 0 && limit != 0) { @@ -664,10 +729,18 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { if (name != null && !name.isEmpty()) { request.setProperty(DeviceManagementConstants.GeoServices.FENCE_NAME, name); } - return getResponse(geoService.getGeoFences(request)); + List geoFences = geoService.getGeoFences(request); + if (!geoFences.isEmpty() && requireEventData) { + geoFences = geoService.attachEventObjects(geoFences); + } + return getResponse(geoFences); } if (name != null && !name.isEmpty()) { - return getResponse(geoService.getGeoFences(name)); + List geoFences = geoService.getGeoFences(name); + if (requireEventData) { + geoFences = geoService.attachEventObjects(geoFences); + } + return getResponse(geoFences); } return getResponse(geoService.getGeoFences()); } catch (GeoLocationBasedServiceException e) { @@ -712,28 +785,55 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { @PUT @Consumes("application/json") @Produces("application/json") - public Response updateGeofence(GeofenceWrapper geofenceWrapper, @PathParam("fenceId") int fenceId) { + public Response updateGeofence(GeofenceWrapper geofenceWrapper, + @PathParam("fenceId") int fenceId, + @QueryParam("eventIds") int[] eventIds) { RequestValidationUtil.validateGeofenceData(geofenceWrapper); + RequestValidationUtil.validateEventConfigurationData(geofenceWrapper.getEventConfig()); try { - GeofenceData geofenceData = new GeofenceData(); - geofenceData.setFenceName(geofenceWrapper.getFenceName()); - geofenceData.setDescription(geofenceWrapper.getDescription()); - geofenceData.setLatitude(geofenceWrapper.getLatitude()); - geofenceData.setLongitude(geofenceWrapper.getLongitude()); - geofenceData.setRadius(geofenceWrapper.getRadius()); - geofenceData.setFenceShape(geofenceWrapper.getFenceShape()); - geofenceData.setGeoJson(geofenceWrapper.getGeoJson()); + GeofenceData geofenceData = mapRequestGeofenceData(geofenceWrapper); GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); if (!geoService.updateGeofence(geofenceData, fenceId)) { String msg = "No valid Geofence found for ID " + fenceId; log.error(msg); return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); } - return Response.status(Response.Status.CREATED).build(); + List eventsToRemove = new ArrayList<>(); + for (int eventId : eventIds) { + eventsToRemove.add(eventId); + } + geoService.updateGeoEventConfigurations(geofenceData, eventsToRemove, + geofenceData.getGroupIds(), fenceId); + return Response.status(Response.Status.CREATED).entity("Geo Fence update successfully").build(); } catch (GeoLocationBasedServiceException e) { - String msg = "Failed to create geofence"; + String msg = "Failed to update geofence"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (EventConfigurationException e) { + String msg = "Failed to update geofence events"; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + private GeofenceData mapRequestGeofenceData(GeofenceWrapper geofenceWrapper) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setFenceName(geofenceWrapper.getFenceName()); + geofenceData.setDescription(geofenceWrapper.getDescription()); + geofenceData.setLatitude(geofenceWrapper.getLatitude()); + geofenceData.setLongitude(geofenceWrapper.getLongitude()); + geofenceData.setRadius(geofenceWrapper.getRadius()); + geofenceData.setFenceShape(geofenceWrapper.getFenceShape()); + geofenceData.setGeoJson(geofenceWrapper.getGeoJson()); + if (geofenceWrapper.getGroupIds() == null || geofenceWrapper.getGroupIds().isEmpty()) { + String msg = "Group ID / IDs are mandatory, since cannot be null or empty"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST) + .setMessage(msg).build()); + } + geofenceData.setGroupIds(geofenceWrapper.getGroupIds()); + geofenceData.setEventConfig(mapRequestEvent(geofenceWrapper.getEventConfig())); + return geofenceData; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java index c588d7fd912..b227f9a231d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java @@ -35,6 +35,7 @@ import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.jaxrs.beans.EventConfig; import org.wso2.carbon.device.mgt.jaxrs.beans.GeofenceWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyWrapper; @@ -719,4 +720,29 @@ public class RequestValidationUtil { new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); } } + + public static void validateEventConfigurationData(List eventConfig) { + if (eventConfig == null ||eventConfig.isEmpty()) { + String msg = "Event configuration is mandatory, since should not be null or empty"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + + for (EventConfig config : eventConfig) { + if (config.getActions() == null || config.getActions().isEmpty()) { + String msg = "Event actions are mandatory, since should not be null or empty"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + + if (config.getEventLogic() == null || config.getEventLogic().trim().isEmpty()) { + String msg = "Event logic is mandatory, since should not be null or empty"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + } + } } 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 e652311aeda..073e8f44e39 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 @@ -62,6 +62,7 @@ import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorization import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshot; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; 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 95cc1a02674..62590a821c1 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 @@ -136,4 +136,10 @@ public final class DeviceManagementConstants { public static final String TENANT_ADMIN_PASSWORD = "tenant-admin-password"; } + public static final class EventServices { + private EventServices() { throw new AssertionError(); } + + public static final String GEOFENCE = "GEOFENCE"; + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventAction.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventAction.java new file mode 100644 index 00000000000..d17e3756f53 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventAction.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +public class EventAction { + private String actionType; + private Object payload; + + public String getActionType() { + return actionType; + } + + public void setActionType(String actionType) { + this.actionType = actionType; + } + + public Object getPayload() { + return payload; + } + + public void setPayload(Object payload) { + this.payload = payload; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfig.java new file mode 100644 index 00000000000..7d649ed9933 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +public class EventConfig { + private int eventId; + private String eventSource; + private String eventLogic; + private String actions; + + public String getEventLogic() { + return eventLogic; + } + + public void setEventLogic(String eventLogic) { + this.eventLogic = eventLogic; + } + + public String getActions() { + return actions; + } + + public void setActions(String actions) { + this.actions = actions; + } + + public int getEventId() { + return eventId; + } + + public void setEventId(int eventId) { + this.eventId = eventId; + } + + public String getEventSource() { + return eventSource; + } + + public void setEventSource(String eventSource) { + this.eventSource = eventSource; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EventConfig) { + EventConfig eventConfig = (EventConfig) obj; + return this.eventSource.equalsIgnoreCase(eventConfig.getEventSource()) && + this.eventLogic.equalsIgnoreCase(eventConfig.getEventLogic()); + } + return false; + } + + @Override + public String toString() { + return "{eventId=" + eventId + + ", eventSource='" + eventSource + '\'' + + ", eventLogic='" + eventLogic + '\'' + + ", actions='" + actions + '\'' + + '}'; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfigurationException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfigurationException.java new file mode 100644 index 00000000000..7d03aca99d3 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfigurationException.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +public class EventConfigurationException extends Exception { + public EventConfigurationException() { + super(); + } + + public EventConfigurationException(String message) { + super(message); + } + + public EventConfigurationException(String message, Throwable cause) { + super(message, cause); + } + + public EventConfigurationException(Throwable cause) { + super(cause); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfigurationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfigurationProviderService.java new file mode 100644 index 00000000000..703807065b0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventConfigurationProviderService.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +import java.util.List; + +public interface EventConfigurationProviderService { + /** + * Create event configuration records + * + * @param eventConfigList event list to be added + * @param groupIds group ids of the events are mapped + * @return generated event ids + * @throws EventConfigurationException errors thrown while creating event configuration + */ + List createEventsOfDeviceGroup(List eventConfigList, List groupIds) + throws EventConfigurationException; + + /** + * Update event configuration records + * + * @param eventConfig updated event configuration list. event ids should be present for + * the updating events and event ids should be -1 for the newly creating events + * @param removedEventIdList event ids of removed while updating the event configuration + * @param groupIds group ids to be mapped with updated events + * @return Newly created event Ids + * @throws EventConfigurationException + */ + List updateEventsOfDeviceGroup(List eventConfig, List removedEventIdList, + List groupIds) throws EventConfigurationException; + + /** + * Retrieve event list using event IDs + * + * @param createdEventIds event ids + * @return {@link EventConfig} List of events of defined IDs + * @throws EventConfigurationException + */ + List getEvents(List createdEventIds) throws EventConfigurationException; + + /** + * Get event sources attached to a specific group + * + * @param groupId mapped group id of events + * @param tenantId event owning tenant + * @return Event sources of the group + * @throws EventConfigurationException error thrown while retrieving event sources + */ + List getEventsSourcesOfGroup(int groupId, int tenantId) throws EventConfigurationException; + + /** + * Delete events by event Ids + * + * @param eventList event list to be deleted + * @throws EventConfigurationException error thrown while deleting event records + */ + void deleteEvents(List eventList) throws EventConfigurationException; + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventMetaData.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventMetaData.java new file mode 100644 index 00000000000..c3f3566286d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventMetaData.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +public interface EventMetaData {} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventOperation.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventOperation.java new file mode 100644 index 00000000000..3fd9d0d276e --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventOperation.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import java.util.List; + +public class EventOperation { + private String eventSource; + private EventMetaData eventDefinition; + private String eventTriggers; + + public String getEventSource() { + return eventSource; + } + + public void setEventSource(String eventSource) { + this.eventSource = eventSource; + } + + public EventMetaData getEventDefinition() { + return eventDefinition; + } + + public void setEventDefinition(EventMetaData eventDefinition) { + this.eventDefinition = eventDefinition; + } + + public String getEventTriggers() { + return eventTriggers; + } + + public void setEventTriggers(List eventList) { + JsonArray eventTriggers = new JsonArray(); + JsonObject eventTrigger; + for (EventConfig eventConfig : eventList) { + eventTrigger = new JsonObject(); + eventTrigger.addProperty("eventId", eventConfig.getEventId()); + eventTrigger.addProperty("eventLogic", eventConfig.getEventLogic()); + eventTrigger.addProperty("actions", eventConfig.getActions()); + eventTriggers.add(eventTrigger); + } + this.eventTriggers = eventTriggers.toString(); + } + + public String toJSON() { + Gson gson = new Gson(); + return gson.toJson(this); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventRevokeOperation.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventRevokeOperation.java new file mode 100644 index 00000000000..109a0eb91f2 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventRevokeOperation.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; +public class EventRevokeOperation { + private String eventSource; + private int id; + + public String getEventSource() { + return eventSource; + } + + public void setEventSource(String eventSource) { + this.eventSource = eventSource; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFenceEventMeta.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFenceEventMeta.java new file mode 100644 index 00000000000..dd58cd5016f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoFenceEventMeta.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config.EventMetaData; + +public class GeoFenceEventMeta implements EventMetaData { + private int id; + private String fenceName; + private String description; + private double latitude; + private double longitude; + private float radius; + private String geoJson; + private String fenceShape; + + public GeoFenceEventMeta() { + } + + public GeoFenceEventMeta(GeofenceData geofenceData) { + this.id = geofenceData.getId(); + this.fenceName = geofenceData.getFenceName(); + this.description = geofenceData.getDescription(); + this.latitude = geofenceData.getLatitude(); + this.longitude = geofenceData.getLongitude(); + this.radius = geofenceData.getRadius(); + this.geoJson = geofenceData.getGeoJson(); + this.fenceShape = geofenceData.getFenceShape(); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getFenceName() { + return fenceName; + } + + public void setFenceName(String fenceName) { + this.fenceName = fenceName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public float getRadius() { + return radius; + } + + public void setRadius(float radius) { + this.radius = radius; + } + + public String getGeoJson() { + return geoJson; + } + + public void setGeoJson(String geoJson) { + this.geoJson = geoJson; + } + + public String getFenceShape() { + return fenceShape; + } + + public void setFenceShape(String fenceShape) { + this.fenceShape = fenceShape; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java index 60bb198a245..8c806f141da 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -21,7 +21,10 @@ package org.wso2.carbon.device.mgt.common.geo.service; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationException; +import java.util.ArrayList; import java.util.List; /** @@ -77,13 +80,14 @@ public interface GeoLocationProviderService { * @param geofenceData fence data * @return true if the fence creation success * @throws GeoLocationBasedServiceException error occurs while creating a geofence + * @throws EventConfigurationException for errors occur while creating event configuration for the geofence */ - boolean createGeofence(GeofenceData geofenceData) throws GeoLocationBasedServiceException; + boolean createGeofence(GeofenceData geofenceData) throws GeoLocationBasedServiceException, EventConfigurationException; /** * Get geofence by ID * @param fenceId id of the fence which should be retrieved - * @return Extracted geofence data + * @return {@link GeofenceData} Extracted geofence data * @throws GeoLocationBasedServiceException error occurs while retrieving a geofence */ GeofenceData getGeoFences(int fenceId) throws GeoLocationBasedServiceException; @@ -91,7 +95,7 @@ public interface GeoLocationProviderService { /** * Get paginated geofence list * @param request Pagination Request - * @return List of Geofences retrieved + * @return {@link GeofenceData} List of Geofences retrieved * @throws GeoLocationBasedServiceException error occurs while retrieving geofences */ List getGeoFences(PaginationRequest request) throws GeoLocationBasedServiceException; @@ -99,14 +103,14 @@ public interface GeoLocationProviderService { /** * Search geo fences using the fence name * @param name searching name of the fence - * @return list of fences found for the specific name + * @return {@link GeofenceData} list of fences found for the specific name * @throws GeoLocationBasedServiceException for errors occur while querying geo fences */ List getGeoFences(String name) throws GeoLocationBasedServiceException; /** * Get all geo fences of the tenant - * @return list of the all geo fences of the tenant + * @return {@link GeofenceData} list of the all geo fences of the tenant * @throws GeoLocationBasedServiceException for errors occur while querying geo fences */ List getGeoFences() throws GeoLocationBasedServiceException; @@ -125,6 +129,46 @@ public interface GeoLocationProviderService { * @param fenceId Id of the fence which should be updated * @return true if update success. false if not a record found for the used Id * @throws GeoLocationBasedServiceException for errors occur while updating geo fences + * @throws EventConfigurationException for errors occur while updating event records of the geofence */ - boolean updateGeofence(GeofenceData geofenceData, int fenceId) throws GeoLocationBasedServiceException; + boolean updateGeofence(GeofenceData geofenceData, int fenceId) + throws GeoLocationBasedServiceException, EventConfigurationException; + + /** + * Update geofence event configuration + * @param geofenceData updated GeoFenceData object + * @param removedEventIdList removed event ids + * @param groupIds newly added group ids to be mapped with event records + * @param fenceId updating fence id + * @return true for successful update of geofence event data + * @throws GeoLocationBasedServiceException any errors occurred while updating event records of the fence + */ + boolean updateGeoEventConfigurations(GeofenceData geofenceData, List removedEventIdList, + List groupIds, int fenceId) throws GeoLocationBasedServiceException; + + /** + * Attach event data into geofence objects + * @param geoFences list of GeofenceData to attach corresponding event data + * @return {@link GeofenceData} events attached geofence object list + * @throws GeoLocationBasedServiceException any errors occurred while attaching event records to geofences + */ + List attachEventObjects(List geoFences) throws GeoLocationBasedServiceException; + + /** + * Get Geofence records of groups. Attaching with corresponding event data of fences + * @param groupId Id of the group geo which fences attached + * @param tenantId Id of the tenant which geo fences attached + * @param requireEventData use true for attach event records with the geo fence data + * @return {@link GeofenceData} Queried geo fence data using group Id + * @throws GeoLocationBasedServiceException any errors occurred while getting geofences of group + */ + List getGeoFencesOfGroup(int groupId, int tenantId, boolean requireEventData) throws GeoLocationBasedServiceException; + + /** + * Get event records mapped with specific geo fence + * @param geoFenceId Id of the Geofence to retrieve mapped events + * @return {@link EventConfig} Event records of the geofence + * @throws GeoLocationBasedServiceException any errors occurred while reading event records to geofence + */ + List getEventsOfGeoFence(int geoFenceId) throws GeoLocationBasedServiceException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeofenceData.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeofenceData.java index 0dbc4a4294a..64471383f7b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeofenceData.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeofenceData.java @@ -18,6 +18,12 @@ package org.wso2.carbon.device.mgt.common.geo.service; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventMetaData; + +import java.util.List; +import java.util.Map; + public class GeofenceData { private int id; private String fenceName; @@ -29,6 +35,9 @@ public class GeofenceData { private String owner; private String geoJson; private String fenceShape; + private List eventConfig; + private List groupIds; + private Map groupData; public int getId() { return id; @@ -109,4 +118,28 @@ public class GeofenceData { public void setFenceShape(String fenceShape) { this.fenceShape = fenceShape; } + + public List getEventConfig() { + return eventConfig; + } + + public void setEventConfig(List eventConfig) { + this.eventConfig = eventConfig; + } + + public List getGroupIds() { + return groupIds; + } + + public void setGroupIds(List groupIds) { + this.groupIds = groupIds; + } + + public Map getGroupData() { + return groupData; + } + + public void setGroupData(Map groupData) { + this.groupData = groupData; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java index 3f309a001be..41b96665e6e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java @@ -98,6 +98,8 @@ public final class DeviceManagementConstants { public static final String MONITOR_OPERATION_CODE = "MONITOR"; public static final String POLICY_OPERATION_CODE = PolicyOperation.POLICY_OPERATION_CODE; public static final String POLICY_REVOKE_OPERATION_CODE = OperationMgtConstants.OperationCodes.POLICY_REVOKE; + public static final String EVENT_CONFIG_OPERATION_CODE = OperationMgtConstants.OperationCodes.EVENT_CONFIG; + public static final String EVENT_REVOKE_OPERATION_CODE = OperationMgtConstants.OperationCodes.EVENT_REVOKE; } public static final class CorrectiveActions { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java index 255047a7a54..c5c778ca23b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -29,11 +29,13 @@ import org.wso2.carbon.device.mgt.core.config.datasource.JNDILookupDefinition; import org.wso2.carbon.device.mgt.core.dao.impl.ApplicationDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.DeviceTypeDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.EnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.event.GenericEventConfigDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.GeofenceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.GenericDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.OracleDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.PostgreSQLDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.SQLServerDeviceDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.event.H2EventConfigDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsDAO; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.impl.DeviceDetailsDAOImpl; @@ -154,6 +156,23 @@ public class DeviceManagementDAOFactory { return new GeofenceDAOImpl(); } + public static EventConfigDAO getEventConfigDAO() { + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + return new GenericEventConfigDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + return new H2EventConfigDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); + } + public static void init(DataSourceConfig config) { dataSource = resolveDataSource(config); try { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventConfigDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventConfigDAO.java new file mode 100644 index 00000000000..288d854b146 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventConfigDAO.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.dao; + +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; + +import java.util.List; + +public interface EventConfigDAO { + + /** + * Create event configuration entries of the db for a selected tenant + * @param eventConfigList event list to be created + * @param tenantId corresponding tenant id of the events + * @return generated event ids while storing geofence data + * @throws EventManagementDAOException error occurred while creating event records + */ + List storeEventRecords(List eventConfigList, int tenantId) throws EventManagementDAOException; + + /** + * Cerate even-group mapping records + * @param eventIds event ids to be mapped with groups + * @param groupIds group ids of the event attached with + * @return true for the successful creation + * @throws EventManagementDAOException error occurred while creating event-group mapping records + */ + boolean addEventGroupMappingRecords(List eventIds, List groupIds) throws EventManagementDAOException; + + /** + * Get events owned by a specific device group + * @param groupIds group ids of the events + * @param tenantId tenant of the events owning + * @return list of event configuration filtered by tenant id and group ids + * @throws EventManagementDAOException error occurred while reading event records + */ + List getEventsOfGroups(List groupIds, int tenantId) throws EventManagementDAOException; + + /** + * Get events of groups using group Id + * @param groupId id of the group + * @param tenantId id of the tenant + * @return EventConfig list of specific group + * @throws EventManagementDAOException errors occur while retrieving events of groups + */ + List getEventsOfGroups(int groupId, int tenantId) throws EventManagementDAOException; + + /** + * Delete event group mapping records using the group ids + * @param groupIdsToDelete id of groups + * @throws EventManagementDAOException error occurred while deleting event-group mapping records + */ + void deleteEventGroupMappingRecordsByGroupIds(List groupIdsToDelete) throws EventManagementDAOException; + + /** + * Update event records of the tenant + * @param eventsToUpdate updating event records + * @throws EventManagementDAOException error occurred while updating events + */ + void updateEventRecords(List eventsToUpdate) throws EventManagementDAOException; + + /** + * Delete events using event ids + * @param eventsIdsToDelete ids of the events which should be deleted + * @throws EventManagementDAOException error occurred while deleting event records + */ + void deleteEventRecords(List eventsIdsToDelete) throws EventManagementDAOException; + + /** + * Get event records by event ids + * @param eventIds filtering event ids + * @return filtered event configuration list + * @throws EventManagementDAOException error occurred while reading events + */ + List getEventsById(List eventIds) throws EventManagementDAOException; + + /** + * Get group ids belong to events using event ids + * @param eventIds Ids of the events mapped with group + * @return Group Id list + * @throws EventManagementDAOException thrown errors while retrieving group Ids of events + */ + List getGroupsOfEvents(List eventIds) throws EventManagementDAOException; + + /** + * Delete event group mapping records using event Ids + * @param eventIds Ids of the events + * @throws EventManagementDAOException thrown errors while deleting event group mappings + */ + void deleteEventGroupMappingRecordsByEventIds(List eventIds) throws EventManagementDAOException; + + /** + * Retrieve event sources mapped with specific groups and tenant + * @param groupId Id of the group + * @param tenantId Id of the tenant + * @return Event source list belong to + * @throws EventManagementDAOException thrown errors while retrieving event sources + */ + List getEventSourcesOfGroups(int groupId, int tenantId) throws EventManagementDAOException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOException.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOException.java new file mode 100644 index 00000000000..2331422fa5c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOException.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.dao; + +public class EventManagementDAOException extends Exception{ + public EventManagementDAOException() { + super(); + } + + public EventManagementDAOException(String message) { + super(message); + } + + public EventManagementDAOException(String message, Throwable cause) { + super(message, cause); + } + + public EventManagementDAOException(Throwable cause) { + super(cause); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GeofenceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GeofenceDAO.java index 0801edd6d95..8c309673676 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GeofenceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GeofenceDAO.java @@ -19,9 +19,13 @@ package org.wso2.carbon.device.mgt.core.dao; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; import java.util.List; +import java.util.Map; +import java.util.Set; /** * Use to manage geofence data in DB @@ -89,4 +93,85 @@ public interface GeofenceDAO { * @throws DeviceManagementDAOException error occurs while updating the data */ int updateGeofence(GeofenceData geofenceData, int fenceId) throws DeviceManagementDAOException; + + /** + * Create geofence-group mapping records for the fence associated groups + * @param geofenceData geofence data to be mapped with device group + * @param groupIds group ids of the geofence + * @return true for the successful record creation + * @throws DeviceManagementDAOException error occurred while saving event records + */ + boolean createGeofenceGroupMapping(GeofenceData geofenceData, List groupIds) throws DeviceManagementDAOException; + + /** + * Get associated group ids of a geofence mapped with + * @param fenceId id of the fence + * @return list of group ids mapped with the specified fence + * @throws DeviceManagementDAOException error occurred while reading group id records + */ + List getGroupIdsOfGeoFence(int fenceId) throws DeviceManagementDAOException; + + /** + * Delete geofence-group mapping records + * @param groupIdsToDelete group ids to be removed from the mapping table + * @throws DeviceManagementDAOException error occurred while deleting group id mapping records + */ + void deleteGeofenceGroupMapping(List groupIdsToDelete) throws DeviceManagementDAOException; + + /** + * Create geofence-event mapping records + * @param fenceId geofence id of the mapping records to be placed + * @param eventIds generated event ids for the geofence event configuration + * @throws DeviceManagementDAOException error occurred while creating geofence event mapping records + */ + void createGeofenceEventMapping(int fenceId, List eventIds) throws DeviceManagementDAOException; + + /** + * Remove geofence-event mapping records + * @param removedEventIdList event ids should be removed from the records + * @throws DeviceManagementDAOException error occurred deleting geofence event mapping + */ + void deleteGeofenceEventMapping(List removedEventIdList) throws DeviceManagementDAOException; + + /** + * Get events of the geofence using fence ids + * @param geofenceIds ids of geo fences to be queried + * @return Event config list mapped with fence id + * @throws DeviceManagementDAOException error occurred while retrieving geo fence event map + */ + Map> getEventsOfGeoFences(List geofenceIds) throws DeviceManagementDAOException; + + /** + * Get events of a particular geofence + * @param geofenceId id of the fence to be queried + * @return EventConfig list of the particular geofence + * @throws DeviceManagementDAOException thrown errors while getting events of geofence + */ + List getEventsOfGeoFence(int geofenceId) throws DeviceManagementDAOException; + + /** + * Get group Ids mapped with fence ids + * @param fenceIds fence id list to be queried + * @return GroupIds mapped with geofence id + * @throws DeviceManagementDAOException thrown errors while retrieving group Ids of geo fence + */ + Set getGroupIdsOfGeoFences(List fenceIds) throws DeviceManagementDAOException; + + /** + * Get geo fences of the specific group and tenant + * @param groupId id of the group + * @param tenantId tenant id of the geo fences + * @return List of geofence data mapped with specific group and tenant + * @throws DeviceManagementDAOException + */ + List getGeoFences(int groupId, int tenantId) throws DeviceManagementDAOException; + + /** + * Get geofence using fence id and attached group Ids + * @param fenceId id of the fence + * @param requireGroupData true if mapped group data needed + * @return Geofence data + * @throws DeviceManagementDAOException + */ + GeofenceData getGeofence(int fenceId, boolean requireGroupData) throws DeviceManagementDAOException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java new file mode 100644 index 00000000000..ece3f2a2bb7 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.EventConfigDAO; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOException; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public abstract class AbstractEventConfigDAO implements EventConfigDAO { + private static final Log log = LogFactory.getLog(AbstractEventConfigDAO.class); + + @Override + public boolean addEventGroupMappingRecords(List eventIds, List groupIds) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_DEVICE_EVENT_GROUP_MAPPING(" + + "EVENT_ID ," + + "GROUP_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIds) { + for (Integer eventId : eventIds) { + stmt.setInt(1, eventId); + stmt.setInt(2, groupId); + stmt.addBatch(); + } + } + return stmt.executeBatch().length > 0; + } + } catch (SQLException e) { + String msg = "Error occurred while creating event group mapping records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public List getEventsOfGroups(List groupIds, int tenantId) throws EventManagementDAOException { + try { + List eventList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_DEVICE_EVENT_GROUP_MAPPING G " + + "WHERE G.EVENT_ID = E.ID " + + "AND G.GROUP_ID IN (%s) " + + "AND E.TENANT_ID = ? " + + "GROUP BY E.ID"; + String inClause = String.join(", ", Collections.nCopies(groupIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer groupId : groupIds) { + stmt.setInt(index++, groupId); + } + stmt.setInt(index, tenantId); + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + EventConfig event = new EventConfig(); + event.setEventId(rst.getInt("EVENT_ID")); + event.setEventSource(rst.getString("EVENT_SOURCE")); + event.setEventLogic(rst.getString("EVENT_LOGIC")); + event.setActions(rst.getString("ACTIONS")); + eventList.add(event); + } + return eventList; + } + } catch (SQLException e) { + String msg = "Error occurred while creating event group mapping records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public List getEventsOfGroups(int groupId, int tenantId) throws EventManagementDAOException { + try { + List eventList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_DEVICE_EVENT_GROUP_MAPPING G " + + "WHERE G.EVENT_ID = E.ID " + + "AND G.GROUP_ID = ? " + + "AND E.TENANT_ID = ? " + + "GROUP BY E.ID"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + EventConfig event = new EventConfig(); + event.setEventId(rst.getInt("EVENT_ID")); + event.setEventSource(rst.getString("EVENT_SOURCE")); + event.setEventLogic(rst.getString("EVENT_LOGIC")); + event.setActions(rst.getString("ACTIONS")); + eventList.add(event); + } + return eventList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving event records of group " + groupId + + " and tenant " + tenantId; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public void deleteEventGroupMappingRecordsByEventIds(List eventsIdsToDelete) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_EVENT_GROUP_MAPPING WHERE EVENT_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(eventsIdsToDelete.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer eventId : eventsIdsToDelete) { + stmt.setInt(index++, eventId); + } + stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting event group mapping records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public void deleteEventGroupMappingRecordsByGroupIds(List groupIdsToDelete) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_EVENT_GROUP_MAPPING WHERE GROUP_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(groupIdsToDelete.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer groupId : groupIdsToDelete) { + stmt.setInt(index++, groupId); + stmt.addBatch(); + } + stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting event group mapping records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public void updateEventRecords(List eventsToUpdate) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "UPDATE DM_DEVICE_EVENT SET " + + "ACTIONS = ? " + + "WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (EventConfig updatingEvent : eventsToUpdate) { + stmt.setString(1, updatingEvent.getActions()); + stmt.setInt(2, updatingEvent.getEventId()); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while updating event records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public void deleteEventRecords(List eventsIdsToDelete) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_EVENT WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer eventId : eventsIdsToDelete) { + stmt.setInt(1, eventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting event records of tenant"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public List getEventsById(List eventIdList) throws EventManagementDAOException { + try { + List eventList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "ID AS EVENT_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT " + + "WHERE ID IN (%s) "; + String inClause = String.join(", ", Collections.nCopies(eventIdList.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer eventId : eventIdList) { + if (eventId != -1) { + stmt.setInt(index++, eventId); + } + } + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + EventConfig event = new EventConfig(); + event.setEventId(rst.getInt("EVENT_ID")); + event.setEventSource(rst.getString("EVENT_SOURCE")); + event.setEventLogic(rst.getString("EVENT_LOGIC")); + event.setActions(rst.getString("ACTIONS")); + eventList.add(event); + } + return eventList; + } + } catch (SQLException e) { + String msg = "Error occurred while creating event group mapping records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public List getGroupsOfEvents(List eventIdList) throws EventManagementDAOException { + try { + List groupIdList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "GROUP_ID " + + "FROM DM_DEVICE_EVENT_GROUP_MAPPING " + + "WHERE EVENT_ID IN (%s) " + + "GROUP BY GROUP_ID"; + String inClause = String.join(", ", Collections.nCopies(eventIdList.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer eventId : eventIdList) { + if (eventId != -1) { + stmt.setInt(index++, eventId); + } + } + ResultSet resultSet = stmt.executeQuery(); + while (resultSet.next()) { + groupIdList.add(resultSet.getInt("GROUP_ID")); + } + return groupIdList; + } + } catch (SQLException e) { + String msg = "Error occurred while creating event group mapping records"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public List getEventSourcesOfGroups(int groupId, int tenantId) throws EventManagementDAOException { + try { + List eventSourceList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "EVENT_SOURCE " + + "FROM DM_DEVICE_EVENT E, DM_DEVICE_EVENT_GROUP_MAPPING G " + + "WHERE G.EVENT_ID = E.ID " + + "AND G.GROUP_ID = ? " + + "AND E.TENANT_ID = ? " + + "GROUP BY EVENT_SOURCE"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + eventSourceList.add(rst.getString("EVENT_SOURCE")); + } + return eventSourceList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving event records of group " + groupId + + " and tenant " + tenantId; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java index e02c3811962..b4e6ad8be29 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationBasedServiceException; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; import java.sql.Connection; import java.sql.PreparedStatement; @@ -35,8 +36,13 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; public class GeofenceDAOImpl implements GeofenceDAO { private static final Log log = LogFactory.getLog(GeofenceDAOImpl.class); @@ -85,8 +91,8 @@ public class GeofenceDAOImpl implements GeofenceDAO { @Override public GeofenceData getGeofence(int fenceId) throws DeviceManagementDAOException { try { - GeofenceData geofenceData = null; Connection conn = this.getConnection(); + GeofenceData geofenceData = null; String sql = "SELECT " + "ID, " + "FENCE_NAME, " + @@ -121,9 +127,9 @@ public class GeofenceDAOImpl implements GeofenceDAO { public List getGeoFencesOfTenant(PaginationRequest request, int tenantId) throws DeviceManagementDAOException { try { + Connection conn = this.getConnection(); boolean isNameProvided = false; List geofenceData; - Connection conn = this.getConnection(); String sql = "SELECT " + "ID, " + "FENCE_NAME, " + @@ -167,8 +173,8 @@ public class GeofenceDAOImpl implements GeofenceDAO { public List getGeoFencesOfTenant(String fenceName, int tenantId) throws DeviceManagementDAOException { try { - List geofenceData; Connection conn = this.getConnection(); + List geofenceData; String sql = "SELECT " + "ID, " + "FENCE_NAME, " + @@ -181,7 +187,8 @@ public class GeofenceDAOImpl implements GeofenceDAO { "OWNER, " + "TENANT_ID " + "FROM DM_GEOFENCE " + - "WHERE FENCE_NAME LIKE ? AND TENANT_ID = ? "; + "WHERE FENCE_NAME LIKE ?" + + "AND TENANT_ID = ? "; try (PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setString(1, fenceName + "%"); stmt.setInt(2, tenantId); @@ -201,8 +208,8 @@ public class GeofenceDAOImpl implements GeofenceDAO { public List getGeoFencesOfTenant(int tenantId) throws DeviceManagementDAOException { try { - List geofenceData; Connection conn = this.getConnection(); + List geofenceData; String sql = "SELECT " + "ID, " + "FENCE_NAME, " + @@ -277,6 +284,29 @@ public class GeofenceDAOImpl implements GeofenceDAO { } } + @Override + public boolean createGeofenceGroupMapping(GeofenceData geofenceData, List groupIds) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE_GROUP_MAPPING(" + + "FENCE_ID, " + + "GROUP_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIds) { + stmt.setInt(1, geofenceData.getId()); + stmt.setInt(2, groupId); + stmt.addBatch(); + } + return stmt.executeBatch().length > 0; + } + } catch (SQLException e) { + String msg = "Error occurred while creating geofence group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } @@ -299,4 +329,305 @@ public class GeofenceDAOImpl implements GeofenceDAO { } return geofenceDataList; } + + @Override + public List getGroupIdsOfGeoFence(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "SELECT " + + "GROUP_ID " + + "FROM DM_GEOFENCE_GROUP_MAPPING " + + "WHERE FENCE_ID = ? "; + List groupIds = new ArrayList<>(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + try (ResultSet rst = stmt.executeQuery()) { + while (rst.next()) { + groupIds.add(rst.getInt(1)); + } + } + } + return groupIds; + } catch (SQLException e) { + String msg = "Error occurred while fetching group IDs of the fence " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void deleteGeofenceGroupMapping(List groupIdsToDelete) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE_GROUP_MAPPING WHERE GROUP_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIdsToDelete) { + stmt.setInt(1, groupId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void createGeofenceEventMapping(int fenceId, List eventIds) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE_EVENT_MAPPING(" + + "FENCE_ID, "+ + "EVENT_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer createdEventId : eventIds) { + stmt.setInt(1, fenceId); + stmt.setInt(2, createdEventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while creating geofence event group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void deleteGeofenceEventMapping(List removedEventIdList) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE_EVENT_MAPPING WHERE EVENT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer eventId : removedEventIdList) { + stmt.setInt(1, eventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence event mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public Map> getEventsOfGeoFences(List geofenceIds) throws DeviceManagementDAOException { + try { + Map> geoFenceEventMap = new HashMap<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "M.FENCE_ID AS FENCE_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_GEOFENCE_EVENT_MAPPING M " + + "WHERE E.ID = M.EVENT_ID " + + "AND M.FENCE_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(geofenceIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer geofenceId : geofenceIds) { + stmt.setInt(index++, geofenceId); + } + ResultSet resultSet = stmt.executeQuery(); + while (resultSet.next()) { + int fenceId = resultSet.getInt("FENCE_ID"); + List eventConfigList = geoFenceEventMap.get(fenceId); + if (eventConfigList == null) { + eventConfigList = new ArrayList<>(); + } + EventConfig event = new EventConfig(); + event.setEventId(resultSet.getInt("EVENT_ID")); + event.setEventSource(resultSet.getString("EVENT_SOURCE")); + event.setEventLogic(resultSet.getString("EVENT_LOGIC")); + event.setActions(resultSet.getString("ACTIONS")); + eventConfigList.add(event); + geoFenceEventMap.put(fenceId, eventConfigList); + } + return geoFenceEventMap; + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id "; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getEventsOfGeoFence(int geofenceId) throws DeviceManagementDAOException { + try { + List eventList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_GEOFENCE_EVENT_MAPPING G " + + "WHERE E.ID = G.EVENT_ID " + + "AND G.FENCE_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, geofenceId); + return getEventConfigs(eventList, stmt); + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id "; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public Set getGroupIdsOfGeoFences(List fenceIds) throws DeviceManagementDAOException { + try { + Set geoFenceGroupSet = new HashSet<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "FENCE_ID, " + + "M.GROUP_ID, " + + "G.GROUP_NAME " + + "FROM DM_GEOFENCE_GROUP_MAPPING M, DM_GROUP G " + + "WHERE M.GROUP_ID = G.ID " + + "AND FENCE_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(fenceIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer fenceId : fenceIds) { + stmt.setInt(index++, fenceId); + } + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + GeoFenceGroupMap geoFenceGroupMap = new GeoFenceGroupMap(); + geoFenceGroupMap.setFenceId(rst.getInt("FENCE_ID")); + geoFenceGroupMap.setGroupId(rst.getInt("GROUP_ID")); + geoFenceGroupMap.setGroupName(rst.getString("GROUP_NAME")); + geoFenceGroupSet.add(geoFenceGroupMap); + } + } + return geoFenceGroupSet; + } catch (SQLException e) { + String msg = "Error occurred while fetching group IDs of the fences"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + private List getEventConfigs(List eventList, PreparedStatement stmt) throws SQLException { + ResultSet resultSet = stmt.executeQuery(); + EventConfig event; + while (resultSet.next()) { + event = new EventConfig(); + event.setEventId(resultSet.getInt("EVENT_ID")); + event.setEventSource(resultSet.getString("EVENT_SOURCE")); + event.setEventLogic(resultSet.getString("EVENT_LOGIC")); + event.setActions(resultSet.getString("ACTIONS")); + eventList.add(event); + } + return eventList; + } + + @Override + public List getGeoFences(int groupId, int tenantId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "SELECT " + + "G.ID AS FENCE_ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE," + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE " + + "FROM DM_GEOFENCE G, DM_GEOFENCE_GROUP_MAPPING M " + + "WHERE M.GROUP_ID = ? AND TENANT_ID = ? " + + "GROUP BY G.ID"; + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + ResultSet rst = stmt.executeQuery(); + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("FENCE_ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geo fences of group " + groupId + + " and tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public GeofenceData getGeofence(int fenceId, boolean requireGroupData) throws DeviceManagementDAOException { + if (!requireGroupData) { + return getGeofence(fenceId); + } + + try { + Connection con = this.getConnection(); + String sql = "SELECT " + + "G.ID AS FENCE_ID, " + + "FENCE_NAME, " + + "G.DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "M.GROUP_ID AS GROUP_ID, " + + "GR.GROUP_NAME " + + "FROM DM_GEOFENCE G, DM_GEOFENCE_GROUP_MAPPING M, DM_GROUP GR " + + "WHERE G.ID = M.FENCE_ID " + + "AND M.GROUP_ID = GR.ID " + + "AND G.ID = ?"; + try (PreparedStatement stmt = con.prepareStatement(sql)){ + stmt.setInt(1, fenceId); + ResultSet rst = stmt.executeQuery(); + Map groupMap = new HashMap<>(); + GeofenceData geofenceData = null; + while (rst.next()) { + groupMap.put(rst.getInt("GROUP_ID"), rst.getString("GROUP_NAME")); + if (rst.isLast()) { + geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("FENCE_ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setGroupData(groupMap); + } + } + return geofenceData; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geo fence data " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/event/GenericEventConfigDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/event/GenericEventConfigDAOImpl.java new file mode 100644 index 00000000000..0dfeee16b20 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/event/GenericEventConfigDAOImpl.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.dao.impl.event; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.EventConfigDAO; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractEventConfigDAO; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +public class GenericEventConfigDAOImpl extends AbstractEventConfigDAO { + private static final Log log = LogFactory.getLog(GenericEventConfigDAOImpl.class); + + @Override + public List storeEventRecords(List eventConfigList, int tenantId) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_DEVICE_EVENT(" + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS, "+ + "CREATED_TIMESTAMP, " + + "TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + for (EventConfig eventConfig : eventConfigList) { + stmt.setString(1, eventConfig.getEventSource()); + stmt.setString(2, eventConfig.getEventLogic()); + stmt.setString(3, eventConfig.getActions()); + stmt.setTimestamp(4, new Timestamp(new Date().getTime())); + stmt.setInt(5, tenantId); + stmt.addBatch(); + } + int[] createdRowCount = stmt.executeBatch(); + List generatedIds = new ArrayList<>(); + ResultSet generatedKeys = stmt.getGeneratedKeys(); + for (int i = 0; i < createdRowCount.length; i++) { + if (generatedKeys.next()) { + generatedIds.add(generatedKeys.getInt(1)); + } + } + return generatedIds; + } + } catch (SQLException e) { + String msg = "Error occurred while creating event configurations for the tenant id " + tenantId; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/event/H2EventConfigDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/event/H2EventConfigDAOImpl.java new file mode 100644 index 00000000000..fef946649f5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/event/H2EventConfigDAOImpl.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.dao.impl.event; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractEventConfigDAO; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class H2EventConfigDAOImpl extends AbstractEventConfigDAO { + private static final Log log = LogFactory.getLog(H2EventConfigDAOImpl.class); + + @Override + public List storeEventRecords(List eventConfigList, int tenantId) throws EventManagementDAOException { + try { + Connection conn = this.getConnection(); + List generatedIds = new ArrayList<>(); + String sql = "INSERT INTO DM_DEVICE_EVENT(" + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS, "+ + "CREATED_TIMESTAMP, " + + "TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + for (EventConfig eventConfig : eventConfigList) { + stmt.setString(1, eventConfig.getEventSource()); + stmt.setString(2, eventConfig.getEventLogic()); + stmt.setString(3, eventConfig.getActions()); + stmt.setTimestamp(4, new Timestamp(new Date().getTime())); + stmt.setInt(5, tenantId); + int affectedRawCount = stmt.executeUpdate(); + if (affectedRawCount > 0) { + ResultSet generatedKeys = stmt.getGeneratedKeys(); + if (generatedKeys.next()) { + generatedIds.add(generatedKeys.getInt(1)); + } + } + } + return generatedIds; + } + } catch (SQLException e) { + String msg = "Error occurred while creating event configurations for the tenant id " + tenantId; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/event/config/GeoFenceGroupMap.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/event/config/GeoFenceGroupMap.java new file mode 100644 index 00000000000..bac19e86782 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/event/config/GeoFenceGroupMap.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.dto.event.config; + +public class GeoFenceGroupMap { + private int fenceId; + private int groupId; + private String groupName; + + public int getFenceId() { + return fenceId; + } + + public void setFenceId(int fenceId) { + this.fenceId = fenceId; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof GeoFenceGroupMap) { + GeoFenceGroupMap map = (GeoFenceGroupMap)obj; + return map.getFenceId() == this.getFenceId() + && map.getGroupId() == this.getGroupId() + && map.getGroupName().equals(this.getGroupName()); + } + return false; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventConfigurationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventConfigurationProviderServiceImpl.java new file mode 100644 index 00000000000..e72d733ec3c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventConfigurationProviderServiceImpl.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +import com.google.common.collect.Lists; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationException; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.EventConfigDAO; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class EventConfigurationProviderServiceImpl implements EventConfigurationProviderService { + private static final Log log = LogFactory.getLog(EventConfigurationProviderServiceImpl.class); + private final EventConfigDAO eventConfigDAO; + + public EventConfigurationProviderServiceImpl() { + eventConfigDAO = DeviceManagementDAOFactory.getEventConfigDAO(); + } + + @Override + public List createEventsOfDeviceGroup(List eventConfigList, List groupIds) + throws EventConfigurationException { + int tenantId; + try { + tenantId = DeviceManagementDAOUtil.getTenantId(); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving tenant Id"; + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } + + try { + DeviceManagementDAOFactory.beginTransaction(); + if (log.isDebugEnabled()) { + log.debug("Creating event records of tenant " + tenantId); + } + List generatedEventIds = eventConfigDAO.storeEventRecords(eventConfigList, tenantId); + if (log.isDebugEnabled()) { + log.debug("Created events with event ids : " + generatedEventIds.toString()); + log.debug("Creating event group mapping for created events with group ids : " + groupIds.toString()); + } + eventConfigDAO.addEventGroupMappingRecords(generatedEventIds, groupIds); + DeviceManagementDAOFactory.commitTransaction(); + if (log.isDebugEnabled()) { + log.debug("Event configuration added successfully for the tenant " + tenantId); + } + return generatedEventIds; + } catch (TransactionManagementException e) { + String msg = "Failed to start/open transaction to store device event configurations"; + throw new EventConfigurationException(msg, e); + } catch (EventManagementDAOException e) { + String msg = "Error occurred while saving event records"; + log.error(msg, e); + DeviceManagementDAOFactory.rollbackTransaction(); + throw new EventConfigurationException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public List updateEventsOfDeviceGroup(List newEventList, List removedEventIdList, + List groupIds) throws EventConfigurationException { + //todo when concerning about other event types, all of this steps might not necessary. + // so divide them into separate service methods + if (log.isDebugEnabled()) { + log.debug("Updating event configurations of tenant"); + } + List eventsToAdd; + try { + DeviceManagementDAOFactory.beginTransaction(); + eventsToAdd = new ArrayList<>(); + List eventsToUpdate = new ArrayList<>(); + List updateEventIdList = new ArrayList<>(); + for (EventConfig newEvent : newEventList) { + if (newEvent.getEventId() == -1) { + eventsToAdd.add(newEvent); + continue; + } + eventsToUpdate.add(newEvent); + updateEventIdList.add(newEvent.getEventId()); + } + List savedGroups = eventConfigDAO.getGroupsOfEvents(updateEventIdList); + List groupIdsToAdd = new ArrayList<>(); + List groupIdsToDelete = new ArrayList<>(); + for (Integer savedGroup : savedGroups) { + if (!groupIds.contains(savedGroup)) { + groupIdsToDelete.add(savedGroup); + } + } + + for (Integer newGroupId : groupIds) { + if (!savedGroups.contains(newGroupId)) { + groupIdsToAdd.add(newGroupId); + } + } + + if (!eventsToUpdate.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("Updating event records "); + } + eventConfigDAO.updateEventRecords(eventsToUpdate); + } + + + if (!groupIdsToDelete.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("Deleting event group mapping records of groups"); + } + eventConfigDAO.deleteEventGroupMappingRecordsByGroupIds(groupIdsToDelete); + } + + if (!groupIdsToAdd.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("Creating event group mapping records for updated events"); + } + eventConfigDAO.addEventGroupMappingRecords(updateEventIdList, groupIdsToAdd); + } + + if (!removedEventIdList.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("Deleting event group mapping records of removing events"); + } + eventConfigDAO.deleteEventGroupMappingRecordsByEventIds(removedEventIdList); + + if (log.isDebugEnabled()) { + log.debug("Deleting removed event records"); + } + eventConfigDAO.deleteEventRecords(removedEventIdList); + } + DeviceManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException e) { + String msg = "Failed to start/open transaction to store device event configurations"; + throw new EventConfigurationException(msg, e); + } catch (EventManagementDAOException e) { + String msg = "Error occurred while saving event records"; + log.error(msg, e); + DeviceManagementDAOFactory.rollbackTransaction(); + throw new EventConfigurationException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + + if (log.isDebugEnabled()) { + log.debug("Adding new events while updating event"); + } + return createEventsOfDeviceGroup(eventsToAdd, groupIds); + } + + @Override + public List getEvents(List createdEventIds) throws EventConfigurationException { + try { + DeviceManagementDAOFactory.openConnection(); + return eventConfigDAO.getEventsById(createdEventIds); + } catch (EventManagementDAOException e) { + String msg = "Error occurred while retrieving event by IDs : " + Arrays.toString(createdEventIds.toArray()); + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } catch (SQLException e) { + String msg = "Failed to open connection while retrieving event by IDs"; + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public List getEventsSourcesOfGroup(int groupId, int tenantId) throws EventConfigurationException { + try { + DeviceManagementDAOFactory.openConnection(); + return eventConfigDAO.getEventSourcesOfGroups(groupId, tenantId); + } catch (EventManagementDAOException e) { + String msg = "Error occurred while retrieving events of group " + groupId + " and tenant " + tenantId; + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } catch (SQLException e) { + String msg = "Failed to open connection while retrieving event by IDs"; + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public void deleteEvents(List events) throws EventConfigurationException { + try { + DeviceManagementDAOFactory.beginTransaction(); + Set eventIdSet = new HashSet<>(); + for (EventConfig eventConfig : events) { + eventIdSet.add(eventConfig.getEventId()); + } + if (!eventIdSet.isEmpty()) { + eventConfigDAO.deleteEventGroupMappingRecordsByEventIds(Lists.newArrayList(eventIdSet)); + eventConfigDAO.deleteEventRecords(Lists.newArrayList(eventIdSet)); + } + DeviceManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException e) { + String msg = "Failed to start/open transaction to delete device event configurations"; + throw new EventConfigurationException(msg, e); + } catch (EventManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting event records"; + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventOperationExecutor.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventOperationExecutor.java new file mode 100644 index 00000000000..462355c754b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventOperationExecutor.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +import com.google.gson.Gson; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationException; +import org.wso2.carbon.device.mgt.common.event.config.EventMetaData; +import org.wso2.carbon.device.mgt.common.event.config.EventOperation; +import org.wso2.carbon.device.mgt.common.event.config.EventRevokeOperation; +import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException; +import org.wso2.carbon.device.mgt.common.geo.service.GeoFenceEventMeta; +import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationBasedServiceException; +import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; +import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.core.geo.task.EventCreateCallback; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMgtConstants; +import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Event create/revoke operation creation task. + * Use at the time of single event create, update, delete + */ +public class EventOperationExecutor implements Runnable { + private static final Log log = LogFactory.getLog(EventOperationExecutor.class); + + private final List groupIds; + private final String eventSource; + private final EventMetaData eventMetaData; + private final int tenantId; + private final String operationCode; + private final GroupManagementProviderService groupManagementService; + private EventCreateCallback callback; + + public EventOperationExecutor(EventMetaData eventMetaData, List groupIds, int tenantId, + String eventSource, String operationCode) { + this.eventMetaData = eventMetaData; + this.groupIds = groupIds; + this.tenantId = tenantId; + this.eventSource = eventSource; + this.operationCode = operationCode; + this.groupManagementService = DeviceManagementDataHolder.getInstance().getGroupManagementProviderService(); + } + + @Override + public void run() { + log.info("Starting event operation creation task"); + if (operationCode == null) { + log.error("Failed to start event operation task. Operation code is null"); + return; + } + if (log.isDebugEnabled()) { + log.info("Starting " + operationCode + " operation creation task for event " + eventSource + + " tenant " + tenantId + " group Ids "+ Arrays.toString(groupIds.toArray())); + } + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true); + ProfileOperation operation = new ProfileOperation(); + operation.setType(Operation.Type.PROFILE); + try { + if (operationCode.equalsIgnoreCase(OperationMgtConstants.OperationCodes.EVENT_CONFIG)) { + operation.setCode(OperationMgtConstants.OperationCodes.EVENT_CONFIG); + buildEventConfigOperation(operation); + } else if (operationCode.equalsIgnoreCase(OperationMgtConstants.OperationCodes.EVENT_REVOKE)){ + operation.setCode(OperationMgtConstants.OperationCodes.EVENT_REVOKE); + buildEventRevokeOperation(operation); + } + } catch (EventConfigurationException e) { + log.error("Event creation failed with message : " + e.getMessage(), e); + return; + } + Set devices = new HashSet<>(); + for (Integer groupId : groupIds) { + DeviceGroup group; + try { + group = groupManagementService.getGroup(groupId, false); + } catch (GroupManagementException e) { + log.error("Failed to retrieve group with group ID " + groupId, e); + continue; + } + try { + if (group != null) { + List allDevicesOfGroup = groupManagementService.getAllDevicesOfGroup(group.getName(), false); + if (allDevicesOfGroup == null || allDevicesOfGroup.isEmpty()) { + log.warn("No devices found in group " + group.getName()); + } else { + devices.addAll(allDevicesOfGroup); + } + } + } catch (GroupManagementException e) { + log.error("Failed to retrieve devices of group with ID " + groupId + " and name " + group.getName(), e); + } + } + + if (devices.isEmpty()) { + log.warn("No devices found for the specified groups " + Arrays.toString(groupIds.toArray())); + return; + } + List deviceIdentifiers = new ArrayList<>(); + for (Device device : devices) { + if (device.getType().equalsIgnoreCase("android")) { + //TODO introduce a proper mechanism for event handling for each device types + deviceIdentifiers.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); + } + } + DeviceManagementProviderService deviceManagementProvider = DeviceManagementDataHolder + .getInstance().getDeviceManagementProvider(); + try { + if (log.isDebugEnabled()) { + log.debug("Creating event operations stared for devices" + Arrays.toString(deviceIdentifiers.toArray())); + } + deviceManagementProvider.addOperation("android", operation, deviceIdentifiers); + //TODO introduce a proper mechanism + } catch (OperationManagementException e) { + log.error("Creating event operation failed with error ", e); + return; + } catch (InvalidDeviceException e) { + log.error("Creating event operation failed.\n" + + "Could not found device/devices for the defined device identifiers.", e); + return; + } + log.info("Event operation creation task completed"); + if (callback != null) { + callback.onCompleteEventOperation(null); + } + } + + /** + * Build operation to create EVENT_REVOKE operation. + * @param operation Operation object to build + */ + private void buildEventRevokeOperation(ProfileOperation operation) { + if (eventSource.equalsIgnoreCase(DeviceManagementConstants.EventServices.GEOFENCE)) { + createGeoFenceRevokeOperation(operation); + } //extend with another cases to handle other types of events + } + + /** + * Build operation to create EVENT_CONFIG operation. + * @param operation Operation object to build + * @throws EventConfigurationException Failed while build the operation object + */ + private void buildEventConfigOperation(ProfileOperation operation) throws EventConfigurationException { + if (eventSource.equalsIgnoreCase(DeviceManagementConstants.EventServices.GEOFENCE)) { + createGeoFenceConfigOperation(operation); + } //extend with another cases to handle other types of events + } + + /** + * Create EVENT_CONFIG operation object and attach payload to configure geo fence events + * @param operation operation object to set the payload + * @throws EventConfigurationException Failed while retrieving event list of geo fence + */ + private void createGeoFenceConfigOperation(ProfileOperation operation) throws EventConfigurationException { + GeoFenceEventMeta geoFenceMeta = (GeoFenceEventMeta) eventMetaData; + try { + GeoLocationProviderService geoLocationProviderService = DeviceManagementDataHolder + .getInstance().getGeoLocationProviderService(); + List eventConfigList = geoLocationProviderService.getEventsOfGeoFence(geoFenceMeta.getId()); + if (log.isDebugEnabled()) { + log.debug("Retrieved event records of Geo Fence " + geoFenceMeta.getId() + + ". events " + Arrays.toString(eventConfigList.toArray())); + } + List eventOperations = new ArrayList<>(); + EventOperation eventOperation = new EventOperation(); + eventOperation.setEventDefinition(eventMetaData); + eventOperation.setEventSource(eventSource); + eventOperation.setEventTriggers(eventConfigList); + eventOperations.add(eventOperation); + operation.setPayLoad(new Gson().toJson(eventOperations)); + }catch (GeoLocationBasedServiceException e) { + throw new EventConfigurationException("Failed to retrieve event data of Geo fence " + geoFenceMeta.getId() + + " : " + geoFenceMeta.getFenceName(), e); + } + } + + /** + * Create EVENT_REVOKE operation object and attach payload to configure geo fence events + * @param operation operation object to set the payload + */ + private void createGeoFenceRevokeOperation(ProfileOperation operation) { + GeoFenceEventMeta geoFenceMeta = (GeoFenceEventMeta) eventMetaData; + EventRevokeOperation eventRevokeOperation = new EventRevokeOperation(); + eventRevokeOperation.setEventSource(eventSource); + eventRevokeOperation.setId(geoFenceMeta.getId()); + operation.setPayLoad(new Gson().toJson(eventRevokeOperation)); + } + + /** + * Can be used to set the task callback to call after the task completed successfully + * @param callback Event callback object implemented inside the task starting class + */ + public void setCallback(EventCreateCallback callback) { + this.callback = callback; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/GroupEventOperationExecutor.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/GroupEventOperationExecutor.java new file mode 100644 index 00000000000..cef77c8675c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/GroupEventOperationExecutor.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.event.config; + +import com.google.gson.Gson; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationException; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; +import org.wso2.carbon.device.mgt.common.event.config.EventOperation; +import org.wso2.carbon.device.mgt.common.event.config.EventRevokeOperation; +import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException; +import org.wso2.carbon.device.mgt.common.geo.service.GeoFenceEventMeta; +import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationBasedServiceException; +import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService; +import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.core.geo.task.EventCreateCallback; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMgtConstants; +import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Event create/revoke operation creation task. + * Use at the time of devices assign into group, remove from group. + */ +public class GroupEventOperationExecutor implements Runnable { + private static final Log log = LogFactory.getLog(GroupEventOperationExecutor.class); + + private final int groupId; + private final List deviceIdentifiers; + private final int tenantId; + private final String operationCode; + private final GeoLocationProviderService geoLocationProviderService; + private final EventConfigurationProviderService eventConfigurationService; + private EventCreateCallback callback; + + public GroupEventOperationExecutor(int groupId, List deviceIdentifiers, int tenantId, String operationCode) { + this.groupId = groupId; + this.deviceIdentifiers = deviceIdentifiers; + this.tenantId = tenantId; + this.operationCode = operationCode; + this.geoLocationProviderService = DeviceManagementDataHolder.getInstance().getGeoLocationProviderService(); + this.eventConfigurationService = DeviceManagementDataHolder.getInstance().getEventConfigurationService(); + } + + @Override + public void run() { + log.info("Starting event operation creation task for devices in group " + groupId + " tenant " + tenantId); + if (log.isDebugEnabled()) { + log.debug("Event creation operation started for devices with IDs " + Arrays.toString(deviceIdentifiers.toArray())); + log.debug("Starting tenant flow for tenant with ID : " + tenantId); + } + ProfileOperation operation = new ProfileOperation(); + if (operationCode != null) { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true); + try { + operation.setCode(operationCode); + operation.setType(Operation.Type.PROFILE); + if (operationCode.equalsIgnoreCase(OperationMgtConstants.OperationCodes.EVENT_CONFIG)) { + buildEventConfigOperationObject(operation); + } else if (operationCode.equalsIgnoreCase(OperationMgtConstants.OperationCodes.EVENT_REVOKE)) { + buildEventRevokeOperation(operation); + } + + } catch (EventConfigurationException e) { + log.error("Failed to retrieve event sources of group " + groupId + ". Event creation operation failed.", e); + return; + } + + DeviceManagementProviderService deviceManagementProvider = DeviceManagementDataHolder + .getInstance().getDeviceManagementProvider(); + try { + if (!deviceIdentifiers.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("Creating event operations stared"); + } + deviceManagementProvider.addOperation("android", operation, deviceIdentifiers); //TODO introduce a proper mechanism + } else { + log.info("Device identifiers are empty, Hence ignoring adding event operation"); + } + } catch (OperationManagementException e) { + log.error("Creating event operation failed with error ", e); + } catch (InvalidDeviceException e) { + log.error("Creating event operation failed.\n" + + "Could not found device/devices for the defined device identifiers.", e); + } + log.info("Event operation creation succeeded"); + if (callback != null) { + callback.onCompleteEventOperation(null); + } + } + + } + + /** + * Build EVENT_REVOKE operation attaching event payload + * @param operation operation object to build + * @throws EventConfigurationException if not events found for the specific group + */ + private void buildEventRevokeOperation(ProfileOperation operation) throws EventConfigurationException { + List eventSources = eventConfigurationService.getEventsSourcesOfGroup(groupId, tenantId); + if (eventSources == null || eventSources.isEmpty()) { + String msg = "No events applied for queried group with ID " + groupId; + log.info(msg); + throw new EventConfigurationException(msg); + } + for (String eventSource : eventSources) { + if (eventSource.equalsIgnoreCase(DeviceManagementConstants.EventServices.GEOFENCE)) { + setGeoFenceRevokeOperationContent(operation); + } //extend with another cases to handle other types of events + } + } + + /** + * Build EVENT_CONFIG operation attaching event payload + * @param operation operation object to build + * @throws EventConfigurationException if not events found for the specific group + */ + private void buildEventConfigOperationObject(ProfileOperation operation) throws EventConfigurationException { + List eventSources = eventConfigurationService.getEventsSourcesOfGroup(groupId, tenantId); + if (eventSources == null || eventSources.isEmpty()) { + String msg = "No events applied for queried group with ID " + groupId; + log.info(msg); + throw new EventConfigurationException(msg); + } + for (String eventSource : eventSources) { + if (eventSource.equalsIgnoreCase(DeviceManagementConstants.EventServices.GEOFENCE)) { + setGeoFenceConfigOperationContent(operation); + } //extend with another cases to handle other types of events + } + } + + /** + * Set operation payload GeoFence for EVENT_CONFIG operation + * @param operation operation object to attach payload + * @throws EventConfigurationException failed while getting events of group + */ + private void setGeoFenceConfigOperationContent(ProfileOperation operation) throws EventConfigurationException { + log.info("Geo fence events found attached with group " + groupId + ", Started retrieving geo fences"); + List geoFencesOfGroup = getGeoFencesOfGroup(); + List eventOperationList = new ArrayList<>(); + for (GeofenceData geofenceData : geoFencesOfGroup) { + GeoFenceEventMeta geoFenceEventMeta = new GeoFenceEventMeta(geofenceData); + EventOperation eventOperation = new EventOperation(); + eventOperation.setEventDefinition(geoFenceEventMeta); + eventOperation.setEventSource(DeviceManagementConstants.EventServices.GEOFENCE); + eventOperation.setEventTriggers(geofenceData.getEventConfig()); + eventOperationList.add(eventOperation); + } + operation.setPayLoad(new Gson().toJson(eventOperationList)); + } + + /** + * Get geo fence list of the group + * @return {@link GeofenceData} geofence data list of the geo fence + * @throws EventConfigurationException error occurred while querying geo fences of group + */ + private List getGeoFencesOfGroup() throws EventConfigurationException { + List geoFencesOfGroup; + try { + geoFencesOfGroup = geoLocationProviderService.getGeoFencesOfGroup(groupId, tenantId, true); + } catch (GeoLocationBasedServiceException e) { + String msg = "Failed to get geo fences of the group"; + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } + if (log.isDebugEnabled()) { + log.debug("Retrieved " + geoFencesOfGroup.size() + " geo fences defined for the group " + groupId); + } + return geoFencesOfGroup; + } + + /** + * Set operation payload GeoFence for EVENT_REVOKE operation + * @param operation operation object to attach payload + * @throws EventConfigurationException failed while getting events of group + */ + private void setGeoFenceRevokeOperationContent(ProfileOperation operation) throws EventConfigurationException { + List geoFencesOfGroup = getGeoFencesOfGroup(); + List revokeOperationList = new ArrayList<>(); + for (GeofenceData geofenceData : geoFencesOfGroup) { + EventRevokeOperation eventRevokeOperation = new EventRevokeOperation(); + eventRevokeOperation.setEventSource(DeviceManagementConstants.EventServices.GEOFENCE); + eventRevokeOperation.setId(geofenceData.getId()); + revokeOperationList.add(eventRevokeOperation); + } + operation.setPayLoad(new Gson().toJson(revokeOperationList)); + } + + /** + * Can be used to set the task callback to call after the task completed successfully + * @param callback Event callback object implemented inside the task starting class + */ + public void setCallback(EventCreateCallback callback) { + this.callback = callback; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index d8409ef112e..9dca01c56f4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -36,8 +36,12 @@ 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; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationException; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; import org.wso2.carbon.device.mgt.common.geo.service.Alert; import org.wso2.carbon.device.mgt.common.geo.service.GeoFence; @@ -50,7 +54,10 @@ import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; +import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMgtConstants; import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub; import org.wso2.carbon.event.processor.stub.types.ExecutionPlanConfigurationDto; import org.wso2.carbon.identity.jwt.client.extension.JWTClient; @@ -83,6 +90,10 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Collections; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; 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; @@ -1248,7 +1259,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } @Override - public boolean createGeofence(GeofenceData geofenceData) throws GeoLocationBasedServiceException { + public boolean createGeofence(GeofenceData geofenceData) throws GeoLocationBasedServiceException, EventConfigurationException { int tenantId; try { tenantId = DeviceManagementDAOUtil.getTenantId(); @@ -1265,7 +1276,8 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic geofenceData = geofenceDAO.saveGeofence(geofenceData); GeoCacheManagerImpl.getInstance() .addFenceToCache(geofenceData, geofenceData.getId(), tenantId); - return true; + geofenceDAO.createGeofenceGroupMapping(geofenceData, geofenceData.getGroupIds()); + DeviceManagementDAOFactory.commitTransaction(); } catch (TransactionManagementException e) { String msg = "Failed to begin transaction for saving geofence"; log.error(msg, e); @@ -1276,7 +1288,75 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic log.error(msg, e); throw new GeoLocationBasedServiceException(msg, e); } finally { + DeviceManagementDAOFactory.closeConnection(); + } + List createdEventIds; + try { + setEventSource(geofenceData.getEventConfig()); + EventConfigurationProviderService eventConfigService = DeviceManagementDataHolder + .getInstance().getEventConfigurationService(); + createdEventIds = eventConfigService.createEventsOfDeviceGroup(geofenceData.getEventConfig(), geofenceData.getGroupIds()); + DeviceManagementDAOFactory.beginTransaction(); + geofenceDAO.createGeofenceEventMapping(geofenceData.getId(), createdEventIds); DeviceManagementDAOFactory.commitTransaction(); + } catch (EventConfigurationException e) { + String msg = "Failed to store Geofence event configurations"; + log.error(msg, e); + if (log.isDebugEnabled()) { + log.debug("Deleting the geofence record with ID " + geofenceData.getId() + + " since the associated event or event group mapping couldn't save successfully"); + } + this.deleteGeofenceData(geofenceData.getId()); + throw new EventConfigurationException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Failed to begin transaction for saving geofence"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (DeviceManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while creating geofence event mapping records"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + createEventTask(OperationMgtConstants.OperationCodes.EVENT_CONFIG, geofenceData, tenantId); + return true; + } + + /** + * Create event revoke task at the time of geofence edit. + * @param geofenceData updated geofence object + * @param tenantId id of the fence owning tenant + */ + private void createEventRevokeTask(GeofenceData geofenceData, int tenantId) { + GeoFenceEventOperationManager eventManager = new GeoFenceEventOperationManager(OperationMgtConstants.OperationCodes.EVENT_REVOKE, + tenantId, values -> createEventTask(OperationMgtConstants.OperationCodes.EVENT_CONFIG, geofenceData, tenantId)); + ScheduledExecutorService eventOperationExecutor = Executors.newSingleThreadScheduledExecutor(); + eventOperationExecutor.schedule(eventManager + .getEventOperationExecutor(geofenceData), 10, TimeUnit.SECONDS); + } + + /** + * Create event config operation at the time of geofence edit, geofence delete + * @param operationCode code of the creating event (EVENT_CONFIG / EVENT_REVOKE) + * @param geofenceData creating/deleting geofence object + * @param tenantId id of the fence owning tenant + */ + private void createEventTask(String operationCode, GeofenceData geofenceData, int tenantId) { + GeoFenceEventOperationManager eventManager = new GeoFenceEventOperationManager(operationCode, tenantId, null); + ScheduledExecutorService eventOperationExecutor = Executors.newSingleThreadScheduledExecutor(); + eventOperationExecutor.schedule(eventManager + .getEventOperationExecutor(geofenceData), 10, TimeUnit.SECONDS); + } + + /** + * Set source of the event to GEOFENCE + * @param eventConfig event list to be set event source + */ + private void setEventSource(List eventConfig) { + for (EventConfig eventConfigEntry : eventConfig) { + eventConfigEntry.setEventSource(DeviceManagementConstants.EventServices.GEOFENCE); } } @@ -1298,7 +1378,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic try { DeviceManagementDAOFactory.openConnection(); - GeofenceData geofence = geofenceDAO.getGeofence(fenceId); + GeofenceData geofence = geofenceDAO.getGeofence(fenceId, true); if (geofence != null) { GeoCacheManagerImpl.getInstance().addFenceToCache(geofence, fenceId, tenantId); } @@ -1416,6 +1496,8 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean deleteGeofenceData(int fenceId) throws GeoLocationBasedServiceException { int tenantId; + GeofenceData geofence; + List eventsOfGeoFence; try { tenantId = DeviceManagementDAOUtil.getTenantId(); } catch (DeviceManagementDAOException e) { @@ -1426,12 +1508,25 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic try { DeviceManagementDAOFactory.beginTransaction(); - if (geofenceDAO.deleteGeofenceById(fenceId) > 0) { - DeviceManagementDAOFactory.commitTransaction(); - GeoCacheManagerImpl.getInstance().removeFenceFromCache(fenceId, tenantId); - return true; + geofence = geofenceDAO.getGeofence(fenceId, true); + if (geofence == null) { + return false; + } + eventsOfGeoFence = geofenceDAO.getEventsOfGeoFence(fenceId); + List eventIds = new ArrayList<>(); + for (EventConfig config : eventsOfGeoFence) { + eventIds.add(config.getEventId()); + } + if (!eventIds.isEmpty()) { + geofenceDAO.deleteGeofenceEventMapping(eventIds); + } + List groupIdsOfGeoFence = geofenceDAO.getGroupIdsOfGeoFence(fenceId); + if (!groupIdsOfGeoFence.isEmpty()) { + geofenceDAO.deleteGeofenceGroupMapping(groupIdsOfGeoFence); } - return false; + geofenceDAO.deleteGeofenceById(fenceId); + DeviceManagementDAOFactory.commitTransaction(); + GeoCacheManagerImpl.getInstance().removeFenceFromCache(fenceId, tenantId); } catch (DeviceManagementDAOException e) { DeviceManagementDAOFactory.rollbackTransaction(); String msg = "Error occurred while deleting geofence"; @@ -1444,11 +1539,13 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } finally { DeviceManagementDAOFactory.closeConnection(); } + this.deleteGeoFenceEvents(geofence, eventsOfGeoFence); + return true; } @Override public boolean updateGeofence(GeofenceData geofenceData, int fenceId) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException, EventConfigurationException { int tenantId; try { tenantId = DeviceManagementDAOUtil.getTenantId(); @@ -1458,13 +1555,30 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic throw new GeoLocationBasedServiceException(msg, e); } + List savedGroupIds; try { DeviceManagementDAOFactory.beginTransaction(); - if (geofenceDAO.updateGeofence(geofenceData, fenceId) > 0) { + int updatedRowCount = geofenceDAO.updateGeofence(geofenceData, fenceId); + savedGroupIds = geofenceDAO.getGroupIdsOfGeoFence(fenceId); + geofenceData.setId(fenceId); + List groupIdsToDelete = new ArrayList<>(); + List groupIdsToAdd = new ArrayList<>(); + for (Integer savedGroupId : savedGroupIds) { + if (!geofenceData.getGroupIds().contains(savedGroupId)) { + groupIdsToDelete.add(savedGroupId); + } + } + for (Integer newGroupId : geofenceData.getGroupIds()) { + if (!savedGroupIds.contains(newGroupId)) { + groupIdsToAdd.add(newGroupId); + } + } + geofenceDAO.deleteGeofenceGroupMapping(groupIdsToDelete); + geofenceDAO.createGeofenceGroupMapping(geofenceData, groupIdsToAdd); + DeviceManagementDAOFactory.commitTransaction(); + if (updatedRowCount > 0) { GeoCacheManagerImpl.getInstance().updateGeoFenceInCache(geofenceData, fenceId, tenantId); - return true; } - return false; } catch (TransactionManagementException e) { String msg = "Failed to begin transaction for saving geofence"; log.error(msg, e); @@ -1475,7 +1589,200 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic log.error(msg, e); throw new GeoLocationBasedServiceException(msg, e); } finally { + DeviceManagementDAOFactory.closeConnection(); + } + return true; + } + + @Override + public boolean updateGeoEventConfigurations(GeofenceData geofenceData, + List removedEventIdList, List groupIds, int fenceId) + throws GeoLocationBasedServiceException { + if (log.isDebugEnabled()) { + log.debug("Updating event configuration of geofence " + fenceId); + } + try { + if (log.isDebugEnabled()) { + log.debug("Deleting geofence event mapping records of geofence " + fenceId); + } + DeviceManagementDAOFactory.beginTransaction(); + geofenceDAO.deleteGeofenceEventMapping(removedEventIdList); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting geofence event mapping of fence " + fenceId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Failed to begin transaction deleting geofence event mapping of fence " + fenceId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + + List createdEventIds; + int tenantId; + try { + tenantId = DeviceManagementDAOUtil.getTenantId(); + setEventSource(geofenceData.getEventConfig()); + EventConfigurationProviderService eventConfigService = DeviceManagementDataHolder + .getInstance().getEventConfigurationService(); + if (eventConfigService == null) { + String msg = "Failed to load EventConfigurationProviderService osgi service of tenant " + tenantId; + log.error(msg); + throw new GeoLocationBasedServiceException(msg); + } + createdEventIds = eventConfigService.updateEventsOfDeviceGroup(geofenceData.getEventConfig(), removedEventIdList, groupIds); + } catch (EventConfigurationException e) { + String msg = "Error occurred while updating event configuration data"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving tenant id while update geofence data"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } + + if (log.isDebugEnabled()) { + log.debug("Creating geofence event mapping records of geofence " + + fenceId + ". created events " + createdEventIds.toString()); + } + try { + DeviceManagementDAOFactory.beginTransaction(); + geofenceDAO.createGeofenceEventMapping(fenceId, createdEventIds); DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while creating geofence event mapping records of geofence " + fenceId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Failed to begin transaction while creating geofence event mapping of fence " + fenceId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + if (log.isDebugEnabled()) { + log.debug("Update geofence event completed."); + } + createEventRevokeTask(geofenceData, tenantId); + return true; + } + + @Override + public List attachEventObjects(List geoFences) throws GeoLocationBasedServiceException { + try { + DeviceManagementDAOFactory.openConnection(); + List fenceIds = new ArrayList<>(); + for (GeofenceData geoFence : geoFences) { + fenceIds.add(geoFence.getId()); + } + if (!fenceIds.isEmpty()) { + Map> eventsOfGeoFences = geofenceDAO.getEventsOfGeoFences(fenceIds); + Set groupIdsOfGeoFences = geofenceDAO.getGroupIdsOfGeoFences(fenceIds); + for (GeofenceData geoFence : geoFences) { + geoFence.setEventConfig(eventsOfGeoFences.get(geoFence.getId())); + for (GeoFenceGroupMap geoFenceGroupMap : groupIdsOfGeoFences) { + if (geoFenceGroupMap.getFenceId() == geoFence.getId()) { + Map groupData = geoFence.getGroupData(); + if (groupData == null) { + groupData = new HashMap<>(); + } + groupData.put(geoFenceGroupMap.getGroupId(), geoFenceGroupMap.getGroupName()); + geoFence.setGroupData(groupData); + } + } + } + } + return geoFences; + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving geo fence events/groups data"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (SQLException e) { + String msg = "Failed open DB connection while getting geo fence event data"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public List getGeoFencesOfGroup(int groupId, int tenantId, boolean requireEventData) throws GeoLocationBasedServiceException { + try { + DeviceManagementDAOFactory.openConnection(); + List geofenceDataList = geofenceDAO.getGeoFences(groupId, tenantId); + if (requireEventData) { + for (GeofenceData geoFenceData : geofenceDataList) { + List eventsOfGeoFence = geofenceDAO.getEventsOfGeoFence(geoFenceData.getId()); + geoFenceData.setEventConfig(eventsOfGeoFence); + } + } + DeviceManagementDAOFactory.closeConnection(); + return geofenceDataList; + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving geo fences of group " + groupId + + " and tenant " + tenantId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (SQLException e) { + String msg = "Failed to obtain connection while retrieving geofence data of group " + + groupId + " and tenant " + tenantId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } + } + + @Override + public List getEventsOfGeoFence(int geoFenceId) throws GeoLocationBasedServiceException { + try { + DeviceManagementDAOFactory.openConnection(); + return geofenceDAO.getEventsOfGeoFence(geoFenceId); + } catch (SQLException e) { + String msg = "Failed to obtain connection while retrieving event data of geo fence " + + geoFenceId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving event data of geo fence " + geoFenceId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + /** + * Delete events of geofence + * @param geofenceData geofence mapped with deleting events + * @param eventList events to be deleted + */ + private void deleteGeoFenceEvents(GeofenceData geofenceData, List eventList) + throws GeoLocationBasedServiceException { + int tenantId; + try { + tenantId = DeviceManagementDAOUtil.getTenantId(); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving tenant id while get geofence data"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } + + try { + EventConfigurationProviderService eventConfigService = DeviceManagementDataHolder + .getInstance().getEventConfigurationService(); + eventConfigService.deleteEvents(eventList); + createEventTask(OperationMgtConstants.OperationCodes.EVENT_REVOKE, geofenceData, tenantId); + } catch (EventConfigurationException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Failed to delete Geofence event configurations"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); } } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventCreateCallback.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventCreateCallback.java new file mode 100644 index 00000000000..a5277e09a83 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventCreateCallback.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.task; +public interface EventCreateCallback { + void onCompleteEventOperation(Object values); +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/GeoFenceEventOperationManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/GeoFenceEventOperationManager.java new file mode 100644 index 00000000000..4863a2fab64 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/GeoFenceEventOperationManager.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.task; + +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.geo.service.GeoFenceEventMeta; +import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.core.event.config.GroupEventOperationExecutor; +import org.wso2.carbon.device.mgt.core.event.config.EventOperationExecutor; + +import java.util.List; + +/** + * Responsible for Event operation task creation management. + * Wrap event operation executor creation + */ +public class GeoFenceEventOperationManager { + private final int tenantId; + private final String eventOperationCode; + private final EventCreateCallback callback; + + public GeoFenceEventOperationManager(String eventOperationCode, int tenantId, EventCreateCallback callback) { + this.eventOperationCode = eventOperationCode; + this.tenantId = tenantId; + this.callback = callback; + } + + /** + * Get executor for create EVENT_CONFIG / EVENT_REVOKE operations at the time of a geofence + * created, updated or deleted + * @param geofenceData created geofence data object + * @return {@link EventOperationExecutor} Created executor to create operations + */ + public EventOperationExecutor getEventOperationExecutor(GeofenceData geofenceData) { + GeoFenceEventMeta geoFenceEventMeta = new GeoFenceEventMeta(geofenceData); + EventOperationExecutor executor = new EventOperationExecutor(geoFenceEventMeta, geofenceData.getGroupIds(), + tenantId, DeviceManagementConstants.EventServices.GEOFENCE, eventOperationCode); + executor.setCallback(callback); + return executor; + } + + /** + * Get executor for create EVENT_CONFIG / EVENT_REVOKE operations at the time of a device/s + * assigned into a group or removed from a group + * @param groupId Id of the assigned / removed group + * @param deviceIdentifiers Device identifiers assigned to / removed from the group + * @return {@link GroupEventOperationExecutor} Created executor to create operations + */ + public GroupEventOperationExecutor getEventOperationExecutor(int groupId, List deviceIdentifiers) { + GroupEventOperationExecutor executor = new GroupEventOperationExecutor(groupId, deviceIdentifiers, tenantId, eventOperationCode); + executor.setCallback(callback); + return executor; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java index e65ebe2fa4c..8e8f5bad674 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java @@ -22,6 +22,8 @@ import org.wso2.carbon.device.mgt.common.DeviceStatusTaskPluginConfig; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; +import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService; import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManager; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager; import org.wso2.carbon.device.mgt.common.spi.DeviceTypeGeneratorService; @@ -71,6 +73,9 @@ public class DeviceManagementDataHolder { private DeviceStatusTaskManagerService deviceStatusTaskManagerService; private DeviceTypeGeneratorService deviceTypeGeneratorService; private PrivacyComplianceProvider privacyComplianceProvider; + private EventConfigurationProviderService eventConfigurationService; + private GeoLocationProviderService geoLocationProviderService; + private final Map deviceStatusTaskPluginConfigs = Collections.synchronizedMap( new HashMap<>()); @@ -286,4 +291,20 @@ public class DeviceManagementDataHolder { public void setDeviceInformationManager(DeviceInformationManager deviceInformationManager) { this.deviceInformationManager = deviceInformationManager; } + + public void setEventConfigurationProviderService(EventConfigurationProviderService eventConfigurationService) { + this.eventConfigurationService = eventConfigurationService; + } + + public EventConfigurationProviderService getEventConfigurationService() { + return eventConfigurationService; + } + + public GeoLocationProviderService getGeoLocationProviderService() { + return geoLocationProviderService; + } + + public void setGeoLocationProviderService(GeoLocationProviderService geoLocationProviderService) { + this.geoLocationProviderService = geoLocationProviderService; + } } \ No newline at end of file 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 60b309ad76e..c4b0c247794 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 @@ -21,6 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; +import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; @@ -50,6 +51,7 @@ 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.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.device.details.mgt.impl.DeviceInformationManagerImpl; +import org.wso2.carbon.device.mgt.core.event.config.EventConfigurationProviderServiceImpl; import org.wso2.carbon.device.mgt.core.geo.service.GeoLocationProviderServiceImpl; import org.wso2.carbon.device.mgt.core.metadata.mgt.MetadataManagementServiceImpl; import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; @@ -328,12 +330,18 @@ public class DeviceManagementServiceComponent { /* Registering Geo Service */ GeoLocationProviderService geoService = new GeoLocationProviderServiceImpl(); + DeviceManagementDataHolder.getInstance().setGeoLocationProviderService(geoService); bundleContext.registerService(GeoLocationProviderService.class.getName(), geoService, null); /* Registering Metadata Service */ MetadataManagementService metadataManagementService = new MetadataManagementServiceImpl(); bundleContext.registerService(MetadataManagementService.class.getName(), metadataManagementService, null); + /* Registering Event Configuration Service */ + EventConfigurationProviderService eventConfigurationService = new EventConfigurationProviderServiceImpl(); + DeviceManagementDataHolder.getInstance().setEventConfigurationProviderService(eventConfigurationService); + bundleContext.registerService(EventConfigurationProviderService.class.getName(), eventConfigurationService, null); + OTPManagementService otpManagementService = new OTPManagementServiceImpl(); bundleContext.registerService(OTPManagementService.class.getName(), otpManagementService, null); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java index 3a9bef08e67..07529f588ec 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java @@ -185,7 +185,9 @@ public class OperationManagerImpl implements OperationManager { boolean isScheduledOperation = this.isTaskScheduledOperation(operation); String initiatedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); - if (initiatedBy == null && isScheduledOperation) { + if (initiatedBy == null && (isScheduledOperation + || operation.getCode().equalsIgnoreCase(OperationMgtConstants.OperationCodes.EVENT_CONFIG) + || operation.getCode().equalsIgnoreCase(OperationMgtConstants.OperationCodes.EVENT_REVOKE))) { if (log.isDebugEnabled()) { log.debug("initiatedBy : " + SYSTEM); } @@ -1331,12 +1333,10 @@ public class OperationManagerImpl implements OperationManager { boolean status; switch (operation.getCode()) { case DeviceManagementConstants.AuthorizationSkippedOperationCodes.POLICY_OPERATION_CODE: - status = true; - break; - case DeviceManagementConstants.AuthorizationSkippedOperationCodes.MONITOR_OPERATION_CODE: - status = true; - break; + case DeviceManagementConstants.AuthorizationSkippedOperationCodes.EVENT_CONFIG_OPERATION_CODE: + case DeviceManagementConstants.AuthorizationSkippedOperationCodes.EVENT_REVOKE_OPERATION_CODE: case DeviceManagementConstants.AuthorizationSkippedOperationCodes.POLICY_REVOKE_OPERATION_CODE: + case DeviceManagementConstants.AuthorizationSkippedOperationCodes.MONITOR_OPERATION_CODE: status = true; break; default: diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMgtConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMgtConstants.java index 955fd506822..ff65e7b1446 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMgtConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMgtConstants.java @@ -25,5 +25,7 @@ public class OperationMgtConstants { } public static final String POLICY_REVOKE = "POLICY_REVOKE"; + public static final String EVENT_CONFIG = "EVENT_CONFIG"; + public static final String EVENT_REVOKE = "EVENT_REVOKE"; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java index 740f6afd61d..b6354272b7d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -41,7 +41,9 @@ import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GroupDAO; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMgtConstants; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; @@ -52,6 +54,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; public class GroupManagementProviderServiceImpl implements GroupManagementProviderService { @@ -795,6 +800,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } } GroupManagementDAOFactory.commitTransaction(); + createEventTask(OperationMgtConstants.OperationCodes.EVENT_CONFIG, groupId, deviceIdentifiers, tenantId); } catch (DeviceManagementException e) { String msg = "Error occurred while retrieving device."; log.error(msg, e); @@ -839,6 +845,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid this.groupDAO.removeDevice(groupId, device.getId(), tenantId); } GroupManagementDAOFactory.commitTransaction(); + createEventTask(OperationMgtConstants.OperationCodes.EVENT_REVOKE, groupId, deviceIdentifiers, tenantId); } catch (DeviceManagementException e) { String msg = "Error occurred while retrieving device."; log.error(msg, e); @@ -1046,4 +1053,18 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid tenantId)); } } + + /** + * Create event config/revoke operation at the time of device removing from a group/assigning into group + * @param eventOperationCode code of the event operation(config/revoke) + * @param groupId Id of the device removing/assigning group + * @param deviceIdentifiers devices assigning to/removing from group + * @param tenantId tenant of the group + */ + private void createEventTask(String eventOperationCode, int groupId, List deviceIdentifiers, int tenantId) { + GeoFenceEventOperationManager eventManager = new GeoFenceEventOperationManager(eventOperationCode, tenantId, null); + ScheduledExecutorService eventOperationExecutor = Executors.newSingleThreadScheduledExecutor(); + eventOperationExecutor.schedule(eventManager + .getEventOperationExecutor(groupId, deviceIdentifiers), 10, TimeUnit.SECONDS); + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 6a64c5b3d99..25cca94229b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -64,6 +64,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManageme import org.wso2.carbon.device.mgt.common.configuration.mgt.EnrollmentConfiguration; 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.event.config.EventConfigurationProviderService; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; @@ -606,6 +607,18 @@ public final class DeviceManagerUtil { return eventsPublisherService; } + public static EventConfigurationProviderService getEventConfigService() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + EventConfigurationProviderService eventConfigService = + (EventConfigurationProviderService) ctx.getOSGiService(EventConfigurationProviderService.class, null); + if (eventConfigService == null) { + String msg = "Event configuration service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return eventConfigService; + } + public static void initializeDeviceCache() { DeviceManagementConfig config = DeviceConfigurationManager.getInstance().getDeviceManagementConfig(); int deviceCacheExpiry = config.getDeviceCacheConfiguration().getExpiryTime(); diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 4d754cd3f93..dcd89c36541 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -649,15 +649,15 @@ ORDER BY TENANT_ID, DEVICE_ID; -- END OF DASHBOARD RELATED VIEWS -- --- GEOFENCE RELATED DATA -- +-- DM_GEOFENCE TABLE-- CREATE TABLE IF NOT EXISTS DM_GEOFENCE ( ID INT NOT NULL AUTO_INCREMENT, - FENCE_NAME VARCHAR(100) NOT NULL, + FENCE_NAME VARCHAR(255) NOT NULL, DESCRIPTION TEXT DEFAULT NULL, - LATITUDE DOUBLE NULL, - LONGITUDE DOUBLE NULL, - RADIUS DOUBLE NULL, + LATITUDE DOUBLE DEFAULT NULL, + LONGITUDE DOUBLE DEFAULT NULL, + RADIUS DOUBLE DEFAULT NULL, GEO_JSON TEXT DEFAULT NULL, FENCE_SHAPE VARCHAR(100) DEFAULT NULL, CREATED_TIMESTAMP TIMESTAMP NOT NULL, @@ -666,4 +666,60 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE ( PRIMARY KEY (ID) ); --- END OF GEOFENCE RELATED DATA -- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- + +-- DM_GEOFENCE_GROUP_MAPPING TABLE-- +CREATE TABLE IF NOT EXISTS DM_GEOFENCE_GROUP_MAPPING ( + ID INT NOT NULL AUTO_INCREMENT, + FENCE_ID INT NOT NULL, + GROUP_ID INT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_dm_geofence_group_mapping_geofence FOREIGN KEY (FENCE_ID) REFERENCES + DM_GEOFENCE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_dm_geofence_group_mapping_group FOREIGN KEY (GROUP_ID) REFERENCES + DM_GROUP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +); + +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- + +-- DM_DEVICE_EVENT TABLE -- + +CREATE TABLE IF NOT EXISTS DM_DEVICE_EVENT ( + ID INT NOT NULL AUTO_INCREMENT, + EVENT_SOURCE VARCHAR(100) NOT NULL, + EVENT_LOGIC VARCHAR(100) NOT NULL, + ACTIONS TEXT DEFAULT NULL, + CREATED_TIMESTAMP TIMESTAMP NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + PRIMARY KEY (ID) +); + +-- END OF DM_DEVICE_EVENT TABLE -- + +-- DM_DEVICE_EVENT_GROUP_MAPPING TABLE-- +CREATE TABLE IF NOT EXISTS DM_DEVICE_EVENT_GROUP_MAPPING ( + ID INT NOT NULL AUTO_INCREMENT, + EVENT_ID INT NOT NULL, + GROUP_ID INT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_dm_event_group_mapping_event FOREIGN KEY (EVENT_ID) REFERENCES + DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_dm_event_group_mapping_group FOREIGN KEY (GROUP_ID) REFERENCES + DM_GROUP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +); + +-- END OF DM_DEVICE_EVENT_GROUP_MAPPING TABLE-- + +-- DM_GEOFENCE_GROUP_MAPPING TABLE-- +CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( + ID INT NOT NULL AUTO_INCREMENT, + FENCE_ID INT NOT NULL, + EVENT_ID INT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_dm_geofence_event_mapping_geofence FOREIGN KEY (FENCE_ID) REFERENCES + DM_GEOFENCE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_dm_geofence_event_mapping_event FOREIGN KEY (EVENT_ID) REFERENCES + DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +); + +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- \ No newline at end of file diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index 63b751823b8..00ff301f6d3 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -730,4 +730,60 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE ( PRIMARY KEY (ID) ) ENGINE=InnoDB; --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- + +-- DM_GEOFENCE_GROUP_MAPPING TABLE-- +CREATE TABLE IF NOT EXISTS DM_GEOFENCE_GROUP_MAPPING ( + ID INT NOT NULL AUTO_INCREMENT, + FENCE_ID INT NOT NULL, + GROUP_ID INT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_dm_geofence_group_mapping_geofence FOREIGN KEY (FENCE_ID) REFERENCES + DM_GEOFENCE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_dm_geofence_group_mapping_group FOREIGN KEY (GROUP_ID) REFERENCES + DM_GROUP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=InnoDB; + +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- + +-- DM_DEVICE_EVENT TABLE -- + +CREATE TABLE IF NOT EXISTS DM_DEVICE_EVENT ( + ID INT NOT NULL AUTO_INCREMENT, + EVENT_SOURCE VARCHAR(100) NOT NULL, + EVENT_LOGIC VARCHAR(100) NOT NULL, + ACTIONS TEXT DEFAULT NULL, + CREATED_TIMESTAMP TIMESTAMP NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + PRIMARY KEY (ID) +) ENGINE=InnoDB; + +-- END OF DM_DEVICE_EVENT TABLE -- + +-- DM_DEVICE_EVENT_GROUP_MAPPING TABLE-- +CREATE TABLE IF NOT EXISTS DM_DEVICE_EVENT_GROUP_MAPPING ( + ID INT NOT NULL AUTO_INCREMENT, + EVENT_ID INT NOT NULL, + GROUP_ID INT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_dm_event_group_mapping_event FOREIGN KEY (EVENT_ID) REFERENCES + DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_dm_event_group_mapping_group FOREIGN KEY (GROUP_ID) REFERENCES + DM_GROUP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=InnoDB; + +-- END OF DM_DEVICE_EVENT_GROUP_MAPPING TABLE-- + +-- DM_GEOFENCE_GROUP_MAPPING TABLE-- +CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( + ID INT NOT NULL AUTO_INCREMENT, + FENCE_ID INT NOT NULL, + EVENT_ID INT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_dm_geofence_event_mapping_geofence FOREIGN KEY (FENCE_ID) REFERENCES + DM_GEOFENCE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_dm_geofence_event_mapping_event FOREIGN KEY (EVENT_ID) REFERENCES + DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=InnoDB; + +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- \ No newline at end of file