From 6dafe59eab3e746165c4fce529fe58cdbed65e2e Mon Sep 17 00:00:00 2001 From: lasanthaDLPDS Date: Thu, 2 May 2019 02:42:30 +0530 Subject: [PATCH] Improve application create functionality --- .../GenericApplicationDAOImpl.java | 2 +- .../mgt/core/impl/ApplicationManagerImpl.java | 228 +++++++++++------- .../ApplicationManagementPublisherAPI.java | 1 + ...ApplicationManagementPublisherAPIImpl.java | 25 +- 4 files changed, 153 insertions(+), 103 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/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 64dc0bd984..5565eb43b8 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 @@ -197,7 +197,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic if (!StringUtils.isEmpty(filter.getAppReleaseState())) { sql += " AND AP_APP_RELEASE.CURRENT_STATE = ?"; } - if (deviceTypeId > 0) { + if (deviceTypeId != -1) { sql += " AND AP_APP.DEVICE_TYPE_ID = ?"; } 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 68f64b4a96..3007cc8607 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 @@ -87,6 +87,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -135,79 +136,126 @@ public class ApplicationManagerImpl implements ApplicationManager { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); - ApplicationDTO applicationDTO; - Application application; if (log.isDebugEnabled()) { log.debug("Application create request is received for the tenant : " + tenantId + " From" + " the user : " + userName); } - try { - applicationDTO = appWrapperToAppDTO(applicationWrapper); - ApplicationReleaseDTO initialApplicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); - applicationDTO.getApplicationReleaseDTOs().clear(); - ApplicationReleaseDTO applicationReleaseDTO = addApplicationReleaseArtifacts(applicationDTO.getType(), - applicationWrapper.getDeviceType(), initialApplicationReleaseDTO, applicationArtifact, false); - applicationDTO.getApplicationReleaseDTOs().add(addImageArtifacts(applicationReleaseDTO, applicationArtifact)); - } catch (UnexpectedServerErrorException e) { - String msg = "Error occurred when getting Device Type data."; - log.error(msg); - throw new ApplicationManagementException(msg, e); - } catch (ResourceManagementException e) { - String msg = "Error Occured when uploading artifacts of the application: " + applicationWrapper.getName(); - log.error(msg); - throw new ApplicationManagementException(msg, e); - } + ApplicationDTO applicationDTO; + List unrestrictedRoles; + Optional category; + List tags; + //validating and verifying application data try { - List applicationReleaseEntities = new ArrayList<>(); - ApplicationReleaseDTO applicationReleaseDTO; + ConnectionManagerUtil.openDBConnection(); + applicationDTO = appWrapperToAppDTO(applicationWrapper); + unrestrictedRoles = applicationWrapper.getUnrestrictedRoles(); + tags = applicationWrapper.getTags(); + + if (unrestrictedRoles != null && !unrestrictedRoles.isEmpty()) { + if (!isValidRestrictedRole(unrestrictedRoles)) { + String msg = "Unrestricted role list contain role/roles which are not in the user store."; + log.error(msg); + throw new ApplicationManagementException(msg); + } + if (!hasUserRole(unrestrictedRoles, userName)) { + String msg = "You are trying to restrict the visibility of the application for a role set, but " + + "in order to perform the action at least one role should be assigned to user: " + + userName; + log.error(msg); + throw new BadRequestException(msg); + } + } Filter filter = new Filter(); filter.setFullMatch(true); filter.setAppName(applicationDTO.getName().trim()); filter.setOffset(0); filter.setLimit(1); - - ConnectionManagerUtil.beginDBTransaction(); List applicationList = applicationDAO .getApplications(filter, applicationDTO.getDeviceTypeId(), tenantId); if (!applicationList.isEmpty()) { - String msg = - "Already an application registered with same name - " + applicationList.get(0) - .getName(); + String msg = "Already an application registered with same name - " + applicationList.get(0).getName() + + " for the device type " + applicationWrapper.getDeviceType(); log.error(msg); throw new RequestValidatingException(msg); } + List registeredCategories = this.applicationDAO.getAllCategories(tenantId); + String categoryName = applicationWrapper.getAppCategory(); + + if (registeredCategories.isEmpty()) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Registered application category set is empty. Since it is mandatory to add application " + + "category when adding new application, registered application category list shouldn't be null."; + log.error(msg); + throw new ApplicationManagementException(msg); + } + category = registeredCategories.stream().filter(obj -> obj.getCategoryName().equals(categoryName)) + .findAny(); + if (!category.isPresent()) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Request contains invalid category: " + categoryName; + log.error(msg); + throw new ApplicationManagementException(msg); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection."; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } catch (UnexpectedServerErrorException e) { + String msg = "Error occurred when getting Device Type data."; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while getting data which is related to application. application name: " + + applicationWrapper.getName() + " and application type: " + applicationWrapper.getType(); + log.error(msg); + throw new ApplicationManagementException(msg, e); + } catch (UserStoreException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred when validating the unrestricted roles given for the application"; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + + //uploading application artifacts + try { + ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); + applicationReleaseDTO = addApplicationReleaseArtifacts(applicationDTO.getType(), + applicationWrapper.getDeviceType(), applicationReleaseDTO, applicationArtifact, false); + applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact); + applicationDTO.getApplicationReleaseDTOs().clear(); + applicationDTO.getApplicationReleaseDTOs().add(applicationReleaseDTO); + } catch (ResourceManagementException e) { + String msg = "Error Occured when uploading artifacts of the application: " + applicationWrapper.getName(); + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + + //insert application data into databse + ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager(); + ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); + try { + List applicationReleaseEntities = new ArrayList<>(); + + ConnectionManagerUtil.beginDBTransaction(); // Insert to application table int appId = this.applicationDAO.createApplication(applicationDTO, tenantId); if (appId == -1) { - log.error("ApplicationDTO creation is Failed"); + log.error("Application data storing is Failed."); ConnectionManagerUtil.rollbackDBTransaction(); + deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue())); return null; } else { if (log.isDebugEnabled()) { log.debug("New ApplicationDTO entry added to AP_APP table. App Id:" + appId); } //adding application unrestricted roles - List unrestrictedRoles = applicationWrapper.getUnrestrictedRoles(); - if (!unrestrictedRoles.isEmpty()) { - if (!isValidRestrictedRole(unrestrictedRoles)) { - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Unrestricted role list contain role/roles which are not in the user store."; - log.error(msg); - throw new ApplicationManagementException(msg); - } - - if (!hasUserRole(unrestrictedRoles, userName)){ - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = - "You are trying to restrict the visibility of the application for a role set, but in order to perform the action at least one role should be assigned to user: " - + userName; - log.error(msg); - throw new BadRequestException(msg); - } + if (unrestrictedRoles != null && !unrestrictedRoles.isEmpty()) { this.visibilityDAO.addUnrestrictedRoles(unrestrictedRoles, appId, tenantId); if (log.isDebugEnabled()) { log.debug("New restricted roles to app ID mapping added to AP_UNRESTRICTED_ROLE table." @@ -215,25 +263,6 @@ public class ApplicationManagerImpl implements ApplicationManager { } } - List registeredCategories = this.applicationDAO.getAllCategories(tenantId); - String categoryName = applicationWrapper.getAppCategory(); - Optional category = registeredCategories.stream() - .filter(obj -> obj.getCategoryName().equals(categoryName)).findAny(); - - if (registeredCategories.isEmpty()) { - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Registered application category set is empty category: " + categoryName; - log.error(msg); - throw new ApplicationManagementException(msg); - } - if (!category.isPresent()){ - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Request contains invalid category: " + categoryName; - log.error(msg); - throw new ApplicationManagementException(msg); - - } - /* In current flow, allow to add one category for an application. If it is required to add multiple categories DAO layer is implemented to match with that requirement. Hence logic is also implemented @@ -241,11 +270,10 @@ public class ApplicationManagerImpl implements ApplicationManager { */ List categoryIds = new ArrayList<>(); categoryIds.add(category.get().getId()); - this.applicationDAO.addCategoryMapping(categoryIds,appId,tenantId); + this.applicationDAO.addCategoryMapping(categoryIds, appId, tenantId); //adding application tags - List tags = applicationWrapper.getTags(); - if (!tags.isEmpty()) { + if (tags != null && !tags.isEmpty()) { List registeredTags = applicationDAO.getAllTags(tenantId); List registeredTagNames = new ArrayList<>(); List tagIds = new ArrayList<>(); @@ -277,61 +305,84 @@ public class ApplicationManagerImpl implements ApplicationManager { log.debug("Creating a new release. App Id:" + appId); } String initialLifecycleState = lifecycleStateManager.getInitialState(); - applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); applicationReleaseDTO.setCurrentState(initialLifecycleState); - applicationReleaseDTO = this.applicationReleaseDAO.createRelease(applicationReleaseDTO, appId, tenantId); + applicationReleaseDTO = this.applicationReleaseDAO + .createRelease(applicationReleaseDTO, appId, tenantId); LifecycleStateDTO lifecycleStateDTO = getLifecycleStateInstance(initialLifecycleState, initialLifecycleState); this.lifecycleStateDAO .addLifecycleState(lifecycleStateDTO, appId, applicationReleaseDTO.getUuid(), tenantId); applicationReleaseEntities.add(applicationReleaseDTO); applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities); - application = appDtoToAppResponse(applicationDTO); + Application application = appDtoToAppResponse(applicationDTO); ConnectionManagerUtil.commitDBTransaction(); + return application; } - return application; } catch (LifeCycleManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred while adding lifecycle state. application name: " + applicationWrapper.getName() - + " application type: is " + applicationWrapper.getType(); + String msg = + "Error occurred while adding lifecycle state. application name: " + applicationWrapper.getName() + + " application type: is " + applicationWrapper.getType(); log.error(msg); + try { + applicationStorageManager.deleteAllApplicationReleaseArtifacts( + Collections.singletonList(applicationReleaseDTO.getAppHashValue())); + } catch (ApplicationStorageManagementException ex) { + String errorLog = + "Error occurred when deleting application artifacts. Application artifacts are tried to " + + "delete because of lifecycle state adding issue in the application creating operation."; + log.error(errorLog); + throw new ApplicationManagementException(errorLog, e); + } throw new ApplicationManagementException(msg, e); } catch (ApplicationManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred while adding application or application release. application name: " + applicationWrapper.getName() + " application type: " + applicationWrapper.getType(); log.error(msg); + deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue())); throw new ApplicationManagementException(msg, e); - } catch(LifecycleManagementException e){ + } catch (LifecycleManagementException e) { ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred when getting initial lifecycle state. application name: " + applicationWrapper .getName() + " application type: is " + applicationWrapper.getType(); log.error(msg); + deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue())); throw new ApplicationManagementException(msg, e); - }catch (DBConnectionException e) { + } catch (DBConnectionException e) { String msg = "Error occurred while getting database connection."; log.error(msg); throw new ApplicationManagementException(msg, e); } catch (VisibilityManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred while adding unrestricted roles. application name: " + applicationWrapper.getName() - + " application type: " + applicationWrapper.getType(); + String msg = + "Error occurred while adding unrestricted roles. application name: " + applicationWrapper.getName() + + " application type: " + applicationWrapper.getType(); log.error(msg); + deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue())); throw new ApplicationManagementException(msg, e); } catch (TransactionManagementException e) { String msg = "Error occurred while disabling AutoCommit."; log.error(msg); throw new ApplicationManagementException(msg, e); - } catch (UserStoreException e) { - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred when validating the unrestricted roles given for the application"; - log.error(msg); - throw new ApplicationManagementException(msg, e); } finally { ConnectionManagerUtil.closeDBConnection(); } } + private void deleteApplicationArtifacts(List directoryPaths) throws ApplicationManagementException { + ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager(); + + try { + applicationStorageManager.deleteAllApplicationReleaseArtifacts(directoryPaths); + } catch (ApplicationStorageManagementException e) { + String errorLog = "Error occurred when deleting application artifacts. directory paths: ." + directoryPaths + .toString(); + log.error(errorLog); + throw new ApplicationManagementException(errorLog, e); + } + } + private ApplicationReleaseDTO addApplicationReleaseArtifacts(String applicationType, String deviceType, ApplicationReleaseDTO applicationReleaseDTO, ApplicationArtifact applicationArtifact, boolean isNewRelease) throws ResourceManagementException, ApplicationManagementException { @@ -576,9 +627,6 @@ public class ApplicationManagerImpl implements ApplicationManager { try { //set default values - if (StringUtils.isEmpty(filter.getSortBy())) { - filter.setSortBy("ASC"); - } if (filter.getLimit() == 0) { filter.setLimit(20); } @@ -586,16 +634,15 @@ public class ApplicationManagerImpl implements ApplicationManager { if (!StringUtils.isEmpty(deviceTypename)) { deviceType = getDeviceTypeData(deviceTypename); } - - ConnectionManagerUtil.openDBConnection(); - - validateFilter(filter); if (deviceType == null) { - appDTOs = applicationDAO.getApplications(filter, 0, tenantId); - } else { - appDTOs = applicationDAO.getApplications(filter, deviceType.getId(), tenantId); + deviceType = new DeviceType(); + deviceType.setId(-1); } + ConnectionManagerUtil.openDBConnection(); + validateFilter(filter); + appDTOs = applicationDAO.getApplications(filter, deviceType.getId(), tenantId); + //todo as a performance improvement get these data from DB. Consider where in clause. for (ApplicationDTO app : appDTOs) { boolean isSearchingApp = true; List filteringTags = filter.getTags(); @@ -905,6 +952,7 @@ public class ApplicationManagerImpl implements ApplicationManager { } private String[] getRoleNames() throws UserStoreException { + //todo check role by role UserRealm userRealm = CarbonContext.getThreadLocalCarbonContext().getUserRealm(); if (userRealm != null) { return userRealm.getUserStoreManager().getRoleNames(); diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java index 8b7b1093cb..ec80a874d8 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java @@ -407,6 +407,7 @@ public interface ApplicationManagementPublisherAPI { code = 404, message = "Application not found"), }) + //todo add new scope and permission Response deleteApplication( @ApiParam( name = "UUID", diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java index 4b5ab8369b..fb53b354ed 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java @@ -84,7 +84,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } return Response.status(Response.Status.OK).entity(applications).build(); } catch(BadRequestException e){ - String msg = "Incompatible request payload is found. Please try with valid reuest payload."; + String msg = "Incompatible request payload is found. Please try with valid request payload."; log.error(msg, e); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); }catch (ApplicationManagementException e) { @@ -161,7 +161,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem if (application != null) { return Response.status(Response.Status.CREATED).entity(application).build(); } else { - String msg = "ApplicationDTO creation is failed"; + String msg = "Application creation is failed"; log.error(msg); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } @@ -285,9 +285,6 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Multipart("binaryFile") Attachment binaryFile) { try { - ApplicationManager applicationManager = APIUtil.getApplicationManager(); - - applicationManager.validateBinaryArtifact(binaryFile, appType); if (!ApplicationType.ENTERPRISE.toString().equals(appType)) { String msg = "If ApplicationDTO type is " + appType + ", therefore you don't have application release artifact to update for application release UUID: " @@ -295,7 +292,8 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem log.error(msg); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } - + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + applicationManager.validateBinaryArtifact(binaryFile, appType); applicationManager.updateApplicationArtifact(deviceType, appType, applicationReleaseUuid, constructApplicationArtifact(binaryFile, null, null, null)); return Response.status(Response.Status.OK) @@ -371,9 +369,10 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem applicationManager.validateImageArtifacts(iconFile, bannerFile, screenshots); if (!applicationManager.updateRelease(deviceType, appType, applicationUUID, applicationReleaseWrapper, constructApplicationArtifact(binaryFile, iconFile, bannerFile, screenshots))) { - log.error("Application release updating is failed. Please contact the administrator. " - + "ApplicationDTO release UUID: " + applicationUUID + ", Supported device type: " + deviceType); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(applicationReleaseWrapper).build(); + String msg ="Application release updating is failed. Please contact the administrator. " + + "ApplicationDTO release UUID: " + applicationUUID + ", Supported device type: " + deviceType; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } return Response.status(Response.Status.OK).entity("Application release is successfully updated.").build(); } catch (BadRequestException e) { @@ -402,9 +401,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } } - /* -//todo ---------------------- -*/ + @DELETE @Path("/{appId}") public Response deleteApplication(@PathParam("appId") int applicationId) { @@ -429,6 +426,10 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } } + + /* +//todo ---------------------- +*/ @GET @Path("/lifecycle/{appId}/{uuid}") public Response getLifecycleState(