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 8c32a8c10a..094bb3408d 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 @@ -176,25 +176,23 @@ public interface ApplicationManager { * @param iconFileStream icon file of the release * @param bannerFileStream bannerFileStream of the release. * @param attachments screenshot attachments of the release - * @return Updated Application Release. * @throws ApplicationManagementException Application Management Exception. */ - ApplicationRelease updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, InputStream - bannerFileStream, List attachments) - throws ApplicationManagementException, ResourceManagementException; + void updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, InputStream + bannerFileStream, List attachments) throws ApplicationManagementException; /** * To update release images. * * @param appId ID of the Application + * @param appType Application type * @param uuid uuid of the Application * @param binaryFile binaryFile of the release. - * @return Updated Application Release. * @throws ApplicationManagementException Application Management Exception. */ - ApplicationRelease updateApplicationArtifact(int appId, String uuid, InputStream binaryFile) - throws ApplicationManagementException, ResourceManagementException, RequestValidatingException, DeviceManagementException; + void updateApplicationArtifact(int appId, String appType, String uuid, InputStream binaryFile) + throws ApplicationManagementException; /** diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationStorageManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationStorageManager.java index a0770582e3..42992ea13e 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationStorageManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationStorageManager.java @@ -53,8 +53,7 @@ public interface ApplicationStorageManager { * @throws ResourceManagementException Resource Management Exception. */ ApplicationRelease updateImageArtifacts(ApplicationRelease applicationRelease, InputStream iconFile, - InputStream bannerFile, List screenshots) - throws ResourceManagementException, ApplicationManagementException; + InputStream bannerFile, List screenshots) throws ResourceManagementException; /** * To upload release artifacts for an Application. 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/release/GenericApplicationReleaseDAOImpl.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/release/GenericApplicationReleaseDAOImpl.java index f255a7c74a..ce5829ac7f 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/release/GenericApplicationReleaseDAOImpl.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/release/GenericApplicationReleaseDAOImpl.java @@ -360,7 +360,8 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements * @param applicationRelease Application Release the properties of which that need to be inserted. * @throws ApplicationManagementDAOException Application Management DAO Exception. */ - @Override public ApplicationRelease updateRelease(int applicationId, ApplicationRelease applicationRelease, int tenantId) + @Override + public ApplicationRelease updateRelease(int applicationId, ApplicationRelease applicationRelease, int tenantId) throws ApplicationManagementDAOException { Connection connection; PreparedStatement statement = null; @@ -389,7 +390,9 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements statement.setInt(15, applicationId); statement.setInt(16, tenantId); statement.setInt(17, applicationRelease.getId()); - statement.executeUpdate(); + if (statement.executeUpdate() == 0) { + return null; + } } catch (DBConnectionException e) { throw new ApplicationManagementDAOException( "Database connection exception while trying to update the application release", e); 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 b029df3c32..2243ef86f8 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 @@ -33,7 +33,9 @@ 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.User; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; +import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException; import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; +import org.wso2.carbon.device.application.mgt.common.exception.LifecycleManagementException; import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException; import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException; import org.wso2.carbon.device.application.mgt.common.exception.TransactionManagementException; @@ -50,6 +52,7 @@ import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException; import org.wso2.carbon.device.application.mgt.core.exception.LifeCycleManagementDAOException; 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.exception.VisibilityManagementDAOException; import org.wso2.carbon.device.application.mgt.core.internal.DataHolder; import org.wso2.carbon.device.application.mgt.core.lifecycle.LifecycleStateManger; @@ -65,7 +68,13 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; /** * Default Concrete implementation of Application Management related implementations. @@ -240,10 +249,10 @@ public class ApplicationManagerImpl implements ApplicationManager { public ApplicationRelease createRelease(int applicationId, ApplicationRelease applicationRelease) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - Application application = getApplicationIfAccessible(applicationId); + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); validateAppReleasePayload(applicationRelease); if (log.isDebugEnabled()) { - log.debug("Application release request is received for the application " + application.toString()); + log.debug("Application release request is received for the application id: " + applicationId); } try { ConnectionManagerUtil.beginDBTransaction(); @@ -252,6 +261,19 @@ public class ApplicationManagerImpl implements ApplicationManager { throw new NotFoundException( "Couldn't find application for the application Id: " + applicationId); } + + // todo check whether admin or app creator. + if (!isAdminUser(userName, tenantId, CarbonConstants.UI_ADMIN_PERMISSION_COLLECTION)) { + String msg = "You don't have permission to create application release for the application id: " + + applicationId + + ". In order to create ann new application realse, you should be either ADMIN user or the application created user."; + throw new ForbiddenException(msg); + } + if (!existingApplication.getUnrestrictedRoles().isEmpty() && !isRoleExists( + existingApplication.getUnrestrictedRoles(), userName)) { + String msg = "Application is visible to limited roles and those roles are not assigned to " + userName; + throw new ApplicationManagementException(msg); + } if (this.applicationReleaseDAO .verifyReleaseExistenceByHash(applicationId, applicationRelease.getAppHashValue(), tenantId)) { throw new BadRequestException("Application release exists for the application Id: " + applicationId @@ -263,7 +285,7 @@ public class ApplicationManagerImpl implements ApplicationManager { "Package name in the payload is different from the existing package name of other application releases."); } applicationRelease = this.applicationReleaseDAO - .createRelease(applicationRelease, application.getId(), tenantId); + .createRelease(applicationRelease, existingApplication.getId(), tenantId); LifecycleState lifecycleState = getLifecycleStateInstant(AppLifecycleState.CREATED.toString(), AppLifecycleState.CREATED.toString()); this.lifecycleStateDAO.addLifecycleState(lifecycleState, applicationId, applicationRelease.getUuid(), tenantId); @@ -280,12 +302,16 @@ public class ApplicationManagerImpl implements ApplicationManager { "Error occurred while adding application release into IoTS app management Application id of the " + "application release: " + applicationId, e); - } catch (LifeCycleManagementDAOException e) { + } catch (LifeCycleManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); - // todo throws when adding lifecycle state throw new ApplicationManagementException( - "Error occurred while adding application release into IoTS app management Application id of the " - + "application release: " + applicationId, e); + "Error occurred while adding new application release lifecycle state to the application release: " + + applicationId, e); + } catch (UserStoreException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occurred whecn checking whether user is admin user or not. Application release: " + + applicationId, e); } } @@ -306,13 +332,9 @@ public class ApplicationManagerImpl implements ApplicationManager { String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); Application application; boolean isAppAllowed = false; - boolean isOpenConnection = false; - List applicationReleases = null; + List applicationReleases; try { - if (state != null) { - ConnectionManagerUtil.openDBConnection(); - isOpenConnection = true; - } + ConnectionManagerUtil.openDBConnection(); application = this.applicationDAO.getApplicationById(appId, tenantId); if (application == null) { throw new NotFoundException("Couldn't find an application for application Id: " + appId); @@ -341,9 +363,7 @@ public class ApplicationManagerImpl implements ApplicationManager { throw new ApplicationManagementException( "User-store exception while getting application with the application id " + appId); } finally { - if (isOpenConnection) { - ConnectionManagerUtil.closeDBConnection(); - } + ConnectionManagerUtil.closeDBConnection(); } } @@ -572,7 +592,8 @@ public class ApplicationManagerImpl implements ApplicationManager { + applicationId); } for (ApplicationRelease applicationRelease : applicationReleases) { - LifecycleState appLifecycleState = getLifecycleState(applicationId, applicationRelease.getUuid()); + LifecycleState appLifecycleState = this.lifecycleStateDAO + .getLatestLifeCycleState(applicationId, applicationRelease.getUuid()); LifecycleState newAppLifecycleState = getLifecycleStateInstant(AppLifecycleState.REMOVED.toString(), appLifecycleState.getCurrentState()); if (lifecycleStateManger.isValidStateChange(newAppLifecycleState.getPreviousState(), @@ -581,9 +602,19 @@ public class ApplicationManagerImpl implements ApplicationManager { .addLifecycleState(newAppLifecycleState, applicationId, applicationRelease.getUuid(), tenantId); } else { - // todo move to appropriate lifecycle changing flow and end by remving release + String currentState = appLifecycleState.getCurrentState(); + List lifecycleFlow = searchLifecycleStateFlow(currentState, + AppLifecycleState.REMOVED.toString()); + for (String nextState : lifecycleFlow) { + LifecycleState lifecycleState = getLifecycleStateInstant(nextState, currentState); + if (lifecycleStateManger.isValidStateChange(currentState, nextState)) { + this.lifecycleStateDAO + .addLifecycleState(lifecycleState, applicationId, applicationRelease.getUuid(), + tenantId); + } + currentState = nextState; + } } - storedLocations.add(applicationRelease.getAppHashValue()); } this.applicationDAO.deleteApplication(applicationId); @@ -595,14 +626,60 @@ public class ApplicationManagerImpl implements ApplicationManager { throw new ApplicationManagementException(msg, e); } catch (LifeCycleManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); - // todo - String msg = "Error occured while check whether current user has the permission to delete an application"; + String msg = "Error occured while changing the application lifecycle state into REMOVED state."; log.error(msg); throw new ApplicationManagementException(msg, e); } return storedLocations; } + private List searchLifecycleStateFlow(String start, String finish) throws ApplicationManagementException { + Map nextNodeMap = new HashMap<>(); + List directions = new LinkedList<>(); + Queue queue = new LinkedList<>(); + + String currentNode = start; + queue.add(currentNode); + + Set visitedNodes = new HashSet<>(); + visitedNodes.add(currentNode); + while (!queue.isEmpty()) { + currentNode = queue.remove(); + if (currentNode.equals(finish)) { + break; + } else { + Set nextStates = lifecycleStateManger.getNextLifecycleStates(currentNode); + if (nextStates.contains(finish)) { + queue = new LinkedList<>(); + queue.add(finish); + nextNodeMap.put(currentNode, finish); + } else { + for (String node : nextStates) { + if (!visitedNodes.contains(node)) { + queue.add(node); + visitedNodes.add(node); + nextNodeMap.put(currentNode, node); + } + } + } + } + } + + //If all nodes are explored and the destination node hasn't been found. + if (!currentNode.equals(finish)) { + String errorMsg = "can't found a feasible path from " + start + " to " + finish; + throw new ApplicationManagementException(errorMsg); + } + + //Reconstruct path + for (String node = start; node != null; node = nextNodeMap.get(node)) { + if (!node.equals(start)) { + directions.add(node); + } + } + return directions; + } + @Override public String deleteApplicationRelease(int applicationId, String releaseUuid, boolean handleConnections) throws ApplicationManagementException { @@ -790,96 +867,165 @@ public class ApplicationManagerImpl implements ApplicationManager { * @param applicationUuid UUID of the Application. * @return Application related with the UUID */ - private ApplicationRelease getAppReleaseIfExists(int applicationId, String applicationUuid) throws - ApplicationManagementException { + private ApplicationRelease getAppReleaseIfExists(int applicationId, String applicationUuid) + throws ValidationException, NotFoundException, ApplicationManagementDAOException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); ApplicationRelease applicationRelease; if (applicationId <= 0) { - throw new ApplicationManagementException( + throw new ValidationException( "Application id could,t be a negative integer. Hence please add " + "valid application id."); } if (applicationUuid == null) { - throw new ApplicationManagementException("Application UUID is null. Application UUID is a required " + throw new ValidationException("Application UUID is null. Application UUID is a required " + "parameter to get the relevant application."); } applicationRelease = this.applicationReleaseDAO.getReleaseByIds(applicationId, applicationUuid, tenantId); if (applicationRelease == null) { - log.error("Doesn't exist a application release for application ID: " + applicationId + throw new NotFoundException("Doesn't exist a application release for application ID: " + applicationId + "and application UUID: " + applicationUuid); } return applicationRelease; - } - private ApplicationRelease updateRelease(int appId, ApplicationRelease applicationRelease) throws - ApplicationManagementException { - validateAppReleasePayload(applicationRelease); + //todo check whether user is whether admin user or application owner, otherwise throw an exception + @Override public void updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, + InputStream bannerFileStream, List attachments) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - if (log.isDebugEnabled()) { - log.debug("Updating the Application release. UUID: " + applicationRelease.getUuid() + ", " + - "Application Id: " + appId); - } - - applicationRelease = this.applicationReleaseDAO.updateRelease(appId, applicationRelease, tenantId); - return applicationRelease; - - } - - @Override - public ApplicationRelease updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, InputStream - bannerFileStream, List attachments) - throws ApplicationManagementException, ResourceManagementException { ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager(); ApplicationRelease applicationRelease; try { - ConnectionManagerUtil.getDBConnection(); - applicationRelease = getAppReleaseIfExists(appId, uuid); + if (appId <= 0) { + throw new ValidationException( + "Application id could,t be a negative integer. Hence please add valid application id."); + } + ConnectionManagerUtil.beginDBTransaction(); + applicationRelease = this.applicationReleaseDAO.getReleaseByIds(appId, uuid, tenantId); if (applicationRelease == null) { - throw new NotFoundException("No App release associated with the app Id " + appId + "and UUID "+ uuid); + ConnectionManagerUtil.rollbackDBTransaction(); + throw new NotFoundException( + "Doesn't exist a application release for application ID: " + appId + "and application UUID: " + + uuid); } - LifecycleState lifecycleState = getLifecycleState(appId, applicationRelease.getUuid()); - if (AppLifecycleState.PUBLISHED.toString().equals(lifecycleState.getCurrentState()) || - AppLifecycleState.DEPRECATED.toString().equals(lifecycleState.getCurrentState())) { - throw new ForbiddenException("Can't Update the application release in " + - "PUBLISHED or DEPRECATED state. Hence please demote the application and update " + - "the application release"); + LifecycleState lifecycleState = this.lifecycleStateDAO + .getLatestLifeCycleState(appId, applicationRelease.getUuid()); + if (AppLifecycleState.PUBLISHED.toString().equals(lifecycleState.getCurrentState()) + || AppLifecycleState.DEPRECATED.toString().equals(lifecycleState.getCurrentState())) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ForbiddenException("Can't Update the application release in PUBLISHED or DEPRECATED state. " + + "Hence please demote the application and update the application release"); } - ApplicationRelease updatedRelease = applicationStorageManager + applicationRelease = applicationStorageManager .updateImageArtifacts(applicationRelease, iconFileStream, bannerFileStream, attachments); - return updateRelease(appId, updatedRelease); - } finally { - ConnectionManagerUtil.closeDBConnection(); + applicationRelease = this.applicationReleaseDAO.updateRelease(appId, applicationRelease, tenantId); + if (applicationRelease == null) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Application release updating count is 0. Application id: " + appId + + " Application release UUID: " + uuid); + + } + ConnectionManagerUtil.commitDBTransaction(); + } catch (DBConnectionException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occured when getting DB connection to update image artifacts of the application, appid: " + + appId + " and uuid " + uuid + ".", e); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occured while getting application release data for updating image artifacts of the application, appid: " + + appId + " and uuid " + uuid + ".", e); + } catch (LifeCycleManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occured while getting latest lifecycle state for updating image artifacts of the application, appid: " + + appId + " and uuid " + uuid + ".", e); + } catch (ResourceManagementException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occured while updating image artifacts of the application, appid: " + appId + " and uuid " + + uuid + " to the system.", e); } } - @Override - public ApplicationRelease updateApplicationArtifact(int appId, String uuid, InputStream binaryFile) - throws ApplicationManagementException, ResourceManagementException, RequestValidatingException, DeviceManagementException { + @Override public void updateApplicationArtifact(int appId, String appType, String uuid, InputStream binaryFile) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager(); ApplicationRelease applicationRelease; try { - ConnectionManagerUtil.openDBConnection(); - applicationRelease = getAppReleaseIfExists(appId, uuid); - Application application = getApplicationById(appId, null); - + boolean isValidAppType = false; List deviceTypes = Util.getDeviceManagementService().getDeviceTypes(); - for (DeviceType deviceType:deviceTypes) { - if (deviceType.getId() == application.getDeviceTypeId()) { - application.setDeviceType(deviceType.getName()); + for (DeviceType deviceType : deviceTypes) { + if (deviceType.getName().equals(appType)) { + isValidAppType = true; + break; } } + if (!isValidAppType) { + throw new ValidationException( + "Invalid request to update application release artifact, invalid application type: " + appType + + " for Application id: " + appId + " application release uuid: " + uuid); + } + if (appId <= 0) { + throw new ValidationException( + "Application id could,t be a negative integer. Hence please add valid application id. application type: " + + appType + " Application id: " + appId + " UUID: " + uuid); + } + + ConnectionManagerUtil.beginDBTransaction(); + Application application = this.applicationDAO.getApplicationById(appId, tenantId); + if (application == null) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new NotFoundException("Doesn't exist a application for the application ID: " + appId); + } + applicationRelease = this.applicationReleaseDAO.getReleaseByIds(appId, uuid, tenantId); if (applicationRelease == null) { - throw new NotFoundException("No App release associated with the app Id " + appId + "and UUID "+ uuid); + ConnectionManagerUtil.rollbackDBTransaction(); + throw new NotFoundException( + "Doesn't exist a application release for application ID: " + appId + "and application UUID: " + + uuid); } - applicationStorageManager + applicationRelease = applicationStorageManager .updateReleaseArtifacts(applicationRelease, application.getType(), application.getDeviceType(), binaryFile); - updateRelease(appId, applicationRelease); - return applicationRelease; - } finally { - ConnectionManagerUtil.closeDBConnection(); + applicationRelease = this.applicationReleaseDAO.updateRelease(appId, applicationRelease, tenantId); + if (applicationRelease == null) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Application release updating count is 0. Application id: " + appId + + " Application release UUID: " + uuid); + + } + ConnectionManagerUtil.commitDBTransaction(); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException("Error occured while getting/updating APPM DB.", e); + } catch (TransactionManagementException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occured while starting the transaction to update application release artifact of the application, appid: " + + appId + " and uuid " + uuid + ".", e); + } catch (RequestValidatingException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException("Error occured while updating application artifact.", e); + } catch (DeviceManagementException e) { + throw new ApplicationManagementException("Error occured while getting supported device types in IoTS", e); + } catch (NotFoundException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Couldn't find application/application elease for appid: " + appId + " and uuid " + uuid + ".", e); + } catch (DBConnectionException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException( + "Error occured when getting DB connection to update application release artifact of the application, appid: " + + appId + " and uuid " + uuid + ".", e); + } catch (ApplicationStorageManagementException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + throw new ApplicationManagementException("In order to update the artifact, couldn't find it in the system", + e); } } @@ -942,15 +1088,10 @@ public class ApplicationManagerImpl implements ApplicationManager { ConnectionManagerUtil.openDBConnection(); lifecycleState = this.lifecycleStateDAO.getLatestLifeCycleState(applicationId, releaseUuid); if (lifecycleState == null) { - throw new NotFoundException( - "Couldn't find the lifecycle data for appid: " + applicationId + " and app release UUID: " - + releaseUuid); - + return null; } lifecycleState.setNextStates(new ArrayList<>(lifecycleStateManger.getNextLifecycleStates(lifecycleState.getCurrentState()))); - } catch (ApplicationManagementException e) { - throw new ApplicationManagementException("Failed to get application and application management", e); } catch (LifeCycleManagementDAOException e) { throw new ApplicationManagementException("Failed to get lifecycle state from database", e); } finally { diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationStorageManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationStorageManagerImpl.java index 37e17821ce..320b8b4f5a 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationStorageManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationStorageManagerImpl.java @@ -164,6 +164,8 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager count++; } } + applicationRelease = uploadImageArtifacts(applicationRelease, iconFileStream, bannerFileStream, + screenShotStreams); return applicationRelease; } catch (ApplicationStorageManagementException e) { throw new ApplicationStorageManagementException("Application Storage exception while trying to" @@ -241,16 +243,13 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager return applicationRelease; } - public InputStream[] cloneInputStream(InputStream inputStream) throws ApplicationStorageManagementException { + private InputStream[] cloneInputStream(InputStream inputStream) throws ApplicationStorageManagementException { - ByteArrayOutputStream byteArrayOutputStream = null; - - try { - byteArrayOutputStream = new ByteArrayOutputStream(); + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[BUFFER_SIZE]; int len; - while ((len = inputStream.read(buffer)) > -1 ) { + while ((len = inputStream.read(buffer)) > -1) { byteArrayOutputStream.write(buffer, 0, len); } byteArrayOutputStream.flush(); @@ -259,17 +258,9 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager InputStream stream2 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); InputStream stream3 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); - return new InputStream[]{stream1, stream2, stream3}; + return new InputStream[] { stream1, stream2, stream3 }; } catch (IOException e) { throw new ApplicationStorageManagementException("Error occurred while cloning input stream ", e); - } finally { - if (byteArrayOutputStream != null) { - try { - byteArrayOutputStream.close(); - } catch (IOException e) { - - } - } } } @@ -312,7 +303,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager @Override public void deleteAllApplicationReleaseArtifacts(List directoryPaths) throws ApplicationStorageManagementException { for (String directoryBasePath : directoryPaths) { - deleteApplicationReleaseArtifacts(directoryBasePath); + deleteApplicationReleaseArtifacts(storagePath + directoryBasePath); } } 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/ApplicationManagementAPI.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/ApplicationManagementAPI.java index 1ab0ec9187..4104cb3ebc 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/ApplicationManagementAPI.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/ApplicationManagementAPI.java @@ -443,6 +443,10 @@ public interface ApplicationManagementAPI { @ApiResponse( code = 200, message = "OK. \n Successfully updated artifacts."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Requesting to update image artifacts with invalid application " + + "or application release data."), @ApiResponse( code = 403, message = "FORBIDDEN. \n Can't Update the application release in PUBLISHED or DEPRECATED " @@ -519,6 +523,9 @@ public interface ApplicationManagementAPI { code = 400, message = "Bad Request. \n " + "Application artifact updating payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 404, + message = "NOT FOUND. \n Couldn't found application/application release to update applocation release artifact."), @ApiResponse( code = 500, message = "Internal Server Error. \n Error occurred while getting the application list.", 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/ApplicationManagementAPIImpl.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/ApplicationManagementAPIImpl.java index 39822c15b0..6a1fbaac3c 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/ApplicationManagementAPIImpl.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/ApplicationManagementAPIImpl.java @@ -25,6 +25,8 @@ import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.wso2.carbon.device.application.mgt.common.*; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException; import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException; +import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException; +import org.wso2.carbon.device.application.mgt.core.exception.ValidationException; import org.wso2.carbon.device.application.mgt.core.util.APIUtil; import org.wso2.carbon.device.application.mgt.publisher.api.services.ApplicationManagementAPI; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; @@ -155,7 +157,7 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { } try { - if (!isValidAppCreatingRequest(iconFile, bannerFile, attachmentList, application)) { + if (isInvalidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, application.getType())) { return Response.status(Response.Status.BAD_REQUEST).build(); } @@ -166,11 +168,12 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { .uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(), null); } else { - if (binaryFile == null){ - String msg = "Binary file is not found for the application release. Application name: " + application.getName() - + " Application type: " + application.getType(); - return Response.status(Response.Status.BAD_REQUEST).entity(new ApplicationManagementException(msg)) - .build(); + if (application.getApplicationReleases().size() > 1) { + String msg = + "Invalid application creating request. Application creating request must have single application " + + "release. Application name:" + application.getName() + " and type: " + + application.getType(); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } applicationRelease = application.getApplicationReleases().get(0); applicationRelease = applicationStorageManager @@ -231,7 +234,7 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { @Path("/{deviceType}/{appType}/{appId}") public Response createRelease( @PathParam("deviceType") String deviceType, - @PathParam("appId") String appType, + @PathParam("appType") String appType, @PathParam("appId") int appId, @Multipart("applicationRelease") ApplicationRelease applicationRelease, @Multipart("binaryFile") Attachment binaryFile, @@ -255,7 +258,7 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { } try { - if (!isValidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, appType)) { + if (isInvalidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, appType)) { return Response.status(Response.Status.BAD_REQUEST).build(); } @@ -318,11 +321,13 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { @Produces(MediaType.APPLICATION_JSON) @Path("/image-artifacts/{appId}/{uuid}") public Response updateApplicationImageArtifacts( - @PathParam("appId") int appId, @PathParam("uuid") String applicationUuid, - @Multipart("icon") Attachment iconFile, @Multipart("banner") Attachment bannerFile, - @Multipart("screenshot1") Attachment screenshot1, @Multipart("screenshot2") Attachment screenshot2, + @PathParam("appId") int appId, + @PathParam("uuid") String applicationReleaseUuid, + @Multipart("icon") Attachment iconFile, + @Multipart("banner") Attachment bannerFile, + @Multipart("screenshot1") Attachment screenshot1, + @Multipart("screenshot2") Attachment screenshot2, @Multipart("screenshot3") Attachment screenshot3) { - try { InputStream iconFileStream = null; InputStream bannerFileStream = null; @@ -334,7 +339,6 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { if (bannerFile != null) { bannerFileStream = bannerFile.getDataHandler().getInputStream(); } - attachments.add(screenshot1.getDataHandler().getInputStream()); if (screenshot2 != null) { attachments.add(screenshot2.getDataHandler().getInputStream()); @@ -343,27 +347,30 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { attachments.add(screenshot3.getDataHandler().getInputStream()); } ApplicationManager applicationManager = APIUtil.getApplicationManager(); - applicationManager.updateApplicationImageArtifact(appId, applicationUuid, iconFileStream, bannerFileStream, - attachments); - + applicationManager + .updateApplicationImageArtifact(appId, applicationReleaseUuid, iconFileStream, bannerFileStream, + attachments); return Response.status(Response.Status.OK) - .entity("Successfully uploaded artifacts for the application " + applicationUuid).build(); + .entity("Successfully uploaded artifacts for the application " + applicationReleaseUuid).build(); } catch (NotFoundException e) { log.error(e.getMessage(), e); - return APIUtil.getResponse(e, Response.Status.NOT_FOUND); + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } catch (ValidationException e) { + log.error(e.getMessage(), e); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (ForbiddenException e) { + log.error(e.getMessage(), e); + return Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build(); } catch (ApplicationManagementException e) { - String msg = "Error occurred while updating the application."; + String msg = "Error occurred while updating the application image artifacts for app id: " + appId + + " application release uuid: " + applicationReleaseUuid; log.error(msg, e); - return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } catch (IOException e) { - String msg = "Exception while trying to read icon, banner files for the application " + applicationUuid; + String msg = + "Exception while trying to read icon, banner files for the application " + applicationReleaseUuid; log.error(msg); - return APIUtil - .getResponse(new ApplicationManagementException(msg, e), Response.Status.INTERNAL_SERVER_ERROR); - } catch (ResourceManagementException e) { - log.error("Error occurred while uploading the image artifacts of the application with the uuid " - + applicationUuid, e); - return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } @@ -375,41 +382,39 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { @PathParam("deviceType") String deviceType, @PathParam("appType") String appType, @PathParam("appId") int applicationId, - @PathParam("uuid") String applicationUuid, + @PathParam("uuid") String applicationReleaseUuid, @Multipart("binaryFile") Attachment binaryFile) { try { - if (binaryFile == null) { - return APIUtil.getResponse("Uploading artifacts for the application is failed " + applicationUuid, - Response.Status.BAD_REQUEST); + return Response.status(Response.Status.BAD_REQUEST) + .entity("binary file is NULL, hence invalid request to update application release artifact for application release UUID: " + + applicationReleaseUuid).build(); } - APIUtil.getApplicationManager().updateApplicationArtifact(applicationId, applicationUuid, + if (!ApplicationType.ENTERPRISE.toString().equals(appType)) { + return Response.status(Response.Status.BAD_REQUEST).entity("If Application type is " + appType + + ", therefore you don't have application release artifact to update for application release UUID: " + + applicationReleaseUuid).build(); + } + APIUtil.getApplicationManager().updateApplicationArtifact(applicationId, appType, applicationReleaseUuid, binaryFile.getDataHandler().getInputStream()); return Response.status(Response.Status.OK) - .entity("Successfully uploaded artifacts for the application release. UUID is " + applicationUuid) - .build(); + .entity("Successfully uploaded artifacts for the application release. UUID is " + + applicationReleaseUuid).build(); } catch (IOException e) { String msg = "Error occurred while trying to read icon, banner files for the application release" - + applicationUuid; + + applicationReleaseUuid; log.error(msg); return APIUtil.getResponse(new ApplicationManagementException(msg, e), Response.Status.BAD_REQUEST); - } catch (ResourceManagementException e) { - log.error("Error occurred while uploading the image artifacts of the application with the uuid " - + applicationUuid, e); - return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } catch (ValidationException e) { + log.error(e.getMessage(), e); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (ApplicationManagementException e) { log.error("Error occurred while updating the image artifacts of the application with the uuid " - + applicationUuid, e); - return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); - } catch (RequestValidatingException e) { - log.error( - "Error occured while handling the application artifact updating request. application release UUID: " - + applicationUuid); - return APIUtil.getResponse(e, Response.Status.BAD_REQUEST); - } catch (DeviceManagementException e) { - log.error("Error occurred while updating the image artifacts of the application with the uuid " - + applicationUuid, e); + + applicationReleaseUuid, e); return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); } } @@ -553,11 +558,12 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { ApplicationManager applicationManager = APIUtil.getApplicationManager(); try { lifecycleState = applicationManager.getLifecycleState(applicationId, applicationUuid); - } catch (NotFoundException e) { - String msg = "Couldn't found application lifecycle details for appid: " + applicationId - + " and app release UUID: " + applicationUuid; - log.error(msg, e); - return Response.status(Response.Status.NOT_FOUND).build(); + if (lifecycleState == null) { + String msg = "Couldn't found application lifecycle details for appid: " + applicationId + + " and app release UUID: " + applicationUuid; + log.error(msg); + return Response.status(Response.Status.NOT_FOUND).build(); + } } catch (ApplicationManagementException e) { String msg = "Error occurred while getting lifecycle state."; log.error(msg, e); @@ -595,60 +601,26 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { return Response.status(Response.Status.CREATED).entity("Lifecycle state added successfully.").build(); } - private boolean isValidAppCreatingRequest(Attachment iconFile, Attachment bannerFile, - List attachmentList, Application application) { - -// if (application.getApplicationReleases().size() > 1) { -// log.error("Invalid application creating request. Application creating request must have single application " -// + "release. Application name:" + application.getName() + " and type: " + application.getType()); -// return false; -// } - - if (iconFile == null) { - log.error("Icon file is not found for the application release. Application name: " + application.getName() - + " and type: " + application.getType()); - return false; - } - - if (bannerFile == null) { - log.error("Banner file is not found for the application release. Application name: " + application.getName() - + " and application type: " + application.getType()); - return false; - } - - if (attachmentList == null || attachmentList.isEmpty()) { - log.error( - "Screenshots are not found for the application release. Application name: " + application.getName() - + " Application type: " + application.getType()); - return false; - } - - return true; - } - - private boolean isValidReleaseCreatingRequest(Attachment binaryFile, Attachment iconFile, Attachment bannerFile, + private boolean isInvalidReleaseCreatingRequest(Attachment binaryFile, Attachment iconFile, Attachment bannerFile, List attachmentList, String appType) { if (iconFile == null) { log.error("Icon file is not found with the application release creating request."); - return false; + return true; } - if (bannerFile == null) { log.error("Banner file is not found with the application release creating request."); - return false; + return true; } - if (attachmentList == null || attachmentList.isEmpty()) { log.error("Screenshots are not found with the application release creating request."); - return false; + return true; } - if (binaryFile == null && ApplicationType.ENTERPRISE.toString().equals(appType)) { log.error("Binary file is not found with the application release creating request. Application type: " + appType); - return false; + return true; } - return true; + return false; } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json index ec52c2e3b8..e35d486222 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json @@ -10,6 +10,7 @@ }, "license": "Apache License 2.0", "dependencies": { + "acorn": "^6.1.1", "antd": "^3.15.0", "react": "^16.8.4", "react-dom": "^16.8.4",