diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ActivityInfoProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ActivityInfoProviderService.java index bf99446804..62f07e362c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ActivityInfoProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ActivityInfoProviderService.java @@ -140,6 +140,93 @@ public interface ActivityInfoProviderService { @HeaderParam("If-Modified-Since") String ifModifiedSince); + @GET + @Path("/{id}/{devicetype}/{deviceid}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Details of an Activity for a specific device", + notes = "Retrieve the details of a specific activity/operation, such as the meta information of " + + "an operation, including the responses from a given device", + tags = "Activity Info Provider", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:get-activity") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the activity details.", + response = Activity.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of " + + "the requested resource."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 404, + message = "Not Found. \n No activity found with the given ID.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the activity data.", + response = ErrorResponse.class) + }) + Response getActivityByDevice( + @ApiParam( + name = "id", + value = "Activity id of the operation/activity.", + required = true, + defaultValue = "ACTIVITY_1") + @PathParam("id") + @Size(max = 45) + String id, + @ApiParam( + name = "devicetype", + value = "The device type name, such as ios, android, windows or fire-alarm.", + required = true) + @PathParam("devicetype") + @Size(max = 45) + String type, + @ApiParam( + name = "deviceid", + value = "The device identifier of the device you want ot get details.", + required = true) + @PathParam("deviceid") + @Size(max = 45) + String deviceid, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time\n." + + "Provide the value in the Java Date Format: EEE, d MMM yyyy HH:mm:ss Z\n." + + "Example: Mon, 05 Jan 2014 15:10:00 +0200", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince); + @GET @ApiOperation( produces = MediaType.APPLICATION_JSON, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ActivityProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ActivityProviderServiceImpl.java index d06b8a8180..2b39044d17 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ActivityProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ActivityProviderServiceImpl.java @@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; @@ -72,6 +73,43 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService } } + + @GET + @Override + @Path("/{id}/{devicetype}/{deviceid}") + public Response getActivityByDevice(@PathParam("id") + @Size(max = 45) String id, + @PathParam("devicetype") + @Size(max = 45) String devicetype, + @PathParam("deviceid") + @Size(max = 45) String deviceid, + @HeaderParam("If-Modified-Since") String ifModifiedSince) { + Activity activity; + DeviceManagementProviderService dmService; + try { + RequestValidationUtil.validateActivityId(id); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceid); + deviceIdentifier.setType(devicetype); + + dmService = DeviceMgtAPIUtils.getDeviceManagementService(); + activity = dmService.getOperationByActivityIdAndDevice(id, deviceIdentifier); + if (activity == null) { + return Response.status(404).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage("No activity can be " + + "found upon the provided activity id '" + id + "'").build()).build(); + } + return Response.status(Response.Status.OK).entity(activity).build(); + } catch (OperationManagementException e) { + String msg = "ErrorResponse occurred while fetching the activity for the supplied id."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + + @GET @Override public Response getActivities(@QueryParam("since") String since, @QueryParam("offset") int offset, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java index 45db0d3eff..8de9f3199e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/operation/mgt/OperationManager.java @@ -93,6 +93,8 @@ public interface OperationManager { Activity getOperationByActivityId(String activity) throws OperationManagementException; + Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException; + List getOperationUpdatedAfter(long timestamp) throws OperationManagementException; List getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java index dc096eb130..8a5d9aa6ce 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java @@ -812,6 +812,28 @@ public class OperationManagerImpl implements OperationManager { } } + public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException { + // This parses the operation id from activity id (ex : ACTIVITY_23) and converts to the integer. + int operationId = Integer.parseInt( + activity.replace(DeviceManagementConstants.OperationAttributes.ACTIVITY, "")); + if (operationId == 0) { + throw new IllegalArgumentException("Operation ID cannot be null or zero (0)."); + } + + Device device = this.getDevice(deviceId); + try { + OperationManagementDAOFactory.openConnection(); + return operationDAO.getActivityByDevice(operationId, device.getId()); + } catch (SQLException e) { + throw new OperationManagementException("Error occurred while opening a connection to the data source.", e); + } catch (OperationManagementDAOException e) { + throw new OperationManagementException("Error occurred while retrieving the operation with activity Id '" + + activity + " and device Id: " + deviceId.getId(), e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + @Override public List getOperationUpdatedAfter(long timestamp) throws OperationManagementException { return null; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java index 5e3848cf9b..dc9b6dfb9a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -70,6 +70,8 @@ public interface OperationDAO { Activity getActivity(int operationId) throws OperationManagementDAOException; + Activity getActivityByDevice(int operationId, int deviceId) throws OperationManagementDAOException; + int getEnrolmentIdFromMappingId(int enrollmentOpMappingId) throws OperationManagementDAOException; List getOperationsUpdatedAfter(long timestamp) throws OperationManagementDAOException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index f581f76085..bd6b996e0b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -384,6 +384,83 @@ public class GenericOperationDAOImpl implements OperationDAO { return activity; } + public Activity getActivityByDevice(int operationId, int deviceId) throws OperationManagementDAOException { + + PreparedStatement stmt = null; + ResultSet rs = null; + Activity activity = null; + List activityStatusList = new ArrayList<>(); + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + String sql = "SELECT eom.ENROLMENT_ID, eom.OPERATION_ID, eom.ID AS EOM_MAPPING_ID, dor.ID AS OP_RES_ID,\n" + + "de.DEVICE_ID, d.DEVICE_IDENTIFICATION, \n" + + "d.DEVICE_TYPE_ID, dt.NAME AS DEVICE_TYPE_NAME, eom.STATUS, eom.CREATED_TIMESTAMP, \n" + + "eom.UPDATED_TIMESTAMP, op.OPERATION_CODE, op.TYPE AS OPERATION_TYPE, dor.OPERATION_RESPONSE, \n" + + "dor.RECEIVED_TIMESTAMP FROM DM_ENROLMENT_OP_MAPPING AS eom \n" + + "INNER JOIN DM_OPERATION AS op ON op.ID=eom.OPERATION_ID\n" + + "INNER JOIN DM_ENROLMENT AS de ON de.ID=eom.ENROLMENT_ID\n" + + "INNER JOIN DM_DEVICE AS d ON d.ID=de.DEVICE_ID \n" + + "INNER JOIN DM_DEVICE_TYPE AS dt ON dt.ID=d.DEVICE_TYPE_ID\n" + + "LEFT JOIN DM_DEVICE_OPERATION_RESPONSE AS dor ON dor.ENROLMENT_ID=de.id \n" + + "AND dor.OPERATION_ID = eom.OPERATION_ID\n" + + "WHERE eom.OPERATION_ID = ? AND de.device_id = ? AND de.TENANT_ID = ?"; + + stmt = conn.prepareStatement(sql); + stmt.setInt(1, operationId); + stmt.setInt(2, deviceId); + stmt.setInt(3, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()); + rs = stmt.executeQuery(); + + int enrolmentId = 0; + ActivityStatus activityStatus = null; + + while (rs.next()) { + if (enrolmentId == 0) { + activity = new Activity(); + activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE"))); + activity.setCreatedTimeStamp(new java.util.Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString()); + activity.setCode(rs.getString("OPERATION_CODE")); + } + if (enrolmentId != rs.getInt("ENROLMENT_ID")) { + activityStatus = new ActivityStatus(); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION")); + deviceIdentifier.setType(rs.getString("DEVICE_TYPE_NAME")); + activityStatus.setDeviceIdentifier(deviceIdentifier); + + activityStatus.setStatus(ActivityStatus.Status.valueOf(rs.getString("STATUS"))); + + List operationResponses = new ArrayList<>(); + if (rs.getInt("UPDATED_TIMESTAMP") != 0) { + activityStatus.setUpdatedTimestamp(new java.util.Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString()); + operationResponses.add(OperationDAOUtil.getOperationResponse(rs)); + } + activityStatus.setResponses(operationResponses); + + activityStatusList.add(activityStatus); + + enrolmentId = rs.getInt("ENROLMENT_ID"); + activity.setActivityStatus(activityStatusList); + } else { + if (rs.getInt("UPDATED_TIMESTAMP") != 0) { + activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs)); + } + } + } + } catch (SQLException e) { + throw new OperationManagementDAOException("Error occurred while getting the operation details from " + + "the database.", e); + } catch (ClassNotFoundException e) { + throw new OperationManagementDAOException("Error occurred while converting the operation response to string.", e); + } catch (IOException e) { + throw new OperationManagementDAOException("IO exception occurred while converting the operations responses.", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, rs); + } + return activity; + } + @Override public List getActivitiesUpdatedAfter(long timestamp) throws OperationManagementDAOException { return this.getActivitiesUpdatedAfter(timestamp, 0, 0); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/PushNotificationBasedOperationManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/PushNotificationBasedOperationManager.java index 0d92577135..79ffacb370 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/PushNotificationBasedOperationManager.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/push/notification/mgt/PushNotificationBasedOperationManager.java @@ -116,6 +116,11 @@ public class PushNotificationBasedOperationManager implements OperationManager { return this.operationManager.getOperationByActivityId(activity); } + @Override + public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException { + return this.operationManager.getOperationByActivityIdAndDevice(activity, deviceId); + } + @Override public List getOperationUpdatedAfter(long timestamp) throws OperationManagementException { return this.operationManager.getOperationUpdatedAfter(timestamp); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index d1d3f5f03d..09911f3cd6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -532,6 +532,8 @@ public interface DeviceManagementProviderService { Activity getOperationByActivityId(String activity) throws OperationManagementException; + Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException; + List getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException; List getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 6543f4bda9..77934202b2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -1008,6 +1008,10 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityId(activity); } + public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException { + return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityIdAndDevice(activity, deviceId); + } + @Override public List getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException { return DeviceManagementDataHolder.getInstance().getOperationManager().getActivitiesUpdatedAfter(timestamp);