From 690eff6660931ac0d0907bba8670b3e5a6ca3c15 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Tue, 13 Feb 2018 15:19:12 +0530 Subject: [PATCH 1/4] Refactoring mobile application subscription API --- .../common/EnterpriseInstallationDetails.java | 85 +++++++++ .../mgt/common/InstallationDetails.java | 46 +---- .../common/services/ApplicationManager.java | 9 +- .../common/services/SubscriptionManager.java | 43 +++-- .../mgt/core/impl/ApplicationManagerImpl.java | 17 +- .../core/impl/SubscriptionManagerImpl.java | 143 ++++++++------- .../application/mgt/core/util/HelperUtil.java | 21 +++ .../mgt/store/api/beans/ErrorResponse.java | 1 + .../services/SubscriptionManagementAPI.java | 169 +++++++++++++++--- .../impl/SubscriptionManagementAPIImpl.java | 94 +++++++--- 10 files changed, 446 insertions(+), 182 deletions(-) create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/EnterpriseInstallationDetails.java diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/EnterpriseInstallationDetails.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/EnterpriseInstallationDetails.java new file mode 100644 index 0000000000..6eac1a76ab --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/EnterpriseInstallationDetails.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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.application.mgt.common; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +public class EnterpriseInstallationDetails { + + /** + * This enum represents the type of entities which an application can be installed on. + * + * e.g: An application can be installed on all the devices belong to a user or a specific device group. + */ + @ApiModel + public enum EnterpriseEntity { + USER, ROLE, DEVICE_GROUP + } + + @ApiModelProperty( + name = "applicationUUID", + value = "Application ID", + required = true, + example = "4354c752-109f-11e8-b642-0ed5f89f718b" + ) + private String applicationUUID; + + @ApiModelProperty( + name = "entityType", + value = "Enterprise entity type", + required = true, + example = "USER" + ) + private EnterpriseEntity entityType; + + @ApiModelProperty( + name = "entityValueList", + value = "List of users/roles or device groups.", + required = true, + example = "user1,user2, user3" + ) + private List entityValueList; + + public String getApplicationUUID() { + return applicationUUID; + } + + public void setApplicationUUID(String applicationUUID) { + this.applicationUUID = applicationUUID; + } + + public EnterpriseEntity getEntityType() { + return entityType; + } + + public void setEntityType(EnterpriseEntity entityType) { + this.entityType = entityType; + } + + public List getEntityValueList() { + return entityValueList; + } + + public void setEntityValueList(List entityValueList) { + this.entityValueList = entityValueList; + } +} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java index 75b484920a..87601d6cc8 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java @@ -25,30 +25,16 @@ public class InstallationDetails { @ApiModelProperty( name = "applicationUUID", value = "Application ID", - required = true) + required = true + ) private String applicationUUID; - @ApiModelProperty( - name = "versionName", - value = "Version name", - required = true) - private String versionName; - @ApiModelProperty( - name = "userNameList", - value = "List of user names.", - required = true) - private List userNameList; - - @ApiModelProperty( - name = "roleNameList", - value = "List of role names.", - required = true) - private List roleNameList; @ApiModelProperty( name = "deviceIdentifiers", value = "List of device identifiers.", required = true, - dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]") + dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]" + ) private List deviceIdentifiers; public String getApplicationUUID() { @@ -59,30 +45,6 @@ public class InstallationDetails { this.applicationUUID = applicationUUID; } - public String getVersionName() { - return versionName; - } - - public void setVersionName(String versionName) { - this.versionName = versionName; - } - - public List getUserNameList() { - return userNameList; - } - - public void setUserNameList(List userNameList) { - this.userNameList = userNameList; - } - - public List getRoleNameList() { - return roleNameList; - } - - public void setRoleNameList(List roleNameList) { - this.roleNameList = roleNameList; - } - public List getDeviceIdentifiers() { return deviceIdentifiers; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java index 8c10189a8f..1dc480a883 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java @@ -18,10 +18,15 @@ */ package org.wso2.carbon.device.application.mgt.common.services; -import org.wso2.carbon.device.application.mgt.common.*; +import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.common.ApplicationList; +import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; +import org.wso2.carbon.device.application.mgt.common.Filter; +import org.wso2.carbon.device.application.mgt.common.LifecycleState; +import org.wso2.carbon.device.application.mgt.common.LifecycleStateTransition; +import org.wso2.carbon.device.application.mgt.common.UnrestrictedRole; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.LifecycleManagementException; -import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import java.util.List; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java index 603ac48015..42386768db 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java @@ -29,35 +29,42 @@ import java.util.List; public interface SubscriptionManager { /** * To install an application to given list of devices. - * @param applicationUUID Application ID - * @param deviceList Device list + * @param applicationUUID ID of the application to install + * @param deviceList list of device ID's to install the application * @return Failed Device List which the application was unable to install - * @throws ApplicationManagementException Application Management Exception + * @throws ApplicationManagementException if unable to install the application to the given devices */ - List installApplicationForDevices(String applicationUUID, String versionName, - List deviceList) + List installApplicationForDevices(String applicationUUID, List deviceList) throws ApplicationManagementException; /** * To install an application to given list of users. - * @param applicationUUID Application ID - * @param userList User list + * @param applicationUUID ID of the application to install + * @param userList list of users to install the application * @return Failed Device List which the application was unable to install - * @throws ApplicationManagementException Application Management Exception + * @throws ApplicationManagementException if unable to install the application to devices belong to given users */ - List installApplicationForUsers(String applicationUUID, - List userList, String versionName) + List installApplicationForUsers(String applicationUUID, List userList) throws ApplicationManagementException; /** - * To install an application to given list of users. - * @param applicationUUID Application ID - * @param roleList Role list + * To install an application to given list of roles. + * @param applicationUUID ID of the application to install + * @param roleList list of roles to install the application * @return Failed Device List which the application was unable to install - * @throws ApplicationManagementException Application Management Exception + * @throws ApplicationManagementException if unable to install the application to devices belong to given roles */ - List installApplicationForRoles(String applicationUUID, - List roleList, String versionName) + List installApplicationForRoles(String applicationUUID, List roleList) + throws ApplicationManagementException; + + /** + * To install an application to given list of roles. + * @param applicationUUID ID of the application to install + * @param deviceGroupList list of device groups to install the application + * @return Failed Device List which the application was unable to install + * @throws ApplicationManagementException if unable to install the application to devices belong to given groups + */ + List installApplicationForGroups(String applicationUUID, List deviceGroupList) throws ApplicationManagementException; /** @@ -67,8 +74,6 @@ public interface SubscriptionManager { * @return Failed Device List which the application was unable to uninstall * @throws ApplicationManagementException Application Management Exception */ - List uninstallApplication(String applicationUUID, - List deviceList) + List uninstallApplication(String applicationUUID, List deviceList) throws ApplicationManagementException; - } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java index 3a8a791f83..0187525a0d 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java @@ -23,7 +23,15 @@ 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.application.mgt.common.*; +import org.wso2.carbon.device.application.mgt.common.AppLifecycleState; +import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.common.ApplicationList; +import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; +import org.wso2.carbon.device.application.mgt.common.Filter; +import org.wso2.carbon.device.application.mgt.common.LifecycleState; +import org.wso2.carbon.device.application.mgt.common.LifecycleStateTransition; +import org.wso2.carbon.device.application.mgt.common.UnrestrictedRole; +import org.wso2.carbon.device.application.mgt.common.User; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; import org.wso2.carbon.device.application.mgt.common.exception.LifecycleManagementException; @@ -38,16 +46,17 @@ import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException; import org.wso2.carbon.device.application.mgt.core.exception.ValidationException; import org.wso2.carbon.device.application.mgt.core.internal.DataHolder; import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil; -import org.wso2.carbon.device.mgt.core.dao.*; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceTypeDAO; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; -import java.util.ArrayList; -import java.util.List; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Date; +import java.util.List; /** * Default Concrete implementation of Application Management related implementations. diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java index b6bb3f5349..e9d1375e60 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -19,19 +19,27 @@ package org.wso2.carbon.device.application.mgt.core.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; +import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager; +import org.wso2.carbon.device.application.mgt.common.services.ApplicationReleaseManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; +import org.wso2.carbon.device.application.mgt.core.util.ApplicationManagementUtil; import org.wso2.carbon.device.application.mgt.core.util.HelperUtil; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.app.mgt.DeviceApplicationMapping; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; +import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import java.util.ArrayList; import java.util.List; @@ -45,106 +53,103 @@ public class SubscriptionManagerImpl implements SubscriptionManager { private static final String INSTALL_APPLICATION = "INSTALL_APPLICATION"; @Override - public List installApplicationForDevices(String applicationUUID, String versionName, - List deviceList) - throws ApplicationManagementException { - return installApplication(applicationUUID, deviceList, versionName); + public List installApplicationForDevices(String applicationUUID, + List deviceList) throws ApplicationManagementException { + if (log.isDebugEnabled()) { + log.debug("Install application: " + applicationUUID + " to " + deviceList.size() + "devices."); + } + return installApplication(applicationUUID, deviceList); } @Override - public List installApplicationForUsers(String applicationUUID, List userList, - String versionName) throws ApplicationManagementException { - log.info("Install application: " + applicationUUID + " to: " + userList.size() + " users."); + public List installApplicationForUsers(String applicationUUID, List userList) + throws ApplicationManagementException { + if (log.isDebugEnabled()) { + log.debug("Install application: " + applicationUUID + " to " + userList.size() + " users."); + } List deviceList = new ArrayList<>(); for (String user : userList) { try { List devicesOfUser = HelperUtil.getDeviceManagementProviderService().getDevicesOfUser(user); for (Device device : devicesOfUser) { - deviceList.add(new DeviceIdentifier(device - .getDeviceIdentifier(), device.getType())); + deviceList.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); + } + if (log.isDebugEnabled()) { + log.debug(devicesOfUser.size() + " found for the provided user list"); } } catch (DeviceManagementException e) { - log.error("Error when extracting the device list from user[" + user + "].", e); + throw new ApplicationManagementException("Error when extracting the device list of user[" + user + "].", + e); } } - return installApplication(applicationUUID, deviceList, versionName); + return installApplication(applicationUUID, deviceList); } @Override - public List installApplicationForRoles(String applicationUUID, List roleList, - String versionName) throws ApplicationManagementException { - log.info("Install application: " + applicationUUID + " to: " + roleList.size() + " roles."); + public List installApplicationForRoles(String applicationUUID, List roleList) + throws ApplicationManagementException { + if (log.isDebugEnabled()) { + log.debug("Install application: " + applicationUUID + " to " + roleList.size() + " roles."); + } List deviceList = new ArrayList<>(); for (String role : roleList) { try { List devicesOfRole = HelperUtil.getDeviceManagementProviderService().getAllDevicesOfRole(role); for (Device device : devicesOfRole) { - deviceList.add(new DeviceIdentifier(device - .getDeviceIdentifier(), device.getType())); + deviceList.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); + } + if (log.isDebugEnabled()) { + log.debug(devicesOfRole.size() + " found for role: " + role); } } catch (DeviceManagementException e) { - log.error("Error when extracting the device list from role[" + role + "].", e); + throw new ApplicationManagementException( + "Error when extracting the device list from role[" + role + "].", e); + } + } + return installApplication(applicationUUID, deviceList); + } + + @Override + public List installApplicationForGroups(String applicationUUID, List deviceGroupList) + throws ApplicationManagementException { + if (log.isDebugEnabled()) { + log.debug("Install application: " + applicationUUID + " to " + deviceGroupList.size() + " groups."); + } + GroupManagementProviderService groupManagementProviderService = HelperUtil.getGroupManagementProviderService(); + List deviceList = new ArrayList<>(); + for (String groupName : deviceGroupList) { + try { + DeviceGroup deviceGroup = groupManagementProviderService.getGroup(groupName); + int deviceCount = groupManagementProviderService.getDeviceCount(deviceGroup.getGroupId()); + List devicesOfGroups = groupManagementProviderService + .getDevices(deviceGroup.getGroupId(), 0, deviceCount); + for (Device device : devicesOfGroups) { + deviceList.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); + } + } catch (GroupManagementException e) { + throw new ApplicationManagementException( + "Error when extracting the device list from group[" + groupName + "].", e); } } - return installApplication(applicationUUID, deviceList, versionName); + return installApplication(applicationUUID, deviceList); } @Override - public List uninstallApplication(String applicationUUID, - List deviceList) + public List uninstallApplication(String applicationUUID, List deviceList) throws ApplicationManagementException { return null; } - private List installApplication(String applicationUUID, List deviceList, - String versionName) throws ApplicationManagementException { + private List installApplication(String applicationUUID, List deviceList) + throws ApplicationManagementException { + //todo: 1. get application and release. + ApplicationReleaseManager applicationReleaseManager = ApplicationManagementUtil + .getApplicationReleaseManagerInstance(); + ApplicationRelease applicationRelease = applicationReleaseManager.getReleaseByUuid(applicationUUID); + //todo: 2. check type and filter devices. + //todo: 3. generate url based on application attributes and app release attributes + + //Todo: check if app type is installable for all the device types: apk -> android, ipa -> ios, webclip -> both return null; -// List failedDeviceList = new ArrayList<>(deviceList); -// // Todo: try whether we can optimise this by sending bulk inserts to db -// // Todo: atomicity is not maintained as deveice managment provider service uses separate db connection. fix this?? -// log.info("Install application: " + applicationUUID + "[" + versionName + "]" + " to: " -// + deviceList.size() + " devices."); -// for (DeviceIdentifier device : deviceList) { -// org.wso2.carbon.device.mgt.common.DeviceIdentifier deviceIdentifier = new org.wso2.carbon.device.mgt -// .common.DeviceIdentifier(device.getId(), device.getType()); -// try { -// DeviceManagementProviderService dmpService = HelperUtil.getDeviceManagementProviderService(); -// if (!dmpService.isEnrolled(deviceIdentifier)) { -// log.error("Device with ID: [" + device.getId() + "] is not enrolled to install the application."); -// } else { -// if (log.isDebugEnabled()) { -// log.debug("Installing application to : " + device.getId()); -// } -// //Todo: generating one time download link for the application and put install operation to device. -// -// // put app install operation to the device -// ProfileOperation operation = new ProfileOperation(); -// operation.setCode(INSTALL_APPLICATION); -// operation.setType(Operation.Type.PROFILE); -// operation.setPayLoad("{'type':'enterprise', 'url':'http://10.100.5.76:8000/app-debug.apk', 'app':'" -// + applicationUUID + "'}"); -// List deviceIdentifiers = new ArrayList<>(); -// deviceIdentifiers.add(deviceIdentifier); -// dmpService.addOperation(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID, -// operation, deviceIdentifiers); -// -// DeviceApplicationMapping deviceApp = new DeviceApplicationMapping(); -// deviceApp.setDeviceIdentifier(device.getId()); -// deviceApp.setApplicationUUID(applicationUUID); -// deviceApp.setVersionName(versionName); -// deviceApp.setInstalled(false); -// dmpService.addDeviceApplicationMapping(deviceApp); -//// DeviceManagementDAOFactory.openConnection(); -//// ApplicationManagementDAOFactory.getSubscriptionDAO().addDeviceApplicationMapping(device.getId(), applicationUUID, false); -// failedDeviceList.remove(device); -// } -// } catch (DeviceManagementException | OperationManagementException | InvalidDeviceException e) { -// log.error("Error while installing application to device[" + deviceIdentifier.getId() + "]", e); -// } -// finally { -// DeviceManagementDAOFactory.closeConnection(); -// } -// } -// return failedDeviceList; } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/HelperUtil.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/HelperUtil.java index b1297dfa8b..fbad305355 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/HelperUtil.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/HelperUtil.java @@ -21,8 +21,11 @@ package org.wso2.carbon.device.application.mgt.core.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; +import java.util.List; import java.util.UUID; /** @@ -33,6 +36,7 @@ public class HelperUtil { private static Log log = LogFactory.getLog(HelperUtil.class); private static DeviceManagementProviderService deviceManagementProviderService; + private static GroupManagementProviderService groupManagementProviderService; public static String generateApplicationUuid() { return UUID.randomUUID().toString(); @@ -56,4 +60,21 @@ public class HelperUtil { return deviceManagementProviderService; } + public static GroupManagementProviderService getGroupManagementProviderService() { + if (groupManagementProviderService == null) { + synchronized (HelperUtil.class) { + if (groupManagementProviderService == null) { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + groupManagementProviderService = (GroupManagementProviderService) ctx + .getOSGiService(GroupManagementProviderService.class, null); + if (groupManagementProviderService == null) { + String msg = "Group management provider service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + } + } + } + return groupManagementProviderService; + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/beans/ErrorResponse.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/beans/ErrorResponse.java index 7727b7a695..3b78219b85 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/beans/ErrorResponse.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/beans/ErrorResponse.java @@ -21,6 +21,7 @@ package org.wso2.carbon.device.application.mgt.publisher.api.beans; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.device.application.mgt.publisher.api.beans.ErrorListItem; import java.util.ArrayList; import java.util.List; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java index fb6d0e2446..05b20d318e 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java @@ -17,14 +17,28 @@ */ package org.wso2.carbon.device.application.mgt.publisher.api.services; -import io.swagger.annotations.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.Info; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; import org.wso2.carbon.apimgt.annotations.api.Scopes; -import org.wso2.carbon.device.application.mgt.publisher.api.beans.ErrorResponse; import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails; import org.wso2.carbon.device.application.mgt.common.InstallationDetails; import javax.validation.Valid; -import javax.ws.rs.*; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -43,9 +57,8 @@ import javax.ws.rs.core.Response; } ), tags = { - @Tag(name = "subscription_management, device_management", description = "Subscription Management " + - "related " - + "APIs") + @Tag(name = "subscription_management, device_management", description = "Subscription Management " + + "related APIs") } ) @Scopes( @@ -82,7 +95,7 @@ public interface SubscriptionManagementAPI { produces = MediaType.APPLICATION_JSON, httpMethod = "POST", value = "Install an application", - notes = "This will install an application to a given list of devices/users/roles", + notes = "This will install an application to a given list of devices", tags = "Subscription Management", extensions = { @Extension(properties = { @@ -95,23 +108,73 @@ public interface SubscriptionManagementAPI { @ApiResponse( code = 200, message = "OK. \n Successfully installed the application.", - response = Application.class), + response = Application.class + ), @ApiResponse( code = 304, - message = "Not Modified. \n " + - "Empty body because the application is already installed."), + message = "Not Modified. \n Empty body because the application is already installed." + ), + @ApiResponse( + code = 404, + message = "Not Found. \n Application cannot be found to install." + ), @ApiResponse( code = 500, - message = "Internal Server Error. \n Error occurred while installing the application.", - response = ErrorResponse.class) + message = "Internal Server Error. \n Error occurred while installing the application." + ) }) Response installApplication( @ApiParam( name = "installationDetails", value = "The application ID and list of devices/users/roles", - required = true) + required = true + ) @Valid InstallationDetails installationDetails); + @POST + @Path("/enterprise-install-application") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Install an application to the devices belong to an enterprise entity", + notes = "This will install an application to a given list of groups/users/roles", + tags = "Subscription Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:subscription:install") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully installed the application.", + response = Application.class + ), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the application is already installed." + ), + @ApiResponse( + code = 404, + message = "Not Found. \n Application cannot be found to install." + ), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while installing the application." + ) + }) + Response enterpriseInstallApplication( + @ApiParam( + name = "enterpriseInstallationDetails", + value = "The application ID and list of devices/users/roles", + required = true) + @Valid EnterpriseInstallationDetails enterpriseInstallationDetails); + @POST @Path("/uninstall-application") @Produces(MediaType.APPLICATION_JSON) @@ -121,7 +184,7 @@ public interface SubscriptionManagementAPI { produces = MediaType.APPLICATION_JSON, httpMethod = "POST", value = "Uninstall an application", - notes = "This will uninstall an application to a given list of devices/users/roles", + notes = "This will uninstall an application from given list of devices", tags = "Subscription Management", extensions = { @Extension(properties = { @@ -134,23 +197,73 @@ public interface SubscriptionManagementAPI { @ApiResponse( code = 200, message = "OK. \n Successfully uninstalled the application.", - response = Application.class), + response = Application.class + ), @ApiResponse( code = 304, - message = "Not Modified. \n " + - "Empty body because the application is already uninstalled."), + message = "Not Modified. \n Empty body because the application is already uninstalled." + ), + @ApiResponse( + code = 404, + message = "Not Found. \n Application cannot be found to uninstall." + ), @ApiResponse( code = 500, - message = "Internal Server Error. \n Error occurred while installing the application.", - response = ErrorResponse.class) + message = "Internal Server Error. \n Error occurred while uninstalling the application." + ) }) Response uninstallApplication( @ApiParam( name = "installationDetails", - value = "The application ID and list of devices/users/roles", + value = "The application ID and list of devices", required = true) @Valid InstallationDetails installationDetails); + @POST + @Path("/enterprise-uninstall-application") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Uninstall an application from the devices belong to an enterprise entity", + notes = "This will uninstall an application from devices belong to given list of groups/users/roles", + tags = "Subscription Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:subscription:uninstall") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully uninstalled the application.", + response = Application.class + ), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the application is already uninstalled." + ), + @ApiResponse( + code = 404, + message = "Not Found. \n Application cannot be found to uninstall." + ), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while uninstalling the application." + ) + }) + Response enterpriseUninstallApplication( + @ApiParam( + name = "enterpriseInstallationDetails", + value = "The application ID and list of groups/users/roles", + required = true + ) + @Valid EnterpriseInstallationDetails enterpriseInstallationDetails); + @GET @Path("/application/{applicationUUID}/device/{deviceId}") @Produces(MediaType.APPLICATION_JSON) @@ -173,23 +286,27 @@ public interface SubscriptionManagementAPI { @ApiResponse( code = 200, message = "OK. \n Successfully installed the application.", - response = Application.class), + response = Application.class + ), @ApiResponse( code = 304, message = "Not Modified. \n " + - "Empty body because the application is already installed."), + "Empty body because the application is already installed." + ), @ApiResponse( code = 500, - message = "Internal Server Error. \n Error occurred while fetching the application.", - response = ErrorResponse.class) + message = "Internal Server Error. \n Error occurred while fetching the application." + ) }) Response getApplication( @ApiParam( name = "applicationUUID", - value = "Application ID") + value = "Application ID" + ) @QueryParam("applicationUUID") String applicationUUID, @ApiParam( name = "deviceId", - value = "The device ID") + value = "The device ID" + ) @QueryParam("deviceId") String deviceId); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java index 54d38779f7..0a290fe6fb 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java @@ -20,6 +20,8 @@ package org.wso2.carbon.device.application.mgt.store.api.services.impl; import io.swagger.annotations.ApiParam; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails; +import org.wso2.carbon.device.application.mgt.publisher.api.beans.ErrorResponse; import org.wso2.carbon.device.application.mgt.store.api.APIUtil; import org.wso2.carbon.device.application.mgt.publisher.api.services.SubscriptionManagementAPI; import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier; @@ -34,6 +36,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Response; import java.util.HashMap; import java.util.List; +import java.util.stream.Stream; /** * Implementation of Subscription Management related APIs. @@ -47,33 +50,78 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ @Override @POST @Path("/install-application") - public Response installApplication(@ApiParam(name = "installationDetails", value = "The application ID and list" + - " the devices/users/roles", required = true) @Valid InstallationDetails installationDetails) { - Object result; + public Response installApplication(@ApiParam(name = "installationDetails", value = "Application ID and list of" + + "devices", required = true) @Valid InstallationDetails installationDetails) { SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); + String applicationUUID = installationDetails.getApplicationUUID(); + + if (applicationUUID.isEmpty() || installationDetails.getDeviceIdentifiers().isEmpty()) { + String msg = "Some or all data in the incoming request is empty. Therefore unable to proceed with the " + + "installation."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + try { - String applicationUUID = installationDetails.getApplicationUUID(); - String versionName = installationDetails.getVersionName(); - if (!installationDetails.getDeviceIdentifiers().isEmpty()) { - List deviceList = installationDetails.getDeviceIdentifiers(); - result = subscriptionManager.installApplicationForDevices(applicationUUID, versionName, deviceList); - } else if (!installationDetails.getUserNameList().isEmpty()) { - List userList = installationDetails.getUserNameList(); - result = subscriptionManager.installApplicationForUsers(applicationUUID, userList, versionName); - } else if (!installationDetails.getRoleNameList().isEmpty()) { - List roleList = installationDetails.getRoleNameList(); - result = subscriptionManager.installApplicationForRoles(applicationUUID, roleList, versionName); + List failedDevices = subscriptionManager.installApplicationForDevices(applicationUUID, + installationDetails.getDeviceIdentifiers()); + HashMap response = new HashMap<>(); + response.put("failedDevices", failedDevices); + return Response.status(Response.Status.OK).entity(response).build(); + } catch (ApplicationManagementException e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("Error occurred while installing the application for devices" + ": " + e.getMessage()) + .build(); + } + } + + @Override + public Response enterpriseInstallApplication(EnterpriseInstallationDetails enterpriseInstallationDetails) { + SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); + String msg; + String applicationUUID = enterpriseInstallationDetails.getApplicationUUID(); + EnterpriseInstallationDetails.EnterpriseEntity enterpriseEntity = enterpriseInstallationDetails.getEntityType(); + List entityValueList = enterpriseInstallationDetails.getEntityValueList(); + List failedDevices; + + if (applicationUUID.isEmpty()) { + msg = "Application UUID is empty in the incoming request. Therefore unable to proceed with the " + + "installation."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + if (enterpriseEntity == null || entityValueList.isEmpty()) { + msg = "Some or all details of the entity is empty in the incoming request. Therefore unable to proceed " + + "with the installation."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + try{ + if (EnterpriseInstallationDetails.EnterpriseEntity.USER.equals(enterpriseEntity)) { + failedDevices = subscriptionManager + .installApplicationForUsers(applicationUUID, entityValueList); + } else if (EnterpriseInstallationDetails.EnterpriseEntity.ROLE.equals(enterpriseEntity)) { + failedDevices = subscriptionManager + .installApplicationForRoles(applicationUUID, entityValueList); + } else if (EnterpriseInstallationDetails.EnterpriseEntity.DEVICE_GROUP.equals(enterpriseEntity)) { + failedDevices = subscriptionManager + .installApplicationForGroups(applicationUUID, entityValueList); } else { - result = "Missing request data!"; - return Response.status(Response.Status.BAD_REQUEST).entity(result).build(); + msg = "Entity type does not match either USER, ROLE or DEVICE_GROUP. Therefore unable to proceed with " + + "the installation"; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } + HashMap response = new HashMap<>(); - response.put("failedDevices", result); + response.put("failedDevices", failedDevices); return Response.status(Response.Status.OK).entity(response).build(); } catch (ApplicationManagementException e) { - String msg = "Error occurred while installing the application"; - log.error(msg, e); - return Response.status(Response.Status.BAD_REQUEST).build(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("Error occurred while installing the application for devices" + ": " + e.getMessage()) + .build(); } } @@ -83,6 +131,12 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ return null; } + @Override + public Response enterpriseUninstallApplication( + EnterpriseInstallationDetails enterpriseInstallationDetails) { + return null; + } + @Override public Response getApplication(@ApiParam(name = "applicationUUID", value = "Application ID") String applicationUUID, @ApiParam(name = "deviceId", value = "The device ID") From f66ff60adad2cd7dad6ee2914e919d841cee8f62 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Thu, 15 Feb 2018 16:42:53 +0530 Subject: [PATCH 2/4] Adding a method to retrieve Application by UUID Application install request is made for a UUID which is associated with an application release. In order to get the details of the application to build the payload of the install application operation, it is required to get the application from the database related to the UUID. --- .../common/services/ApplicationManager.java | 8 ++ .../mgt/core/dao/ApplicationDAO.java | 10 +++ .../application/mgt/core/dao/common/Util.java | 33 +++++++ .../GenericApplicationDAOImpl.java | 86 ++++++++++++++++++- .../mgt/core/impl/ApplicationManagerImpl.java | 23 +++++ 5 files changed, 157 insertions(+), 3 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java index 1dc480a883..3eb431e12c 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java @@ -128,6 +128,14 @@ public interface ApplicationManager { */ Application getApplicationById(int applicationId) throws ApplicationManagementException; + /** + * To get an application associated with the release. + * + * @param appReleaseUUID UUID of the app release + * @return {@link Application} associated with the release + * @throws ApplicationManagementException If unable to retrieve {@link Application} associated with the given UUID + */ + Application getApplicationByRelease(String appReleaseUUID) throws ApplicationManagementException; /** * To get Application with the given UUID. diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationDAO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationDAO.java index b34d178dea..e376d038f1 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationDAO.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationDAO.java @@ -150,5 +150,15 @@ public interface ApplicationDAO { * @throws ApplicationManagementDAOException Application Management DAO Exception. */ void deleteTags(int applicationId) throws ApplicationManagementDAOException; + + /** + * To get an {@link Application} associated with the given release + * + * @param appReleaseUUID UUID of the {@link ApplicationRelease} + * @param tenantId ID of the tenant + * @return {@link Application} associated with the given release UUID + * @throws ApplicationManagementDAOException if unable to fetch the Application from the data store. + */ + Application getApplicationByRelease(String appReleaseUUID, int tenantId) throws ApplicationManagementDAOException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/Util.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/Util.java index f5c5bd33d2..5c48f38486 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/Util.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/Util.java @@ -146,6 +146,39 @@ public class Util { return application; } + + /** + * Populates {@link ApplicationRelease} object with the result obtained from the database. + * + * @param rs {@link ResultSet} from obtained from the database + * @return {@link ApplicationRelease} object populated with the data + * @throws SQLException If unable to populate {@link ApplicationRelease} object with the data + */ + public static ApplicationRelease readApplicationRelease(ResultSet rs) throws SQLException { + ApplicationRelease appRelease = new ApplicationRelease(); + + appRelease.setId(rs.getInt("RELEASE_ID")); + appRelease.setVersion(rs.getString("VERSION")); + appRelease.setTenantId(rs.getString("TENANT_ID")); + appRelease.setUuid(rs.getString("UUID")); + appRelease.setReleaseType(rs.getString("RELEASE_TYPE")); + appRelease.setPrice(rs.getDouble("APP_PRICE")); + appRelease.setAppHashValue(rs.getString("APP_HASH_VALUE")); + appRelease.setAppStoredLoc(rs.getString("STORED_LOCATION")); + appRelease.setBannerLoc(rs.getString("BANNER_LOCATION")); + appRelease.setApplicationCreator(rs.getString("CREATED_BY")); + appRelease.setCreatedAt(rs.getTimestamp("CREATED_AT")); + appRelease.setPublishedBy(rs.getString("PUBLISHED_BY")); + appRelease.setPublishedAt(rs.getTimestamp("PUBLISHED_AT")); + appRelease.setStars(rs.getInt("STARS")); + appRelease.setIsSharedWithAllTenants(rs.getInt("SHARED_WITH_ALL_TENANTS")); + appRelease.setMetaData(rs.getString("APP_META_INFO")); + appRelease.setScreenshotLoc1(rs.getString("SC_1_LOCATION")); + appRelease.setScreenshotLoc2(rs.getString("SC_2_LOCATION")); + appRelease.setScreenshotLoc3(rs.getString("SC_3_LOCATION")); + + return appRelease; + } /** * Cleans up the statement and resultset after executing the query * diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java index e3c6bf748a..ca4a69fbf3 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java @@ -21,7 +21,13 @@ package org.wso2.carbon.device.application.mgt.core.dao.impl.application; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONException; -import org.wso2.carbon.device.application.mgt.common.*; +import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.common.ApplicationList; +import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; +import org.wso2.carbon.device.application.mgt.common.Filter; +import org.wso2.carbon.device.application.mgt.common.Pagination; +import org.wso2.carbon.device.application.mgt.common.Tag; +import org.wso2.carbon.device.application.mgt.common.UnrestrictedRole; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO; @@ -29,7 +35,12 @@ import org.wso2.carbon.device.application.mgt.core.dao.common.Util; import org.wso2.carbon.device.application.mgt.core.dao.impl.AbstractDAOImpl; import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; -import java.sql.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; import java.util.List; /** @@ -122,7 +133,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic ResultSet rs = null; int isExist = 0; int index = 0; - String sql = "SELECT * FROM AP_APP WHERE NAME = ? AND TYPE = ? TENANT_ID = ?"; + String sql = "SELECT * FROM AP_APP WHERE NAME = ? AND TYPE = ? AND TENANT_ID = ?"; try{ conn = this.getDBConnection(); conn.setAutoCommit(false); @@ -525,6 +536,75 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic } } + @Override + public Application getApplicationByRelease(String appReleaseUUID, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()){ + log.debug("Getting application with the UUID (" + appReleaseUUID + ") from the database"); + } + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getDBConnection(); + String sql = "SELECT AP_APP_RELEASE.ID AS RELEASE_ID, AP_APP_RELEASE.VERSION, AP_APP_RELEASE.TENANT_ID," + + "AP_APP_RELEASE.UUID, AP_APP_RELEASE.RELEASE_TYPE, AP_APP_RELEASE.APP_PRICE, " + + "AP_APP_RELEASE.STORED_LOCATION, AP_APP_RELEASE.BANNER_LOCATION, AP_APP_RELEASE.SC_1_LOCATION," + + "AP_APP_RELEASE.SC_2_LOCATION, AP_APP_RELEASE.SC_3_LOCATION, AP_APP_RELEASE.APP_HASH_VALUE," + + "AP_APP_RELEASE.SHARED_WITH_ALL_TENANTS, AP_APP_RELEASE.APP_META_INFO, AP_APP_RELEASE.CREATED_BY," + + "AP_APP_RELEASE.CREATED_AT, AP_APP_RELEASE.PUBLISHED_BY, AP_APP_RELEASE.PUBLISHED_AT, " + + "AP_APP_RELEASE.STARS," + + "AP_APP.ID AS APP_ID, AP_APP.NAME AS APP_NAME, AP_APP.TYPE AS APP_TYPE, " + + "AP_APP.APP_CATEGORY AS APP_CATEGORY, AP_APP.IS_FREE, AP_UNRESTRICTED_ROLES.ROLE AS ROLE " + + "FROM AP_APP, AP_UNRESTRICTED_ROLES, AP_APP_RELEASE " + + "WHERE AP_APP_RELEASE.UUID=? AND AP_APP.TENANT_ID=?;"; + + stmt = conn.prepareStatement(sql); + stmt.setString(1, appReleaseUUID); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved details of the application with the UUID " + appReleaseUUID); + } + + Application application = null; + while(rs.next()) { + ApplicationRelease appRelease = Util.readApplicationRelease(rs); + application = new Application(); + + application.setId(rs.getInt("APP_ID")); + application.setName(rs.getString("APP_NAME")); + application.setType(rs.getString("APP_TYPE")); + application.setAppCategory(rs.getString("APP_CATEGORY")); + application.setIsFree(rs.getInt("IS_FREE")); + application.setIsRestricted(rs.getInt("RESTRICTED")); + + UnrestrictedRole unrestrictedRole = new UnrestrictedRole(); + unrestrictedRole.setRole(rs.getString("ROLE")); + List unrestrictedRoleList = new ArrayList<>(); + unrestrictedRoleList.add(unrestrictedRole); + + application.setUnrestrictedRoles(unrestrictedRoleList); + + List applicationReleaseList = new ArrayList<>(); + applicationReleaseList.add(appRelease); + + application.setApplicationReleases(applicationReleaseList); + } + return application; + } catch (SQLException e) { + throw new ApplicationManagementDAOException("Error occurred while getting application details with UUID " + + appReleaseUUID + " While executing query ", e); + } catch (JSONException e) { + throw new ApplicationManagementDAOException("Error occurred while parsing JSON", e); + } catch (DBConnectionException e) { + throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e); + } finally { + Util.cleanupResources(stmt, rs); + } + } + @Override public int getApplicationId(String appName, String appType, int tenantId) throws ApplicationManagementDAOException { Connection conn; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java index 0187525a0d..6375e6ee69 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java @@ -282,6 +282,29 @@ public class ApplicationManagerImpl implements ApplicationManager { } } + @Override + public Application getApplicationByRelease(String appReleaseUUID) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + Application application; + try { + ConnectionManagerUtil.openDBConnection(); + application = ApplicationManagementDAOFactory.getApplicationDAO() + .getApplicationByRelease(appReleaseUUID, tenantId); + + if (application.getUnrestrictedRoles().isEmpty() || isRoleExists(application.getUnrestrictedRoles(), + userName)) { + return application; + } + return null; + } catch (UserStoreException e) { + throw new ApplicationManagementException( + "User-store exception while getting application with the application UUID " + appReleaseUUID); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + public Boolean verifyApplicationExistenceById(int appId) throws ApplicationManagementException { try { Boolean isAppExist; From debe93cb03c4fedb087db80eee1bf998bc576d88 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Fri, 16 Feb 2018 13:38:15 +0530 Subject: [PATCH 3/4] Improving application subscription API Changing the DeviceIdentifier bean to the same as org.wso2.carbon.device.mgt.common.DeviceIdentifier and implement the install app device. Adding an ApplicationInstallResponse as the response to respond with more information to the application install request. related to wso2/product-iots#1688 --- .../pom.xml | 5 + .../common/ApplicationInstallResponse.java | 71 +++++++++++ .../mgt/common/DeviceIdentifier.java | 71 ----------- .../mgt/common/InstallationDetails.java | 1 + .../common/services/SubscriptionManager.java | 19 +-- .../pom.xml | 2 +- .../core/impl/SubscriptionManagerImpl.java | 117 +++++++++++++++--- .../pom.xml | 4 + .../services/SubscriptionManagementAPI.java | 9 +- .../impl/SubscriptionManagementAPIImpl.java | 24 ++-- 10 files changed, 202 insertions(+), 121 deletions(-) create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/ApplicationInstallResponse.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/pom.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/pom.xml index da6c8bc20f..0a807f27b8 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/pom.xml +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/pom.xml @@ -58,6 +58,7 @@ org.apache.commons.codec.binary;version="${commons-codec.wso2.osgi.version.range}", org.wso2.carbon.device.mgt.core.dto.*;version="${carbon.device.mgt.version}", org.wso2.carbon.device.mgt.core.dao.*;version="${carbon.device.mgt.version}", + org.wso2.carbon.device.mgt.common.operation.mgt.*;version="${carbon.device.mgt.version}", org.w3c.dom, org.json, org.xml.sax, @@ -114,6 +115,10 @@ org.wso2.carbon.devicemgt org.wso2.carbon.device.mgt.core + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/ApplicationInstallResponse.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/ApplicationInstallResponse.java new file mode 100644 index 0000000000..fa0c56b2d7 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/ApplicationInstallResponse.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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.application.mgt.common; + +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; + +import java.util.List; + +public class ApplicationInstallResponse { + @ApiModelProperty( + name = "successfulDevices", + value = "List of successful devices", + dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]" + ) + private List successfulDevices; + + @ApiModelProperty( + name = "failedDevices", + value = "List of failed devices", + dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]" + ) + private List failedDevices; + + @ApiModelProperty( + name = "activity", + value = "Activity corresponding to the operation" + ) + private Activity activity; + + public List getSuccessfulDevices() { + return successfulDevices; + } + + public void setSuccessfulDevices(List successfulDevices) { + this.successfulDevices = successfulDevices; + } + + public List getFailedDevices() { + return failedDevices; + } + + public void setFailedDevices(List failedDevices) { + this.failedDevices = failedDevices; + } + + public Activity getActivity() { + return activity; + } + + public void setActivity(Activity activity) { + this.activity = activity; + } +} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java deleted file mode 100644 index 8f7e656319..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2014, 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.application.mgt.common; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - - -@ApiModel(value = "DeviceIdentifier", description = "This contains device details that is used to identify a device " + - "uniquely.") -public class DeviceIdentifier { - - @ApiModelProperty( - name = "id", - value = "Identity of the device.", - required = true, - example = "d24f870f390352a4") - private String id; - - @ApiModelProperty( - name = "type", - value = "Type of the device.", - required = true, - example = "android") - private String type; - - public DeviceIdentifier() {} - - public DeviceIdentifier(String id, String type) { - this.id = id; - this.type = type; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type.trim(); - } - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - @Override - public String toString() { - return "deviceId {" + - "id='" + id + '\'' + - ", type='" + type + '\'' + - '}'; - } -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java index 87601d6cc8..55dc80ae79 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/InstallationDetails.java @@ -18,6 +18,7 @@ package org.wso2.carbon.device.application.mgt.common; import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import java.util.List; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java index 42386768db..078e233816 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java @@ -18,8 +18,9 @@ */ package org.wso2.carbon.device.application.mgt.common.services; -import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import java.util.List; @@ -31,40 +32,40 @@ public interface SubscriptionManager { * To install an application to given list of devices. * @param applicationUUID ID of the application to install * @param deviceList list of device ID's to install the application - * @return Failed Device List which the application was unable to install + * @return {@link ApplicationInstallResponse} object which contains installed application and devices * @throws ApplicationManagementException if unable to install the application to the given devices */ - List installApplicationForDevices(String applicationUUID, List deviceList) + ApplicationInstallResponse installApplicationForDevices(String applicationUUID, List deviceList) throws ApplicationManagementException; /** * To install an application to given list of users. * @param applicationUUID ID of the application to install * @param userList list of users to install the application - * @return Failed Device List which the application was unable to install + * @return {@link ApplicationInstallResponse} object which contains installed application and devices * @throws ApplicationManagementException if unable to install the application to devices belong to given users */ - List installApplicationForUsers(String applicationUUID, List userList) + ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List userList) throws ApplicationManagementException; /** * To install an application to given list of roles. * @param applicationUUID ID of the application to install * @param roleList list of roles to install the application - * @return Failed Device List which the application was unable to install + * @return {@link ApplicationInstallResponse} object which contains installed application and devices * @throws ApplicationManagementException if unable to install the application to devices belong to given roles */ - List installApplicationForRoles(String applicationUUID, List roleList) + ApplicationInstallResponse installApplicationForRoles(String applicationUUID, List roleList) throws ApplicationManagementException; /** * To install an application to given list of roles. * @param applicationUUID ID of the application to install * @param deviceGroupList list of device groups to install the application - * @return Failed Device List which the application was unable to install + * @return {@link ApplicationInstallResponse} object which contains installed application and devices * @throws ApplicationManagementException if unable to install the application to devices belong to given groups */ - List installApplicationForGroups(String applicationUUID, List deviceGroupList) + ApplicationInstallResponse installApplicationForGroups(String applicationUUID, List deviceGroupList) throws ApplicationManagementException; /** diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml index 31014dc167..57b8686ef8 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml @@ -42,7 +42,7 @@ org.apache.felix maven-bundle-plugin - 1.4.0 + 3.0.1 true diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java index e9d1375e60..74892a9548 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -19,30 +19,31 @@ package org.wso2.carbon.device.application.mgt.core.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; -import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager; -import org.wso2.carbon.device.application.mgt.common.services.ApplicationReleaseManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; import org.wso2.carbon.device.application.mgt.core.util.ApplicationManagementUtil; import org.wso2.carbon.device.application.mgt.core.util.HelperUtil; import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.InvalidDeviceException; -import org.wso2.carbon.device.mgt.common.app.mgt.DeviceApplicationMapping; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.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.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; +import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * This is the default implementation for the Subscription Manager. @@ -53,7 +54,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { private static final String INSTALL_APPLICATION = "INSTALL_APPLICATION"; @Override - public List installApplicationForDevices(String applicationUUID, + public ApplicationInstallResponse installApplicationForDevices(String applicationUUID, List deviceList) throws ApplicationManagementException { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + deviceList.size() + "devices."); @@ -62,7 +63,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } @Override - public List installApplicationForUsers(String applicationUUID, List userList) + public ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List userList) throws ApplicationManagementException { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + userList.size() + " users."); @@ -86,7 +87,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } @Override - public List installApplicationForRoles(String applicationUUID, List roleList) + public ApplicationInstallResponse installApplicationForRoles(String applicationUUID, List roleList) throws ApplicationManagementException { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + roleList.size() + " roles."); @@ -110,7 +111,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } @Override - public List installApplicationForGroups(String applicationUUID, List deviceGroupList) + public ApplicationInstallResponse installApplicationForGroups(String applicationUUID, List deviceGroupList) throws ApplicationManagementException { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + deviceGroupList.size() + " groups."); @@ -140,16 +141,92 @@ public class SubscriptionManagerImpl implements SubscriptionManager { return null; } - private List installApplication(String applicationUUID, List deviceList) + private ApplicationInstallResponse installApplication(String applicationUUID, List deviceList) throws ApplicationManagementException { - //todo: 1. get application and release. - ApplicationReleaseManager applicationReleaseManager = ApplicationManagementUtil - .getApplicationReleaseManagerInstance(); - ApplicationRelease applicationRelease = applicationReleaseManager.getReleaseByUuid(applicationUUID); - //todo: 2. check type and filter devices. - //todo: 3. generate url based on application attributes and app release attributes - - //Todo: check if app type is installable for all the device types: apk -> android, ipa -> ios, webclip -> both - return null; + DeviceManagementProviderService deviceManagementProviderService = HelperUtil + .getDeviceManagementProviderService(); + + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + Application application = applicationManager.getApplicationByRelease(applicationUUID); + ApplicationInstallResponse response = validateDevices(deviceList, application.getType()); + + Map> deviceTypeIdentifierMap = response.getSuccessfulDevices().stream() + .collect(Collectors.groupingBy(DeviceIdentifier::getType)); + + for(Map.Entry> entry: deviceTypeIdentifierMap.entrySet()) { + Operation operation = generateOperationPayloadByDeviceType(entry.getKey(), application); + try { + Activity activity = deviceManagementProviderService + .addOperation(entry.getKey(), operation, entry.getValue()); + response.setActivity(activity); + } catch (OperationManagementException e) { + throw new ApplicationManagementException("Error occurred while adding the application install" + + " operation to devices" , e); + } catch (InvalidDeviceException e) { + //This exception should not occur because the validation has already been done. + throw new ApplicationManagementException("The list of device identifiers are invalid"); + } + } + + //todo: add device application mapping + + return response; + } + + private Operation generateOperationPayloadByDeviceType(String deviceType, Application application) { + ProfileOperation operation = new ProfileOperation(); + operation.setCode(INSTALL_APPLICATION); + operation.setType(Operation.Type.PROFILE); + + //todo: generate operation payload correctly for all types of devices. + operation.setPayLoad( + "{'type':'enterprise', 'url':'" + application.getApplicationReleases().get(0).getAppStoredLoc() + + "', 'app':'" + application.getApplicationReleases().get(0).getUuid() + "'}"); + return operation; + } + + /** + * Validates the preconditions which is required to satisfy from the device which is required to install the + * application. + * + * This method check two preconditions whether the application type is compatible to install in the device and + * whether the device is enrolled in the system. + * + * @param deviceIdentifierList List of {@link DeviceIdentifier} which the validation happens + * @param appPlatform type of the application + * @return {@link ApplicationInstallResponse} which contains compatible and incompatible device identifiers + */ + private ApplicationInstallResponse validateDevices(List deviceIdentifierList, + String appPlatform) { + ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse(); + List failedDevices = new ArrayList<>(); + List compatibleDevices = new ArrayList<>(); + + for (DeviceIdentifier deviceIdentifier : deviceIdentifierList) { + try { + if (appPlatform == null || !(appPlatform.equals("WEB_CLIP") || appPlatform + .equals(deviceIdentifier.getType()))) { + log.error("Device with ID: [" + deviceIdentifier.getId() + "] of type: [" + + deviceIdentifier.getType() + "] is not compatible with the application of type: [" + + appPlatform + "]"); + failedDevices.add(deviceIdentifier); + continue; + } + + if (!DeviceManagerUtil.isValidDeviceIdentifier(deviceIdentifier)) { + log.error("Device with ID: [" + deviceIdentifier.getId() + "] is not valid to install the " + + "application."); + applicationInstallResponse.getFailedDevices().add(deviceIdentifier); + } + } catch (DeviceManagementException e) { + log.error("Error occurred while validating the device: [" + deviceIdentifier.getId() + "]", e); + failedDevices.add(deviceIdentifier); + } + compatibleDevices.add(deviceIdentifier); + } + applicationInstallResponse.setFailedDevices(failedDevices); + applicationInstallResponse.setSuccessfulDevices(compatibleDevices); + + return applicationInstallResponse; } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/pom.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/pom.xml index 6ed2dd59bf..1a7bbecce2 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/pom.xml +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/pom.xml @@ -163,6 +163,10 @@ org.wso2.carbon.device.application.mgt.common provided + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + io.swagger swagger-annotations diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java index 05b20d318e..8449da1cf5 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java @@ -29,6 +29,7 @@ import io.swagger.annotations.SwaggerDefinition; import io.swagger.annotations.Tag; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails; import org.wso2.carbon.device.application.mgt.common.InstallationDetails; @@ -107,8 +108,8 @@ public interface SubscriptionManagementAPI { value = { @ApiResponse( code = 200, - message = "OK. \n Successfully installed the application.", - response = Application.class + message = "OK. \n Successfully sent the install application operation.", + response = ApplicationInstallResponse.class ), @ApiResponse( code = 304, @@ -152,8 +153,8 @@ public interface SubscriptionManagementAPI { value = { @ApiResponse( code = 200, - message = "OK. \n Successfully installed the application.", - response = Application.class + message = "OK. \n Successfully sent the install application operation.", + response = ApplicationInstallResponse.class ), @ApiResponse( code = 304, diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java index 0a290fe6fb..b183dbc629 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java @@ -20,14 +20,14 @@ package org.wso2.carbon.device.application.mgt.store.api.services.impl; import io.swagger.annotations.ApiParam; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails; -import org.wso2.carbon.device.application.mgt.publisher.api.beans.ErrorResponse; import org.wso2.carbon.device.application.mgt.store.api.APIUtil; import org.wso2.carbon.device.application.mgt.publisher.api.services.SubscriptionManagementAPI; -import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.application.mgt.common.InstallationDetails; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import javax.validation.Valid; import javax.ws.rs.POST; @@ -36,7 +36,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Response; import java.util.HashMap; import java.util.List; -import java.util.stream.Stream; /** * Implementation of Subscription Management related APIs. @@ -63,10 +62,8 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ } try { - List failedDevices = subscriptionManager.installApplicationForDevices(applicationUUID, + ApplicationInstallResponse response= subscriptionManager.installApplicationForDevices(applicationUUID, installationDetails.getDeviceIdentifiers()); - HashMap response = new HashMap<>(); - response.put("failedDevices", failedDevices); return Response.status(Response.Status.OK).entity(response).build(); } catch (ApplicationManagementException e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR) @@ -82,7 +79,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ String applicationUUID = enterpriseInstallationDetails.getApplicationUUID(); EnterpriseInstallationDetails.EnterpriseEntity enterpriseEntity = enterpriseInstallationDetails.getEntityType(); List entityValueList = enterpriseInstallationDetails.getEntityValueList(); - List failedDevices; + ApplicationInstallResponse response; if (applicationUUID.isEmpty()) { msg = "Application UUID is empty in the incoming request. Therefore unable to proceed with the " @@ -100,23 +97,18 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ try{ if (EnterpriseInstallationDetails.EnterpriseEntity.USER.equals(enterpriseEntity)) { - failedDevices = subscriptionManager - .installApplicationForUsers(applicationUUID, entityValueList); + response = subscriptionManager.installApplicationForUsers(applicationUUID, entityValueList); } else if (EnterpriseInstallationDetails.EnterpriseEntity.ROLE.equals(enterpriseEntity)) { - failedDevices = subscriptionManager - .installApplicationForRoles(applicationUUID, entityValueList); + response = subscriptionManager.installApplicationForRoles(applicationUUID, entityValueList); } else if (EnterpriseInstallationDetails.EnterpriseEntity.DEVICE_GROUP.equals(enterpriseEntity)) { - failedDevices = subscriptionManager - .installApplicationForGroups(applicationUUID, entityValueList); + response = subscriptionManager.installApplicationForGroups(applicationUUID, entityValueList); } else { msg = "Entity type does not match either USER, ROLE or DEVICE_GROUP. Therefore unable to proceed with " + "the installation"; log.error(msg); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } - - HashMap response = new HashMap<>(); - response.put("failedDevices", failedDevices); + return Response.status(Response.Status.OK).entity(response).build(); } catch (ApplicationManagementException e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR) From b911c9e169eb9a51bc53ba957ce2caf620e82b1b Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Mon, 19 Feb 2018 21:07:31 +0530 Subject: [PATCH 4/4] Adding entity application mapping to the database When an application installation request is made other than adding an application install operation a mapping between the devices and the installed applications are kept in the database. In a case where an enterprise wide installation happens a mapping is made with the respective entity and the application. This commit implement the mapping function. Related to issue wso2/product-iots#1688 --- .../mgt/core/dao/SubscriptionDAO.java | 65 +++++++- .../GenericSubscriptionDAOImpl.java | 157 ++++++++++++++---- .../core/impl/SubscriptionManagerImpl.java | 133 ++++++++++++--- .../impl/SubscriptionManagementAPIImpl.java | 5 +- 4 files changed, 300 insertions(+), 60 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java index 59f3b532f1..e7d02adb78 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java @@ -18,12 +18,71 @@ */ package org.wso2.carbon.device.application.mgt.core.dao; +import org.wso2.carbon.device.application.mgt.common.Application; +import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; + +import java.util.List; + /** * This interface provides the list of operations that are supported with subscription database. * */ -import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; - public interface SubscriptionDAO { - int addDeviceApplicationMapping(String deviceIdentifier, String applicationUUID, boolean installed) throws ApplicationManagementException; + + /** + * Adds a mapping between devices and the application which the application is installed on. + * + * @param tenantId id of the tenant + * @param subscribedBy username of the user who subscribe the application + * @param deviceList List of {@link Device} which the application is installed on + * @param appId id of the {@link Application} which installs + * @param releaseId id of the {@link org.wso2.carbon.device.application.mgt.common.ApplicationRelease} + * @throws ApplicationManagementDAOException If unable to add a mapping between device and application + */ + void subscribeDeviceToApplication(int tenantId, String subscribedBy, List deviceList, int appId, + int releaseId) throws ApplicationManagementDAOException; + + /** + * Adds a mapping between user and the application which the application is installed on. This mapping will be + * added when an enterprise installation triggered to the user. + * + * @param tenantId id of the tenant + * @param subscribedBy username of the user who subscribe the application + * @param userList list of user names of the users whose devices are subscribed to the application + * @param appId id of the {@link Application} which installs + * @param releaseId id of the {@link org.wso2.carbon.device.application.mgt.common.ApplicationRelease} + * @throws ApplicationManagementDAOException If unable to add a mapping between device and application + */ + void subscribeUserToApplication(int tenantId, String subscribedBy, List userList, int appId, int releaseId) + throws ApplicationManagementDAOException; + + /** + * Adds a mapping between user and the application which the application is installed on. This mapping will be + * added when an enterprise installation triggered to the role. + * + * @param tenantId id of the tenant + * @param subscribedBy username of the user who subscribe the application + * @param roleList list of roles which belongs devices are subscribed to the application + * @param appId id of the {@link Application} which installs + * @param releaseId id of the {@link org.wso2.carbon.device.application.mgt.common.ApplicationRelease} + * @throws ApplicationManagementDAOException If unable to add a mapping between device and application + */ + void subscribeRoleToApplication(int tenantId, String subscribedBy, List roleList, int appId, int releaseId) + throws ApplicationManagementDAOException; + + /** + * Adds a mapping between user and the application which the application is installed on. This mapping will be + * added when an enterprise installation triggered to the role. + * + * @param tenantId id of the tenant + * @param subscribedBy username of the user who subscribe the application + * @param groupList list of {@link DeviceGroup} which belongs the devices that are subscribed to the application + * @param appId id of the {@link Application} which installs + * @param releaseId id of the {@link org.wso2.carbon.device.application.mgt.common.ApplicationRelease} + * @throws ApplicationManagementDAOException If unable to add a mapping between device and application + */ + void subscribeGroupToApplication(int tenantId, String subscribedBy, List groupList, int appId, + int releaseId) throws ApplicationManagementDAOException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java index b2d2b520d1..3a89159814 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java @@ -19,55 +19,152 @@ package org.wso2.carbon.device.application.mgt.core.dao.impl.subscription; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; +import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; import org.wso2.carbon.device.application.mgt.core.dao.SubscriptionDAO; import org.wso2.carbon.device.application.mgt.core.dao.common.Util; import org.wso2.carbon.device.application.mgt.core.dao.impl.AbstractDAOImpl; +import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; -import java.sql.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements SubscriptionDAO { private static Log log = LogFactory.getLog(GenericSubscriptionDAOImpl.class); @Override - public int addDeviceApplicationMapping(String deviceIdentifier, String applicationUUID, boolean installed) throws - ApplicationManagementException { + public void subscribeDeviceToApplication(int tenantId, String subscribedBy, List deviceList, int appId, + int releaseId) throws ApplicationManagementDAOException { Connection conn; PreparedStatement stmt = null; - ResultSet rs = null; - int mappingId = -1; try { conn = this.getDBConnection(); - String sql = "SELECT ID FROM APPM_DEVICE_APPLICATION_MAPPING WHERE DEVICE_IDENTIFIER = ? AND " + - "APPLICATION_UUID = ?"; + long time = System.currentTimeMillis() / 1000; + String sql = "INSERT INTO AP_DEVICE_SUBSCRIPTION(TENANT_ID, SUBSCRIBED_BY, SUBSCRIBED_TIMESTAMP, " + + "DM_DEVICE_ID, AP_APP_RELEASE_ID, AP_APP_ID) VALUES (?, ?, ?, ?, ?, ?)"; stmt = conn.prepareStatement(sql); - stmt.setString(1, deviceIdentifier); - stmt.setString(2, applicationUUID); - rs = stmt.executeQuery(); + for (Device device : deviceList) { + stmt.setInt(1, tenantId); + stmt.setString(2, subscribedBy); + stmt.setLong(3, time); + stmt.setInt(4, device.getId()); + stmt.setInt(5, releaseId); + stmt.setInt(6, appId); + stmt.addBatch(); + if (log.isDebugEnabled()) { + log.debug("Adding a mapping to device ID[" + device.getId() + "] to the application [" + appId + + "], release[" + releaseId + "]"); + } + } + stmt.executeBatch(); + } catch (SQLException | DBConnectionException e) { + throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB", + e); + } finally { + Util.cleanupResources(stmt, null); + } + } + + @Override + public void subscribeUserToApplication(int tenantId, String subscribedBy, List userList, int appId, + int releaseId) throws ApplicationManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getDBConnection(); + long time = System.currentTimeMillis() / 1000; + String sql = "INSERT INTO AP_USER_SUBSCRIPTION(TENANT_ID, SUBSCRIBED_BY, SUBSCRIBED_TIMESTAMP, " + + "USER_NAME, AP_APP_RELEASE_ID, AP_APP_ID) VALUES (?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + for (String user : userList) { + stmt = conn.prepareStatement(sql); + stmt.setInt(1, tenantId); + stmt.setString(2, subscribedBy); + stmt.setLong(3, time); + stmt.setString(4, user); + stmt.setInt(5, releaseId); + stmt.setInt(6, appId); + stmt.addBatch(); + if (log.isDebugEnabled()) { + log.debug("Adding a mapping to user[" + user + "] to the application [" + appId + "], release[" + + releaseId + "]"); + } + } + stmt.executeBatch(); + } catch (SQLException | DBConnectionException e) { + throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB", + e); + } finally { + Util.cleanupResources(stmt, null); + } + } - if (!rs.next()) { - sql = "INSERT INTO APPM_DEVICE_APPLICATION_MAPPING (DEVICE_IDENTIFIER, APPLICATION_UUID, " + - "INSTALLED) VALUES (?, ?, ?)"; - stmt = conn.prepareStatement(sql, new String[]{"id"}); - stmt.setString(1, deviceIdentifier); - stmt.setString(2, applicationUUID); - stmt.setBoolean(3, installed); - stmt.executeUpdate(); + @Override + public void subscribeRoleToApplication(int tenantId, String subscribedBy, List roleList, int appId, + int releaseId) throws ApplicationManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getDBConnection(); + long time = System.currentTimeMillis() / 1000; + String sql = "INSERT INTO AP_ROLE_SUBSCRIPTION(TENANT_ID, SUBSCRIBED_BY, SUBSCRIBED_TIMESTAMP, " + + "ROLE_NAME, AP_APP_RELEASE_ID, AP_APP_ID) VALUES (?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + for (String role : roleList) { + stmt.setInt(1, tenantId); + stmt.setString(2, subscribedBy); + stmt.setLong(3, time); + stmt.setString(4, role); + stmt.setInt(5, releaseId); + stmt.setInt(6, appId); + stmt.addBatch(); + if (log.isDebugEnabled()) { + log.debug("Adding a mapping to role[" + role + "] to the application [" + appId + "], release[" + + releaseId + "]"); + } + } + stmt.executeBatch(); + } catch (SQLException | DBConnectionException e) { + throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB", + e); + } finally { + Util.cleanupResources(stmt, null); + } + } - rs = stmt.getGeneratedKeys(); - if (rs.next()) { - mappingId = rs.getInt(1); + @Override + public void subscribeGroupToApplication(int tenantId, String subscribedBy, List groupList, int appId, + int releaseId) throws ApplicationManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getDBConnection(); + long time = System.currentTimeMillis() / 1000; + String sql = "INSERT INTO AP_GROUP_SUBSCRIPTION(TENANT_ID, SUBSCRIBED_BY, SUBSCRIBED_TIMESTAMP, " + + "DM_GROUP_ID, AP_APP_RELEASE_ID, AP_APP_ID) VALUES (?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + for (DeviceGroup group : groupList) { + stmt.setInt(1, tenantId); + stmt.setString(2, subscribedBy); + stmt.setLong(3, time); + stmt.setInt(4, group.getGroupId()); + stmt.setInt(5, releaseId); + stmt.setInt(6, appId); + stmt.addBatch(); + if (log.isDebugEnabled()) { + log.debug("Adding a mapping to group ID[" + group.getGroupId() + "] to the application [" + appId + + "], release[" + releaseId + "]"); } - return mappingId; - } else { - log.warn("Device[" + deviceIdentifier + "] application[" + applicationUUID + "] mapping already " + - "exists in the DB"); - return -1; } - } catch (SQLException e) { - throw new ApplicationManagementException("Error occurred while adding device application mapping to DB", e); + stmt.executeBatch(); + } catch (SQLException | DBConnectionException e) { + throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB", + e); } finally { - Util.cleanupResources(stmt, rs); + Util.cleanupResources(stmt, null); } } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java index 74892a9548..b82057447f 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -19,15 +19,19 @@ package org.wso2.carbon.device.application.mgt.core.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.application.mgt.common.Application; import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; -import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; +import org.wso2.carbon.device.application.mgt.core.dao.SubscriptionDAO; +import org.wso2.carbon.device.application.mgt.core.dao.common.ApplicationManagementDAOFactory; import org.wso2.carbon.device.application.mgt.core.util.ApplicationManagementUtil; +import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil; import org.wso2.carbon.device.application.mgt.core.util.HelperUtil; 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.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; @@ -52,6 +56,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager { private static final Log log = LogFactory.getLog(SubscriptionManagerImpl.class); private static final String INSTALL_APPLICATION = "INSTALL_APPLICATION"; + private SubscriptionDAO subscriptionDAO; + + public SubscriptionManagerImpl() { + this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO(); + } @Override public ApplicationInstallResponse installApplicationForDevices(String applicationUUID, @@ -59,7 +68,10 @@ public class SubscriptionManagerImpl implements SubscriptionManager { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + deviceList.size() + "devices."); } - return installApplication(applicationUUID, deviceList); + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + Application application = applicationManager.getApplicationByRelease(applicationUUID); + + return installApplication(application, deviceList); } @Override @@ -68,13 +80,15 @@ public class SubscriptionManagerImpl implements SubscriptionManager { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + userList.size() + " users."); } + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + Application application = applicationManager.getApplicationByRelease(applicationUUID); List deviceList = new ArrayList<>(); for (String user : userList) { try { List devicesOfUser = HelperUtil.getDeviceManagementProviderService().getDevicesOfUser(user); - for (Device device : devicesOfUser) { - deviceList.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); - } + devicesOfUser.stream() + .map(device -> new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())) + .forEach(deviceList::add); if (log.isDebugEnabled()) { log.debug(devicesOfUser.size() + " found for the provided user list"); } @@ -83,7 +97,22 @@ public class SubscriptionManagerImpl implements SubscriptionManager { e); } } - return installApplication(applicationUUID, deviceList); + + ApplicationInstallResponse response = installApplication(application, deviceList); + + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + int applicationReleaseId = application.getApplicationReleases().get(0).getId(); + + try { + ConnectionManagerUtil.openDBConnection(); + subscriptionDAO.subscribeUserToApplication(tenantId, subscriber, userList, application.getId(), + applicationReleaseId); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + + return response; } @Override @@ -92,13 +121,15 @@ public class SubscriptionManagerImpl implements SubscriptionManager { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + roleList.size() + " roles."); } + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + Application application = applicationManager.getApplicationByRelease(applicationUUID); List deviceList = new ArrayList<>(); for (String role : roleList) { try { List devicesOfRole = HelperUtil.getDeviceManagementProviderService().getAllDevicesOfRole(role); - for (Device device : devicesOfRole) { - deviceList.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); - } + devicesOfRole.stream() + .map(device -> new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())) + .forEach(deviceList::add); if (log.isDebugEnabled()) { log.debug(devicesOfRole.size() + " found for role: " + role); } @@ -107,7 +138,22 @@ public class SubscriptionManagerImpl implements SubscriptionManager { "Error when extracting the device list from role[" + role + "].", e); } } - return installApplication(applicationUUID, deviceList); + + ApplicationInstallResponse response = installApplication(application, deviceList); + + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + int applicationReleaseId = application.getApplicationReleases().get(0).getId(); + + try { + ConnectionManagerUtil.openDBConnection(); + subscriptionDAO.subscribeRoleToApplication(tenantId, subscriber, roleList, application.getId(), + applicationReleaseId); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + + return response; } @Override @@ -116,23 +162,42 @@ public class SubscriptionManagerImpl implements SubscriptionManager { if (log.isDebugEnabled()) { log.debug("Install application: " + applicationUUID + " to " + deviceGroupList.size() + " groups."); } + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + Application application = applicationManager.getApplicationByRelease(applicationUUID); GroupManagementProviderService groupManagementProviderService = HelperUtil.getGroupManagementProviderService(); + List groupList = new ArrayList<>(); List deviceList = new ArrayList<>(); for (String groupName : deviceGroupList) { try { DeviceGroup deviceGroup = groupManagementProviderService.getGroup(groupName); + groupList.add(deviceGroup); int deviceCount = groupManagementProviderService.getDeviceCount(deviceGroup.getGroupId()); List devicesOfGroups = groupManagementProviderService .getDevices(deviceGroup.getGroupId(), 0, deviceCount); - for (Device device : devicesOfGroups) { - deviceList.add(new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())); - } + devicesOfGroups.stream() + .map(device -> new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())) + .forEach(deviceList::add); } catch (GroupManagementException e) { throw new ApplicationManagementException( "Error when extracting the device list from group[" + groupName + "].", e); } } - return installApplication(applicationUUID, deviceList); + + ApplicationInstallResponse response = installApplication(application, deviceList); + + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + int applicationReleaseId = application.getApplicationReleases().get(0).getId(); + + try { + ConnectionManagerUtil.openDBConnection(); + subscriptionDAO.subscribeGroupToApplication(tenantId, subscriber, groupList, application.getId(), + applicationReleaseId); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + + return response; } @Override @@ -141,34 +206,54 @@ public class SubscriptionManagerImpl implements SubscriptionManager { return null; } - private ApplicationInstallResponse installApplication(String applicationUUID, List deviceList) - throws ApplicationManagementException { + private ApplicationInstallResponse installApplication(Application application, + List deviceIdentifierList) throws ApplicationManagementException { DeviceManagementProviderService deviceManagementProviderService = HelperUtil .getDeviceManagementProviderService(); - ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); - Application application = applicationManager.getApplicationByRelease(applicationUUID); - ApplicationInstallResponse response = validateDevices(deviceList, application.getType()); - + ApplicationInstallResponse response = validateDevices(deviceIdentifierList, application.getType()); + /* + Group the valid device list by device type. Following lambda expression produces a map containing device type + as the key and the list of device identifiers as the corresponding value. + */ Map> deviceTypeIdentifierMap = response.getSuccessfulDevices().stream() .collect(Collectors.groupingBy(DeviceIdentifier::getType)); - for(Map.Entry> entry: deviceTypeIdentifierMap.entrySet()) { + for (Map.Entry> entry : deviceTypeIdentifierMap.entrySet()) { Operation operation = generateOperationPayloadByDeviceType(entry.getKey(), application); try { Activity activity = deviceManagementProviderService .addOperation(entry.getKey(), operation, entry.getValue()); response.setActivity(activity); } catch (OperationManagementException e) { - throw new ApplicationManagementException("Error occurred while adding the application install" - + " operation to devices" , e); + response.setSuccessfulDevices(null); + response.setFailedDevices(deviceIdentifierList); + throw new ApplicationManagementException("Error occurred while adding the application install " + + "operation to devices", e); } catch (InvalidDeviceException e) { //This exception should not occur because the validation has already been done. throw new ApplicationManagementException("The list of device identifiers are invalid"); } } - //todo: add device application mapping + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + int applicationReleaseId = application.getApplicationReleases().get(0).getId(); + try { + ConnectionManagerUtil.openDBConnection(); + List deviceList = new ArrayList<>(); + for (DeviceIdentifier deviceIdentifier : response.getSuccessfulDevices()) { + try { + deviceList.add(deviceManagementProviderService.getDevice(deviceIdentifier)); + } catch (DeviceManagementException e) { + log.error("Unable to fetch device for device identifier: " + deviceIdentifier.toString()); + } + } + subscriptionDAO.subscribeDeviceToApplication(tenantId, subscriber, deviceList, application.getId(), + applicationReleaseId); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } return response; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java index b183dbc629..558400b39c 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java @@ -62,7 +62,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ } try { - ApplicationInstallResponse response= subscriptionManager.installApplicationForDevices(applicationUUID, + ApplicationInstallResponse response = subscriptionManager.installApplicationForDevices(applicationUUID, installationDetails.getDeviceIdentifiers()); return Response.status(Response.Status.OK).entity(response).build(); } catch (ApplicationManagementException e) { @@ -95,7 +95,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } - try{ + try { if (EnterpriseInstallationDetails.EnterpriseEntity.USER.equals(enterpriseEntity)) { response = subscriptionManager.installApplicationForUsers(applicationUUID, entityValueList); } else if (EnterpriseInstallationDetails.EnterpriseEntity.ROLE.equals(enterpriseEntity)) { @@ -108,7 +108,6 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ log.error(msg); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } - return Response.status(Response.Status.OK).entity(response).build(); } catch (ApplicationManagementException e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR)