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 62f07e362c7..655559713a6 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 @@ -227,6 +227,70 @@ public interface ActivityInfoProviderService { required = false) @HeaderParam("If-Modified-Since") String ifModifiedSince); + @GET + @Path("/type/{operationCode}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Activity Details", + notes = "Get the details of the operations/activities executed by the server on the devices registered" + + " with WSO2 EMM, during a defined time period.", + 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 = ActivityList.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 = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 404, + message = "Not Found. \n No activities found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the activity data.", + response = ErrorResponse.class) + }) + Response getActivities( + @ApiParam( + name = "operationCode", + value = "Operation Code of the Activity", + required = true) + @PathParam("operationCode") String operationCode, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + required = true, + defaultValue = "0") + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many activity details you require from the starting pagination index/offset.", + required = true, + defaultValue = "5") + @QueryParam("limit") int limit); + @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 a6751024e0d..4b1d7bee503 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 @@ -115,6 +115,48 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService } } + @GET + @Override + @Path("/type/{operationCode}") + public Response getActivities(@PathParam("operationCode") String operationCode, + @QueryParam("offset") int offset, @QueryParam("limit") int limit){ + if (log.isDebugEnabled()) { + log.debug("getActivities -> Operation Code : " +operationCode+ "offset " + offset + " limit: " + limit ); + } + RequestValidationUtil.validatePaginationParameters(offset, limit); + Response response = validateAdminUser(); + if(response == null){ + List activities; + ActivityList activityList = new ActivityList(); + DeviceManagementProviderService dmService; + try { + if (log.isDebugEnabled()) { + log.debug("Calling database to get activities for the operation code :" +operationCode); + } + dmService = DeviceMgtAPIUtils.getDeviceManagementService(); + activities = dmService.getFilteredActivities(operationCode, limit, offset); + activityList.setList(activities); + if (log.isDebugEnabled()) { + log.debug("Calling database to get activity count."); + } + int count = dmService.getTotalCountOfFilteredActivities(operationCode); + if (log.isDebugEnabled()) { + log.debug("Activity count: " + count); + } + activityList.setCount(count); + return Response.ok().entity(activityList).build(); + } catch (OperationManagementException e) { + String msg + = "ErrorResponse occurred while fetching the activities for the given operation code."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } else { + return response; + } + } + @GET @Override 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 72fe612f0e9..19443007ae4 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 @@ -96,6 +96,10 @@ public interface OperationManager { List getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementException; + List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementException; + + int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException; + int getActivityCountUpdatedAfter(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 ccb69a1e0be..3f80da96939 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 @@ -779,6 +779,37 @@ public class OperationManagerImpl implements OperationManager { } } + + @Override + public List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementException{ + try { + OperationManagementDAOFactory.openConnection(); + return operationDAO.getFilteredActivities(operationCode, limit, offset); + } 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 getting the activity list for the given " + + "given operationCode: " + operationCode, e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + + @Override + public int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException{ + try { + OperationManagementDAOFactory.openConnection(); + return operationDAO.getTotalCountOfFilteredActivities(operationCode); + } 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 getting the activity count for the given " + + "operation code:" + operationCode, e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + @Override public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException { try { 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 e58341da8af..14dfc680903 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 @@ -20,9 +20,8 @@ package org.wso2.carbon.device.mgt.core.operation.mgt.dao; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; -import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; -import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping; import java.util.List; import java.util.Map; @@ -66,6 +65,10 @@ public interface OperationDAO { List getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementDAOException; + List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementDAOException; + + int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementDAOException; + int getActivityCountUpdatedAfter(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 a243d910932..d897f861db6 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 @@ -386,6 +386,192 @@ public class GenericOperationDAOImpl implements OperationDAO { return activity; } + @Override + public List getFilteredActivities(String operationCode, int limit, int offset) + throws OperationManagementDAOException{ + PreparedStatement stmt = null; + ResultSet rs = null; + List activities = new ArrayList<>(); + try{ + Connection conn = OperationManagementDAOFactory.getConnection(); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + String sql = "SELECT " + + " opr.ENROLMENT_ID, " + + " opr.CREATED_TIMESTAMP, " + + " opr.UPDATED_TIMESTAMP, " + + " opr.OPERATION_ID, " + + " opr.OPERATION_CODE, " + + " opr.OPERATION_TYPE, " + + " opr.STATUS, " + + " opr.DEVICE_ID, " + + " opr.DEVICE_IDENTIFICATION, " + + " opr.DEVICE_TYPE, " + + " ops.RECEIVED_TIMESTAMP, " + + " ops.ID OP_RES_ID, " + + " ops.OPERATION_RESPONSE " + + " FROM " + + " (SELECT " + + " opm.ID MAPPING_ID, " + + " opm.ENROLMENT_ID, " + + " opm.CREATED_TIMESTAMP, " + + " opm.UPDATED_TIMESTAMP, " + + " opm.OPERATION_ID, " + + " op.OPERATION_CODE, " + + " op.TYPE OPERATION_TYPE, " + + " opm.STATUS, " + + " en.DEVICE_ID, " + + " de.DEVICE_IDENTIFICATION, " + + " dt.NAME DEVICE_TYPE, " + + " de.TENANT_ID " + + " FROM" + + " DM_ENROLMENT_OP_MAPPING opm " + + " INNER JOIN DM_OPERATION op ON opm.OPERATION_ID = op.ID " + + " INNER JOIN DM_ENROLMENT en ON opm.ENROLMENT_ID = en.ID " + + " INNER JOIN DM_DEVICE de ON en.DEVICE_ID = de.ID " + + " INNER JOIN DM_DEVICE_TYPE dt ON dt.ID = de.DEVICE_TYPE_ID " + + " WHERE " + + " op.OPERATION_CODE = ? " + + " AND de.TENANT_ID = ? " + + " ORDER BY opm.UPDATED_TIMESTAMP " + + " LIMIT ? OFFSET ?) opr " + + " LEFT JOIN DM_DEVICE_OPERATION_RESPONSE ops ON opr.MAPPING_ID = ops.EN_OP_MAP_ID " + + " WHERE " + + " opr.OPERATION_CODE = ? " + + " AND opr.TENANT_ID = ? "; + stmt = conn.prepareStatement(sql); + + stmt.setString(1, operationCode); + stmt.setInt(2, tenantId); + stmt.setInt(3, limit); + stmt.setInt(4, offset); + stmt.setString(5, operationCode); + stmt.setInt(6, tenantId); + + rs = stmt.executeQuery(); + + int operationId = 0; + int enrolmentId = 0; + int responseId = 0; + Activity activity = null; + ActivityStatus activityStatus = null; + while (rs.next()) { + + if (operationId != rs.getInt("OPERATION_ID")) { + activity = new Activity(); + activities.add(activity); + List statusList = new ArrayList<>(); + activityStatus = new ActivityStatus(); + + operationId = rs.getInt("OPERATION_ID"); + enrolmentId = rs.getInt("ENROLMENT_ID"); + + 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")); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION")); + deviceIdentifier.setType(rs.getString("DEVICE_TYPE")); + 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()); + + } + if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) { + operationResponses.add(OperationDAOUtil.getOperationResponse(rs)); + responseId = rs.getInt("OP_RES_ID"); + } + activityStatus.setResponses(operationResponses); + statusList.add(activityStatus); + activity.setActivityStatus(statusList); + activity.setActivityId(OperationDAOUtil.getActivityId(rs.getInt("OPERATION_ID"))); + + } + + if (operationId == rs.getInt("OPERATION_ID") && enrolmentId != rs.getInt("ENROLMENT_ID")) { + activityStatus = new ActivityStatus(); + + 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")); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION")); + deviceIdentifier.setType(rs.getString("DEVICE_TYPE")); + 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()); + } + if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) { + operationResponses.add(OperationDAOUtil.getOperationResponse(rs)); + responseId = rs.getInt("OP_RES_ID"); + } + activityStatus.setResponses(operationResponses); + activity.getActivityStatus().add(activityStatus); + + enrolmentId = rs.getInt("ENROLMENT_ID"); + } + + if (rs.getInt("OP_RES_ID") != 0 && responseId != rs.getInt("OP_RES_ID")) { + if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) { + activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs)); + responseId = rs.getInt("OP_RES_ID"); + } + } + } + + } 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 activities; + + } + + @Override + public int getTotalCountOfFilteredActivities(String operationCode)throws OperationManagementDAOException { + PreparedStatement stmt = null; + ResultSet rs = null; + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + + String sql = "SELECT COUNT(*) AS COUNT FROM DM_ENROLMENT_OP_MAPPING m\n" + + " INNER JOIN DM_ENROLMENT d ON m.ENROLMENT_ID = d.ID\n" + + " INNER JOIN DM_OPERATION o ON m.OPERATION_ID = o.ID\n" + + "WHERE o.OPERATION_CODE = ? AND d.TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, operationCode); + stmt.setInt(2, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()); + rs = stmt.executeQuery(); + if (rs.next()) { + return rs.getInt("COUNT"); + } + } catch (SQLException e) { + throw new OperationManagementDAOException( + "Error occurred while getting the activity count from " + "the database.", e); + } finally { + OperationManagementDAOUtil.cleanupResources(stmt, rs); + } + return 0; + } + + @Override public List getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementDAOException { 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 b3730d34b87..a92f968a049 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 @@ -36,7 +36,6 @@ import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; -import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; @@ -569,6 +568,10 @@ public interface DeviceManagementProviderService { List getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementException; + List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementException; + + int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException; + int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException; List getMonitoringOperationList(String deviceType); 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 56915c293ed..3399bd39387 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 @@ -1483,6 +1483,17 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return DeviceManagementDataHolder.getInstance().getOperationManager().getActivitiesUpdatedAfter(timestamp, limit, offset); } + @Override + public List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementException{ + limit = DeviceManagerUtil.validateActivityListPageSize(limit); + return DeviceManagementDataHolder.getInstance().getOperationManager().getFilteredActivities(operationCode, limit, offset); + } + + @Override + public int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException{ + return DeviceManagementDataHolder.getInstance().getOperationManager().getTotalCountOfFilteredActivities(operationCode); + } + @Override public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException { return DeviceManagementDataHolder.getInstance().getOperationManager().getActivityCountUpdatedAfter(timestamp);