diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/Operation.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/Operation.java index 7e3b2fe7c6e..b3b863a5f35 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/Operation.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/Operation.java @@ -37,7 +37,7 @@ public class Operation implements Serializable { } public enum Status { - IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED + IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED, NOTNOW } public enum Control { 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 d85108e9600..78bfdec53f0 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 @@ -76,6 +76,9 @@ public interface OperationManager { */ List getPendingOperations(DeviceIdentifier deviceId) throws OperationManagementException; + Operation getNextPendingOperation(DeviceIdentifier deviceId, long notNowOperationFrequency) + throws OperationManagementException; + Operation getNextPendingOperation(DeviceIdentifier deviceId) throws OperationManagementException; void updateOperation(DeviceIdentifier deviceId, Operation operation) throws OperationManagementException; 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 07c2674f0fe..03acfa9a11b 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 @@ -30,7 +30,7 @@ public class Operation implements Serializable { } public enum Status { - IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED + IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED, NOTNOW } public enum Control { 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 2ac5150a59d..89e541615cb 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 @@ -64,6 +64,7 @@ import org.wso2.carbon.device.mgt.core.task.impl.DeviceTaskManagerImpl; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; @@ -537,6 +538,13 @@ public class OperationManagerImpl implements OperationManager { @Override public Operation getNextPendingOperation(DeviceIdentifier deviceId) throws OperationManagementException { + // setting notNowOperationFrequency to -1 to avoid picking notnow operations + return this.getNextPendingOperation(deviceId, -1); + } + + @Override + public Operation getNextPendingOperation(DeviceIdentifier deviceId, long notNowOperationFrequency) + throws OperationManagementException { if (log.isDebugEnabled()) { log.debug("device identifier id:[" + deviceId.getId() + "] type:[" + deviceId.getType() + "]"); } @@ -565,8 +573,32 @@ public class OperationManagerImpl implements OperationManager { try { OperationManagementDAOFactory.openConnection(); - org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation dtoOperation = operationDAO.getNextOperation( - enrolmentInfo.getId()); + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation dtoOperation = null; + + // check whether notnow is set + if (notNowOperationFrequency > 0) { + // retrieve Notnow operations + dtoOperation = operationDAO.getNextOperation(enrolmentInfo.getId(), + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.NOTNOW); + } + + if (dtoOperation != null) { + long currentTime = Calendar.getInstance().getTime().getTime(); + log.info("Current timestamp:" + currentTime); + long updatedTime = Timestamp.valueOf(dtoOperation.getReceivedTimeStamp()).getTime(); + log.info("Updated timestamp: " + updatedTime); + + // check if notnow frequency is met and set next pending operation if not, otherwise let notnow + // operation to proceed + if ((currentTime - updatedTime) < notNowOperationFrequency) { + dtoOperation = operationDAO.getNextOperation(enrolmentInfo.getId(), + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING); + } + } else { + dtoOperation = operationDAO.getNextOperation(enrolmentInfo.getId(), + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING); + } + if (dtoOperation != null) { if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Type.COMMAND.equals(dtoOperation.getType() )) { 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 67dcd517c2e..81d47cfc852 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 @@ -46,7 +46,7 @@ public interface OperationDAO { List getOperationsForDevice(int enrolmentId, PaginationRequest request) throws OperationManagementDAOException; - Operation getNextOperation(int enrolmentId) throws OperationManagementDAOException; + Operation getNextOperation(int enrolmentId, Operation.Status status) throws OperationManagementDAOException; boolean updateOperationStatus(int enrolmentId, int operationId,Operation.Status status) 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 900c41cf964..646f6a9051d 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 @@ -1372,7 +1372,7 @@ public class GenericOperationDAOImpl implements OperationDAO { } @Override - public Operation getNextOperation(int enrolmentId) throws OperationManagementDAOException { + public Operation getNextOperation(int enrolmentId, Operation.Status status) throws OperationManagementDAOException { PreparedStatement stmt = null; ResultSet rs = null; try { @@ -1383,7 +1383,7 @@ public class GenericOperationDAOImpl implements OperationDAO { "WHERE dm.ENROLMENT_ID = ? AND dm.STATUS = ?) om ON o.ID = om.OPERATION_ID " + "ORDER BY om.UPDATED_TIMESTAMP ASC, om.ID ASC LIMIT 1"); stmt.setInt(1, enrolmentId); - stmt.setString(2, Operation.Status.PENDING.toString()); + stmt.setString(2, status.toString()); rs = stmt.executeQuery(); Operation operation = null; @@ -1392,11 +1392,7 @@ public class GenericOperationDAOImpl implements OperationDAO { operation.setType(OperationDAOUtil.getType(rs.getString("TYPE"))); operation.setId(rs.getInt("ID")); operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); -// if (rs.getTimestamp("RECEIVED_TIMESTAMP") == null) { -// operation.setReceivedTimeStamp(""); -// } else { -// operation.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); -// } + if (rs.getLong("UPDATED_TIMESTAMP") == 0) { operation.setReceivedTimeStamp(""); } else { 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 aac946a409e..c3a1b37008e 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 @@ -551,6 +551,9 @@ public interface DeviceManagementProviderService { Operation getNextPendingOperation(DeviceIdentifier deviceId) throws OperationManagementException; + Operation getNextPendingOperation(DeviceIdentifier deviceId, long notNowOperationFrequency) + throws OperationManagementException; + void updateOperation(DeviceIdentifier deviceId, Operation operation) throws OperationManagementException; boolean updateProperties(DeviceIdentifier deviceId, List properties) 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 ae2b5d422ff..c7d23ecaaa4 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 @@ -1445,8 +1445,15 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv @Override public Operation getNextPendingOperation(DeviceIdentifier deviceId) throws OperationManagementException { + // // setting notNowOperationFrequency to -1 to avoid picking notnow operations return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()) - .getNextPendingOperation(deviceId); + .getNextPendingOperation(deviceId, -1); + } + + public Operation getNextPendingOperation(DeviceIdentifier deviceId, long notNowOperationFrequency) + throws OperationManagementException { + return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()) + .getNextPendingOperation(deviceId, notNowOperationFrequency); } @Override diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/operation/OperationManagementTests.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/operation/OperationManagementTests.java index bb5657d8fbf..b1734948d42 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/operation/OperationManagementTests.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/operation/OperationManagementTests.java @@ -18,6 +18,8 @@ package org.wso2.carbon.device.mgt.core.operation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.powermock.api.mockito.PowerMockito; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -81,6 +83,8 @@ public class OperationManagementTests extends BaseDeviceManagementTest { private Activity commandActivity; private long commandActivityBeforeUpdatedTimestamp; + private static Log log = LogFactory.getLog(OperationManagementTests.class); + @BeforeClass public void init() throws Exception { for (int i = 0; i < NO_OF_DEVICES; i++) { @@ -363,6 +367,35 @@ public class OperationManagementTests extends BaseDeviceManagementTest { Assert.assertTrue(operation.getType().equals(Operation.Type.POLICY)); } + @Test(dependsOnMethods = "getNextPendingOperation") + public void getNextNotNowOperation() throws OperationManagementException { + //This is required to introduce a delay for the update operation of the device. + try { + Thread.sleep(2000); + } catch (InterruptedException ignored) { + } + DeviceIdentifier deviceIdentifier = this.deviceIds.get(0); + Operation operation = this.operationMgtService.getNextPendingOperation(deviceIdentifier); + int operationId = operation.getId(); + operation.setStatus(Operation.Status.NOTNOW); + operation.setOperationResponse("The operation is successfully completed"); + this.operationMgtService.updateOperation(deviceIdentifier, operation); + //This is required to introduce a delay for the update operation of the device. + try { + Thread.sleep(2000); + } catch (InterruptedException ignored) { + } + operation = this.operationMgtService.getNextPendingOperation(deviceIdentifier); + Assert.assertTrue(operation.getId() != operationId, "Fetched the incorrect operation"); + log.info("Waiting 10000ms for NotNow operation to be fetched"); + try { + Thread.sleep(10000); + } catch (InterruptedException ignored) { + } + operation = this.operationMgtService.getNextPendingOperation(deviceIdentifier, 7000); + Assert.assertTrue(operation.getId() == operationId, "Fetched the incorrect NotNow operation"); + } + @Test(dependsOnMethods = "updateOperation", expectedExceptions = OperationManagementException.class) public void getNextPendingOperationAsNonAdmin() throws OperationManagementException { startTenantFlowAsNonAdmin(); @@ -406,7 +439,7 @@ public class OperationManagementTests extends BaseDeviceManagementTest { DeviceIdentifier deviceIdentifier = this.deviceIds.get(0); List operation = this.operationMgtService.getOperationsByDeviceAndStatus(deviceIdentifier, Operation.Status.PENDING); - Assert.assertEquals(operation.size(), 3); + Assert.assertEquals(operation.size(), 2); } @Test(dependsOnMethods = "getOperationByDeviceAndOperationId", expectedExceptions = OperationManagementException.class) @@ -479,8 +512,8 @@ public class OperationManagementTests extends BaseDeviceManagementTest { public void getActivityCountUpdatedAfter() throws OperationManagementException, ParseException { int activityCount = this.operationMgtService.getActivityCountUpdatedAfter (this.commandActivityBeforeUpdatedTimestamp / 1000); - Assert.assertTrue(activityCount == 1, - "The activities updated after the created should be 1"); + Assert.assertTrue(activityCount == 2, + "The activities updated after the created should be 2"); } @Test