From d07f5b37132534a8ad3d4a76c7185404f8b7fbc6 Mon Sep 17 00:00:00 2001 From: Yohan Avishke Date: Wed, 29 Jan 2020 11:03:21 +0000 Subject: [PATCH] Add API to download device-type agent --- .../mgt/api/services/ArtifactDownloadAPI.java | 37 +++++++++++++++++ .../impl/ArtifactDownloadAPIImpl.java | 40 +++++++++++++++++++ .../services/ApplicationStorageManager.java | 12 ++++++ .../mgt/common/services/AppmDataHandler.java | 11 +++++ .../impl/ApplicationStorageManagerImpl.java | 24 +++++++++++ .../mgt/core/impl/AppmDataHandlerImpl.java | 28 ++++++++++++- .../application/mgt/core/util/Constants.java | 2 + 7 files changed, 153 insertions(+), 1 deletion(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/ArtifactDownloadAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/ArtifactDownloadAPI.java index f6f149ea62b..acae6d1a5b8 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/ArtifactDownloadAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/ArtifactDownloadAPI.java @@ -131,4 +131,41 @@ public interface ArtifactDownloadAPI { value = "UUID of the application release.", required = true) @PathParam("uuid") String uuid); + + @GET + @Path("/{deviceType}/agent/{tenantId}") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @ApiOperation( + produces = MediaType.APPLICATION_OCTET_STREAM, + httpMethod = "GET", + value = "get the agent of a device type", + notes = "This will download an agent depending on the device type" + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully got the agent.", + response = ApplicationList.class), + @ApiResponse( + code = 404, + message = "Not Found. There doesn't have an defined agent for the resource." + + "query."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while getting the agent.", + response = ErrorResponse.class) + }) + Response getAndroidAgent( + @ApiParam( + name = "deviceType", + value = "Device type of the agent.", + example = "android", + required = true) + @PathParam("deviceType") String deviceType, + @ApiParam( + name = "tenantId", + value = "Tenant Id of the application artifact belongs.", + required = true) + @PathParam("tenantId") int tenantId); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/ArtifactDownloadAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/ArtifactDownloadAPIImpl.java index 0d796a0c820..d0199b1134a 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/ArtifactDownloadAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/ArtifactDownloadAPIImpl.java @@ -110,4 +110,44 @@ public class ArtifactDownloadAPIImpl implements ArtifactDownloadAPI { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + @GET + @Override + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("/{deviceType}/agent/{tenantId}") + public Response getAndroidAgent(@PathParam("deviceType") String deviceType, + @PathParam("tenantId") int tenantId) { + AppmDataHandler dataHandler = APIUtil.getDataHandler(); + try (InputStream fileInputStream = dataHandler.getAgentStream(tenantId, deviceType)) { + byte[] content = IOUtils.toByteArray(fileInputStream); + try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) { + Response.ResponseBuilder response = Response + .ok(binaryDuplicate, MediaType.APPLICATION_OCTET_STREAM); + response.status(Response.Status.OK); + response.header("Content-Disposition", "attachment; filename=\"" + deviceType + " agent\""); + response.header("Content-Length", content.length); + return response.build(); + } catch (IOException e) { + String msg = "Error occurred while creating input stream from buffer array. "; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } catch (NotFoundException e) { + String msg = "Couldn't find an agent for device type: " + deviceType; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (BadRequestException e){ + String msg = "Invalid device type received: " + deviceType + ".Valid device type is android"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while getting the application release artifact file. "; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (IOException e) { + String msg = "Error occurred while getting the byte array of application release artifact file. "; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } } 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 604e1cbab67..5bfe26e86b1 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 @@ -20,6 +20,7 @@ package org.wso2.carbon.device.application.mgt.common.services; import org.wso2.carbon.device.application.mgt.common.ApplicationInstaller; import org.wso2.carbon.device.application.mgt.common.dto.ApplicationReleaseDTO; 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.common.exception.ResourceManagementException; import java.io.InputStream; @@ -110,4 +111,15 @@ public interface ApplicationStorageManager { */ InputStream getFileStream(String hashVal, String folderName, String fileName, int tenantId) throws ApplicationStorageManagementException; + + /** + * Get the InputStream of the file which is located in filePath + * + * @param deviceType device type name + * @param tenantId local tenant's id + * @return {@link InputStream} + * @throws ApplicationStorageManagementException throws if an error occurs when accessing the file. + */ + InputStream getFileStream(String deviceType, int tenantId) + throws ApplicationStorageManagementException, RequestValidatingException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/AppmDataHandler.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/AppmDataHandler.java index 7385688db58..cfeaed58358 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/AppmDataHandler.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/AppmDataHandler.java @@ -37,4 +37,15 @@ public interface AppmDataHandler { InputStream getArtifactStream(int tenantId, String uuid, String folderName, String artifactName) throws ApplicationManagementException; + + /** + * Get agent apk + * + * @param tenantId local tenant + * @param deviceType device type name + * @return {@link InputStream} + * @throws ApplicationManagementException throws if an error occurs when accessing the file. + */ + InputStream getAgentStream(int tenantId, String deviceType) + 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/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 69aa1711ac5..8312ecfe579 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 @@ -20,12 +20,14 @@ package org.wso2.carbon.device.application.mgt.core.impl; import com.dd.plist.NSDictionary; import net.dongliu.apk.parser.bean.ApkMeta; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.application.mgt.common.ApplicationInstaller; import org.wso2.carbon.device.application.mgt.common.dto.ApplicationReleaseDTO; import org.wso2.carbon.device.application.mgt.common.DeviceTypes; 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.common.exception.ResourceManagementException; import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager; import org.wso2.carbon.device.application.mgt.core.exception.ParsingException; @@ -249,6 +251,28 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager } } + @Override + public InputStream getFileStream(String deviceType, int tenantId) + throws ApplicationStorageManagementException, RequestValidatingException { + if (StringUtils.isNotBlank(deviceType) && deviceType.equals("android")) { + String fileName = Constants.ANDROID_AGENT; + String filePath = + storagePath + File.separator + "agents" + File.separator + deviceType + File.separator + + tenantId + File.separator + fileName; + try { + return StorageManagementUtil.getInputStream(filePath); + } catch (IOException e) { + String msg = "Error occured when accessing the file in file path: " + filePath; + log.error(msg, e); + throw new ApplicationStorageManagementException(msg, e); + } + } else { + String msg = "Error occurred while accessing the file invalid device type: " + deviceType; + log.error(msg); + throw new RequestValidatingException(msg); + } + } + /*** * This method is responsible to delete artifact file which is located in the artifact path. * diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/AppmDataHandlerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/AppmDataHandlerImpl.java index 95b747a3f47..d77b13a9916 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/AppmDataHandlerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/AppmDataHandlerImpl.java @@ -24,11 +24,13 @@ import org.wso2.carbon.device.application.mgt.common.config.LifecycleState; 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.LifecycleManagementException; +import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException; import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager; import org.wso2.carbon.device.application.mgt.common.services.AppmDataHandler; import org.wso2.carbon.device.application.mgt.common.config.UIConfiguration; import org.wso2.carbon.device.application.mgt.core.dao.ApplicationReleaseDAO; import org.wso2.carbon.device.application.mgt.core.dao.common.ApplicationManagementDAOFactory; +import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException; import org.wso2.carbon.device.application.mgt.core.util.DAOUtil; import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException; @@ -76,7 +78,7 @@ public class AppmDataHandlerImpl implements AppmDataHandler { InputStream inputStream = applicationStorageManager .getFileStream(appReleaseHashValue, folderName, artifactName, tenantId); if (inputStream == null) { - String msg = "Couldn't file the file in the file system."; + String msg = "Couldn't find the file in the file system."; log.error(msg); throw new ApplicationManagementException(msg); } @@ -94,4 +96,28 @@ public class AppmDataHandlerImpl implements AppmDataHandler { ConnectionManagerUtil.closeDBConnection(); } } + + @Override + public InputStream getAgentStream(int tenantId, String deviceType) + throws ApplicationManagementException { + ApplicationStorageManager applicationStorageManager = DAOUtil.getApplicationStorageManager(); + try { + InputStream inputStream = applicationStorageManager + .getFileStream(deviceType, tenantId); + if (inputStream == null) { + String msg = "Couldn't find the file in the file system for device type: " + deviceType; + log.error(msg); + throw new NotFoundException(msg); + } + return inputStream; + } catch (ApplicationStorageManagementException e) { + String msg = "Error occurred when getting input stream of the " + deviceType + " agent."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (RequestValidatingException e) { + String msg = "Error invalid request received with device type: " + deviceType; + log.error(msg, e); + throw new BadRequestException(msg, e); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java index cbbe2229c5f..c43c943d23a 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java @@ -61,6 +61,8 @@ public class Constants { public static final String SUBSCRIBED = "SUBSCRIBED"; public static final String UNSUBSCRIBED = "UNSUBSCRIBED"; + public static final String ANDROID_AGENT = "android-agent.apk"; + /** * Database types supported by Application Management.