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 index 703807065b..5649f9db57 100644 --- 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 @@ -72,4 +72,11 @@ public interface EventConfigurationProviderService { */ void deleteEvents(List eventList) throws EventConfigurationException; + /** + * Create task entry to be executed at the time of event operation task running + * @param eventTaskEntry event task entry + * @param groupIds group ids of the event task entry assigned + * @throws EventConfigurationException error thrown while creating task records + */ + void createEventOperationTask(EventTaskEntry eventTaskEntry, List groupIds) 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/EventTaskEntry.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventTaskEntry.java new file mode 100644 index 0000000000..2fa7b70a78 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/event/config/EventTaskEntry.java @@ -0,0 +1,98 @@ +/* + * 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 EventTaskEntry { + private int id; + private int deviceId; + private int groupId; + private String operationCode; + private String eventSource; + private int eventMetaId; + private int tenantId; + private ExecutionStatus executionStatus; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getOperationCode() { + return operationCode; + } + + public void setOperationCode(String operationCode) { + this.operationCode = operationCode; + } + + public ExecutionStatus getExecutionStatus() { + return executionStatus; + } + + public void setExecutionStatus(ExecutionStatus executionStatus) { + this.executionStatus = executionStatus; + } + + public String getEventSource() { + return eventSource; + } + + public void setEventSource(String eventSource) { + this.eventSource = eventSource; + } + + public int getEventMetaId() { + return eventMetaId; + } + + public void setEventMetaId(int eventMetaId) { + this.eventMetaId = eventMetaId; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } + + public enum ExecutionStatus { + CREATED, PENDING, COMPLETED; + } +} 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 index dd58cd5016..4c876c8c19 100644 --- 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 @@ -30,8 +30,7 @@ public class GeoFenceEventMeta implements EventMetaData { private String geoJson; private String fenceShape; - public GeoFenceEventMeta() { - } + public GeoFenceEventMeta() {} public GeoFenceEventMeta(GeofenceData geofenceData) { this.id = geofenceData.getId(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java index 2a967238e1..4b8adcc357 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java @@ -24,6 +24,7 @@ import org.wso2.carbon.device.mgt.core.config.archival.ArchivalConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.DeviceCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.GeoFenceCacheConfiguration; +import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration; import org.wso2.carbon.device.mgt.core.config.geo.location.GeoLocationConfiguration; import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations; import org.wso2.carbon.device.mgt.core.config.keymanager.KeyManagerConfigurations; @@ -56,6 +57,7 @@ public final class DeviceManagementConfig { private DeviceStatusTaskConfig deviceStatusTaskConfig; private DeviceCacheConfiguration deviceCacheConfiguration; private GeoFenceCacheConfiguration geoFenceCacheConfiguration; + private EventOperationTaskConfiguration eventOperationTaskConfiguration; private CertificateCacheConfiguration certificateCacheConfiguration; private OperationAnalyticsConfiguration operationAnalyticsConfiguration; private GeoLocationConfiguration geoLocationConfiguration; @@ -165,6 +167,15 @@ public final class DeviceManagementConfig { this.geoFenceCacheConfiguration = geoFenceCacheConfiguration; } + @XmlElement(name = "EventOperationTaskConfiguration", required = true) + public EventOperationTaskConfiguration getEventOperationTaskConfiguration() { + return eventOperationTaskConfiguration; + } + + public void setEventOperationTaskConfiguration(EventOperationTaskConfiguration eventOperationTaskConfiguration) { + this.eventOperationTaskConfiguration = eventOperationTaskConfiguration; + } + @XmlElement(name = "CertificateCacheConfiguration", required = true) public CertificateCacheConfiguration getCertificateCacheConfiguration() { return certificateCacheConfiguration; 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 index 288d854b14..5fe43c233b 100644 --- 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 @@ -19,8 +19,10 @@ package org.wso2.carbon.device.mgt.core.dao; import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.event.config.EventTaskEntry; import java.util.List; +import java.util.Map; public interface EventConfigDAO { @@ -112,4 +114,33 @@ public interface EventConfigDAO { * @throws EventManagementDAOException thrown errors while retrieving event sources */ List getEventSourcesOfGroups(int groupId, int tenantId) throws EventManagementDAOException; + + /** + * Create record for event creation task which will be executed periodically + * @param eventTaskEntry event task object + * @param groupIds group ids of the event assigned + * @return true if record added successfully + * @throws EventManagementDAOException failed while creating the entry record + */ + boolean createEventTaskEntry(EventTaskEntry eventTaskEntry, List groupIds) throws EventManagementDAOException; + + /** + * Retrieve task entries by status of the task + * @param status status of the task + * @return map of tenant id and event task entries + * @throws EventManagementDAOException if errors occurred while retrieving records + */ + Map> getAvailableEventTaskEntries(String status) throws EventManagementDAOException; + + /** + * Update event task records of group and set them as COMPLETED + * @param code operation code + * @param eventSource source of the event to be updated + * @param groupIds groupId list of the task entries + * @param tenantId tenant of the records + * @return true if the update done successfully + * @throws EventManagementDAOException if errors occurred while retrieving records + */ + boolean setEventTaskComplete(String code, String eventSource, List groupIds, 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/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 index ece3f2a2bb..d883f4f157 100644 --- 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 @@ -24,14 +24,18 @@ 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.common.event.config.EventTaskEntry; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; public abstract class AbstractEventConfigDAO implements EventConfigDAO { private static final Log log = LogFactory.getLog(AbstractEventConfigDAO.class); @@ -323,6 +327,117 @@ public abstract class AbstractEventConfigDAO implements EventConfigDAO { } } + + @Override + public boolean createEventTaskEntry(EventTaskEntry eventTaskEntry, List groupIds) + throws EventManagementDAOException { + try { + Connection connection = this.getConnection(); + String sql = "INSERT INTO DM_EVENT_OPERATION_ASSIGNMENT_TASK(" + + "DEVICE_ID, " + + "GROUP_ID, " + + "OPERATION_CODE, " + + "EVENT_SOURCE, " + + "EVENT_META_ID, " + + "STATUS, " + + "TENANT_ID, " + + "CREATED_TIMESTAMP) " + + "VALUES(?, ?, ?, ?, ?, ?, ?, ?)"; + try (PreparedStatement stm = connection.prepareStatement(sql)){ + for (Integer groupId : groupIds) { + stm.setInt(1, eventTaskEntry.getDeviceId()); + stm.setInt(2, groupId); + stm.setString(3, eventTaskEntry.getOperationCode()); + stm.setString(4, eventTaskEntry.getEventSource()); + stm.setInt(5, eventTaskEntry.getEventMetaId()); + stm.setString(6, eventTaskEntry.getExecutionStatus().toString()); + stm.setInt(7, eventTaskEntry.getTenantId()); + stm.setTimestamp(8, new Timestamp(System.currentTimeMillis())); + stm.addBatch(); + } + return stm.executeBatch().length > 0; + } + } catch (SQLException e) { + String msg = "Failed while creating event task entry for event operation " + eventTaskEntry.getOperationCode() + + " of the tenant " + eventTaskEntry.getTenantId(); + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public Map> getAvailableEventTaskEntries(String status) throws EventManagementDAOException { + Map> eventTaskEntries = new HashMap<>(); + try { + Connection connection = this.getConnection(); + String sql = "SELECT " + + "ID, "+ + "DEVICE_ID, " + + "GROUP_ID, " + + "OPERATION_CODE, " + + "EVENT_SOURCE, " + + "EVENT_META_ID, " + + "TENANT_ID " + + "FROM DM_EVENT_OPERATION_ASSIGNMENT_TASK " + + "WHERE STATUS = ?"; + try (PreparedStatement stm = connection.prepareStatement(sql)){ + stm.setString(1, status); + ResultSet resultSet = stm.executeQuery(); + while (resultSet.next()) { + int tenantId = resultSet.getInt("TENANT_ID"); + List eventsOfTenant = eventTaskEntries.get(tenantId); + if (eventsOfTenant == null) { + eventsOfTenant = new ArrayList<>(); + } + EventTaskEntry eventTaskEntry = new EventTaskEntry(); + eventTaskEntry.setId(resultSet.getInt("ID")); + eventTaskEntry.setOperationCode(resultSet.getString("OPERATION_CODE")); + eventTaskEntry.setGroupId(resultSet.getInt("GROUP_ID")); + eventTaskEntry.setEventMetaId(resultSet.getInt("EVENT_META_ID")); + eventTaskEntry.setDeviceId(resultSet.getInt("DEVICE_ID")); + eventTaskEntry.setTenantId(tenantId); + eventTaskEntry.setEventSource(resultSet.getString("EVENT_SOURCE")); + eventsOfTenant.add(eventTaskEntry); + eventTaskEntries.put(tenantId, eventsOfTenant); + } + return eventTaskEntries; + } + } catch (SQLException e) { + String msg = "Failed while retrieving event task entries"; + log.error(msg, e); + throw new EventManagementDAOException(msg, e); + } + } + + @Override + public boolean setEventTaskComplete(String code, String eventSource, List groupIds, int tenantId) + throws EventManagementDAOException { + try { + Connection connection = this.getConnection(); + String sql = "UPDATE DM_EVENT_OPERATION_ASSIGNMENT_TASK " + + "SET STATUS = ?, "+ + "COMPLETED_TIMESTAMP = ? " + + "WHERE STATUS = ? AND OPERATION_CODE = ? AND EVENT_SOURCE = ? AND GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stm = connection.prepareStatement(sql)){ + for (Integer groupId : groupIds) { + stm.setString(1, EventTaskEntry.ExecutionStatus.COMPLETED.toString()); + stm.setTimestamp(2, new Timestamp(System.currentTimeMillis())); + stm.setString(3, EventTaskEntry.ExecutionStatus.CREATED.toString()); + stm.setString(4, code); + stm.setString(5, eventSource); + stm.setInt(6, groupId); + stm.setInt(7, tenantId); + stm.addBatch(); + } + return stm.executeBatch().length > 0; + } + } catch (SQLException e) { + String msg = "Failed while retrieving event task entries"; + 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/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 index 0dfeee16b2..ecd5a3dc59 100644 --- 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 @@ -22,7 +22,6 @@ 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; @@ -33,7 +32,6 @@ 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; 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 index c27fc72b81..767c82cfbc 100644 --- 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 @@ -30,6 +30,7 @@ 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 org.wso2.carbon.device.mgt.common.event.config.EventTaskEntry; import java.sql.SQLException; import java.util.ArrayList; @@ -236,4 +237,28 @@ public class EventConfigurationProviderServiceImpl implements EventConfiguration throw new EventConfigurationException(msg, e); } } + + @Override + public void createEventOperationTask(EventTaskEntry eventTaskEntry, List groupIds) + throws EventConfigurationException { + try { + DeviceManagementDAOFactory.beginTransaction(); + eventConfigDAO.createEventTaskEntry(eventTaskEntry, groupIds); + DeviceManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException e) { + String msg = "Failed to start transaction while creating event operation task entries of tenant " + + eventTaskEntry.getTenantId(); + log.error(msg, e); + throw new EventConfigurationException(msg, e); + } catch (EventManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while creating event task entries for event " + eventTaskEntry + .getEventSource() + " with code " + eventTaskEntry.getOperationCode() + " of the tenant " + + eventTaskEntry.getTenantId(); + log.error(msg, e); + throw new EventConfigurationException(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/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 deleted file mode 100644 index 462355c754..0000000000 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventOperationExecutor.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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/EventOperationTaskConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventOperationTaskConfiguration.java new file mode 100644 index 0000000000..ff60602ad9 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/EventOperationTaskConfiguration.java @@ -0,0 +1,44 @@ +/* + * 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 javax.xml.bind.annotation.XmlElement; + +public class EventOperationTaskConfiguration { + private boolean isEnabled; + private int frequency; + + @XmlElement(name = "Enable", required = true) + public boolean isEnabled() { + return isEnabled; + } + + public void setEnabled(boolean enabled) { + isEnabled = enabled; + } + + @XmlElement(name = "Frequency", required = true) + public int getFrequency() { + return frequency; + } + + public void setFrequency(int frequency) { + this.frequency = frequency; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/GroupEventOperationCreationTask.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/GroupEventOperationCreationTask.java new file mode 100644 index 0000000000..230fbc10b8 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/event/config/GroupEventOperationCreationTask.java @@ -0,0 +1,307 @@ +/* + * 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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; +import org.json.JSONObject; +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.EventOperation; +import org.wso2.carbon.device.mgt.common.event.config.EventRevokeOperation; +import org.wso2.carbon.device.mgt.common.event.config.EventTaskEntry; +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.GeofenceData; +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.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.GeofenceDAO; +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 org.wso2.carbon.device.mgt.core.task.impl.RandomlyAssignedScheduleTask; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Event create/revoke operation creation task. + * Use at the time of single event create, update, delete + */ +public class GroupEventOperationCreationTask extends RandomlyAssignedScheduleTask { + private static final Log log = LogFactory.getLog(GroupEventOperationCreationTask.class); + private static final String TASK_NAME = "GROUP_EVENT_CREATE_TASK"; + + private GroupManagementProviderService groupManagementService; + private EventConfigDAO eventConfigDAO; + private GeofenceDAO geofenceDAO; + private int tenantId; + + @Override + protected void setup() { + if (this.groupManagementService == null) { + this.groupManagementService = DeviceManagementDataHolder.getInstance().getGroupManagementProviderService(); + } + if (this.eventConfigDAO == null) { + this.eventConfigDAO = DeviceManagementDAOFactory.getEventConfigDAO(); + } + if (this.geofenceDAO == null) { + this.geofenceDAO = DeviceManagementDAOFactory.getGeofenceDAO(); + } + } + + @Override + protected void executeRandomlyAssignedTask() { + if (log.isDebugEnabled()) { + log.debug("Starting event operation creation task"); + } + try { + DeviceManagementDAOFactory.openConnection(); + Map> eventTaskEntries = eventConfigDAO + .getAvailableEventTaskEntries(EventTaskEntry.ExecutionStatus.CREATED.toString()); + DeviceManagementDAOFactory.closeConnection(); + for (Map.Entry> eventTaskEntry : eventTaskEntries.entrySet()) { + this.tenantId = eventTaskEntry.getKey(); + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(this.tenantId, true); + this.processEventsOfTenant(eventTaskEntry.getValue()); + PrivilegedCarbonContext.endTenantFlow(); + } + } catch (EventManagementDAOException e) { + log.error("Failed while retrieving event task entries", e); + } catch (SQLException e) { + log.error("Failed while opening connection", e); + } + } + + /** + * Process event entries of a particular tenant + * @param eventTaskEntries list of geo fence task entries + */ + private void processEventsOfTenant(List eventTaskEntries) { + Map> eventSourceTaskMap = new HashMap<>(); + for (EventTaskEntry eventTaskEntry : eventTaskEntries) { + List eventsOfSource = eventSourceTaskMap.get(eventTaskEntry.getEventSource()); + if (eventsOfSource == null) { + eventsOfSource = new ArrayList<>(); + } + eventsOfSource.add(eventTaskEntry); + eventSourceTaskMap.put(eventTaskEntry.getEventSource(), eventsOfSource); + } + for (Map.Entry> eventEntry : eventSourceTaskMap.entrySet()) { + switch (eventEntry.getKey()) { + case DeviceManagementConstants.EventServices.GEOFENCE : + processGeoFenceEventList(eventEntry.getValue()); + break; + default: + log.error("Invalid event source" + eventEntry.getKey()); + } + } + } + + /** + * Devide event task entries into configuration entries and revoke entries + * @param geoFenceTaskList list of geo fence task entries + */ + private void processGeoFenceEventList(List geoFenceTaskList) { + Map> geoFenceConfigEventMap = new HashMap<>(); + Map> geoFenceRevokeEventMap = new HashMap<>(); + for (EventTaskEntry geoFenceTask : geoFenceTaskList) { + if (geoFenceTask.getOperationCode().equals(OperationMgtConstants.OperationCodes.EVENT_CONFIG)) { + List groupIdList = geoFenceConfigEventMap.get(geoFenceTask.getEventMetaId()); + if (groupIdList == null) { + groupIdList = new ArrayList<>(); + } + groupIdList.add(geoFenceTask.getGroupId()); + geoFenceConfigEventMap.put(geoFenceTask.getEventMetaId(), groupIdList); + } else if (geoFenceTask.getOperationCode().equals(OperationMgtConstants.OperationCodes.EVENT_REVOKE)) { + List groupIdList = geoFenceRevokeEventMap.get(geoFenceTask.getEventMetaId()); + if (groupIdList == null) { + groupIdList = new ArrayList<>(); + } + groupIdList.add(geoFenceTask.getGroupId()); + geoFenceRevokeEventMap.put(geoFenceTask.getEventMetaId(), groupIdList); + } + } + if (!geoFenceConfigEventMap.isEmpty()) { + buildGeoFenceConfigOperation(geoFenceConfigEventMap); + } + if (!geoFenceRevokeEventMap.isEmpty()) { + buildGeoFenceRevokeOperation(geoFenceRevokeEventMap); + } + } + + /** + * Build EVENT_REVOKE operation for geo fence event operation + * @param geoFenceRevokeEventMap group Ids mapped with geofence ID + */ + private void buildGeoFenceRevokeOperation(Map> geoFenceRevokeEventMap) { + try { + DeviceManagementDAOFactory.openConnection(); + for (Map.Entry> eventGroupEntry : geoFenceRevokeEventMap.entrySet()) { + ProfileOperation revokeOperation = new ProfileOperation(); + revokeOperation.setType(Operation.Type.PROFILE); + revokeOperation.setCode(OperationMgtConstants.OperationCodes.EVENT_REVOKE); + + GeofenceData geofence = geofenceDAO.getGeofence(eventGroupEntry.getKey()); + EventRevokeOperation eventRevokeOperation = new EventRevokeOperation(); + eventRevokeOperation.setEventSource(DeviceManagementConstants.EventServices.GEOFENCE); + eventRevokeOperation.setId(geofence.getId()); + + JSONArray payloadArray = new JSONArray(); + payloadArray.put(new JSONObject(eventRevokeOperation)); + revokeOperation.setPayLoad(payloadArray.toString()); + createOperationEntryForGroup(revokeOperation, DeviceManagementConstants.EventServices.GEOFENCE, + eventGroupEntry.getValue()); + } + DeviceManagementDAOFactory.closeConnection(); + } catch (SQLException e) { + log.error("Failed while opening connection", e); + } catch (DeviceManagementDAOException e) { + log.error("Error occurred while retrieving geofence data", e); + } + } + + /** + * Build EVENT_CONFIG operation for geo fence event operation + * @param geoFenceConfigEventMap group Ids mapped with geofence ID + */ + private void buildGeoFenceConfigOperation(Map> geoFenceConfigEventMap) { + try { + DeviceManagementDAOFactory.openConnection(); + for (Map.Entry> eventGroupEntry : geoFenceConfigEventMap.entrySet()) { + ProfileOperation configOperation = new ProfileOperation(); + configOperation.setType(Operation.Type.PROFILE); + configOperation.setCode(OperationMgtConstants.OperationCodes.EVENT_CONFIG); + + GeofenceData geofence = geofenceDAO.getGeofence(eventGroupEntry.getKey()); + List eventsOfGeoFence = geofenceDAO.getEventsOfGeoFence(geofence.getId()); + EventOperation eventOperation = new EventOperation(); + eventOperation.setEventDefinition(new GeoFenceEventMeta(geofence)); + eventOperation.setEventSource(DeviceManagementConstants.EventServices.GEOFENCE); + eventOperation.setEventTriggers(eventsOfGeoFence); + JSONArray payloadArray = new JSONArray(); + payloadArray.put(new JSONObject(eventOperation)); + configOperation.setPayLoad(payloadArray.toString()); + createOperationEntryForGroup(configOperation, DeviceManagementConstants.EventServices.GEOFENCE, + eventGroupEntry.getValue()); + } + DeviceManagementDAOFactory.closeConnection(); + } catch (SQLException e) { + log.error("Failed while opening connection", e); + } catch (DeviceManagementDAOException e) { + log.error("Error occurred while retrieving geofence data", e); + } + } + + /** + * Create event operation of the groups + * @param operation creating operation + * @param eventSource event source type + * @param groupIds group Id list + */ + private void createOperationEntryForGroup(ProfileOperation operation, String eventSource, List groupIds) { + 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; + } + if (log.isDebugEnabled()) { + log.debug("Event operation creation task completed"); + } + try { + eventConfigDAO.setEventTaskComplete(operation.getCode(), eventSource, groupIds, this.tenantId); + } catch (EventManagementDAOException e) { + log.error("Failed while updating event task records", e); + } + } + + @Override + public String getTaskName() { + return TASK_NAME; + } + + @Override + public void setProperties(Map map) { + + } +} 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 2f8d1872aa..ad78e3080a 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 @@ -42,6 +42,7 @@ 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.event.config.EventTaskEntry; 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; @@ -1261,6 +1262,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean createGeofence(GeofenceData geofenceData) throws GeoLocationBasedServiceException, EventConfigurationException { int tenantId; + EventConfigurationProviderService eventConfigService; try { tenantId = DeviceManagementDAOUtil.getTenantId(); geofenceData.setTenantId(tenantId); @@ -1293,8 +1295,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic List createdEventIds; try { setEventSource(geofenceData.getEventConfig()); - EventConfigurationProviderService eventConfigService = DeviceManagementDataHolder - .getInstance().getEventConfigurationService(); + eventConfigService = DeviceManagementDataHolder.getInstance().getEventConfigurationService(); createdEventIds = eventConfigService.createEventsOfDeviceGroup(geofenceData.getEventConfig(), geofenceData.getGroupIds()); DeviceManagementDAOFactory.beginTransaction(); geofenceDAO.createGeofenceEventMapping(geofenceData.getId(), createdEventIds); @@ -1320,35 +1321,17 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } 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); + try { + eventConfigService.createEventOperationTask(getEventOperationTask(OperationMgtConstants + .OperationCodes.EVENT_CONFIG, geofenceData.getId(), tenantId), geofenceData.getGroupIds()); + } catch (EventConfigurationException e) { + String msg = "Failed while creating EVENT_REVOKE operation creation task entry while updating geo fence " + + geofenceData.getFenceName() + " of the tenant " + tenantId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } + return true; } /** @@ -1599,6 +1582,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic public boolean updateGeoEventConfigurations(GeofenceData geofenceData, List removedEventIdList, List groupIds, int fenceId) throws GeoLocationBasedServiceException { + EventConfigurationProviderService eventConfigService; if (log.isDebugEnabled()) { log.debug("Updating event configuration of geofence " + fenceId); } @@ -1627,8 +1611,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic try { tenantId = DeviceManagementDAOUtil.getTenantId(); setEventSource(geofenceData.getEventConfig()); - EventConfigurationProviderService eventConfigService = DeviceManagementDataHolder - .getInstance().getEventConfigurationService(); + eventConfigService = DeviceManagementDataHolder.getInstance().getEventConfigurationService(); if (eventConfigService == null) { String msg = "Failed to load EventConfigurationProviderService osgi service of tenant " + tenantId; log.error(msg); @@ -1668,7 +1651,15 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic if (log.isDebugEnabled()) { log.debug("Update geofence event completed."); } - createEventRevokeTask(geofenceData, tenantId); + try { + eventConfigService.createEventOperationTask(getEventOperationTask(OperationMgtConstants + .OperationCodes.EVENT_REVOKE, geofenceData.getId(), tenantId), geofenceData.getGroupIds()); + } catch (EventConfigurationException e) { + String msg = "Failed while creating EVENT_REVOKE operation creation task entry while updating geo fence " + + geofenceData.getFenceName() + " of the tenant " + tenantId; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } return true; } @@ -1776,7 +1767,8 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic EventConfigurationProviderService eventConfigService = DeviceManagementDataHolder .getInstance().getEventConfigurationService(); eventConfigService.deleteEvents(eventList); - createEventTask(OperationMgtConstants.OperationCodes.EVENT_REVOKE, geofenceData, tenantId); + eventConfigService.createEventOperationTask(getEventOperationTask(OperationMgtConstants + .OperationCodes.EVENT_REVOKE, geofenceData.getId(), tenantId), geofenceData.getGroupIds()); } catch (EventConfigurationException e) { DeviceManagementDAOFactory.rollbackTransaction(); String msg = "Failed to delete Geofence event configurations"; @@ -1786,4 +1778,21 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic DeviceManagementDAOFactory.closeConnection(); } } + + /** + * Build and retrieve the EventTaskEntry object + * @param operationCode operationCode of the requesting EventTask + * @param geoFenceId id of the geofence which the task creating + * @param tenantId id of the tenant owns the geofence + * @return built EventTaskEntry object + */ + private EventTaskEntry getEventOperationTask(String operationCode, int geoFenceId, int tenantId) { + EventTaskEntry eventTaskEntry = new EventTaskEntry(); + eventTaskEntry.setEventSource(DeviceManagementConstants.EventServices.GEOFENCE); + eventTaskEntry.setExecutionStatus(EventTaskEntry.ExecutionStatus.CREATED); + eventTaskEntry.setOperationCode(operationCode); + eventTaskEntry.setEventMetaId(geoFenceId); + eventTaskEntry.setTenantId(tenantId); + return eventTaskEntry; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventOperationTaskException.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventOperationTaskException.java new file mode 100644 index 0000000000..4e8e14d914 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventOperationTaskException.java @@ -0,0 +1,33 @@ +/* + * 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 class EventOperationTaskException extends Exception{ + public EventOperationTaskException(String message) { + super(message); + } + + public EventOperationTaskException(String message, Throwable cause) { + super(message, cause); + } + + public EventOperationTaskException(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/geo/task/EventOperationTaskManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventOperationTaskManagerImpl.java new file mode 100644 index 0000000000..f66ffdf6e5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/task/EventOperationTaskManagerImpl.java @@ -0,0 +1,84 @@ +/* + * 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.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration; +import org.wso2.carbon.device.mgt.core.event.config.GroupEventOperationCreationTask; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskException; +import org.wso2.carbon.ntask.common.TaskException; +import org.wso2.carbon.ntask.core.TaskInfo; +import org.wso2.carbon.ntask.core.TaskManager; +import org.wso2.carbon.ntask.core.service.TaskService; + +public class EventOperationTaskManagerImpl { + private static final Log log = LogFactory.getLog(EventOperationTaskManagerImpl.class); + + public static final String GROUP_EVENT_OPERATION_TASK_TYPE = "GROUP_EVENT_CREATION"; + private static final String TASK_NAME = "GROUP_EVENT_TASK"; + private static final String TASK_CLASS = GroupEventOperationCreationTask.class.getName(); + + public void startGroupEventOperationTask(EventOperationTaskConfiguration eventTaskConfig) + throws EventOperationTaskException { + try { + TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService(); + taskService.registerTaskType(GROUP_EVENT_OPERATION_TASK_TYPE); + + if (log.isDebugEnabled()) { + log.debug("Group event creation task is started"); + log.debug( + "Group event creation task is at frequency of : " + eventTaskConfig.getFrequency()); + } + TaskManager taskManager = taskService.getTaskManager(GROUP_EVENT_OPERATION_TASK_TYPE); + TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo(); + //Convert to milli seconds + triggerInfo.setIntervalMillis(eventTaskConfig.getFrequency()); + triggerInfo.setRepeatCount(-1); + if (!taskManager.isTaskScheduled(GROUP_EVENT_OPERATION_TASK_TYPE)) { + TaskInfo taskInfo = new TaskInfo(TASK_NAME, TASK_CLASS, null, triggerInfo); + taskManager.registerTask(taskInfo); + taskManager.rescheduleTask(taskInfo.getName()); + } else { + String msg = "Group event creation task is already started"; + log.error(msg); + throw new EventOperationTaskException(msg); + } + } catch (TaskException e) { + String msg = "Error occurred while creating the group event operation task"; + log.error(msg, e); + throw new EventOperationTaskException(msg, e); + } + } + + public void stopGroupEventOperationTaskTask() throws EventOperationTaskException { + try { + TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService(); + if (taskService != null && taskService.isServerInit()) { + TaskManager taskManager = taskService.getTaskManager(GROUP_EVENT_OPERATION_TASK_TYPE); + taskManager.deleteTask(TASK_NAME); + } + } catch (TaskException e) { + String msg = "Error occurred while stopping the group event operation task"; + log.error(msg, e); + throw new EventOperationTaskException(msg, e); + } + } +} 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 index 4863a2fab6..6d17a1d85a 100644 --- 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 @@ -23,7 +23,6 @@ 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; @@ -42,20 +41,6 @@ public class GeoFenceEventOperationManager { 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 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 88ea281d62..286446c904 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 @@ -33,6 +33,7 @@ import org.wso2.carbon.device.mgt.core.config.license.LicenseConfig; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeServiceIdentifier; +import org.wso2.carbon.device.mgt.core.geo.task.EventOperationTaskManagerImpl; import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; @@ -77,6 +78,7 @@ public class DeviceManagementDataHolder { private PrivacyComplianceProvider privacyComplianceProvider; private EventConfigurationProviderService eventConfigurationService; private GeoLocationProviderService geoLocationProviderService; + private EventOperationTaskManagerImpl eventOperationTaskManager; private final Map deviceStatusTaskPluginConfigs = Collections.synchronizedMap( new HashMap<>()); @@ -318,4 +320,12 @@ public class DeviceManagementDataHolder { public void setGeoLocationProviderService(GeoLocationProviderService geoLocationProviderService) { this.geoLocationProviderService = geoLocationProviderService; } + + public void setEventOperationTaskManager(EventOperationTaskManagerImpl eventOperationTaskManager) { + this.eventOperationTaskManager = eventOperationTaskManager; + } + + public EventOperationTaskManagerImpl getEventOperationTaskManager() { + return eventOperationTaskManager; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceTaskManagerServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceTaskManagerServiceComponent.java index 489a29c72c..c88a2d5454 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceTaskManagerServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceTaskManagerServiceComponent.java @@ -26,7 +26,10 @@ import org.wso2.carbon.device.mgt.common.DeviceStatusTaskPluginConfig; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig; +import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration; import org.wso2.carbon.device.mgt.core.dto.DeviceType; +import org.wso2.carbon.device.mgt.core.geo.task.EventOperationTaskException; +import org.wso2.carbon.device.mgt.core.geo.task.EventOperationTaskManagerImpl; import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskException; import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskManagerService; import org.wso2.carbon.device.mgt.core.status.task.impl.DeviceStatusTaskManagerServiceImpl; @@ -60,6 +63,7 @@ public class DeviceTaskManagerServiceComponent { log.debug("Initializing device task manager bundle."); } startOperationMonitoringTask(componentContext.getBundleContext()); + startGroupEventCreationTask(componentContext.getBundleContext()); //Start the DeviceStatusMonitoringTask for registered DeviceTypes deviceManagementConfig = DeviceConfigurationManager.getInstance(). getDeviceManagementConfig(); @@ -108,6 +112,9 @@ public class DeviceTaskManagerServiceComponent { stopOperationMonitoringTask(); if (deviceManagementConfig != null && deviceManagementConfig.getDeviceStatusTaskConfig().isEnabled()) { stopDeviceStatusMonitoringTask(); + } else if (deviceManagementConfig != null && deviceManagementConfig.getEventOperationTaskConfiguration() + .isEnabled()) { + stopGroupEventCreationTask(); } } catch (Throwable e) { log.error("Error occurred while shutting down device task manager service.", e); @@ -143,6 +150,38 @@ public class DeviceTaskManagerServiceComponent { } } + /** + * Start event operation creation task + * @param bundleContext OsgiBundle context + */ + private void startGroupEventCreationTask(BundleContext bundleContext) { + DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().getDeviceManagementConfig(); + EventOperationTaskConfiguration eventTaskConfig = deviceManagementConfig.getEventOperationTaskConfiguration(); + if (eventTaskConfig.isEnabled()) { + EventOperationTaskManagerImpl eventOperationTaskManager = new EventOperationTaskManagerImpl(); + DeviceManagementDataHolder.getInstance().setEventOperationTaskManager(eventOperationTaskManager); + bundleContext.registerService(EventOperationTaskManagerImpl.class, eventOperationTaskManager, null); + try { + eventOperationTaskManager.startGroupEventOperationTask(eventTaskConfig); + } catch (EventOperationTaskException e) { + log.error("Error occurred while creating group event creation task"); + } + } + } + + /** + * Stop event operation creation task + */ + private void stopGroupEventCreationTask() { + EventOperationTaskManagerImpl eventOperationTaskManager = DeviceManagementDataHolder.getInstance() + .getEventOperationTaskManager(); + try { + eventOperationTaskManager.stopGroupEventOperationTaskTask(); + } catch (EventOperationTaskException e) { + log.error("Error occurred while stopping group event creation task"); + } + } + protected void setTaskService(TaskService taskService) { if (log.isDebugEnabled()) { log.debug("Setting the task service."); diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml index cbb8cc6905..c547a5c06c 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml @@ -97,6 +97,10 @@ server environment--> 10000 + + true + 60000 + true 86400 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 dcd89c3654..2de968cb81 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 @@ -722,4 +722,22 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( 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 +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- + +-- DM_GROUP_EVENT_ASSIGNMENT_TASK TABLE-- + +CREATE TABLE IF NOT EXISTS DM_EVENT_OPERATION_ASSIGNMENT_TASK ( + ID INT NOT NULL AUTO_INCREMENT, + DEVICE_ID INT DEFAULT NULL, + GROUP_ID INT DEFAULT NULL, + OPERATION_CODE VARCHAR(100) NOT NULL, + EVENT_SOURCE VARCHAR(250) NOT NULL, + EVENT_META_ID INT DEFAULT NULL, + STATUS VARCHAR(100) NOT NULL, + TENANT_ID INT NOT NULL, + CREATED_TIMESTAMP TIMESTAMP NOT NULL, + COMPLETED_TIMESTAMP TIMESTAMP DEFAULT NULL, + PRIMARY KEY (ID) +); + +-- END OF DM_GROUP_EVENT_ASSIGNMENT_TASK 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 00ff301f6d..56cb0022b3 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 @@ -786,4 +786,22 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( 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 +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- + +-- DM_GROUP_EVENT_ASSIGNMENT_TASK TABLE-- + +CREATE TABLE IF NOT EXISTS DM_EVENT_OPERATION_ASSIGNMENT_TASK ( + ID INT NOT NULL AUTO_INCREMENT, + DEVICE_ID INT DEFAULT NULL, + GROUP_ID INT DEFAULT NULL, + OPERATION_CODE VARCHAR(100) NOT NULL, + EVENT_SOURCE VARCHAR(250) NOT NULL, + EVENT_META_ID INT DEFAULT NULL, + STATUS VARCHAR(100) NOT NULL, + TENANT_ID INT NOT NULL, + CREATED_TIMESTAMP TIMESTAMP NOT NULL, + COMPLETED_TIMESTAMP TIMESTAMP DEFAULT NULL, + PRIMARY KEY (ID) +) ENGINE=InnoDB; + +-- END OF DM_GROUP_EVENT_ASSIGNMENT_TASK TABLE-- \ No newline at end of file