From 5831d277daa6d8283e9228e41e372b79252cc5be Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Mon, 27 Mar 2017 11:48:30 +0530 Subject: [PATCH 01/11] Fixing https://github.com/wso2/carbon-device-mgt-plugins/issues/613 --- .../mgt/core/enforcement/DelegationTask.java | 7 +- .../PolicyEnforcementDelegatorImpl.java | 36 +++++++++- .../policy/mgt/core/mgt/PolicyManager.java | 3 +- .../mgt/bean/UpdatedPolicyDeviceListBean.java | 65 +++++++++++++++++++ .../mgt/core/mgt/impl/PolicyManagerImpl.java | 9 +-- 5 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/bean/UpdatedPolicyDeviceListBean.java diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/DelegationTask.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/DelegationTask.java index dea10f5fac2..adccce97230 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/DelegationTask.java +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/DelegationTask.java @@ -29,6 +29,7 @@ import org.wso2.carbon.policy.mgt.common.PolicyManagementException; import org.wso2.carbon.policy.mgt.core.cache.impl.PolicyCacheManagerImpl; import org.wso2.carbon.policy.mgt.core.internal.PolicyManagementDataHolder; import org.wso2.carbon.policy.mgt.core.mgt.PolicyManager; +import org.wso2.carbon.policy.mgt.core.mgt.bean.UpdatedPolicyDeviceListBean; import org.wso2.carbon.policy.mgt.core.mgt.impl.PolicyManagerImpl; import java.util.ArrayList; @@ -54,7 +55,8 @@ public class DelegationTask implements Task { try { PolicyManager policyManager = new PolicyManagerImpl(); - List deviceTypes = policyManager.applyChangesMadeToPolicies(); + UpdatedPolicyDeviceListBean updatedPolicyDeviceList = policyManager.applyChangesMadeToPolicies(); + List deviceTypes = updatedPolicyDeviceList.getChangedDeviceTypes(); PolicyCacheManagerImpl.getInstance().rePopulateCache(); @@ -78,7 +80,8 @@ public class DelegationTask implements Task { // } } if (!toBeNotified.isEmpty()) { - PolicyEnforcementDelegator enforcementDelegator = new PolicyEnforcementDelegatorImpl(toBeNotified); + PolicyEnforcementDelegator enforcementDelegator = new PolicyEnforcementDelegatorImpl + (toBeNotified, updatedPolicyDeviceList.getUpdatedPolicyIds()); enforcementDelegator.delegate(); } } catch (DeviceManagementException e) { diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegatorImpl.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegatorImpl.java index 9a3bcfa8948..fa02314460f 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegatorImpl.java +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegatorImpl.java @@ -44,8 +44,9 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato private static final Log log = LogFactory.getLog(PolicyEnforcementDelegatorImpl.class); private List devices; + private List updatedPolicyIds; - public PolicyEnforcementDelegatorImpl(List devices) { + public PolicyEnforcementDelegatorImpl(List devices, List updatedPolicyIds) { log.info("Policy re-enforcing stared due to change of the policies."); @@ -56,6 +57,7 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato } } this.devices = devices; + this.updatedPolicyIds = updatedPolicyIds; } @@ -66,12 +68,22 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato identifier.setId(device.getDeviceIdentifier()); identifier.setType(device.getType()); + Policy devicePolicy = this.getAppliedPolicyToDevice(identifier); Policy policy = this.getEffectivePolicy(identifier); List deviceIdentifiers = new ArrayList<>(); deviceIdentifiers.add(identifier); if (policy != null) { - this.addPolicyRevokeOperation(deviceIdentifiers); - this.addPolicyOperation(deviceIdentifiers, policy); + /* + We add policy operation for the device if, + 1) Device does not have any policy or + 2) New Policy or + 3) Device existing policy has changed + */ + if (devicePolicy == null || devicePolicy.getId() != policy.getId() || updatedPolicyIds.contains + (policy.getId())) { + this.addPolicyRevokeOperation(deviceIdentifiers); + this.addPolicyOperation(deviceIdentifiers, policy); + } } else { //This means all the applicable policies have been removed from device. Hence calling a policy revoke. this.addPolicyRevokeOperation(deviceIdentifiers); @@ -154,4 +166,22 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato policyRevokeOperation.setType(Operation.Type.COMMAND); return policyRevokeOperation; } + + /** + * Provides the applied policy for give device + * + * @param identifier Device Identifier + * @return Applied Policy + * @throws PolicyDelegationException exception throws when retrieving applied policy for given device + */ + public Policy getAppliedPolicyToDevice(DeviceIdentifier identifier) throws PolicyDelegationException { + try { + PolicyManagerService policyManagerService = new PolicyManagerServiceImpl(); + return policyManagerService.getAppliedPolicyToDevice(identifier); + } catch (PolicyManagementException e) { + String msg = "Error occurred while retrieving the applied policy for devices."; + log.error(msg, e); + throw new PolicyDelegationException(msg, e); + } + } } diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/PolicyManager.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/PolicyManager.java index 8f18a89ffd4..68c57b5049f 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/PolicyManager.java +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/PolicyManager.java @@ -21,6 +21,7 @@ import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; import org.wso2.carbon.policy.mgt.common.PolicyManagementException; +import org.wso2.carbon.policy.mgt.core.mgt.bean.UpdatedPolicyDeviceListBean; import java.util.HashMap; import java.util.List; @@ -67,7 +68,7 @@ public interface PolicyManager { void addAppliedPolicyFeaturesToDevice(DeviceIdentifier deviceIdentifier, Policy policy) throws PolicyManagementException; - List applyChangesMadeToPolicies() throws PolicyManagementException; + UpdatedPolicyDeviceListBean applyChangesMadeToPolicies() throws PolicyManagementException; void addAppliedPolicyToDevice(DeviceIdentifier deviceIdentifier, Policy policy) throws PolicyManagementException; diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/bean/UpdatedPolicyDeviceListBean.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/bean/UpdatedPolicyDeviceListBean.java new file mode 100644 index 00000000000..2071d1ff5bd --- /dev/null +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/bean/UpdatedPolicyDeviceListBean.java @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.wso2.carbon.policy.mgt.core.mgt.bean; + +import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; +import org.wso2.carbon.device.mgt.core.dto.DeviceType; + + +import java.util.List; + +/** + * This class stores list of updated policies and list of changed devices for Policy Manager + */ +public class UpdatedPolicyDeviceListBean { + + private List updatedPolicies; + private List updatedPolicyIds; + private List changedDeviceTypes; + + public UpdatedPolicyDeviceListBean(List updatedPolicies, List updatedPolicyIds, List + deviceTypes) { + this.updatedPolicies = updatedPolicies; + this.updatedPolicyIds = updatedPolicyIds; + this.changedDeviceTypes = deviceTypes; + } + + public List getUpdatedPolicies() { + return updatedPolicies; + } + + public void setUpdatedPolicies(List updatedPolicies) { + this.updatedPolicies = updatedPolicies; + } + + public List getUpdatedPolicyIds() { + return updatedPolicyIds; + } + + public void setUpdatedPolicyIds(List updatedPolicyIds) { + this.updatedPolicyIds = updatedPolicyIds; + } + + public List getChangedDeviceTypes() { + return changedDeviceTypes; + } + + public void setChangedDeviceTypes(List changedDeviceTypes) { + this.changedDeviceTypes = changedDeviceTypes; + } +} diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/impl/PolicyManagerImpl.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/impl/PolicyManagerImpl.java index 3614f756970..b8c0efd98f1 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/impl/PolicyManagerImpl.java +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/mgt/impl/PolicyManagerImpl.java @@ -39,6 +39,7 @@ import org.wso2.carbon.policy.mgt.core.cache.impl.PolicyCacheManagerImpl; import org.wso2.carbon.policy.mgt.core.dao.*; import org.wso2.carbon.policy.mgt.core.mgt.PolicyManager; import org.wso2.carbon.policy.mgt.core.mgt.ProfileManager; +import org.wso2.carbon.policy.mgt.core.mgt.bean.UpdatedPolicyDeviceListBean; import org.wso2.carbon.policy.mgt.core.util.PolicyManagerUtil; import java.sql.SQLException; @@ -830,15 +831,15 @@ public class PolicyManagerImpl implements PolicyManager { } @Override - public List applyChangesMadeToPolicies() throws PolicyManagementException { + public UpdatedPolicyDeviceListBean applyChangesMadeToPolicies() throws PolicyManagementException { List changedDeviceTypes = new ArrayList<>(); + List updatedPolicies = new ArrayList<>(); + List updatedPolicyIds = new ArrayList<>(); try { //HashMap map = policyDAO.getUpdatedPolicyIdandDeviceTypeId(); - List updatedPolicies = new ArrayList<>(); // List activePolicies = new ArrayList<>(); // List inactivePolicies = new ArrayList<>(); - List updatedPolicyIds = new ArrayList<>(); // List allPolicies = this.getPolicies(); List allPolicies = PolicyCacheManagerImpl.getInstance().getAllPolicies(); @@ -867,7 +868,7 @@ public class PolicyManagerImpl implements PolicyManager { } finally { PolicyManagementDAOFactory.closeConnection(); } - return changedDeviceTypes; + return new UpdatedPolicyDeviceListBean(updatedPolicies, updatedPolicyIds, changedDeviceTypes); } From eecb0a0a312fca5d32f56507e0fbc5df44f23b06 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Tue, 25 Apr 2017 18:50:59 +0530 Subject: [PATCH 02/11] Add push notification status column to DM_ENROLMENT_OP_MAPPING --- .../src/main/resources/dbscripts/cdm/h2.sql | 1 + .../src/main/resources/dbscripts/cdm/mssql.sql | 1 + .../src/main/resources/dbscripts/cdm/mysql.sql | 1 + .../src/main/resources/dbscripts/cdm/oracle.sql | 1 + .../src/main/resources/dbscripts/cdm/postgresql.sql | 1 + 5 files changed, 5 insertions(+) diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql index 498a439c076..e63c647b37f 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -114,6 +114,7 @@ CREATE TABLE IF NOT EXISTS DM_ENROLMENT_OP_MAPPING ( ENROLMENT_ID INTEGER NOT NULL, OPERATION_ID INTEGER NOT NULL, STATUS VARCHAR(50) NULL, + PUSH_NOTIFICATION_STATUS VARCHAR(50) NULL, CREATED_TIMESTAMP INT NOT NULL, UPDATED_TIMESTAMP INT NOT NULL, PRIMARY KEY (ID), diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql index ed33177429d..a2c7d4dea30 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -148,6 +148,7 @@ CREATE TABLE DM_ENROLMENT_OP_MAPPING ( ENROLMENT_ID INTEGER NOT NULL, OPERATION_ID INTEGER NOT NULL, STATUS VARCHAR(50) NULL, + PUSH_NOTIFICATION_STATUS VARCHAR(50) NULL, CREATED_TIMESTAMP BIGINT NOT NULL, UPDATED_TIMESTAMP BIGINT NOT NULL, PRIMARY KEY (ID), diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql index 6bec98fc5b4..6de158c415c 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -128,6 +128,7 @@ CREATE TABLE IF NOT EXISTS DM_ENROLMENT_OP_MAPPING ( ENROLMENT_ID INTEGER NOT NULL, OPERATION_ID INTEGER NOT NULL, STATUS VARCHAR(50) NULL, + PUSH_NOTIFICATION_STATUS VARCHAR(50) NULL, CREATED_TIMESTAMP INTEGER NOT NULL, UPDATED_TIMESTAMP INTEGER NOT NULL, PRIMARY KEY (ID), diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql index 4bd5f55de94..31b7d60fe41 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -210,6 +210,7 @@ CREATE TABLE DM_ENROLMENT_OP_MAPPING ( ENROLMENT_ID NUMBER(10) NOT NULL, OPERATION_ID NUMBER(10) NOT NULL, STATUS VARCHAR2(50) NULL, + PUSH_NOTIFICATION_STATUS VARCHAR2(50) NULL, CREATED_TIMESTAMP NUMBER(14) NOT NULL, UPDATED_TIMESTAMP NUMBER(14) NOT NULL, PRIMARY KEY (ID), diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql index a4f07d7781f..6c1fc86a915 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -115,6 +115,7 @@ CREATE TABLE IF NOT EXISTS DM_ENROLMENT_OP_MAPPING ( ENROLMENT_ID INTEGER NOT NULL, OPERATION_ID INTEGER NOT NULL, STATUS VARCHAR(50) NULL, + PUSH_NOTIFICATION_STATUS VARCHAR(50) NULL, CREATED_TIMESTAMP INTEGER NOT NULL, UPDATED_TIMESTAMP INTEGER NOT NULL, CONSTRAINT fk_dm_device_operation_mapping_device FOREIGN KEY (ENROLMENT_ID) REFERENCES From 642f64c2d443bb375efb82487ff2becb11f57084 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Tue, 25 Apr 2017 18:51:44 +0530 Subject: [PATCH 03/11] Add new push notification scheduler --- .../src/main/resources/conf/cdm-config.xml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml index 42a0372076a..7e165de6cea 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml @@ -25,12 +25,17 @@ - - org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.FCMBasedPushNotificationProvider - - org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt.MQTTBasedPushNotificationProvider - org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp.XMPPBasedPushNotificationProvider - + + 1 + 1000 + true + + org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.FCMBasedPushNotificationProvider + + org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt.MQTTBasedPushNotificationProvider + org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp.XMPPBasedPushNotificationProvider + + https://localhost:9443 admin From 3c1e4ba205215ce3c42e4ddd2497822b69816917 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Tue, 25 Apr 2017 18:55:31 +0530 Subject: [PATCH 04/11] Add new classes for improve Performance of push notifications --- .../config/PushNotificationProvider.java | 28 ++++ .../operation/mgt/OperationMapping.java | 54 ++++++++ .../PushNotificationConfiguration.java | 71 ++++++++++ .../mgt/task/PushNotificationJob.java | 122 ++++++++++++++++++ .../task/PushNotificationSchedulerTask.java | 55 ++++++++ 5 files changed, 330 insertions(+) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/PushNotificationProvider.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/PushNotificationProvider.java index 43aee84397d..59e6e68b7ba 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/PushNotificationProvider.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/PushNotificationProvider.java @@ -59,6 +59,8 @@ public class PushNotificationProvider { protected ConfigProperties configProperties; @XmlAttribute(name = "type") protected String type; + @XmlAttribute(name = "isScheduled") + protected boolean isScheduled; /** * Gets the value of the fileBasedProperties property. @@ -124,4 +126,30 @@ public class PushNotificationProvider { this.type = value; } + /** + * Gets the value of the isScheduled property. + * This property will be used to determine whether to use scheduler task to send push notification + * If true push notification will be sent using scheduler task + * If false push notifications will be sent immediately. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isScheduled() { + return isScheduled; + } + + /** + * Sets the value of the isScheduled property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public void setScheduled(boolean scheduled) { + isScheduled = scheduled; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java new file mode 100644 index 00000000000..f9feed6d8d6 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.wso2.carbon.device.mgt.common.operation.mgt; + +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; + +/** + * Class for represent operation mapping + */ +public class OperationMapping { + + private DeviceIdentifier deviceIdentifier; + private int operationId; + private int tenantId; + + public int getOperationId() { + return operationId; + } + + public void setOperationId(int operationId) { + this.operationId = operationId; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } + + public DeviceIdentifier getDeviceIdentifier() { + return deviceIdentifier; + } + + public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) { + this.deviceIdentifier = deviceIdentifier; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java new file mode 100644 index 00000000000..6872affcf82 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.wso2.carbon.device.mgt.core.config.push.notification; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +/** + * This class is for Push notification related Configurations + */ +@XmlRootElement(name = "PushNotificationConfiguration") +public class PushNotificationConfiguration { + + private int SchedulerBatchSize; + private int SchedulerBatchDelayMills; + private boolean SchedulerTaskEnabled; + private List pushNotificationProviders; + + @XmlElement(name = "SchedulerBatchSize", required = true) + public int getSchedulerBatchSize() { + return SchedulerBatchSize; + } + + public void setSchedulerBatchSize(int SchedulerBatchSize) { + this.SchedulerBatchSize = SchedulerBatchSize; + } + + @XmlElement(name = "SchedulerBatchDelayMills", required = true) + public int getSchedulerBatchDelayMills() { + return SchedulerBatchDelayMills; + } + + public void setSchedulerBatchDelayMills(int SchedulerBatchDelayMills) { + this.SchedulerBatchDelayMills = SchedulerBatchDelayMills; + } + @XmlElement(name = "SchedulerTaskEnabled", required = true) + public boolean isSchedulerTaskEnabled() { + return SchedulerTaskEnabled; + } + + public void setSchedulerTaskEnabled(boolean schedulerTaskEnabled) { + SchedulerTaskEnabled = schedulerTaskEnabled; + } + + @XmlElementWrapper(name = "PushNotificationProviders", required = true) + @XmlElement(name = "Provider", required = true) + public List getPushNotificationProviders() { + return pushNotificationProviders; + } + + public void setPushNotificationProviders(List pushNotificationProviders) { + this.pushNotificationProviders = pushNotificationProviders; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java new file mode 100644 index 00000000000..f9dc91d9dd0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java @@ -0,0 +1,122 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.wso2.carbon.device.mgt.core.push.notification.mgt.task; + +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.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; +import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; +import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; +import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; +import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.tenant.TenantManager; + +import java.util.LinkedList; +import java.util.List; + +/** + * ${{@link PushNotificationJob}} is for sending push notifications for given device batch. + */ +public class PushNotificationJob implements Runnable { + + private static Log log = LogFactory.getLog(PushNotificationJob.class); + private final OperationDAO operationDAO = OperationManagementDAOFactory.getOperationDAO(); + private final OperationMappingDAO operationMappingDAO = OperationManagementDAOFactory.getOperationMappingDAO(); + private final DeviceManagementProviderService provider = DeviceManagementDataHolder.getInstance() + .getDeviceManagementProvider(); + private final TenantManager tenantManager = DeviceManagementDataHolder.getInstance().getRealmService() + .getTenantManager(); + + @Override + public void run() { + List operationsCompletedList = new LinkedList<>(); + try { + if (log.isDebugEnabled()) { + log.debug("Push notification job started"); + } + //Get next available operation list per device batch + List operationMappings = operationDAO.getOperationMappingsByStatus(Operation.Status + .PENDING, Operation.PushStatus.SCHEDULED, DeviceConfigurationManager.getInstance() + .getDeviceManagementConfig().getPushNotificationConfiguration().getSchedulerBatchSize()); + // Sending push notification to each device + for (OperationMapping operationMapping : operationMappings) { + try { + if (log.isDebugEnabled()) { + log.debug("Sending push notification for operationId :" + operationMapping.getOperationId() + + "to deviceId : " + operationMapping.getDeviceIdentifier().getId()); + } + // Set tenant id and domain + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(operationMapping.getTenantId()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantManager.getDomain + (operationMapping.getTenantId())); + // Get notification strategy for given device type + NotificationStrategy notificationStrategy = provider.getNotificationStrategyByDeviceType + (operationMapping.getDeviceIdentifier().getType()); + // Send the push notification on given strategy + notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(), + provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping + .getOperationId()))); + operationsCompletedList.add(operationMapping); + } catch (DeviceManagementException e) { + log.error("Error occurred while getting notification strategy for operation mapping " + + operationMapping.getDeviceIdentifier().getType(), e); + } catch (OperationManagementException e) { + log.error("Unable to get the operation for operation " + operationMapping.getOperationId(), e); + } catch (PushNotificationExecutionFailedException e) { + log.error("Error occurred while sending push notification to operation: " + operationMapping + .getOperationId(), e); + } catch (UserStoreException e) { + log.error("Tenant domain cannot be found for given tenant id: " + operationMapping.getTenantId() + , e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + if (log.isDebugEnabled()) { + log.debug("Push notification job running completed."); + } + } catch (OperationManagementDAOException e) { + log.error("Unable to retrieve scheduled pending operations for task. ", e); + } finally { + // Update push notification status to competed for operations which already sent + try { + OperationManagementDAOFactory.beginTransaction(); + operationMappingDAO.updateOperationMapping(operationsCompletedList, Operation.PushStatus.COMPLETED); + OperationManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException | OperationManagementDAOException e) { + OperationManagementDAOFactory.rollbackTransaction(); + log.error("Error occurred while updating operation mappings for sent notifications ", e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java new file mode 100644 index 00000000000..97aaf4c4fda --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.wso2.carbon.device.mgt.core.push.notification.mgt.task; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * ${{@link PushNotificationSchedulerTask}} for scheduling push notification job. + */ +public class PushNotificationSchedulerTask implements Runnable { + + private static Log log = LogFactory.getLog(PushNotificationSchedulerTask.class); + private final ExecutorService executor = Executors.newSingleThreadExecutor(); + private Future lastExecution; + final PushNotificationJob pushNotificationJob = new PushNotificationJob(); + + @Override + public void run() { + /* + There will be only one push notification job submit to thread pool. + Scheduler will submit new job only if last execution is completed. + */ + if (lastExecution != null && !lastExecution.isDone()) { + if (log.isDebugEnabled()) { + log.debug("Previous push notification job is already running. New notification job will start " + + "after existing job completed."); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Submitting new notification job."); + } + lastExecution = executor.submit(pushNotificationJob); + } +} From 65667119f9b97f137fdf2bfa499319b93f9fc2ec Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Tue, 25 Apr 2017 19:01:48 +0530 Subject: [PATCH 05/11] Add push notification configurations for push notification stratagies --- .../deployer/template/DeviceTypeManagerService.java | 13 ++++++++++--- .../provider/fcm/FCMNotificationStrategy.java | 7 ++++++- .../provider/mqtt/MQTTNotificationStrategy.java | 7 +++++++ .../provider/xmpp/XMPPNotificationStrategy.java | 6 ++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java index 64398d37150..fa1a8442118 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java @@ -20,7 +20,12 @@ package org.wso2.carbon.device.mgt.extensions.device.type.deployer.template; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.device.mgt.common.*; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.DeviceManager; +import org.wso2.carbon.device.mgt.common.InitialOperationConfig; +import org.wso2.carbon.device.mgt.common.MonitoringOperation; +import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; +import org.wso2.carbon.device.mgt.common.ProvisioningConfig; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; @@ -112,7 +117,8 @@ public class DeviceTypeManagerService implements DeviceManagementService { for (Property property : pushNotificationProvider.getConfigProperties().getProperty()) { staticProps.put(property.getName(), property.getValue()); } - pushNotificationConfig = new PushNotificationConfig(pushNotificationProvider.getType(), staticProps); + pushNotificationConfig = new PushNotificationConfig(pushNotificationProvider.getType(), + pushNotificationProvider.isScheduled(), staticProps); } else { try { PlatformConfiguration deviceTypeConfig = deviceManager.getConfiguration(); @@ -121,7 +127,8 @@ public class DeviceTypeManagerService implements DeviceManagementService { if (configuration.size() > 0) { Map properties = this.getConfigProperty(configuration); pushNotificationConfig = new PushNotificationConfig( - pushNotificationProvider.getType(), properties); + pushNotificationProvider.getType(), pushNotificationProvider.isScheduled(), + properties); } } } catch (DeviceManagementException e) { diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java index 6dd66f08367..da488c54353 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java @@ -42,7 +42,7 @@ public class FCMNotificationStrategy implements NotificationStrategy { private static final String FCM_API_KEY = "fcmAPIKey"; private static final int TIME_TO_LIVE = 60; private static final int HTTP_STATUS_CODE_OK = 200; - private PushNotificationConfig config; + private final PushNotificationConfig config; public FCMNotificationStrategy(PushNotificationConfig config) { this.config = config; @@ -133,4 +133,9 @@ public class FCMNotificationStrategy implements NotificationStrategy { return fcmToken; } + @Override + public PushNotificationConfig getConfig() { + return config; + } + } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/mqtt/MQTTNotificationStrategy.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/mqtt/MQTTNotificationStrategy.java index 93be8189997..8af53af6b26 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/mqtt/MQTTNotificationStrategy.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/mqtt/MQTTNotificationStrategy.java @@ -45,8 +45,10 @@ public class MQTTNotificationStrategy implements NotificationStrategy { private static final String MQTT_ADAPTER_TOPIC = "mqtt.adapter.topic"; private String mqttAdapterName; private static final Log log = LogFactory.getLog(MQTTNotificationStrategy.class); + private final PushNotificationConfig config; public MQTTNotificationStrategy(PushNotificationConfig config) { + this.config = config; OutputEventAdapterConfiguration adapterConfig = new OutputEventAdapterConfiguration(); adapterConfig.setType(MQTTAdapterConstants.MQTT_ADAPTER_TYPE); mqttAdapterName = config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_NAME); @@ -137,5 +139,10 @@ public class MQTTNotificationStrategy implements NotificationStrategy { MQTTDataHolder.getInstance().getOutputEventAdapterService().destroy(mqttAdapterName); } + @Override + public PushNotificationConfig getConfig() { + return config; + } + } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/XMPPNotificationStrategy.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/XMPPNotificationStrategy.java index 0d7229a193f..af3a1c6c4be 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/XMPPNotificationStrategy.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/XMPPNotificationStrategy.java @@ -45,10 +45,12 @@ public class XMPPNotificationStrategy implements NotificationStrategy { private String xmppAdapterName; private static final Log log = LogFactory.getLog(XMPPNotificationStrategy.class); private String subDomain; + private final PushNotificationConfig config; public XMPPNotificationStrategy(PushNotificationConfig config) { + this.config = config; OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration(); xmppAdapterName = config.getProperty(XMPPAdapterConstants.XMPP_ADAPTER_PROPERTY_NAME); outputEventAdapterConfiguration.setName(xmppAdapterName); @@ -106,4 +108,8 @@ public class XMPPNotificationStrategy implements NotificationStrategy { XMPPDataHolder.getInstance().getOutputEventAdapterService().destroy(xmppAdapterName); } + @Override + public PushNotificationConfig getConfig() { + return config; + } } From 9fa4eedca5ddb23c52ef916d3023602b4149cf26 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Tue, 25 Apr 2017 19:07:37 +0530 Subject: [PATCH 06/11] Add Scheduled for push notification sending --- .../notification/NotificationStrategy.java | 6 ++ .../notification/PushNotificationConfig.java | 8 +- .../mgt/core/DeviceManagementConstants.java | 8 ++ .../core/config/DeviceManagementConfig.java | 21 +++--- .../mgt/core/dto/operation/mgt/Operation.java | 4 + .../DeviceManagementServiceComponent.java | 33 ++++++++- .../operation/mgt/OperationManagerImpl.java | 18 ++++- .../core/operation/mgt/dao/OperationDAO.java | 4 + .../mgt/dao/OperationMappingDAO.java | 14 +++- .../mgt/dao/impl/GenericOperationDAOImpl.java | 66 ++++++++++++++--- .../mgt/dao/impl/OperationMappingDAOImpl.java | 73 +++++++++++++++++-- .../operation/OracleOperationDAOImpl.java | 41 ++++++++++- .../operation/SQLServerOperationDAOImpl.java | 40 ++++++++++ .../DeviceManagementProviderService.java | 17 ++++- .../DeviceManagementProviderServiceImpl.java | 44 +++++++++-- 15 files changed, 346 insertions(+), 51 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/NotificationStrategy.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/NotificationStrategy.java index bce041a2f2f..c1f7e37da7e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/NotificationStrategy.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/NotificationStrategy.java @@ -31,4 +31,10 @@ public interface NotificationStrategy { */ void undeploy(); + /** + * Provides push notification configuration + * + */ + PushNotificationConfig getConfig(); + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java index 56cb65648ea..882df04a645 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java @@ -26,11 +26,13 @@ import java.util.Map; public class PushNotificationConfig { private String type; + private boolean isScheduled; Map properties; - public PushNotificationConfig(String type, Map properties) { + public PushNotificationConfig(String type, boolean isScheduled, Map properties) { this.type = type; this.properties = properties; + this.isScheduled = isScheduled; } @XmlElement(name = "Type", required = true) @@ -38,6 +40,10 @@ public class PushNotificationConfig { return type; } + public boolean isScheduled() { + return isScheduled; + } + public Map getProperties() { return properties; } 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 a1749b8f317..7e5e1843585 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 @@ -86,4 +86,12 @@ public final class DeviceManagementConstants { public static final String ACTIVITY = "ACTIVITY_"; } + public static final class PushNotifications { + private PushNotifications() { + throw new AssertionError(); + } + public static final int DEFAULT_BATCH_DELAY_MILLS = 60000; + public static final int DEFAULT_BATCH_SIZE = 1000; + } + } 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 20e4eba5c22..cc9a6256a63 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 @@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.core.config; import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations; import org.wso2.carbon.device.mgt.core.config.pagination.PaginationConfiguration; import org.wso2.carbon.device.mgt.core.config.policy.PolicyConfiguration; +import org.wso2.carbon.device.mgt.core.config.push.notification.PushNotificationConfiguration; import org.wso2.carbon.device.mgt.core.config.task.TaskConfiguration; import javax.xml.bind.annotation.XmlElement; @@ -39,7 +40,7 @@ public final class DeviceManagementConfig { private IdentityConfigurations identityConfigurations; private PolicyConfiguration policyConfiguration; private PaginationConfiguration paginationConfiguration; - private List pushNotificationProviders; + private PushNotificationConfiguration pushNotificationConfiguration; @XmlElement(name = "ManagementRepository", required = true) @@ -79,16 +80,6 @@ public final class DeviceManagementConfig { this.taskConfiguration = taskConfiguration; } - @XmlElementWrapper(name = "PushNotificationProviders", required = true) - @XmlElement(name = "Provider", required = true) - public List getPushNotificationProviders() { - return pushNotificationProviders; - } - - public void setPushNotificationProviders(List pushNotificationProviders) { - this.pushNotificationProviders = pushNotificationProviders; - } - @XmlElement(name = "PaginationConfiguration", required = true) public PaginationConfiguration getPaginationConfiguration() { return paginationConfiguration; @@ -98,5 +89,13 @@ public final class DeviceManagementConfig { this.paginationConfiguration = paginationConfiguration; } + @XmlElement(name = "PushNotificationConfiguration", required = true) + public PushNotificationConfiguration getPushNotificationConfiguration() { + return pushNotificationConfiguration; + } + + public void setPushNotificationConfiguration(PushNotificationConfiguration pushNotificationConfiguration) { + this.pushNotificationConfiguration = pushNotificationConfiguration; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java index c61b2d304fc..2263ccdf7bf 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java @@ -35,6 +35,10 @@ public class Operation implements Serializable { REPEAT, NO_REPEAT, PAUSE_SEQUENCE, STOP_SEQUENCE } + public enum PushStatus { + SCHEDULED, IN_PROGRESS, COMPLETED + } + private String code; private Properties properties; private Type type; 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 7930aab2b3e..b63aa0d2a17 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 @@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.OperationManagerImpl; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository; +import org.wso2.carbon.device.mgt.core.push.notification.mgt.task.PushNotificationSchedulerTask; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; @@ -62,6 +63,11 @@ import org.wso2.carbon.utils.ConfigurationContextService; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * @scr.component name="org.wso2.carbon.device.manager" immediate="true" @@ -151,7 +157,8 @@ public class DeviceManagementServiceComponent { this.initOperationsManager(); PushNotificationProviderRepository pushNotificationRepo = new PushNotificationProviderRepository(); - List pushNotificationProviders = config.getPushNotificationProviders(); + List pushNotificationProviders = config.getPushNotificationConfiguration() + .getPushNotificationProviders(); if (pushNotificationProviders != null) { for (String pushNoteProvider : pushNotificationProviders) { pushNotificationRepo.addProvider(pushNoteProvider); @@ -179,6 +186,24 @@ public class DeviceManagementServiceComponent { if (log.isDebugEnabled()) { log.debug("Device management core bundle has been successfully initialized"); } + // Start Push Notification Scheduler Task + if (config.getPushNotificationConfiguration().isSchedulerTaskEnabled()) { + if (config.getPushNotificationConfiguration().getSchedulerBatchSize() <= 0) { + log.error("Push notification batch size cannot be 0 or less than 0. Setting default batch size to:" + + " " + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_SIZE); + config.getPushNotificationConfiguration().setSchedulerBatchSize(DeviceManagementConstants.PushNotifications + .DEFAULT_BATCH_SIZE); + } + if (config.getPushNotificationConfiguration().getSchedulerBatchDelayMills() <= 0) { + log.error("Push notification batch delay cannot be 0 or less than 0. Setting default batch delay " + + "milliseconds to" + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_DELAY_MILLS); + config.getPushNotificationConfiguration().setSchedulerBatchDelayMills(DeviceManagementConstants.PushNotifications + .DEFAULT_BATCH_DELAY_MILLS); + } + ScheduledExecutorService pushNotificationExecutor = Executors.newScheduledThreadPool(1); + pushNotificationExecutor.schedule(new PushNotificationSchedulerTask(), config.getPushNotificationConfiguration() + .getSchedulerBatchDelayMills(), TimeUnit.MILLISECONDS); + } } catch (Throwable e) { log.error("Error occurred while initializing device management core bundle", e); } @@ -269,7 +294,7 @@ public class DeviceManagementServiceComponent { try { if (log.isDebugEnabled()) { log.debug("Setting Device Management Service Provider: '" + - deviceManagementService.getType() + "'"); + deviceManagementService.getType() + "'"); } synchronized (LOCK) { deviceManagers.add(deviceManagementService); @@ -278,10 +303,10 @@ public class DeviceManagementServiceComponent { } } log.info("Device Type deployed successfully : " + deviceManagementService.getType() + " for tenant " - + deviceManagementService.getProvisioningConfig().getProviderTenantDomain()); + + deviceManagementService.getProvisioningConfig().getProviderTenantDomain()); } catch (Throwable e) { log.error("Failed to register device management service for device type" + deviceManagementService.getType() + - " for tenant " + deviceManagementService.getProvisioningConfig().getProviderTenantDomain(), e); + " for tenant " + deviceManagementService.getProvisioningConfig().getProviderTenantDomain(), e); } } 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 e79d95c5cc2..aeb44e559f1 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 @@ -145,6 +145,11 @@ public class OperationManagerImpl implements OperationManager { int operationId = this.lookupOperationDAO(operation).addOperation(operationDto); boolean isScheduledOperation = this.isTaskScheduledOperation(operation, deviceIds); boolean isNotRepeated = false; + boolean isScheduled = false; + if (notificationStrategy != null) { + isScheduled = notificationStrategy.getConfig().isScheduled(); + } + boolean hasExistingTaskOperation; int enrolmentId; if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == operationDto. @@ -161,7 +166,7 @@ public class OperationManagerImpl implements OperationManager { if (isScheduledOperation) { hasExistingTaskOperation = operationDAO.updateTaskOperation(enrolmentId, operationCode); if (!hasExistingTaskOperation) { - operationMappingDAO.addOperationMapping(operationId, enrolmentId); + operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); } } else if (isNotRepeated) { operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode, @@ -169,17 +174,22 @@ public class OperationManagerImpl implements OperationManager { Operation.Status.PENDING, org.wso2.carbon.device.mgt.core.dto.operation.mgt. Operation.Status.REPEATED); - operationMappingDAO.addOperationMapping(operationId, enrolmentId); + operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); } else { - operationMappingDAO.addOperationMapping(operationId, enrolmentId); + operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); } - if (notificationStrategy != null) { + if (notificationStrategy != null && !notificationStrategy.getConfig().isScheduled()) { try { notificationStrategy.execute(new NotificationContext(deviceId, operation)); + operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon + .device.mgt.core.dto.operation.mgt.Operation.PushStatus.COMPLETED); } catch (PushNotificationExecutionFailedException e) { log.error("Error occurred while sending push notifications to " + deviceId.getType() + " device carrying id '" + deviceId + "'", e); + // Reschedule if push notification failed. + operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon + .device.mgt.core.dto.operation.mgt.Operation.PushStatus.SCHEDULED); } } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java index d8c6b789877..63100f702cd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.core.operation.mgt.dao; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; @@ -80,4 +81,7 @@ public interface OperationDAO { boolean resetAttemptCount(int enrolmentId) throws OperationManagementDAOException; + List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException;; + } \ 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/operation/mgt/dao/OperationMappingDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java index d1327941001..0a2c45841df 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java @@ -18,10 +18,20 @@ */ package org.wso2.carbon.device.mgt.core.operation.mgt.dao; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; + +import java.util.List; + public interface OperationMappingDAO { - void addOperationMapping(int operationId, Integer deviceIds) throws OperationManagementDAOException; + void addOperationMapping(int operationId, Integer deviceId, boolean isScheduled) throws OperationManagementDAOException; + + void removeOperationMapping(int operationId, Integer deviceId) throws OperationManagementDAOException; - void removeOperationMapping(int operationId, Integer deviceIds) throws OperationManagementDAOException; + void updateOperationMapping(int operationId, Integer deviceId, Operation.PushStatus pushStatus) throws + OperationManagementDAOException; + void updateOperationMapping(List operationMappingList, Operation.PushStatus pushStatus) throws + OperationManagementDAOException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index c70a2a87aa3..a16aa42d5fd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -24,6 +24,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO; @@ -32,11 +33,20 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOF import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.util.OperationDAOUtil; -import java.io.*; -import java.sql.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +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.Calendar; import java.util.Date; +import java.util.LinkedList; import java.util.List; /** @@ -162,8 +172,8 @@ public class GenericOperationDAOImpl implements OperationDAO { try { Connection connection = OperationManagementDAOFactory.getConnection(); String query = "SELECT EOM.ID FROM DM_ENROLMENT_OP_MAPPING AS EOM INNER JOIN DM_OPERATION DM " + - "ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND " + - "EOM.STATUS = ?;"; + "ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND " + + "EOM.STATUS = ?;"; stmt = connection.prepareStatement(query); stmt.setInt(1, enrolmentId); stmt.setString(2, operationCode); @@ -176,7 +186,7 @@ public class GenericOperationDAOImpl implements OperationDAO { } if (id != 0) { stmt = connection.prepareStatement("UPDATE DM_ENROLMENT_OP_MAPPING SET UPDATED_TIMESTAMP = ? " + - "WHERE ID = ?"); + "WHERE ID = ?"); stmt.setLong(1, System.currentTimeMillis() / 1000); stmt.setInt(2, id); stmt.executeUpdate(); @@ -184,7 +194,7 @@ public class GenericOperationDAOImpl implements OperationDAO { } } catch (SQLException e) { throw new OperationManagementDAOException("Error occurred while update device mapping operation status " + - "metadata", e); + "metadata", e); } finally { OperationManagementDAOUtil.cleanupResources(stmt); } @@ -420,14 +430,13 @@ public class GenericOperationDAOImpl implements OperationDAO { "WHERE opm.UPDATED_TIMESTAMP > ? \n" + "AND de.TENANT_ID = ? \n"; - if(timestamp == 0){ + if (timestamp == 0) { sql += "ORDER BY opm.OPERATION_ID LIMIT ? OFFSET ?;"; - }else{ + } else { sql += "ORDER BY opm.UPDATED_TIMESTAMP asc LIMIT ? OFFSET ?"; } - stmt = conn.prepareStatement(sql); stmt.setLong(1, timestamp); @@ -1068,7 +1077,7 @@ public class GenericOperationDAOImpl implements OperationDAO { try { conn = OperationManagementDAOFactory.getConnection(); String query = "UPDATE DM_POLICY_COMPLIANCE_STATUS SET ATTEMPTS = 0, LAST_REQUESTED_TIME = ? " + - "WHERE ENROLMENT_ID = ? AND TENANT_ID = ?"; + "WHERE ENROLMENT_ID = ? AND TENANT_ID = ?"; stmt = conn.prepareStatement(query); stmt.setTimestamp(1, currentTimestamp); stmt.setInt(2, enrolmentId); @@ -1082,4 +1091,41 @@ public class GenericOperationDAOImpl implements OperationDAO { } return status; } + + @Override + public List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException { + + PreparedStatement stmt = null; + ResultSet rs = null; + OperationMapping operationMapping; + List operationMappings = new LinkedList<>(); + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + String sql = "SELECT op_mappings.ENROLMENT_ID, op_mappings.OPERATION_ID, d_type.NAME ,d.TENANT_ID FROM " + + "DM_DEVICE d, DM_ENROLMENT_OP_MAPPING op_mappings, DM_DEVICE_TYPE d_type WHERE op_mappings" + + ".STATUS = '?' AND op_mappings.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = d_type.ID " + + "AND d.ID=op_mappings.ENROLMENT_ID ORDER BY op_mappings.OPERATION_ID LIMIT ?"; + + stmt = conn.prepareStatement(sql); + stmt.setString(1, opStatus.toString()); + stmt.setString(2, pushStatus.toString()); + stmt.setInt(3, limit); + rs = stmt.executeQuery(); + + while (rs.next()) { + operationMapping = new OperationMapping(); + operationMapping.setOperationId(rs.getInt("OPERATION_ID")); + operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")), + rs.getString("NAME"))); + operationMapping.setTenantId(rs.getInt("TENANT_ID")); + operationMappings.add(operationMapping); + } + } catch (SQLException e) { + throw new OperationManagementDAOException("SQL error while getting operation mappings from database. ", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, rs); + } + return operationMappings; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java index 17492d4026e..473f1d76b39 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java @@ -18,6 +18,7 @@ */ package org.wso2.carbon.device.mgt.core.operation.mgt.dao.impl; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; @@ -27,23 +28,30 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.List; public class OperationMappingDAOImpl implements OperationMappingDAO { @Override - public void addOperationMapping(int operationId, Integer deviceId) throws OperationManagementDAOException { + public void addOperationMapping(int operationId, Integer deviceId, boolean isScheduled) throws + OperationManagementDAOException { PreparedStatement stmt = null; try { - long time = System.currentTimeMillis()/1000; + long time = System.currentTimeMillis() / 1000; Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "INSERT INTO DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID, OPERATION_ID, STATUS, CREATED_TIMESTAMP, " + - "UPDATED_TIMESTAMP) VALUES (?, ?, ?, ?, ?)"; + String sql = "INSERT INTO DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID, OPERATION_ID, STATUS, " + + "PUSH_NOTIFICATION_STATUS, CREATED_TIMESTAMP, UPDATED_TIMESTAMP) VALUES (?, ?, ?, ?, ?, ?)"; stmt = conn.prepareStatement(sql); stmt.setInt(1, deviceId); stmt.setInt(2, operationId); stmt.setString(3, Operation.Status.PENDING.toString()); - stmt.setLong(4, time); + if (isScheduled) { + stmt.setString(4, Operation.PushStatus.SCHEDULED.toString()); + } else { + stmt.setString(4, Operation.PushStatus.IN_PROGRESS.toString()); + } stmt.setLong(5, time); + stmt.setLong(6, time); stmt.executeUpdate(); } catch (SQLException e) { throw new OperationManagementDAOException("Error occurred while persisting device operation mappings", e); @@ -54,13 +62,13 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { @Override public void removeOperationMapping(int operationId, - Integer deviceIds) throws OperationManagementDAOException { + Integer deviceId) throws OperationManagementDAOException { PreparedStatement stmt = null; try { Connection conn = OperationManagementDAOFactory.getConnection(); String sql = "DELETE FROM DM_ENROLMENT_OP_MAPPING WHERE ENROLMENT_ID = ? AND OPERATION_ID = ?"; stmt = conn.prepareStatement(sql); - stmt.setInt(1, 0); + stmt.setInt(1, deviceId); stmt.setInt(2, operationId); stmt.executeUpdate(); } catch (SQLException e) { @@ -70,4 +78,55 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { } } + @Override + public void updateOperationMapping(int operationId, Integer deviceId, Operation.PushStatus pushStatus) throws OperationManagementDAOException { + PreparedStatement stmt = null; + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + String sql = "UPDATE DM_ENROLMENT_OP_MAPPING SET PUSH_NOTIFICATION_STATUS = ? WHERE ENROLMENT_ID = ? and " + + "OPERATION_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, pushStatus.toString()); + stmt.setInt(2, deviceId); + stmt.setInt(3, operationId); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new OperationManagementDAOException("Error occurred while updating device operation mappings", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void updateOperationMapping(List operationMappingList, Operation.PushStatus pushStatus) throws + OperationManagementDAOException { + PreparedStatement stmt = null; + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + String sql = "UPDATE DM_ENROLMENT_OP_MAPPING SET PUSH_NOTIFICATION_STATUS = ? WHERE ENROLMENT_ID = ? and " + + "OPERATION_ID = ?"; + stmt = conn.prepareStatement(sql); + if (conn.getMetaData().supportsBatchUpdates()) { + for (OperationMapping operationMapping : operationMappingList) { + stmt.setString(1, pushStatus.toString()); + stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId())); + stmt.setInt(3, operationMapping.getOperationId()); + stmt.addBatch(); + } + stmt.executeBatch(); + } else { + for (OperationMapping operationMapping : operationMappingList) { + stmt.setString(1, pushStatus.toString()); + stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId())); + stmt.setInt(3, operationMapping.getOperationId()); + stmt.executeUpdate(); + } + } + } catch (SQLException e) { + throw new OperationManagementDAOException("Error occurred while updating device operation mappings as " + + "batch ", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, null); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java index 2591a267ba1..7a4f3a6af8b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java @@ -23,6 +23,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; @@ -37,6 +38,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; /** @@ -135,7 +137,7 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { @Override public void updateEnrollmentOperationsStatus(int enrolmentId, String operationCode, - Operation.Status existingStatus, Operation.Status newStatus) throws OperationManagementDAOException { + Operation.Status existingStatus, Operation.Status newStatus) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; try { @@ -361,4 +363,41 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { } return 0; } + + @Override + public List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException { + + PreparedStatement stmt = null; + ResultSet rs = null; + OperationMapping operationMapping; + List operationMappings = new LinkedList<>(); + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + String sql = "SELECT op_mappings.ENROLMENT_ID, op_mappings.OPERATION_ID, d_type.NAME ,d.TENANT_ID FROM " + + "DM_DEVICE d, DM_ENROLMENT_OP_MAPPING op_mappings, DM_DEVICE_TYPE d_type WHERE op_mappings" + + ".STATUS = '?' AND op_mappings.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = d_type.ID " + + "AND d.ID=op_mappings.ENROLMENT_ID AND ROWNUM <= ? ORDER BY op_mappings.OPERATION_ID"; + + stmt = conn.prepareStatement(sql); + stmt.setString(1, opStatus.toString()); + stmt.setString(2, pushStatus.toString()); + stmt.setInt(3, limit); + rs = stmt.executeQuery(); + + while (rs.next()) { + operationMapping = new OperationMapping(); + operationMapping.setOperationId(rs.getInt("OPERATION_ID")); + operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")), + rs.getString("NAME"))); + operationMapping.setTenantId(rs.getInt("TENANT_ID")); + operationMappings.add(operationMapping); + } + } catch (SQLException e) { + throw new OperationManagementDAOException("SQL error while getting operation mappings from database. ", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, rs); + } + return operationMappings; + } } \ 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/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java index b98ca93f7b8..b7a5f3cd6b0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java @@ -23,6 +23,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; @@ -37,6 +38,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; /** @@ -264,4 +266,42 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl { return activities; } + @Override + public List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException { + + PreparedStatement stmt = null; + ResultSet rs = null; + OperationMapping operationMapping; + List operationMappings = new LinkedList<>(); + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + String sql = "SELECT op_mappings.ENROLMENT_ID, op_mappings.OPERATION_ID, d_type.NAME ,d.TENANT_ID FROM " + + "DM_DEVICE d, DM_ENROLMENT_OP_MAPPING op_mappings, DM_DEVICE_TYPE d_type WHERE op_mappings" + + ".STATUS = '?' AND op_mappings.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = d_type.ID " + + "AND d.ID=op_mappings.ENROLMENT_ID ORDER BY op_mappings.OPERATION_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + + stmt = conn.prepareStatement(sql); + stmt.setString(1, opStatus.toString()); + stmt.setString(2, pushStatus.toString()); + stmt.setInt(3, 0); + stmt.setInt(4, limit); + rs = stmt.executeQuery(); + + while (rs.next()) { + operationMapping = new OperationMapping(); + operationMapping.setOperationId(rs.getInt("OPERATION_ID")); + operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")), + rs.getString("NAME"))); + operationMapping.setTenantId(rs.getInt("TENANT_ID")); + operationMappings.add(operationMapping); + } + } catch (SQLException e) { + throw new OperationManagementDAOException("SQL error while getting operation mappings from database. ", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, rs); + } + return operationMappings; + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index a48cb423c8d..91174685410 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -32,6 +32,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; 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.common.policy.mgt.PolicyMonitoringManager; +import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import java.util.Date; import java.util.HashMap; @@ -130,7 +131,8 @@ public interface DeviceManagementProviderService { /** * This method returns the list of device owned by a user of given device type. - * @param userName user name. + * + * @param userName user name. * @param deviceType device type name * @return * @throws DeviceManagementException @@ -210,13 +212,21 @@ public interface DeviceManagementProviderService { * This method is used to check whether the device is enrolled with the give user. * * @param deviceId identifier of the device that needs to be checked against the user. - * @param user username of the device owner. - * + * @param user username of the device owner. * @return true if the user owns the device else will return false. * @throws DeviceManagementException If some unusual behaviour is observed while fetching the device. */ boolean isEnrolled(DeviceIdentifier deviceId, String user) throws DeviceManagementException; + /** + * This method is used to get notification strategy for given device type + * + * @param deviceType Device type + * @return Notification Strategy for device type + * @throws DeviceManagementException + */ + NotificationStrategy getNotificationStrategyByDeviceType(String deviceType) throws DeviceManagementException; + License getLicense(String deviceType, String languageCode) throws DeviceManagementException; void addLicense(String deviceType, License license) throws DeviceManagementException; @@ -239,6 +249,7 @@ public interface DeviceManagementProviderService { /** * Returns the device of specified id. + * * @param deviceId device Id * @return Device returns null when device is not avaialble. * @throws DeviceManagementException diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index f89fe627c30..6672311c3d6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -23,7 +23,21 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.device.mgt.common.*; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.DeviceManager; +import org.wso2.carbon.device.mgt.common.DeviceNotFoundException; +import org.wso2.carbon.device.mgt.common.DeviceTypeIdentifier; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.FeatureManager; +import org.wso2.carbon.device.mgt.common.InitialOperationConfig; +import org.wso2.carbon.device.mgt.common.InvalidDeviceException; +import org.wso2.carbon.device.mgt.common.MonitoringOperation; +import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.TransactionManagementException; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; @@ -37,7 +51,9 @@ import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; 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.common.operation.mgt.OperationManager; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; +import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.DeviceManagementPluginRepository; @@ -307,7 +323,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return enrolmentInfos; } - @Override + @Override public boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException { DeviceManager deviceManager = this.getDeviceManager(deviceId.getType()); if (deviceManager == null) { @@ -649,7 +665,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv device.setDeviceInfo(info); } catch (DeviceDetailsMgtDAOException e) { log.error("Error occurred while retrieving advance info of '" + device.getType() + - "' that carries the id '" + device.getDeviceIdentifier() + "'"); + "' that carries the id '" + device.getDeviceIdentifier() + "'"); } catch (SQLException e) { log.error("Error occurred while opening a connection to the data source", e); } finally { @@ -663,7 +679,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv device.setApplications(applications); } catch (DeviceManagementDAOException e) { log.error("Error occurred while retrieving the application list of '" + device.getType() + "', " + - "which carries the id '" + device.getId() + "'", e); + "which carries the id '" + device.getId() + "'", e); } catch (SQLException e) { log.error("Error occurred while opening a connection to the data source", e); } finally { @@ -674,7 +690,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv if (deviceManager == null) { if (log.isDebugEnabled()) { log.debug("Device Manager associated with the device type '" + device.getType() + "' is null. " + - "Therefore, not attempting method 'isEnrolled'"); + "Therefore, not attempting method 'isEnrolled'"); } devices.add(device); continue; @@ -689,6 +705,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } return devices; } + @Override public List getAllDevices(String deviceType) throws DeviceManagementException { List devices = new ArrayList<>(); @@ -779,7 +796,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv try { EmailContext ctx = new EmailContext.EmailContextBuilder(new ContentProviderInfo(templateName, params), - metaInfo.getRecipients()).build(); + metaInfo.getRecipients()).build(); DeviceManagementDataHolder.getInstance().getEmailSenderService().sendEmail(ctx); } catch (EmailSendingFailedException ex) { throw new DeviceManagementException("Error occurred while sending enrollment invitation", ex); @@ -1958,6 +1975,17 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return false; } + @Override + public NotificationStrategy getNotificationStrategyByDeviceType(String deviceType) throws DeviceManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + OperationManager operationManager = pluginRepository.getOperationManager(deviceType, tenantId); + if (operationManager != null) { + return operationManager.getNotificationStrategy(); + } else { + throw new DeviceManagementException("Cannot find operation manager for given device type :" + deviceType); + } + } + /** * Change device status. * @@ -2007,7 +2035,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv throw new DeviceManagementException("Error occurred while opening a connection to the data source", e); } catch (DeviceManagementDAOException e) { throw new DeviceManagementException("Error occurred while updating the enrollment information device for" + - "id '" + deviceId + "' ." , e); + "id '" + deviceId + "' .", e); } finally { try { DeviceManagementDAOFactory.getConnection().setAutoCommit(isAutoCommit); @@ -2085,7 +2113,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv List deviceIdentifiers = new ArrayList<>(); deviceIdentifiers.add(deviceIdentifier); if (init != null) { - List initialOperations = init.getOperations(); + List initialOperations = init.getOperations(); for (String str : initialOperations) { CommandOperation operation = new CommandOperation(); From 76f8d963f7594cc1f5be0a976b311bf433d3df0f Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Thu, 27 Apr 2017 12:23:01 +0530 Subject: [PATCH 07/11] Improve push notifications for request with device list less than batch size --- .../operation/mgt/OperationManagerImpl.java | 17 +++++++++++++-- .../core}/operation/mgt/OperationMapping.java | 21 ++++++++++++++++++- .../core/operation/mgt/dao/OperationDAO.java | 2 +- .../mgt/dao/OperationMappingDAO.java | 4 ++-- .../mgt/dao/impl/GenericOperationDAOImpl.java | 2 +- .../mgt/dao/impl/OperationMappingDAOImpl.java | 8 +++---- .../operation/OracleOperationDAOImpl.java | 2 +- .../operation/SQLServerOperationDAOImpl.java | 2 +- .../mgt/task/PushNotificationJob.java | 5 +++-- 9 files changed, 48 insertions(+), 15 deletions(-) rename components/device-mgt/{org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common => org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core}/operation/mgt/OperationMapping.java (72%) 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 aeb44e559f1..aaf77bf2d83 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 @@ -40,6 +40,7 @@ import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; @@ -146,7 +147,12 @@ public class OperationManagerImpl implements OperationManager { boolean isScheduledOperation = this.isTaskScheduledOperation(operation, deviceIds); boolean isNotRepeated = false; boolean isScheduled = false; - if (notificationStrategy != null) { + + // check whether device list is greater than batch size notification strategy has enable to send push + // notification using scheduler task + if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig(). + getPushNotificationConfiguration().getSchedulerBatchSize() < authorizedDeviceList.size() && + notificationStrategy != null) { isScheduled = notificationStrategy.getConfig().isScheduled(); } @@ -178,8 +184,15 @@ public class OperationManagerImpl implements OperationManager { } else { operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); } - if (notificationStrategy != null && !notificationStrategy.getConfig().isScheduled()) { + /* + If notification strategy has not enable to send push notification using scheduler task + we will send notification immediately + */ + if (notificationStrategy != null && !isScheduled) { try { + if (log.isDebugEnabled()) { + log.debug("Sending push notification to " + deviceId + " add operation thread."); + } notificationStrategy.execute(new NotificationContext(deviceId, operation)); operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon .device.mgt.core.dto.operation.mgt.Operation.PushStatus.COMPLETED); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java similarity index 72% rename from components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java index f9feed6d8d6..6775ebd92a8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationMapping.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java @@ -15,9 +15,10 @@ * specific language governing permissions and limitations * under the License. */ -package org.wso2.carbon.device.mgt.common.operation.mgt; +package org.wso2.carbon.device.mgt.core.operation.mgt; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; /** * Class for represent operation mapping @@ -27,6 +28,8 @@ public class OperationMapping { private DeviceIdentifier deviceIdentifier; private int operationId; private int tenantId; + private Operation.Status status; + private Operation.PushStatus pushStatus; public int getOperationId() { return operationId; @@ -51,4 +54,20 @@ public class OperationMapping { public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) { this.deviceIdentifier = deviceIdentifier; } + + public Operation.Status getStatus() { + return status; + } + + public void setStatus(Operation.Status status) { + this.status = status; + } + + public Operation.PushStatus getPushStatus() { + return pushStatus; + } + + public void setPushStatus(Operation.PushStatus pushStatus) { + this.pushStatus = pushStatus; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java index 63100f702cd..d22684f6a39 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -20,7 +20,7 @@ package org.wso2.carbon.device.mgt.core.operation.mgt.dao; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java index 0a2c45841df..003aad11f57 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java @@ -18,7 +18,7 @@ */ package org.wso2.carbon.device.mgt.core.operation.mgt.dao; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import java.util.List; @@ -31,7 +31,7 @@ public interface OperationMappingDAO { void updateOperationMapping(int operationId, Integer deviceId, Operation.PushStatus pushStatus) throws OperationManagementDAOException; - void updateOperationMapping(List operationMappingList, Operation.PushStatus pushStatus) throws + void updateOperationMapping(List operationMappingList) throws OperationManagementDAOException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index a16aa42d5fd..1e145c14f49 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -24,7 +24,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java index 473f1d76b39..f9b8b5e8a8c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java @@ -18,8 +18,8 @@ */ package org.wso2.carbon.device.mgt.core.operation.mgt.dao.impl; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil; @@ -98,7 +98,7 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { } @Override - public void updateOperationMapping(List operationMappingList, Operation.PushStatus pushStatus) throws + public void updateOperationMapping(List operationMappingList) throws OperationManagementDAOException { PreparedStatement stmt = null; try { @@ -108,7 +108,7 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { stmt = conn.prepareStatement(sql); if (conn.getMetaData().supportsBatchUpdates()) { for (OperationMapping operationMapping : operationMappingList) { - stmt.setString(1, pushStatus.toString()); + stmt.setString(1, operationMapping.getPushStatus().toString()); stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId())); stmt.setInt(3, operationMapping.getOperationId()); stmt.addBatch(); @@ -116,7 +116,7 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { stmt.executeBatch(); } else { for (OperationMapping operationMapping : operationMappingList) { - stmt.setString(1, pushStatus.toString()); + stmt.setString(1, operationMapping.getPushStatus().toString()); stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId())); stmt.setInt(3, operationMapping.getOperationId()); stmt.executeUpdate(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java index 7a4f3a6af8b..c78afd44a8d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java @@ -23,7 +23,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java index b7a5f3cd6b0..c553fee8d75 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java @@ -23,7 +23,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java index f9dc91d9dd0..c34ce466632 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java @@ -23,7 +23,7 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.TransactionManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; @@ -84,6 +84,7 @@ public class PushNotificationJob implements Runnable { notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(), provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping .getOperationId()))); + operationMapping.setPushStatus(Operation.PushStatus.COMPLETED); operationsCompletedList.add(operationMapping); } catch (DeviceManagementException e) { log.error("Error occurred while getting notification strategy for operation mapping " + @@ -109,7 +110,7 @@ public class PushNotificationJob implements Runnable { // Update push notification status to competed for operations which already sent try { OperationManagementDAOFactory.beginTransaction(); - operationMappingDAO.updateOperationMapping(operationsCompletedList, Operation.PushStatus.COMPLETED); + operationMappingDAO.updateOperationMapping(operationsCompletedList); OperationManagementDAOFactory.commitTransaction(); } catch (TransactionManagementException | OperationManagementDAOException e) { OperationManagementDAOFactory.rollbackTransaction(); From a5759f9818bbd152223e10ec4d9e48dbe7822136 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Sun, 30 Apr 2017 13:56:06 +0530 Subject: [PATCH 08/11] Add tenant based operation mappings --- .../mgt/task/PushNotificationJob.java | 123 ------------------ .../task/PushNotificationSchedulerTask.java | 108 ++++++++++++--- 2 files changed, 90 insertions(+), 141 deletions(-) delete mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java deleted file mode 100644 index c34ce466632..00000000000 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationJob.java +++ /dev/null @@ -1,123 +0,0 @@ -/* -* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -* -* WSO2 Inc. licenses this file to you under the Apache License, -* Version 2.0 (the "License"); you may not use this file except -* in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -*/ -package org.wso2.carbon.device.mgt.core.push.notification.mgt.task; - -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.DeviceManagementException; -import org.wso2.carbon.device.mgt.common.TransactionManagementException; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; -import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; -import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; -import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; -import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; -import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; -import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; -import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; -import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO; -import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; -import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; -import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO; -import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; -import org.wso2.carbon.user.api.UserStoreException; -import org.wso2.carbon.user.core.tenant.TenantManager; - -import java.util.LinkedList; -import java.util.List; - -/** - * ${{@link PushNotificationJob}} is for sending push notifications for given device batch. - */ -public class PushNotificationJob implements Runnable { - - private static Log log = LogFactory.getLog(PushNotificationJob.class); - private final OperationDAO operationDAO = OperationManagementDAOFactory.getOperationDAO(); - private final OperationMappingDAO operationMappingDAO = OperationManagementDAOFactory.getOperationMappingDAO(); - private final DeviceManagementProviderService provider = DeviceManagementDataHolder.getInstance() - .getDeviceManagementProvider(); - private final TenantManager tenantManager = DeviceManagementDataHolder.getInstance().getRealmService() - .getTenantManager(); - - @Override - public void run() { - List operationsCompletedList = new LinkedList<>(); - try { - if (log.isDebugEnabled()) { - log.debug("Push notification job started"); - } - //Get next available operation list per device batch - List operationMappings = operationDAO.getOperationMappingsByStatus(Operation.Status - .PENDING, Operation.PushStatus.SCHEDULED, DeviceConfigurationManager.getInstance() - .getDeviceManagementConfig().getPushNotificationConfiguration().getSchedulerBatchSize()); - // Sending push notification to each device - for (OperationMapping operationMapping : operationMappings) { - try { - if (log.isDebugEnabled()) { - log.debug("Sending push notification for operationId :" + operationMapping.getOperationId() + - "to deviceId : " + operationMapping.getDeviceIdentifier().getId()); - } - // Set tenant id and domain - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(operationMapping.getTenantId()); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantManager.getDomain - (operationMapping.getTenantId())); - // Get notification strategy for given device type - NotificationStrategy notificationStrategy = provider.getNotificationStrategyByDeviceType - (operationMapping.getDeviceIdentifier().getType()); - // Send the push notification on given strategy - notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(), - provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping - .getOperationId()))); - operationMapping.setPushStatus(Operation.PushStatus.COMPLETED); - operationsCompletedList.add(operationMapping); - } catch (DeviceManagementException e) { - log.error("Error occurred while getting notification strategy for operation mapping " + - operationMapping.getDeviceIdentifier().getType(), e); - } catch (OperationManagementException e) { - log.error("Unable to get the operation for operation " + operationMapping.getOperationId(), e); - } catch (PushNotificationExecutionFailedException e) { - log.error("Error occurred while sending push notification to operation: " + operationMapping - .getOperationId(), e); - } catch (UserStoreException e) { - log.error("Tenant domain cannot be found for given tenant id: " + operationMapping.getTenantId() - , e); - } finally { - PrivilegedCarbonContext.endTenantFlow(); - } - } - if (log.isDebugEnabled()) { - log.debug("Push notification job running completed."); - } - } catch (OperationManagementDAOException e) { - log.error("Unable to retrieve scheduled pending operations for task. ", e); - } finally { - // Update push notification status to competed for operations which already sent - try { - OperationManagementDAOFactory.beginTransaction(); - operationMappingDAO.updateOperationMapping(operationsCompletedList); - OperationManagementDAOFactory.commitTransaction(); - } catch (TransactionManagementException | OperationManagementDAOException e) { - OperationManagementDAOFactory.rollbackTransaction(); - log.error("Error occurred while updating operation mappings for sent notifications ", e); - } finally { - OperationManagementDAOFactory.closeConnection(); - } - } - } -} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java index 97aaf4c4fda..a87ff4868c7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java @@ -19,37 +19,109 @@ package org.wso2.carbon.device.mgt.core.push.notification.mgt.task; 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.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; +import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; +import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; +import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; /** - * ${{@link PushNotificationSchedulerTask}} for scheduling push notification job. + * ${{@link PushNotificationSchedulerTask}} is for sending push notifications for given device batch. */ public class PushNotificationSchedulerTask implements Runnable { private static Log log = LogFactory.getLog(PushNotificationSchedulerTask.class); - private final ExecutorService executor = Executors.newSingleThreadExecutor(); - private Future lastExecution; - final PushNotificationJob pushNotificationJob = new PushNotificationJob(); + private final OperationDAO operationDAO = OperationManagementDAOFactory.getOperationDAO(); + private final OperationMappingDAO operationMappingDAO = OperationManagementDAOFactory.getOperationMappingDAO(); + private final DeviceManagementProviderService provider = DeviceManagementDataHolder.getInstance() + .getDeviceManagementProvider(); @Override public void run() { - /* - There will be only one push notification job submit to thread pool. - Scheduler will submit new job only if last execution is completed. - */ - if (lastExecution != null && !lastExecution.isDone()) { - if (log.isDebugEnabled()) { - log.debug("Previous push notification job is already running. New notification job will start " + - "after existing job completed."); + Map> operationMappingsTenantMap = new HashMap<>(); + List operationsCompletedList = new LinkedList<>(); + if (log.isDebugEnabled()) { + log.debug("Push notification job started"); + } + try { + //Get next available operation list per device batch + DeviceManagementDAOFactory.openConnection(); + operationMappingsTenantMap = operationDAO.getOperationMappingsByStatus(Operation.Status + .PENDING, Operation.PushStatus.SCHEDULED, DeviceConfigurationManager.getInstance() + .getDeviceManagementConfig().getPushNotificationConfiguration().getSchedulerBatchSize()); + } catch (SQLException e) { + log.error("Error occurred while opening a connection to the data source", e); + } catch (OperationManagementDAOException e) { + log.error("Unable to retrieve scheduled pending operations for task.", e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + // Sending push notification to each device + for (List operationMappings : operationMappingsTenantMap.values()) { + for (OperationMapping operationMapping : operationMappings) { + try { + if (log.isDebugEnabled()) { + log.debug("Sending push notification for operationId :" + operationMapping.getOperationId() + + "to deviceId : " + operationMapping.getDeviceIdentifier().getId()); + } + // Set tenant id and domain + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(operationMapping.getTenantId(), true); + // Get notification strategy for given device type + NotificationStrategy notificationStrategy = provider.getNotificationStrategyByDeviceType + (operationMapping.getDeviceIdentifier().getType()); + // Send the push notification on given strategy + notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(), + provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping + .getOperationId()))); + operationMapping.setPushStatus(Operation.PushStatus.COMPLETED); + operationsCompletedList.add(operationMapping); + } catch (DeviceManagementException e) { + log.error("Error occurred while getting notification strategy for operation mapping " + + operationMapping.getDeviceIdentifier().getType(), e); + } catch (OperationManagementException e) { + log.error("Unable to get the operation for operation " + operationMapping.getOperationId(), e); + } catch (PushNotificationExecutionFailedException e) { + log.error("Error occurred while sending push notification to operation: " + operationMapping + .getOperationId(), e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + } + // Update push notification status to competed for operations which already sent + if (operationsCompletedList.size() > 0) { + try { + OperationManagementDAOFactory.beginTransaction(); + operationMappingDAO.updateOperationMapping(operationsCompletedList); + OperationManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException | OperationManagementDAOException e) { + OperationManagementDAOFactory.rollbackTransaction(); + log.error("Error occurred while updating operation mappings for sent notifications ", e); + } finally { + OperationManagementDAOFactory.closeConnection(); } - return; } if (log.isDebugEnabled()) { - log.debug("Submitting new notification job."); + log.debug("Push notification job running completed."); } - lastExecution = executor.submit(pushNotificationJob); } } From 3938064210e3d96b62ba74252ad1753288da2e5a Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Sun, 30 Apr 2017 14:29:30 +0530 Subject: [PATCH 09/11] Add opeerations mapping map for tenants and fixes for code review --- .../notification/PushNotificationConfig.java | 1 + .../mgt/core/dto/operation/mgt/Operation.java | 2 +- .../DeviceManagementServiceComponent.java | 4 +-- .../operation/mgt/OperationManagerImpl.java | 4 +-- .../core/operation/mgt/dao/OperationDAO.java | 13 +++++-- .../mgt/dao/impl/GenericOperationDAOImpl.java | 31 +++++++++------- .../mgt/dao/impl/OperationMappingDAOImpl.java | 2 +- .../operation/OracleOperationDAOImpl.java | 31 +++++++++------- .../operation/SQLServerOperationDAOImpl.java | 35 ++++++++++--------- 9 files changed, 73 insertions(+), 50 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java index 882df04a645..6b9e9f9f3e4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/push/notification/PushNotificationConfig.java @@ -40,6 +40,7 @@ public class PushNotificationConfig { return type; } + @XmlElement(name = "isScheduled") public boolean isScheduled() { return isScheduled; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java index 2263ccdf7bf..c3acb18076e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java @@ -36,7 +36,7 @@ public class Operation implements Serializable { } public enum PushStatus { - SCHEDULED, IN_PROGRESS, COMPLETED + SCHEDULED, COMPLETED } private String code; 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 b63aa0d2a17..deec497e120 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 @@ -63,9 +63,7 @@ import org.wso2.carbon.utils.ConfigurationContextService; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -200,7 +198,7 @@ public class DeviceManagementServiceComponent { config.getPushNotificationConfiguration().setSchedulerBatchDelayMills(DeviceManagementConstants.PushNotifications .DEFAULT_BATCH_DELAY_MILLS); } - ScheduledExecutorService pushNotificationExecutor = Executors.newScheduledThreadPool(1); + ScheduledExecutorService pushNotificationExecutor = Executors.newSingleThreadScheduledExecutor(); pushNotificationExecutor.schedule(new PushNotificationSchedulerTask(), config.getPushNotificationConfiguration() .getSchedulerBatchDelayMills(), TimeUnit.MILLISECONDS); } 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 aaf77bf2d83..362bf0722e9 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 @@ -131,7 +131,7 @@ public class OperationManagerImpl implements OperationManager { DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds); List authorizedDeviceList = deviceAuthorizationResult.getValidDeviceIDList(); if (authorizedDeviceList.size() <= 0) { - log.info("User : " + getUser() + " is not authorized to perform operations on given device-list."); + log.warn("User : " + getUser() + " is not authorized to perform operations on given device-list."); Activity activity = new Activity(); //Send the operation statuses only for admin triggered operations String deviceType = validDeviceIds.get(0).getType(); @@ -191,7 +191,7 @@ public class OperationManagerImpl implements OperationManager { if (notificationStrategy != null && !isScheduled) { try { if (log.isDebugEnabled()) { - log.debug("Sending push notification to " + deviceId + " add operation thread."); + log.debug("Sending push notification to " + deviceId + " from add operation method."); } notificationStrategy.execute(new NotificationContext(deviceId, operation)); operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java index d22684f6a39..79da36c052d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -25,6 +25,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import java.util.List; +import java.util.Map; public interface OperationDAO { @@ -81,7 +82,15 @@ public interface OperationDAO { boolean resetAttemptCount(int enrolmentId) throws OperationManagementDAOException; - List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, - int limit) throws OperationManagementDAOException;; + /** + * This method provides operation mappings for given status + * @param opStatus Operation status + * @param pushStatus Push notification Status + * @param limit Limit for no devices + * @return Tenant based operation mappings list + * @throws OperationManagementDAOException + */ + Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException;; } \ 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/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index 1e145c14f49..f29c3ed05da 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -24,9 +24,9 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; -import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; @@ -46,8 +46,10 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * This class holds the generic implementation of OperationDAO which can be used to support ANSI db syntax. @@ -1093,32 +1095,35 @@ public class GenericOperationDAOImpl implements OperationDAO { } @Override - public List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, - int limit) throws OperationManagementDAOException { - + public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; OperationMapping operationMapping; - List operationMappings = new LinkedList<>(); + Map> operationMappingsTenantMap = new HashMap<>(); try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT op_mappings.ENROLMENT_ID, op_mappings.OPERATION_ID, d_type.NAME ,d.TENANT_ID FROM " + - "DM_DEVICE d, DM_ENROLMENT_OP_MAPPING op_mappings, DM_DEVICE_TYPE d_type WHERE op_mappings" + - ".STATUS = '?' AND op_mappings.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = d_type.ID " + - "AND d.ID=op_mappings.ENROLMENT_ID ORDER BY op_mappings.OPERATION_ID LIMIT ?"; - + String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " + + "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = '?' AND " + + "op.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID ORDER BY " + + "op.OPERATION_ID LIMIT ?"; stmt = conn.prepareStatement(sql); stmt.setString(1, opStatus.toString()); stmt.setString(2, pushStatus.toString()); stmt.setInt(3, limit); rs = stmt.executeQuery(); - while (rs.next()) { + int tenantID = rs.getInt("TENANT_ID"); + List operationMappings = operationMappingsTenantMap.get(tenantID); + if (operationMappings == null) { + operationMappings = new LinkedList<>(); + operationMappingsTenantMap.put(tenantID, operationMappings); + } operationMapping = new OperationMapping(); operationMapping.setOperationId(rs.getInt("OPERATION_ID")); operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")), rs.getString("NAME"))); - operationMapping.setTenantId(rs.getInt("TENANT_ID")); + operationMapping.setTenantId(tenantID); operationMappings.add(operationMapping); } } catch (SQLException e) { @@ -1126,6 +1131,6 @@ public class GenericOperationDAOImpl implements OperationDAO { } finally { OperationManagementDAOUtil.cleanupResources(stmt, rs); } - return operationMappings; + return operationMappingsTenantMap; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java index f9b8b5e8a8c..867353aa8d4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java @@ -48,7 +48,7 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { if (isScheduled) { stmt.setString(4, Operation.PushStatus.SCHEDULED.toString()); } else { - stmt.setString(4, Operation.PushStatus.IN_PROGRESS.toString()); + stmt.setString(4, Operation.PushStatus.COMPLETED.toString()); } stmt.setLong(5, time); stmt.setLong(6, time); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java index c78afd44a8d..19f604fa03d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java @@ -23,9 +23,9 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; -import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil; @@ -38,8 +38,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * This class holds the implementation of OperationDAO which can be used to support Oracle db syntax. @@ -364,33 +366,38 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { return 0; } - @Override - public List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, - int limit) throws OperationManagementDAOException { + @Override + public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; OperationMapping operationMapping; - List operationMappings = new LinkedList<>(); + Map> operationMappingsTenantMap = new HashMap<>(); try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT op_mappings.ENROLMENT_ID, op_mappings.OPERATION_ID, d_type.NAME ,d.TENANT_ID FROM " + - "DM_DEVICE d, DM_ENROLMENT_OP_MAPPING op_mappings, DM_DEVICE_TYPE d_type WHERE op_mappings" + - ".STATUS = '?' AND op_mappings.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = d_type.ID " + - "AND d.ID=op_mappings.ENROLMENT_ID AND ROWNUM <= ? ORDER BY op_mappings.OPERATION_ID"; + String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " + + "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = '?' AND op" + + ".PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID AND ROWNUM" + + " <= ? ORDER BY op.OPERATION_ID"; stmt = conn.prepareStatement(sql); stmt.setString(1, opStatus.toString()); stmt.setString(2, pushStatus.toString()); stmt.setInt(3, limit); rs = stmt.executeQuery(); - while (rs.next()) { + int tenantID = rs.getInt("TENANT_ID"); + List operationMappings = operationMappingsTenantMap.get(tenantID); + if (operationMappings == null) { + operationMappings = new LinkedList<>(); + operationMappingsTenantMap.put(tenantID, operationMappings); + } operationMapping = new OperationMapping(); operationMapping.setOperationId(rs.getInt("OPERATION_ID")); operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")), rs.getString("NAME"))); - operationMapping.setTenantId(rs.getInt("TENANT_ID")); + operationMapping.setTenantId(tenantID); operationMappings.add(operationMapping); } } catch (SQLException e) { @@ -398,6 +405,6 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { } finally { OperationManagementDAOUtil.cleanupResources(stmt, rs); } - return operationMappings; + return operationMappingsTenantMap; } } \ 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/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java index c553fee8d75..6a69c5d4af1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java @@ -23,9 +23,9 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; -import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil; @@ -38,8 +38,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * This class holds the implementation of OperationDAO which can be used to support SQLServer db syntax. @@ -267,33 +269,35 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl { } @Override - public List getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, - int limit) throws OperationManagementDAOException { - + public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + int limit) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; OperationMapping operationMapping; - List operationMappings = new LinkedList<>(); + Map> operationMappingsTenantMap = new HashMap<>(); try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT op_mappings.ENROLMENT_ID, op_mappings.OPERATION_ID, d_type.NAME ,d.TENANT_ID FROM " + - "DM_DEVICE d, DM_ENROLMENT_OP_MAPPING op_mappings, DM_DEVICE_TYPE d_type WHERE op_mappings" + - ".STATUS = '?' AND op_mappings.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = d_type.ID " + - "AND d.ID=op_mappings.ENROLMENT_ID ORDER BY op_mappings.OPERATION_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; - + String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " + + "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = '?' AND op" + + ".PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = dt.ID " + + "AND d.ID=op.ENROLMENT_ID ORDER BY op.OPERATION_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; stmt = conn.prepareStatement(sql); stmt.setString(1, opStatus.toString()); stmt.setString(2, pushStatus.toString()); - stmt.setInt(3, 0); - stmt.setInt(4, limit); + stmt.setInt(3, limit); rs = stmt.executeQuery(); - while (rs.next()) { + int tenantID = rs.getInt("TENANT_ID"); + List operationMappings = operationMappingsTenantMap.get(tenantID); + if (operationMappings == null) { + operationMappings = new LinkedList<>(); + operationMappingsTenantMap.put(tenantID, operationMappings); + } operationMapping = new OperationMapping(); operationMapping.setOperationId(rs.getInt("OPERATION_ID")); operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")), rs.getString("NAME"))); - operationMapping.setTenantId(rs.getInt("TENANT_ID")); + operationMapping.setTenantId(tenantID); operationMappings.add(operationMapping); } } catch (SQLException e) { @@ -301,7 +305,6 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl { } finally { OperationManagementDAOUtil.cleanupResources(stmt, rs); } - return operationMappings; + return operationMappingsTenantMap; } - } From 1470abeb0bfd571f4fde58865306894979e21529 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Mon, 1 May 2017 20:43:32 +0530 Subject: [PATCH 10/11] Add initial thread delay config for cdm-config.xml --- .../src/main/resources/conf/cdm-config.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml index 7e165de6cea..99d5473b46b 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml @@ -26,8 +26,9 @@ - 1 - 1000 + 1000 + 60000 + 60000 true org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.FCMBasedPushNotificationProvider From e1e2b14b5f2a328e0fdf20c6ff03b218eeba8c2c Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Mon, 1 May 2017 20:44:30 +0530 Subject: [PATCH 11/11] Rename push status to push notification status and add configurable initial delay for scheduler task --- .../operation/mgt/OperationManager.java | 1 + .../mgt/core/DeviceManagementConstants.java | 1 + .../PushNotificationConfiguration.java | 33 +++-- .../mgt/core/dto/operation/mgt/Operation.java | 2 +- .../DeviceManagementServiceComponent.java | 30 +++-- .../operation/mgt/OperationManagerImpl.java | 6 +- .../core/operation/mgt/OperationMapping.java | 10 +- .../core/operation/mgt/dao/OperationDAO.java | 6 +- .../mgt/dao/OperationMappingDAO.java | 2 +- .../mgt/dao/impl/GenericOperationDAOImpl.java | 11 +- .../mgt/dao/impl/OperationMappingDAOImpl.java | 12 +- .../operation/OracleOperationDAOImpl.java | 8 +- .../operation/SQLServerOperationDAOImpl.java | 8 +- .../task/PushNotificationSchedulerTask.java | 124 +++++++++--------- 14 files changed, 139 insertions(+), 115 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java index 8c8818f736d..ce548628b9a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java @@ -21,6 +21,7 @@ import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import java.util.List; +import java.util.Map; /** * This represents the Device Operation management functionality which should be implemented by 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 7e5e1843585..15df1e44356 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 @@ -90,6 +90,7 @@ public final class DeviceManagementConstants { private PushNotifications() { throw new AssertionError(); } + public static final int DEFAULT_SCHEDULER_TASK_INITIAL_DELAY = 60000; public static final int DEFAULT_BATCH_DELAY_MILLS = 60000; public static final int DEFAULT_BATCH_SIZE = 1000; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java index 6872affcf82..58ec787668f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/push/notification/PushNotificationConfiguration.java @@ -28,35 +28,46 @@ import java.util.List; @XmlRootElement(name = "PushNotificationConfiguration") public class PushNotificationConfiguration { - private int SchedulerBatchSize; - private int SchedulerBatchDelayMills; - private boolean SchedulerTaskEnabled; + private int schedulerBatchSize; + private int schedulerBatchDelayMills; + private int schedulerTaskInitialDelay; + private boolean schedulerTaskEnabled; private List pushNotificationProviders; @XmlElement(name = "SchedulerBatchSize", required = true) public int getSchedulerBatchSize() { - return SchedulerBatchSize; + return schedulerBatchSize; } - public void setSchedulerBatchSize(int SchedulerBatchSize) { - this.SchedulerBatchSize = SchedulerBatchSize; + public void setSchedulerBatchSize(int schedulerBatchSize) { + this.schedulerBatchSize = schedulerBatchSize; } @XmlElement(name = "SchedulerBatchDelayMills", required = true) public int getSchedulerBatchDelayMills() { - return SchedulerBatchDelayMills; + return schedulerBatchDelayMills; } - public void setSchedulerBatchDelayMills(int SchedulerBatchDelayMills) { - this.SchedulerBatchDelayMills = SchedulerBatchDelayMills; + public void setSchedulerBatchDelayMills(int schedulerBatchDelayMills) { + this.schedulerBatchDelayMills = schedulerBatchDelayMills; } + + @XmlElement(name = "SchedulerTaskInitialDelay", required = true) + public int getSchedulerTaskInitialDelay() { + return schedulerTaskInitialDelay; + } + + public void setSchedulerTaskInitialDelay(int schedulerTaskInitialDelay) { + this.schedulerTaskInitialDelay = schedulerTaskInitialDelay; + } + @XmlElement(name = "SchedulerTaskEnabled", required = true) public boolean isSchedulerTaskEnabled() { - return SchedulerTaskEnabled; + return schedulerTaskEnabled; } public void setSchedulerTaskEnabled(boolean schedulerTaskEnabled) { - SchedulerTaskEnabled = schedulerTaskEnabled; + this.schedulerTaskEnabled = schedulerTaskEnabled; } @XmlElementWrapper(name = "PushNotificationProviders", required = true) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java index c3acb18076e..3b5322bbf76 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dto/operation/mgt/Operation.java @@ -35,7 +35,7 @@ public class Operation implements Serializable { REPEAT, NO_REPEAT, PAUSE_SEQUENCE, STOP_SEQUENCE } - public enum PushStatus { + public enum PushNotificationStatus { SCHEDULED, COMPLETED } 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 deec497e120..0c1a62471d3 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 @@ -182,25 +182,37 @@ public class DeviceManagementServiceComponent { * of Device Management Service component in order to avoid bundle start up order related complications */ notifyStartupListeners(); if (log.isDebugEnabled()) { - log.debug("Device management core bundle has been successfully initialized"); + log.debug("Push notification batch enabled : " + config.getPushNotificationConfiguration() + .isSchedulerTaskEnabled()); } // Start Push Notification Scheduler Task if (config.getPushNotificationConfiguration().isSchedulerTaskEnabled()) { if (config.getPushNotificationConfiguration().getSchedulerBatchSize() <= 0) { - log.error("Push notification batch size cannot be 0 or less than 0. Setting default batch size to:" + - " " + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_SIZE); - config.getPushNotificationConfiguration().setSchedulerBatchSize(DeviceManagementConstants.PushNotifications - .DEFAULT_BATCH_SIZE); + log.error("Push notification batch size cannot be 0 or less than 0. Setting default batch size " + + "to:" + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_SIZE); + config.getPushNotificationConfiguration().setSchedulerBatchSize(DeviceManagementConstants + .PushNotifications.DEFAULT_BATCH_SIZE); } if (config.getPushNotificationConfiguration().getSchedulerBatchDelayMills() <= 0) { log.error("Push notification batch delay cannot be 0 or less than 0. Setting default batch delay " + "milliseconds to" + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_DELAY_MILLS); - config.getPushNotificationConfiguration().setSchedulerBatchDelayMills(DeviceManagementConstants.PushNotifications - .DEFAULT_BATCH_DELAY_MILLS); + config.getPushNotificationConfiguration().setSchedulerBatchDelayMills(DeviceManagementConstants + .PushNotifications.DEFAULT_BATCH_DELAY_MILLS); + } + if (config.getPushNotificationConfiguration().getSchedulerTaskInitialDelay() < 0) { + log.error("Push notification initial delay cannot be less than 0. Setting default initial " + + "delay milliseconds to" + DeviceManagementConstants.PushNotifications + .DEFAULT_SCHEDULER_TASK_INITIAL_DELAY); + config.getPushNotificationConfiguration().setSchedulerTaskInitialDelay(DeviceManagementConstants + .PushNotifications.DEFAULT_SCHEDULER_TASK_INITIAL_DELAY); } ScheduledExecutorService pushNotificationExecutor = Executors.newSingleThreadScheduledExecutor(); - pushNotificationExecutor.schedule(new PushNotificationSchedulerTask(), config.getPushNotificationConfiguration() - .getSchedulerBatchDelayMills(), TimeUnit.MILLISECONDS); + pushNotificationExecutor.scheduleWithFixedDelay(new PushNotificationSchedulerTask(), config + .getPushNotificationConfiguration().getSchedulerTaskInitialDelay(), config + .getPushNotificationConfiguration().getSchedulerBatchDelayMills(), TimeUnit.MILLISECONDS); + } + if (log.isDebugEnabled()) { + log.debug("Device management core bundle has been successfully initialized"); } } catch (Throwable e) { log.error("Error occurred while initializing device management core bundle", e); 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 362bf0722e9..41530bfb489 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 @@ -194,15 +194,13 @@ public class OperationManagerImpl implements OperationManager { log.debug("Sending push notification to " + deviceId + " from add operation method."); } notificationStrategy.execute(new NotificationContext(deviceId, operation)); - operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon - .device.mgt.core.dto.operation.mgt.Operation.PushStatus.COMPLETED); + operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.COMPLETED); } catch (PushNotificationExecutionFailedException e) { log.error("Error occurred while sending push notifications to " + deviceId.getType() + " device carrying id '" + deviceId + "'", e); // Reschedule if push notification failed. - operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon - .device.mgt.core.dto.operation.mgt.Operation.PushStatus.SCHEDULED); + operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED); } } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java index 6775ebd92a8..6f42a78d15c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationMapping.java @@ -29,7 +29,7 @@ public class OperationMapping { private int operationId; private int tenantId; private Operation.Status status; - private Operation.PushStatus pushStatus; + private Operation.PushNotificationStatus pushNotificationStatus; public int getOperationId() { return operationId; @@ -63,11 +63,11 @@ public class OperationMapping { this.status = status; } - public Operation.PushStatus getPushStatus() { - return pushStatus; + public Operation.PushNotificationStatus getPushNotificationStatus() { + return pushNotificationStatus; } - public void setPushStatus(Operation.PushStatus pushStatus) { - this.pushStatus = pushStatus; + public void setPushNotificationStatus(Operation.PushNotificationStatus pushNotificationStatus) { + this.pushNotificationStatus = pushNotificationStatus; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java index 79da36c052d..5e3848cf9b7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -85,12 +85,12 @@ public interface OperationDAO { /** * This method provides operation mappings for given status * @param opStatus Operation status - * @param pushStatus Push notification Status + * @param pushNotificationStatus Push notification Status * @param limit Limit for no devices * @return Tenant based operation mappings list * @throws OperationManagementDAOException */ - Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, - int limit) throws OperationManagementDAOException;; + Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus, + int limit) throws OperationManagementDAOException; } \ 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/operation/mgt/dao/OperationMappingDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java index 003aad11f57..72d02ec9bc6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationMappingDAO.java @@ -29,7 +29,7 @@ public interface OperationMappingDAO { void removeOperationMapping(int operationId, Integer deviceId) throws OperationManagementDAOException; - void updateOperationMapping(int operationId, Integer deviceId, Operation.PushStatus pushStatus) throws + void updateOperationMapping(int operationId, Integer deviceId, Operation.PushNotificationStatus pushNotificationStatus) throws OperationManagementDAOException; void updateOperationMapping(List operationMappingList) throws OperationManagementDAOException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index f29c3ed05da..3e50f498006 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -1095,21 +1095,22 @@ public class GenericOperationDAOImpl implements OperationDAO { } @Override - public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus, int limit) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; + Connection conn; OperationMapping operationMapping; Map> operationMappingsTenantMap = new HashMap<>(); try { - Connection conn = OperationManagementDAOFactory.getConnection(); + conn = OperationManagementDAOFactory.getConnection(); String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " + - "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = '?' AND " + - "op.PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID ORDER BY " + + "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = ? AND " + + "op.PUSH_NOTIFICATION_STATUS = ? AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID ORDER BY " + "op.OPERATION_ID LIMIT ?"; stmt = conn.prepareStatement(sql); stmt.setString(1, opStatus.toString()); - stmt.setString(2, pushStatus.toString()); + stmt.setString(2, pushNotificationStatus.toString()); stmt.setInt(3, limit); rs = stmt.executeQuery(); while (rs.next()) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java index 867353aa8d4..0846813fdfc 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/OperationMappingDAOImpl.java @@ -46,9 +46,9 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { stmt.setInt(2, operationId); stmt.setString(3, Operation.Status.PENDING.toString()); if (isScheduled) { - stmt.setString(4, Operation.PushStatus.SCHEDULED.toString()); + stmt.setString(4, Operation.PushNotificationStatus.SCHEDULED.toString()); } else { - stmt.setString(4, Operation.PushStatus.COMPLETED.toString()); + stmt.setString(4, Operation.PushNotificationStatus.COMPLETED.toString()); } stmt.setLong(5, time); stmt.setLong(6, time); @@ -79,14 +79,14 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { } @Override - public void updateOperationMapping(int operationId, Integer deviceId, Operation.PushStatus pushStatus) throws OperationManagementDAOException { + public void updateOperationMapping(int operationId, Integer deviceId, Operation.PushNotificationStatus pushNotificationStatus) throws OperationManagementDAOException { PreparedStatement stmt = null; try { Connection conn = OperationManagementDAOFactory.getConnection(); String sql = "UPDATE DM_ENROLMENT_OP_MAPPING SET PUSH_NOTIFICATION_STATUS = ? WHERE ENROLMENT_ID = ? and " + "OPERATION_ID = ?"; stmt = conn.prepareStatement(sql); - stmt.setString(1, pushStatus.toString()); + stmt.setString(1, pushNotificationStatus.toString()); stmt.setInt(2, deviceId); stmt.setInt(3, operationId); stmt.executeUpdate(); @@ -108,7 +108,7 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { stmt = conn.prepareStatement(sql); if (conn.getMetaData().supportsBatchUpdates()) { for (OperationMapping operationMapping : operationMappingList) { - stmt.setString(1, operationMapping.getPushStatus().toString()); + stmt.setString(1, operationMapping.getPushNotificationStatus().toString()); stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId())); stmt.setInt(3, operationMapping.getOperationId()); stmt.addBatch(); @@ -116,7 +116,7 @@ public class OperationMappingDAOImpl implements OperationMappingDAO { stmt.executeBatch(); } else { for (OperationMapping operationMapping : operationMappingList) { - stmt.setString(1, operationMapping.getPushStatus().toString()); + stmt.setString(1, operationMapping.getPushNotificationStatus().toString()); stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId())); stmt.setInt(3, operationMapping.getOperationId()); stmt.executeUpdate(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java index 19f604fa03d..321a13e46ce 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java @@ -368,7 +368,7 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { @Override - public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus, int limit) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; @@ -377,13 +377,13 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { try { Connection conn = OperationManagementDAOFactory.getConnection(); String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " + - "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = '?' AND op" + - ".PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID AND ROWNUM" + + "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = ? AND op" + + ".PUSH_NOTIFICATION_STATUS = ? AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID AND ROWNUM" + " <= ? ORDER BY op.OPERATION_ID"; stmt = conn.prepareStatement(sql); stmt.setString(1, opStatus.toString()); - stmt.setString(2, pushStatus.toString()); + stmt.setString(2, pushNotificationStatus.toString()); stmt.setInt(3, limit); rs = stmt.executeQuery(); while (rs.next()) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java index 6a69c5d4af1..d19a5b151bf 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java @@ -269,7 +269,7 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl { } @Override - public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushStatus pushStatus, + public Map> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus, int limit) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; @@ -278,12 +278,12 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl { try { Connection conn = OperationManagementDAOFactory.getConnection(); String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " + - "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = '?' AND op" + - ".PUSH_NOTIFICATION_STATUS = '?' AND d.DEVICE_TYPE_ID = dt.ID " + + "DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = ? AND op" + + ".PUSH_NOTIFICATION_STATUS = ? AND d.DEVICE_TYPE_ID = dt.ID " + "AND d.ID=op.ENROLMENT_ID ORDER BY op.OPERATION_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; stmt = conn.prepareStatement(sql); stmt.setString(1, opStatus.toString()); - stmt.setString(2, pushStatus.toString()); + stmt.setString(2, pushNotificationStatus.toString()); stmt.setInt(3, limit); rs = stmt.executeQuery(); while (rs.next()) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java index a87ff4868c7..3ac4126f308 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/task/PushNotificationSchedulerTask.java @@ -27,7 +27,6 @@ import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; -import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; @@ -37,7 +36,6 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOF import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; -import java.sql.SQLException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -56,72 +54,74 @@ public class PushNotificationSchedulerTask implements Runnable { @Override public void run() { - Map> operationMappingsTenantMap = new HashMap<>(); - List operationsCompletedList = new LinkedList<>(); - if (log.isDebugEnabled()) { - log.debug("Push notification job started"); - } try { - //Get next available operation list per device batch - DeviceManagementDAOFactory.openConnection(); - operationMappingsTenantMap = operationDAO.getOperationMappingsByStatus(Operation.Status - .PENDING, Operation.PushStatus.SCHEDULED, DeviceConfigurationManager.getInstance() - .getDeviceManagementConfig().getPushNotificationConfiguration().getSchedulerBatchSize()); - } catch (SQLException e) { - log.error("Error occurred while opening a connection to the data source", e); - } catch (OperationManagementDAOException e) { - log.error("Unable to retrieve scheduled pending operations for task.", e); - } finally { - DeviceManagementDAOFactory.closeConnection(); - } - // Sending push notification to each device - for (List operationMappings : operationMappingsTenantMap.values()) { - for (OperationMapping operationMapping : operationMappings) { - try { - if (log.isDebugEnabled()) { - log.debug("Sending push notification for operationId :" + operationMapping.getOperationId() + - "to deviceId : " + operationMapping.getDeviceIdentifier().getId()); - } - // Set tenant id and domain - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(operationMapping.getTenantId(), true); - // Get notification strategy for given device type - NotificationStrategy notificationStrategy = provider.getNotificationStrategyByDeviceType - (operationMapping.getDeviceIdentifier().getType()); - // Send the push notification on given strategy - notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(), - provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping - .getOperationId()))); - operationMapping.setPushStatus(Operation.PushStatus.COMPLETED); - operationsCompletedList.add(operationMapping); - } catch (DeviceManagementException e) { - log.error("Error occurred while getting notification strategy for operation mapping " + - operationMapping.getDeviceIdentifier().getType(), e); - } catch (OperationManagementException e) { - log.error("Unable to get the operation for operation " + operationMapping.getOperationId(), e); - } catch (PushNotificationExecutionFailedException e) { - log.error("Error occurred while sending push notification to operation: " + operationMapping - .getOperationId(), e); - } finally { - PrivilegedCarbonContext.endTenantFlow(); - } + Map> operationMappingsTenantMap = new HashMap<>(); + List operationsCompletedList = new LinkedList<>(); + if (log.isDebugEnabled()) { + log.debug("Push notification job started"); } - } - // Update push notification status to competed for operations which already sent - if (operationsCompletedList.size() > 0) { try { - OperationManagementDAOFactory.beginTransaction(); - operationMappingDAO.updateOperationMapping(operationsCompletedList); - OperationManagementDAOFactory.commitTransaction(); - } catch (TransactionManagementException | OperationManagementDAOException e) { - OperationManagementDAOFactory.rollbackTransaction(); - log.error("Error occurred while updating operation mappings for sent notifications ", e); + //Get next available operation list per device batch + OperationManagementDAOFactory.openConnection(); + operationMappingsTenantMap = operationDAO.getOperationMappingsByStatus(Operation.Status + .PENDING, Operation.PushNotificationStatus.SCHEDULED, DeviceConfigurationManager.getInstance() + .getDeviceManagementConfig().getPushNotificationConfiguration().getSchedulerBatchSize()); + } catch (OperationManagementDAOException e) { + log.error("Unable to retrieve scheduled pending operations for task.", e); } finally { OperationManagementDAOFactory.closeConnection(); } - } - if (log.isDebugEnabled()) { - log.debug("Push notification job running completed."); + // Sending push notification to each device + for (List operationMappings : operationMappingsTenantMap.values()) { + for (OperationMapping operationMapping : operationMappings) { + try { + if (log.isDebugEnabled()) { + log.debug("Sending push notification for operationId :" + operationMapping.getOperationId() + + "to deviceId : " + operationMapping.getDeviceIdentifier().getId()); + } + // Set tenant id and domain + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(operationMapping.getTenantId(), true); + // Get notification strategy for given device type + NotificationStrategy notificationStrategy = provider.getNotificationStrategyByDeviceType + (operationMapping.getDeviceIdentifier().getType()); + // Send the push notification on given strategy + notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(), + provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping + .getOperationId()))); + operationMapping.setPushNotificationStatus(Operation.PushNotificationStatus.COMPLETED); + operationsCompletedList.add(operationMapping); + } catch (DeviceManagementException e) { + log.error("Error occurred while getting notification strategy for operation mapping " + + operationMapping.getDeviceIdentifier().getType(), e); + } catch (OperationManagementException e) { + log.error("Unable to get the operation for operation " + operationMapping.getOperationId(), e); + } catch (PushNotificationExecutionFailedException e) { + log.error("Error occurred while sending push notification to operation: " + operationMapping + .getOperationId(), e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + } + // Update push notification status to competed for operations which already sent + if (operationsCompletedList.size() > 0) { + try { + OperationManagementDAOFactory.beginTransaction(); + operationMappingDAO.updateOperationMapping(operationsCompletedList); + OperationManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException | OperationManagementDAOException e) { + OperationManagementDAOFactory.rollbackTransaction(); + log.error("Error occurred while updating operation mappings for sent notifications ", e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + if (log.isDebugEnabled()) { + log.debug("Push notification job running completed."); + } + } catch (Throwable cause) { + log.error("PushNotificationSchedulerTask failed due to " + cause); } } }