From 3ca4672ac655d0357ca4d94ad3f4035f4ac1097a Mon Sep 17 00:00:00 2001 From: aselarbd Date: Fri, 7 Sep 2018 14:21:14 +0530 Subject: [PATCH 1/3] This commit fix the issue "Change password option does not work from the portal IOT server 3.1.0 " For more info refer https://github.com/wso2/product-iots/issues/1835 --- .../APIManagementProviderServiceImpl.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java index 487177ed613..aaa3cb87c11 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java @@ -26,6 +26,7 @@ import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey; import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException; import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder; import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil; +import org.wso2.carbon.apimgt.integration.client.OAuthRequestInterceptor; import org.wso2.carbon.apimgt.integration.client.store.*; import org.wso2.carbon.apimgt.integration.generated.client.store.model.*; import org.wso2.carbon.context.PrivilegedCarbonContext; @@ -58,8 +59,19 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe tenantDomain, CONTENT_TYPE, null, null); return true; } catch (FeignException e) { - return false; - } + if (e.status() == 401) { + OAuthRequestInterceptor oAuthRequestInterceptor = new OAuthRequestInterceptor(); + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + oAuthRequestInterceptor.removeToken(username, tenantDomain); + try { + storeClient.getIndividualTier().tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER, + APP_TIER_TYPE,tenantDomain, CONTENT_TYPE, null, null); + } catch (FeignException ex) { + log.error("Invalid Attempt : " + ex); + return false; + } + } } + return false; } @Override From 8fbe1a4234e9aea185b4b0c803e61f39476e5ffc Mon Sep 17 00:00:00 2001 From: aselarbd Date: Fri, 7 Sep 2018 14:56:31 +0530 Subject: [PATCH 2/3] This is the fix for the enrollment error occurred when a user enrols android device to EMM 2.2.0 in FCM enabled environment if whitelist policy is enforced. Please find the GitHub issue from [1] [1]: https://github.com/wso2/product-iots/issues/1827 --- .../notification/provider/fcm/FCMNotificationStrategy.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 83a9289442f..7c1700c2108 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 @@ -64,7 +64,9 @@ public class FCMNotificationStrategy implements NotificationStrategy { if (NOTIFIER_TYPE_FCM.equals(config.getType())) { Device device = FCMDataHolder.getInstance().getDeviceManagementProviderService() .getDeviceWithTypeProperties(ctx.getDeviceId()); - this.sendWakeUpCall(ctx.getOperation().getCode(), device); + if(getFCMToken(device.getProperties()) != null) { + this.sendWakeUpCall(ctx.getOperation().getCode(), device); + } } else { if (log.isDebugEnabled()) { log.debug("Not using FCM notifier as notifier type is set to " + config.getType() + From ba8537e1981801cedbae3136495da825acf3768b Mon Sep 17 00:00:00 2001 From: aselarbd Date: Mon, 10 Sep 2018 11:56:59 +0530 Subject: [PATCH 3/3] This is the fix for the intermittent issues when applying policies on devices Please find the GitHub issue from [1] [1]: https://github.com/wso2/product-iots/issues/1833 --- .../operation/mgt/OperationManager.java | 8 +- .../operation/mgt/OperationManagerImpl.java | 166 +++++++++++++++++- .../core/operation/mgt/dao/OperationDAO.java | 4 +- .../mgt/dao/impl/GenericOperationDAOImpl.java | 31 ++++ .../mgt/dao/impl/PolicyOperationDAOImpl.java | 75 +++++++- .../DeviceManagementProviderService.java | 5 + .../DeviceManagementProviderServiceImpl.java | 7 + .../PolicyEnforcementDelegator.java | 3 + .../PolicyEnforcementDelegatorImpl.java | 24 ++- 9 files changed, 310 insertions(+), 13 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 d85108e9600..567cc1a1d68 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 @@ -22,6 +22,8 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; + import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import java.util.List; @@ -44,6 +46,10 @@ public interface OperationManager { Activity addOperation(Operation operation, List devices) throws OperationManagementException, InvalidDeviceException; + + void addOperationsForPolicyRevoke(Policy policy, List devices) throws OperationManagementException, + InvalidDeviceException; + /** * Method to retrieve the list of all operations to a device. * @@ -114,4 +120,4 @@ public interface OperationManager { */ NotificationStrategy getNotificationStrategy(); -} \ 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/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 959d7799e4f..5b7de442051 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 @@ -38,6 +38,8 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; 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.Policy; +import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature; 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.PushNotificationConfig; @@ -64,13 +66,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.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * This class implements all the functionality exposed as part of the OperationManager. Any transaction initiated @@ -326,6 +322,160 @@ public class OperationManagerImpl implements OperationManager { } } + private Operation getPolicyRevokeOperation() { + CommandOperation policyRevokeOperation = new CommandOperation(); + policyRevokeOperation.setEnabled(true); + policyRevokeOperation.setCode(OperationMgtConstants.OperationCodes.POLICY_REVOKE); + policyRevokeOperation.setType(Operation.Type.COMMAND); + return policyRevokeOperation; + } + private Operation transformPolicy(Policy policy) { + List effectiveFeatures = policy.getProfile().getProfileFeaturesList(); + List profileOperationList = new ArrayList(); + PolicyOperation policyOperation = new PolicyOperation(); + policyOperation.setEnabled(true); + policyOperation.setType(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Type.POLICY); + policyOperation.setCode(PolicyOperation.POLICY_OPERATION_CODE); + for (ProfileFeature feature : effectiveFeatures) { + ProfileOperation profileOperation = new ProfileOperation(); + profileOperation.setCode(feature.getFeatureCode()); + profileOperation.setEnabled(true); + profileOperation.setStatus(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Status.PENDING); + profileOperation.setType(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Type.PROFILE); + profileOperation.setPayLoad(feature.getContent()); + profileOperationList.add(profileOperation); + } + policyOperation.setProfileOperations(profileOperationList); + policyOperation.setPayLoad(policyOperation.getProfileOperations()); + return policyOperation; + } + @Override + public void addOperationsForPolicyRevoke(Policy policy, List deviceIds) + throws OperationManagementException, InvalidDeviceException { + Operation revokeOperation = getPolicyRevokeOperation(); + Operation operation = transformPolicy(policy); + if (log.isDebugEnabled()) { + log.debug("operation:[" + operation.toString() + "]"); + for (DeviceIdentifier deviceIdentifier : deviceIds) { + log.debug("device identifier id:[" + deviceIdentifier.getId() + "] type:[" + + deviceIdentifier.getType() + "]"); + } + } + try { + DeviceIDHolder deviceValidationResult = DeviceManagerUtil.validateDeviceIdentifiers(deviceIds); + List validDeviceIds = deviceValidationResult.getValidDeviceIDList(); + if (validDeviceIds.size() > 0) { + DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds); + List authorizedDeviceList = deviceAuthorizationResult.getValidDeviceIDList(); + OperationManagementDAOFactory.beginTransaction(); + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation policyOperationDto = + OperationDAOUtil.convertOperation(operation); + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation revokeOperationDto = + OperationDAOUtil.convertOperation(revokeOperation); + boolean isScheduledOperation = this.isTaskScheduledOperation(operation); + boolean isNotRepeated = false; + boolean isScheduled = false; + NotificationStrategy notificationStrategy = getNotificationStrategy(); + // 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(); + } + List operationList = new LinkedList(); + operationList.add(revokeOperationDto); + operationList.add(policyOperationDto); + List operationIds = this.lookupOperationDAO(operation).addOperations(operationList); + List devices = new ArrayList<>(); + if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == policyOperationDto. + getControl()) { + isNotRepeated = true; + } + //Need to happen for both revoke and new policy operation + addOperationMappings(authorizedDeviceList, revokeOperationDto, operationIds.get(0), isScheduledOperation, + isNotRepeated, isScheduled, devices); + sendPushNotifications(revokeOperation, operationIds.get(0), isScheduled, notificationStrategy, devices); + //Need to happen for both revoke and new policy operation + addOperationMappings(authorizedDeviceList, policyOperationDto, operationIds.get(1), isScheduledOperation, + isNotRepeated, isScheduled, devices); + sendPushNotifications(operation, operationIds.get(1), isScheduled, notificationStrategy, devices); + OperationManagementDAOFactory.commitTransaction(); + } else { + throw new InvalidDeviceException("Invalid device Identifiers found."); + } + } catch (OperationManagementDAOException e) { + OperationManagementDAOFactory.rollbackTransaction(); + throw new OperationManagementException("Error occurred while adding operation", e); + } catch (TransactionManagementException e) { + throw new OperationManagementException("Error occurred while initiating the transaction", e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + private String addOperationMappings(List authorizedDeviceList, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto, int operationId, boolean isScheduledOperation, boolean isNotRepeated, boolean isScheduled, List devices) throws OperationManagementException, OperationManagementDAOException { + int enrolmentId; + boolean hasExistingTaskOperation;//TODO have to create a sql to load device details from deviceDAO using single query. + String operationCode = operationDto.getCode(); + for (DeviceIdentifier deviceId : authorizedDeviceList) { + Device device = getDevice(deviceId); + devices.add(device); + enrolmentId = device.getEnrolmentInfo().getId(); + //Do not repeat the task operations + if (isScheduledOperation) { + hasExistingTaskOperation = operationDAO.updateTaskOperation(enrolmentId, operationCode); + if (!hasExistingTaskOperation) { + operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); + } + } else if (isNotRepeated) { + operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode, + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING, + org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.REPEATED); + operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); + } else { + operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); + } + } + return operationCode; + } + /* + * If notification strategy has not enable to send push notification using scheduler task we will send + * notification immediately. This is done in separate loop inorder to prevent overlap with DB insert + * operations with the possible db update operations trigger followed by pending operation call. + * Otherwise device may call pending operation while DB is locked for write and deadlock can occur. + */ + private void sendPushNotifications(Operation operation, int operationId, boolean isScheduled, NotificationStrategy notificationStrategy, List devices) { + int enrolmentId; + if (notificationStrategy != null && !isScheduled) { + for (Device device : devices) { + DeviceIdentifier deviceId = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType()); + if (log.isDebugEnabled()) { + log.debug("Sending push notification to " + deviceId + " from add operation method."); + } + operation.setId(operationId); + operation.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId); + try { + notificationStrategy.execute(new NotificationContext(deviceId, operation)); + } catch (PushNotificationExecutionFailedException e) { + log.error("Error occurred while sending push notifications to " + deviceId.getType() + + " device carrying id '" + deviceId + "'", e); + /* + Reschedule if push notification failed. Doing db transactions in atomic way to prevent + deadlocks. + */ + enrolmentId = device.getEnrolmentInfo().getId(); + try { + operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon + .device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED); + } catch (OperationManagementDAOException ex) { + // Not throwing this exception in order to keep sending remaining notifications if any. + log.error("Error occurred while setting push notification status to SCHEDULED.", ex); + } + } + } + } + } + private List getActivityStatus(DeviceIDHolder deviceIdValidationResult, DeviceIDHolder deviceAuthResult, String deviceType) { List activityStatuses = new ArrayList<>(); @@ -1124,4 +1274,4 @@ public class OperationManagerImpl implements OperationManager { private boolean isSameUser(String user, String owner) { return user.equalsIgnoreCase(owner); } -} \ 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/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 81f589db411..641a91c9ed7 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 @@ -30,6 +30,8 @@ public interface OperationDAO { int addOperation(Operation operation) throws OperationManagementDAOException; + List addOperations(List operations) throws OperationManagementDAOException; + Operation getOperation(int operationId) throws OperationManagementDAOException; Operation getOperationByDeviceAndId(int enrolmentId, int operationId) throws OperationManagementDAOException; @@ -88,4 +90,4 @@ public interface OperationDAO { 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/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 8782a813294..cb543de8f3f 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 @@ -86,6 +86,37 @@ public class GenericOperationDAOImpl implements OperationDAO { } } + //This implementation has been done this way due to H2 not supporting batch inserts properly. + //Even though records are added in batch mode, only the id of the last added record will be returned, which is a problem. + public List addOperations(List operations) throws OperationManagementDAOException { + List ids = new LinkedList(); + for (Operation operation : operations) { + PreparedStatement stmt = null; + ResultSet rs = null; + try { + Connection connection = OperationManagementDAOFactory.getConnection(); + String sql = "INSERT INTO DM_OPERATION(TYPE, CREATED_TIMESTAMP, RECEIVED_TIMESTAMP, OPERATION_CODE) " + + "VALUES (?, ?, ?, ?)"; + stmt = connection.prepareStatement(sql, new String[]{"id"}); + stmt.setString(1, operation.getType().toString()); + stmt.setTimestamp(2, new Timestamp(new Date().getTime())); + stmt.setTimestamp(3, null); + stmt.setString(4, operation.getCode()); + stmt.executeUpdate(); + rs = stmt.getGeneratedKeys(); + int id = -1; + if (rs.next()) { + ids.add(rs.getInt(1)); + } + } catch (SQLException e) { + throw new OperationManagementDAOException("Error occurred while adding operation metadata", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, rs); + } + } + return ids; + } + public boolean updateOperationStatus(int enrolmentId, int operationId, Operation.Status status) throws OperationManagementDAOException { PreparedStatement 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/PolicyOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/PolicyOperationDAOImpl.java index 7f142b7d04c..15bf7cbe65d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/PolicyOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/PolicyOperationDAOImpl.java @@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.core.operation.mgt.dao.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.core.dto.operation.mgt.CommandOperation; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.PolicyOperation; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; @@ -46,7 +47,6 @@ public class PolicyOperationDAOImpl extends GenericOperationDAOImpl { operation.setCreatedTimeStamp(new Timestamp(new java.util.Date().getTime()).toString()); operation.setId(operationId); operation.setEnabled(true); - PolicyOperation policyOperation = (PolicyOperation) operation; Connection conn = OperationManagementDAOFactory.getConnection(); stmt = conn.prepareStatement("INSERT INTO DM_POLICY_OPERATION(OPERATION_ID, OPERATION_DETAILS) " + "VALUES(?, ?)"); @@ -82,6 +82,79 @@ public class PolicyOperationDAOImpl extends GenericOperationDAOImpl { return operationId; } + + private int addCommandOperation(int operationId, Operation operation) throws OperationManagementDAOException { + CommandOperation commandOp = (CommandOperation) operation; + PreparedStatement stmt = null; + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + stmt = conn.prepareStatement("INSERT INTO DM_COMMAND_OPERATION(OPERATION_ID, ENABLED) VALUES(?, ?)"); + stmt.setInt(1, operationId); + stmt.setBoolean(2, commandOp.isEnabled()); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new OperationManagementDAOException("Error occurred while adding command operation", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt); + } + return operationId; + } + @Override + public List addOperations(List operations) throws OperationManagementDAOException { + List operationIds; + int counter = 0; + operationIds = super.addOperations(operations); + for(Operation operation : operations) { + if(operation.getType().equals(Operation.Type.COMMAND)){ + addCommandOperation(operationIds.get(counter), operation); + } else if(operation.getType().equals(Operation.Type.POLICY)){ + addPolicyOperation(operationIds.get(counter), operation); + } + counter++; + } + return operationIds; + } + private void addPolicyOperation(int operationId, Operation operation) throws OperationManagementDAOException { + PreparedStatement stmt = null; + ByteArrayOutputStream bao = null; + ObjectOutputStream oos = null; + try { + operation.setCreatedTimeStamp(new Timestamp(new java.util.Date().getTime()).toString()); + operation.setId(operationId); + operation.setEnabled(true); + Connection conn = OperationManagementDAOFactory.getConnection(); + stmt = conn.prepareStatement("INSERT INTO DM_POLICY_OPERATION(OPERATION_ID, OPERATION_DETAILS) " + + "VALUES(?, ?)"); + bao = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(bao); + oos.writeObject(operation); + stmt.setInt(1, operationId); + stmt.setBytes(2, bao.toByteArray()); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new OperationManagementDAOException("Error occurred while adding policy operation", e); + } catch (IOException e) { + throw new OperationManagementDAOException("Error occurred while serializing policy operation object", e); + } finally { + if (bao != null) { + try { + bao.close(); + } catch (IOException e) { + log.warn("Error occurred while closing ByteArrayOutputStream", e); + } + } + if (oos != null) { + try { + oos.close(); + } catch (IOException e) { + log.warn("Error occurred while closing ObjectOutputStream", e); + } + } + OperationManagementDAOUtil.cleanupResources(stmt); + } + } + + @Override public Operation getOperation(int operationId) throws OperationManagementDAOException { PreparedStatement stmt = null; 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..97871a73f02 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.license.mgt.License; 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.Policy; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; @@ -541,6 +542,10 @@ public interface DeviceManagementProviderService { Activity addOperation(String type, Operation operation, List devices) throws OperationManagementException, InvalidDeviceException; + void addPolicyOperations(String type, Policy policy, + List devices) throws OperationManagementException, InvalidDeviceException; + + List getOperations(DeviceIdentifier deviceId) throws OperationManagementException; PaginationResult getOperations(DeviceIdentifier deviceId, 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..d772d02ae3b 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 @@ -53,6 +53,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.operation.mgt.OperationManager; +import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; @@ -1423,6 +1424,12 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return pluginRepository.getOperationManager(type, this.getTenantId()).addOperation(operation, devices); } + @Override + public void addPolicyOperations(String type, Policy policy, + List devices) throws OperationManagementException, InvalidDeviceException { + pluginRepository.getOperationManager(type, this.getTenantId()).addOperationsForPolicyRevoke(policy, devices); + } + @Override public List getOperations(DeviceIdentifier deviceId) throws OperationManagementException { return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()).getOperations(deviceId); diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegator.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegator.java index aac07ce6000..c603be7d842 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegator.java +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/main/java/org/wso2/carbon/policy/mgt/core/enforcement/PolicyEnforcementDelegator.java @@ -33,4 +33,7 @@ public interface PolicyEnforcementDelegator { void addPolicyRevokeOperation(List deviceIdentifiers) throws PolicyDelegationException; + void revokePolicyOperation(List deviceIdentifiers, Policy policy) throws PolicyDelegationException; + + } 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 fa02314460f..7471b7ae9f4 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 @@ -81,8 +81,7 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato */ if (devicePolicy == null || devicePolicy.getId() != policy.getId() || updatedPolicyIds.contains (policy.getId())) { - this.addPolicyRevokeOperation(deviceIdentifiers); - this.addPolicyOperation(deviceIdentifiers, policy); + this.revokePolicyOperation(deviceIdentifiers, policy); } } else { //This means all the applicable policies have been removed from device. Hence calling a policy revoke. @@ -167,6 +166,27 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato return policyRevokeOperation; } + @Override + public void revokePolicyOperation(List deviceIdentifiers, Policy policy) throws + PolicyDelegationException { + try { + String type = null; + if (deviceIdentifiers.size() > 0) { + type = deviceIdentifiers.get(0).getType(); + } + PolicyManagementDataHolder.getInstance().getDeviceManagementService().addPolicyOperations(type, policy, + deviceIdentifiers); + } catch (InvalidDeviceException e) { + String msg = "Invalid DeviceIdentifiers found."; + log.error(msg, e); + throw new PolicyDelegationException(msg, e); + } catch (OperationManagementException e) { + String msg = "Error occurred while adding the operation to device."; + log.error(msg, e); + throw new PolicyDelegationException(msg, e); + } + } + /** * Provides the applied policy for give device *