From f347861000f3aa3b26c2ad689e5a2cf7c88f4de2 Mon Sep 17 00:00:00 2001 From: Malsha Piumini Date: Sat, 14 Nov 2020 17:25:36 +0000 Subject: [PATCH] Add functionality to filter Operation Logs --- .../service/api/DeviceManagementService.java | 34 +++- .../impl/DeviceManagementServiceImpl.java | 60 +++++-- .../impl/util/RequestValidationUtil.java | 164 ++++++++++++++++- .../impl/DeviceManagementServiceImplTest.java | 8 +- .../mgt/common/OperationLogFilters.java | 72 ++++++++ .../device/mgt/common/PaginationRequest.java | 9 +- .../mgt/dao/impl/GenericOperationDAOImpl.java | 161 +++++++++++++---- .../operation/OracleOperationDAOImpl.java | 158 +++++++++++++---- .../operation/PostgreSQLOperationDAOImpl.java | 157 ++++++++++++++--- .../operation/SQLServerOperationDAOImpl.java | 165 ++++++++++++++---- 10 files changed, 840 insertions(+), 148 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/OperationLogFilters.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java index 60799bf5a27..0ab9dbfeac1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java @@ -1493,8 +1493,38 @@ public interface DeviceManagementService { @ApiParam( name = "ownership", value = "Provides the ownership of the required device.") - @QueryParam("owner") - String ownership); + @QueryParam("ownership") + String ownership, + @ApiParam( + name = "createdFrom", + value = "Since when user wants to filter operation logs using the created data and time") + @QueryParam("createdFrom") + Long createdFrom, + @ApiParam( + name = "createdTo", + value = "Till when user wants to filter operation logs using the created data and time") + @QueryParam("createdTo") + Long createdTo, + @ApiParam( + name = "updatedFrom", + value = "Since when user wants to filter operation logs using the received date and time") + @QueryParam("updatedFrom") + Long updatedFrom, + @ApiParam( + name = "updatedTo", + value = "Till when user wants to filter operation logs using the received date and time") + @QueryParam("updatedTo") + Long updatedTo, + @ApiParam( + name = "operationCode", + value = "Provides the operation codes to filter the operation logs via operation codes") + @QueryParam("operationCode") + List operationCode, + @ApiParam( + name = "operationStatus", + value = "Provides the status codes to filter operation logs via status") + @QueryParam("operationStatus") + List status); @GET @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/DeviceManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java index 73a07b7aadb..742fd7ed5d9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -36,8 +36,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl; -import java.util.LinkedList; -import java.util.Queue; +import java.text.DateFormat; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.lang.StringUtils; @@ -45,16 +44,17 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.DeviceFilters; -import org.wso2.carbon.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.Feature; import org.wso2.carbon.device.mgt.common.FeatureManager; import org.wso2.carbon.device.mgt.common.MonitoringOperation; +import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.OperationLogFilters; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.DeviceFilters; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException; @@ -81,6 +81,7 @@ import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.NonComplianceData; import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.PolicyComplianceException; import org.wso2.carbon.device.mgt.common.search.PropertyMap; import org.wso2.carbon.device.mgt.common.search.SearchContext; + import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; @@ -92,14 +93,16 @@ import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; + import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceCompliance; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.OperationList; import org.wso2.carbon.device.mgt.jaxrs.beans.OperationRequest; +import org.wso2.carbon.device.mgt.jaxrs.beans.ComplianceDeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationList; import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean; -import org.wso2.carbon.device.mgt.jaxrs.beans.ComplianceDeviceList; + import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; @@ -128,9 +131,13 @@ import javax.ws.rs.DefaultValue; import javax.ws.rs.core.Response; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; + import java.util.Date; import java.util.List; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Calendar; @Path("/devices") public class DeviceManagementServiceImpl implements DeviceManagementService { @@ -871,21 +878,30 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { @QueryParam("offset") int offset, @QueryParam("limit") int limit, @QueryParam("owner") String owner, - @QueryParam("ownership") String ownership) { + @QueryParam("ownership") String ownership, + @QueryParam("createdFrom") Long createdFrom, + @QueryParam("createdTo") Long createdTo, + @QueryParam("updatedFrom") Long updatedFrom, + @QueryParam("updatedTo") Long updatedTo, + @QueryParam("operationCode") List operationCode, + @QueryParam("operationStatus") List status) { OperationList operationsList = new OperationList(); + RequestValidationUtil requestValidationUtil = new RequestValidationUtil(); RequestValidationUtil.validateOwnerParameter(owner); RequestValidationUtil.validatePaginationParameters(offset, limit); PaginationRequest request = new PaginationRequest(offset, limit); request.setOwner(owner); - PaginationResult result; - DeviceManagementProviderService dms; try { + //validating the operation log filters + OperationLogFilters olf = requestValidationUtil.validateOperationLogFilters(operationCode, createdFrom, + createdTo, updatedFrom, updatedTo, status, type); + request.setOperationLogFilters(olf); RequestValidationUtil.validateDeviceIdentifier(type, id); - dms = DeviceMgtAPIUtils.getDeviceManagementService(); + DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); if (!StringUtils.isBlank(ownership)) { request.setOwnership(ownership); } - result = dms.getOperations(new DeviceIdentifier(id, type), request); + PaginationResult result = dms.getOperations(new DeviceIdentifier(id, type), request); operationsList.setList((List) result.getData()); operationsList.setCount(result.getRecordsTotal()); return Response.status(Response.Status.OK).entity(operationsList).build(); @@ -895,6 +911,20 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { log.error(msg, e); return Response.serverError().entity( new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } catch (InputValidationException e) { + String msg = "Error occurred while fetching the operations for the '" + type + "' device, which " + + "carries the id '" + id + "'"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (DeviceManagementException e) { + String msg = "Error occurred while retrieving the list of [" + type + "] features with params " + + "{featureType: operation, hidden: true}"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (DeviceTypeNotFoundException e) { + String msg = "No device type found with name '" + type + "'"; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java index a0259da67eb..7323b535126 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java @@ -23,11 +23,16 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpStatus; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.Feature; +import org.wso2.carbon.device.mgt.common.FeatureManager; +import org.wso2.carbon.device.mgt.common.OperationLogFilters; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException; import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; import org.wso2.carbon.device.mgt.common.notification.mgt.Notification; import org.wso2.carbon.device.mgt.core.dto.DeviceType; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; @@ -35,20 +40,24 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.ProfileFeature; import org.wso2.carbon.device.mgt.jaxrs.beans.RoleInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.Scope; +import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceTypeManagementService; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import org.wso2.carbon.policy.mgt.common.PolicyPayloadValidator; +import javax.ws.rs.core.Response; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; import java.util.ArrayList; +import java.util.Calendar; import java.util.Arrays; -import java.util.Collections; -import java.util.List; public class RequestValidationUtil { private static final Log log = LogFactory.getLog(RequestValidationUtil.class); - /** * Checks if multiple criteria are specified in a conditional request. * @@ -476,6 +485,155 @@ public class RequestValidationUtil { } } + /** + * Checks if operation log filters are valid + * + * @param type Device type upon which the selection is done + * @param createdFrom Since when created date and time upon to filter operation logs + * @param createdTo Till when created date and time upon to filter operation logs + * @param updatedFrom Since when received date and time upon to filter operation logs + * @param updatedTo Till when received date and time upon to filter operation logs + * @param status List of operation status codes upon to filter operation logs + */ + public OperationLogFilters validateOperationLogFilters(List operationCode, + Long createdFrom, Long createdTo, Long updatedFrom, + Long updatedTo, List status, String type) + throws DeviceTypeNotFoundException, DeviceManagementException { + OperationLogFilters operationLogFilters = new OperationLogFilters(); + Calendar date = Calendar.getInstance(); + long timeMilli = date.getTimeInMillis(); + + if (updatedFrom != null || updatedTo != null) { + validateDates(updatedFrom, updatedTo); + //if user only sends the fromDate toDate sets as current date + if (updatedFrom != null && updatedTo == null) { + timeMilli = timeMilli / 1000; + operationLogFilters.setUpdatedDayTo(timeMilli); + operationLogFilters.setUpdatedDayFrom(updatedFrom); + } else { + operationLogFilters.setUpdatedDayFrom(updatedFrom); + operationLogFilters.setUpdatedDayTo(updatedTo); + } + } + if (createdTo != null || createdFrom != null) { + validateDates(createdFrom, createdTo); + createdFrom = createdFrom * 1000; + //if user only sends the fromDate toDate sets as current date + if (createdFrom != null && createdTo == null) { + operationLogFilters.setCreatedDayFrom(createdFrom); + operationLogFilters.setCreatedDayTo(timeMilli); + } else { + createdTo = createdTo * 1000; + operationLogFilters.setCreatedDayFrom(createdFrom); + operationLogFilters.setCreatedDayTo(createdTo); + } + } + if (status != null && !status.isEmpty()) { + validateStatusFiltering(status); + operationLogFilters.setStatus(status); + } + + if (operationCode != null && !operationCode.isEmpty()) { + validateOperationCodeFiltering(operationCode, type); + operationLogFilters.setOperationCode(operationCode); + } + return operationLogFilters; + } + + /** + * Checks if date ranges requested by user are valid + * + * @param toDate Till when created/updated dates upon to validate dates + * @param fromDate Since when created/updated dates upon to validate dates + */ + public static void validateDates(Long fromDate, Long toDate) { + Calendar date = Calendar.getInstance(); + long timeMilli = date.getTimeInMillis(); + timeMilli = timeMilli / 1000; + //if user only sends toDate + if (fromDate == null && toDate != null) { + String msg = "Request parameter must sent with the from date parameter"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + //if user sends future dates + if (fromDate != null && toDate != null) { + if (timeMilli < fromDate || timeMilli < toDate) { + String msg = "Bad Request cannot apply future dates"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + } + //if user send future dates - only when from date sends + if (fromDate != null && toDate == null) { + if (fromDate > timeMilli) { + String msg = "Bad Request cannot apply future dates"; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + } + } + + /** + * Checks if user requested operation status codes are valid. + * + * @param status status codes upon to filter operation logs using status + */ + public static void validateStatusFiltering(List status) { + for (int i = 0; i < status.size(); i++) { + if (Constants.OperationStatus.COMPLETED.toUpperCase().equals(status.get(i)) + || Constants.OperationStatus.ERROR.toUpperCase().equals(status.get(i)) + || Constants.OperationStatus.NOTNOW.toUpperCase().equals(status.get(i)) + || Constants.OperationStatus.REPEATED.toUpperCase().equals(status.get(i)) + || Constants.OperationStatus.PENDING.toUpperCase().equals(status.get(i)) + || Constants.OperationStatus.IN_PROGRESS.toUpperCase().equals(status.get(i))) { + } else { + String msg = "Invalid status type: " + status + ". \nValid status types are COMPLETED | ERROR | " + + "IN_PROGRESS | NOTNOW | PENDING | REPEATED"; + log.error(msg); + throw new InputValidationException(new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST) + .setMessage(msg).build()); + } + } + } + + /** + * Checks if user requested operation codes are valid. + * + * @param operationCode operation codes upon to filter operation logs using operation codes + * @param type status codes upon to filter operation logs using status + */ + public static void validateOperationCodeFiltering(List operationCode, String type) + throws DeviceTypeNotFoundException, DeviceManagementException { + int count = 0; + List features; + DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); + FeatureManager fm = dms.getFeatureManager(type); + features = fm.getFeatures("operation"); + for (String oc : operationCode) { + for (Feature f : features) { + if (f.getCode().equals(oc)) { + count++; + break; + } + } + } + if (!(count == operationCode.size())) { + String msg = "Requested Operation code invalid"; + log.error(msg); + throw new InputValidationException(new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST) + .setMessage(msg).build()); + } + } + /** * Validate if the metaData and metaKey values are non empty & in proper format. * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImplTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImplTest.java index d6adc35fc23..bb9de05c1fd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImplTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImplTest.java @@ -648,24 +648,28 @@ public class DeviceManagementServiceImplTest { @Test(description = "Testing getting operation list of a device") public void testGetDeviceOperations() { + List operationCodes = new ArrayList<>(); + List statusCodes = new ArrayList<>(); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) .toReturn(this.deviceManagementProviderService); Response response = this.deviceManagementService .getDeviceOperations(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), "", 10, 5, DEFAULT_USERNAME, - DEFAULT_OWNERSHIP); + DEFAULT_OWNERSHIP, null, null, null, null, operationCodes, statusCodes); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "Expects to return HTTP 200 when the operation is retrieved successfully."); } @Test(description = "Testing getting operation list of a device when unable to retrieve operations") public void testGetDeviceOperationsException() throws OperationManagementException { + List operationCodes = new ArrayList<>(); + List statusCodes = new ArrayList<>(); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) .toReturn(this.deviceManagementProviderService); Mockito.when(this.deviceManagementProviderService.getOperations(Mockito.any(DeviceIdentifier.class), Mockito.any(PaginationRequest.class))).thenThrow(new OperationManagementException()); Response response = this.deviceManagementService .getDeviceOperations(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), "", 10, 5, DEFAULT_USERNAME, - DEFAULT_OWNERSHIP); + DEFAULT_OWNERSHIP, null, null, null, null, operationCodes, statusCodes); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Expects to return HTTP 500 when an exception occurred while retrieving operation list of the device"); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/OperationLogFilters.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/OperationLogFilters.java new file mode 100644 index 00000000000..8796c62e0f6 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/OperationLogFilters.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common; + +import java.util.List; + +/** + * This class carries information related to operation log filtering values which will be used in the UI to filter operations. + */ +public class OperationLogFilters { + private List operationCode; + private Long createdDayFrom; + private Long createdDayTo ; + private Long updatedDayFrom; + private Long updatedDayTo ; + private List status; + public OperationLogFilters() { + } + public OperationLogFilters(List operationCode , Long createdDayFrom, Long createdDayTo, + Long updatedDayFrom, Long updatedDayTo, List status) { + this.operationCode = operationCode; + this.createdDayFrom = createdDayFrom; + this.createdDayTo = createdDayTo; + this.updatedDayFrom = updatedDayFrom; + this.updatedDayTo = updatedDayTo; + this.status = status; + } + public List getOperationCode() { + return operationCode; + } + public void setOperationCode(List operationCode) { + this.operationCode = operationCode; + } + public List getStatus() { + return status; + } + public void setStatus(List status) { + this.status = status; + } + public Long getUpdatedDayFrom() { + return updatedDayFrom; + } + public void setUpdatedDayFrom(Long updatedDayFrom) { + this.updatedDayFrom = updatedDayFrom; + } + public Long getUpdatedDayTo() { + return updatedDayTo; + } + public void setUpdatedDayTo(Long updatedDayTo) { + this.updatedDayTo = updatedDayTo; + } + public Long getCreatedDayFrom() { return createdDayFrom; } + public void setCreatedDayFrom(Long createdDayFrom) { this.createdDayFrom = createdDayFrom; } + public Long getCreatedDayTo() { return createdDayTo; } + public void setCreatedDayTo(Long createdDayTo) { this.createdDayTo = createdDayTo; } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationRequest.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationRequest.java index 56cecfe008a..94cf5c52729 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationRequest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationRequest.java @@ -42,12 +42,17 @@ public class PaginationRequest { private String filter; private Map property = new HashMap<>(); private List statusList = new ArrayList<>(); - + private OperationLogFilters operationLogFilters = new OperationLogFilters(); + public OperationLogFilters getOperationLogFilters() { + return operationLogFilters; + } + public void setOperationLogFilters(OperationLogFilters operationLogFilters) { + this.operationLogFilters = operationLogFilters; + } public PaginationRequest(int start, int rowCount) { this.startIndex = start; this.rowCount = rowCount; } - public int getStartIndex() { return startIndex; } 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 7094afdcd36..373b0d3a9b9 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 @@ -44,12 +44,14 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.HashMap; +import java.util.Date; /** * This class holds the generic implementation of OperationDAO which can be used to support ANSI db syntax. @@ -1327,44 +1329,139 @@ public class GenericOperationDAOImpl implements OperationDAO { @Override public List getOperationsForDevice(int enrolmentId, PaginationRequest request) throws OperationManagementDAOException { - PreparedStatement stmt = null; - ResultSet rs = null; Operation operation; List operations = new ArrayList(); + String createdTo = null; + String createdFrom = null; + DateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + boolean isCreatedDayProvided = false; + boolean isUpdatedDayProvided = false; //updated day = received day + boolean isOperationCodeProvided = false; + boolean isStatusProvided = false; + if (request.getOperationLogFilters().getCreatedDayFrom() != null) { + createdFrom = simple.format(request.getOperationLogFilters().getCreatedDayFrom()); + } + if (request.getOperationLogFilters().getCreatedDayTo() != null) { + createdTo = simple.format(request.getOperationLogFilters().getCreatedDayTo()); + } + Long updatedFrom = request.getOperationLogFilters().getUpdatedDayFrom(); + Long updatedTo = request.getOperationLogFilters().getUpdatedDayTo(); + List operationCode = request.getOperationLogFilters().getOperationCode(); + List status = request.getOperationLogFilters().getStatus(); + String sql = "SELECT " + + "o.ID, " + + "TYPE, " + + "o.CREATED_TIMESTAMP, " + + "o.RECEIVED_TIMESTAMP, " + + "o.OPERATION_CODE, " + + "om.STATUS, " + + "om.ID AS OM_MAPPING_ID, " + + "om.UPDATED_TIMESTAMP " + + "FROM " + + "DM_OPERATION o " + + "INNER JOIN " + + "(SELECT dm.OPERATION_ID, " + + "dm.ID, " + + "dm.STATUS, " + + "dm.UPDATED_TIMESTAMP " + + "FROM " + + "DM_ENROLMENT_OP_MAPPING dm " + + "WHERE " + + "dm.ENROLMENT_ID = ?"; + + if (updatedFrom != null && updatedFrom != 0 && updatedTo != null && updatedTo != 0) { + sql = sql + " AND dm.UPDATED_TIMESTAMP BETWEEN ? AND ?"; + isUpdatedDayProvided = true; + } + sql = sql + ") om ON o.ID = om.OPERATION_ID "; + if (createdFrom != null && !createdFrom.isEmpty() && createdTo != null && !createdTo.isEmpty()) { + sql = sql + " WHERE o.CREATED_TIMESTAMP BETWEEN ? AND ?"; + isCreatedDayProvided = true; + } + if ((isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " AND (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } else if ((!isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " WHERE (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } + if ((isCreatedDayProvided || isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + int size = operationCode.size(); + sql = sql + " AND (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } else if ((!isCreatedDayProvided && !isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + int size = operationCode.size(); + sql = sql + " WHERE (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } + sql = sql + " ORDER BY o.CREATED_TIMESTAMP DESC LIMIT ?,?"; try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT o.ID, o.TYPE, o.CREATED_TIMESTAMP, o.RECEIVED_TIMESTAMP, " + - "o.OPERATION_CODE, om.STATUS, om.ID AS OM_MAPPING_ID, om.UPDATED_TIMESTAMP FROM DM_OPERATION o " + - "INNER JOIN (SELECT * FROM DM_ENROLMENT_OP_MAPPING dm " + - "WHERE dm.ENROLMENT_ID = ?) om ON o.ID = om.OPERATION_ID " + - "ORDER BY o.CREATED_TIMESTAMP DESC, o.ID DESC LIMIT ?,?"; - stmt = conn.prepareStatement(sql); - stmt.setInt(1, enrolmentId); - stmt.setInt(2, request.getStartIndex()); - stmt.setInt(3, request.getRowCount()); - rs = stmt.executeQuery(); - - while (rs.next()) { - operation = new Operation(); - operation.setId(rs.getInt("ID")); - operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); - operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); - if (rs.getLong("UPDATED_TIMESTAMP") == 0) { - operation.setReceivedTimeStamp(""); - } else { - operation.setReceivedTimeStamp( - new java.sql.Timestamp((rs.getLong("UPDATED_TIMESTAMP") * 1000)).toString()); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int paramIndex = 1; + stmt.setInt(paramIndex++, enrolmentId); + if (isUpdatedDayProvided) { + stmt.setLong(paramIndex++, updatedFrom); + stmt.setLong(paramIndex++, updatedTo); + } + if (isCreatedDayProvided) { + stmt.setString(paramIndex++, createdFrom); + stmt.setString(paramIndex++, createdTo); + } + if (isStatusProvided) { + int size = status.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, status.get(i)); + } + } + if (isOperationCodeProvided) { + int size = operationCode.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, operationCode.get(i)); + } + } + stmt.setInt(paramIndex++, request.getStartIndex()); + stmt.setInt(paramIndex, request.getRowCount()); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + operation = new Operation(); + operation.setId(rs.getInt("ID")); + operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); + operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); + if (rs.getLong("UPDATED_TIMESTAMP") == 0) { + operation.setReceivedTimeStamp(""); + } else { + operation.setReceivedTimeStamp( + new java.sql.Timestamp((rs.getLong("UPDATED_TIMESTAMP") * 1000)).toString()); + } + operation.setCode(rs.getString("OPERATION_CODE")); + operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); + OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); + operations.add(operation); + } } - operation.setCode(rs.getString("OPERATION_CODE")); - operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); - OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); - operations.add(operation); } } catch (SQLException e) { throw new OperationManagementDAOException("SQL error occurred while retrieving the operation " + "available for the device'" + enrolmentId + "' with status '", e); - } finally { - OperationManagementDAOUtil.cleanupResources(stmt, rs); } return operations; } 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/operation/OracleOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java index 37de111d8a9..e84b723262d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/OracleOperationDAOImpl.java @@ -37,11 +37,13 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.ArrayList; +import java.util.LinkedList; /** * This class holds the implementation of OperationDAO which can be used to support Oracle db syntax. @@ -53,44 +55,140 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl { @Override public List getOperationsForDevice(int enrolmentId, PaginationRequest request) throws OperationManagementDAOException { - PreparedStatement stmt = null; - ResultSet rs = null; Operation operation; List operations = new ArrayList(); + String createdTo = null; + String createdFrom = null; + DateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + boolean isCreatedDayProvided = false; + boolean isUpdatedDayProvided = false; //updated day = received day + boolean isOperationCodeProvided = false; + boolean isStatusProvided = false; + if (request.getOperationLogFilters().getCreatedDayFrom() != null) { + createdFrom = simple.format(request.getOperationLogFilters().getCreatedDayFrom()); + } + if (request.getOperationLogFilters().getCreatedDayTo() != null) { + createdTo = simple.format(request.getOperationLogFilters().getCreatedDayTo()); + } + Long updatedFrom = request.getOperationLogFilters().getUpdatedDayFrom(); + Long updatedTo = request.getOperationLogFilters().getUpdatedDayTo(); + List operationCode = request.getOperationLogFilters().getOperationCode(); + List status = request.getOperationLogFilters().getStatus(); + String sql = "SELECT " + + "o.ID, " + + "TYPE, " + + "o.CREATED_TIMESTAMP, " + + "o.RECEIVED_TIMESTAMP, " + + "o.OPERATION_CODE, " + + "om.STATUS, " + + "om.ID AS OM_MAPPING_ID, " + + "om.UPDATED_TIMESTAMP " + + "FROM " + + "DM_OPERATION o " + + "INNER JOIN " + + "(SELECT " + + "dm.OPERATION_ID, " + + "dm.ID, " + + "dm.STATUS, " + + "dm.UPDATED_TIMESTAMP " + + "FROM " + + "DM_ENROLMENT_OP_MAPPING dm " + + "WHERE " + + "dm.ENROLMENT_ID = ?"; + + if (updatedFrom != null && updatedFrom != 0 && updatedTo != null && updatedTo != 0) { + sql = sql + " AND dm.UPDATED_TIMESTAMP BETWEEN ? AND ?"; + isUpdatedDayProvided = true; + } + sql = sql + ") om ON o.ID = om.OPERATION_ID "; + if (createdFrom != null && !createdFrom.isEmpty() && createdTo != null && !createdTo.isEmpty()) { + sql = sql + " WHERE o.CREATED_TIMESTAMP BETWEEN ? AND ?"; + isCreatedDayProvided = true; + } + if ((isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " AND (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } else if ((!isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " WHERE (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } + if ((isCreatedDayProvided || isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + int size = operationCode.size(); + sql = sql + " AND (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } else if ((!isCreatedDayProvided && !isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + int size = operationCode.size(); + sql = sql + " WHERE (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } + sql = sql + " ORDER BY o.CREATED_TIMESTAMP DESC FFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + int paramIndex = 1; try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT o.ID, TYPE, o.CREATED_TIMESTAMP, o.RECEIVED_TIMESTAMP, " - + "o.OPERATION_CODE, om.STATUS, om.ID AS OM_MAPPING_ID, om.UPDATED_TIMESTAMP FROM DM_OPERATION o " - + "INNER JOIN (SELECT dm.OPERATION_ID, dm.ID, dm.STATUS, dm.UPDATED_TIMESTAMP FROM DM_ENROLMENT_OP_MAPPING dm " - + "WHERE dm.ENROLMENT_ID = ?) om ON o.ID = om.OPERATION_ID ORDER BY o.CREATED_TIMESTAMP DESC " - + "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; - stmt = conn.prepareStatement(sql); - stmt.setInt(1, enrolmentId); - stmt.setInt(2, request.getStartIndex()); - stmt.setInt(3, request.getRowCount()); - rs = stmt.executeQuery(); - - while (rs.next()) { - operation = new Operation(); - operation.setId(rs.getInt("ID")); - operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); - operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); - if (rs.getTimestamp("RECEIVED_TIMESTAMP") == null) { - operation.setReceivedTimeStamp(""); - } else { - operation.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(paramIndex++, enrolmentId); + if (isUpdatedDayProvided) { + stmt.setLong(paramIndex++, updatedFrom); + stmt.setLong(paramIndex++, updatedTo); + } + if (isCreatedDayProvided) { + stmt.setString(paramIndex++, createdFrom); + stmt.setString(paramIndex++, createdTo); + } + if (isStatusProvided) { + int size = status.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, status.get(i)); + } + } + if (isOperationCodeProvided) { + int size = operationCode.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, operationCode.get(i)); + } + } + stmt.setInt(paramIndex++, request.getStartIndex()); + stmt.setInt(paramIndex, request.getRowCount()); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + operation = new Operation(); + operation.setId(rs.getInt("ID")); + operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); + operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); + if (rs.getTimestamp("RECEIVED_TIMESTAMP") == null) { + operation.setReceivedTimeStamp(""); + } else { + operation.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); + } + operation.setCode(rs.getString("OPERATION_CODE")); + operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); + OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); + operations.add(operation); + } } - operation.setCode(rs.getString("OPERATION_CODE")); - operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); - OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); - operations.add(operation); } } catch (SQLException e) { throw new OperationManagementDAOException( "SQL error occurred while retrieving the operation " + "available for the device'" + enrolmentId + "' with status '", e); - } finally { - OperationManagementDAOUtil.cleanupResources(stmt, rs); } return operations; } 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/operation/PostgreSQLOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/PostgreSQLOperationDAOImpl.java index 17ccdb27ce7..cbf6c074208 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/PostgreSQLOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/PostgreSQLOperationDAOImpl.java @@ -32,9 +32,11 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; -import java.util.ArrayList; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.ArrayList; /** * This class holds the implementation of OperationDAO which can be used to support PostgreSQL db syntax. @@ -44,42 +46,139 @@ public class PostgreSQLOperationDAOImpl extends GenericOperationDAOImpl { @Override public List getOperationsForDevice(int enrolmentId, PaginationRequest request) throws OperationManagementDAOException { - PreparedStatement stmt = null; - ResultSet rs = null; Operation operation; List operations = new ArrayList(); + String createdTo = null; + String createdFrom = null; + DateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + boolean isCreatedDayProvided = false; + boolean isUpdatedDayProvided = false; //updated day = received day + boolean isOperationCodeProvided = false; + boolean isStatusProvided = false; + if (request.getOperationLogFilters().getCreatedDayFrom() != null) { + createdFrom = simple.format(request.getOperationLogFilters().getCreatedDayFrom()); + } + if (request.getOperationLogFilters().getCreatedDayTo() != null) { + createdTo = simple.format(request.getOperationLogFilters().getCreatedDayTo()); + } + Long updatedFrom = request.getOperationLogFilters().getUpdatedDayFrom(); + Long updatedTo = request.getOperationLogFilters().getUpdatedDayTo(); + List operationCode = request.getOperationLogFilters().getOperationCode(); + List status = request.getOperationLogFilters().getStatus(); + String sql = "SELECT " + + "o.ID, " + + "TYPE, " + + "o.CREATED_TIMESTAMP, " + + "o.RECEIVED_TIMESTAMP, " + + "o.OPERATION_CODE, " + + "om.STATUS, " + + "om.ID AS OM_MAPPING_ID, " + + "om.UPDATED_TIMESTAMP " + + "FROM " + + "DM_OPERATION o " + + "INNER JOIN " + + "(SELECT " + + "dm.OPERATION_ID, " + + "dm.ID, " + + "dm.STATUS, " + + "dm.UPDATED_TIMESTAMP " + + "FROM " + + "DM_ENROLMENT_OP_MAPPING dm " + + "WHERE " + + "dm.ENROLMENT_ID = ?"; + + if (updatedFrom != null && updatedFrom != 0 && updatedTo != null && updatedTo != 0) { + sql = sql + " AND dm.UPDATED_TIMESTAMP BETWEEN ? AND ?"; + isUpdatedDayProvided = true; + } + sql = sql + ") om ON o.ID = om.OPERATION_ID "; + if (createdFrom != null && !createdFrom.isEmpty() && createdTo != null && !createdTo.isEmpty()) { + sql = sql + " WHERE o.CREATED_TIMESTAMP BETWEEN ? AND ?"; + isCreatedDayProvided = true; + } + if ((isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " AND (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } else if ((!isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " WHERE (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } + if ((isCreatedDayProvided || isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + int size = operationCode.size(); + sql = sql + " AND (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } else if ((!isCreatedDayProvided && !isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + int size = operationCode.size(); + sql = sql + " WHERE (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } + sql = sql + " ORDER BY o.CREATED_TIMESTAMP DESC LIMIT ? OFFSET ?"; + int paramIndex = 1; try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT o.ID, o.TYPE, o.CREATED_TIMESTAMP, o.RECEIVED_TIMESTAMP, " + - "o.OPERATION_CODE, om.STATUS FROM DM_OPERATION o " + - "INNER JOIN (SELECT * FROM DM_ENROLMENT_OP_MAPPING dm " + - "WHERE dm.ENROLMENT_ID = ?) om ON o.ID = om.OPERATION_ID ORDER BY o.CREATED_TIMESTAMP DESC LIMIT ? OFFSET ?"; - stmt = conn.prepareStatement(sql); - stmt.setInt(1, enrolmentId); - stmt.setInt(2, request.getRowCount()); - stmt.setInt(3, request.getStartIndex()); - rs = stmt.executeQuery(); - - while (rs.next()) { - operation = new Operation(); - operation.setId(rs.getInt("ID")); - operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); - operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); - if (rs.getTimestamp("RECEIVED_TIMESTAMP") == null) { - operation.setReceivedTimeStamp(""); - } else { - operation.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(paramIndex++, enrolmentId); + if (isUpdatedDayProvided) { + stmt.setLong(paramIndex++, updatedFrom); + stmt.setLong(paramIndex++, updatedTo); + } + if (isCreatedDayProvided) { + stmt.setString(paramIndex++, createdFrom); + stmt.setString(paramIndex++, createdTo); + } + if (isStatusProvided) { + int size = status.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, status.get(i)); + } + } + if (isOperationCodeProvided) { + int size = operationCode.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, operationCode.get(i)); + } + } + stmt.setInt(paramIndex++, request.getStartIndex()); + stmt.setInt(paramIndex, request.getRowCount()); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + operation = new Operation(); + operation.setId(rs.getInt("ID")); + operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); + operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); + if (rs.getTimestamp("RECEIVED_TIMESTAMP") == null) { + operation.setReceivedTimeStamp(""); + } else { + operation.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); + } + operation.setCode(rs.getString("OPERATION_CODE")); + operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); + OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); + operations.add(operation); + } } - operation.setCode(rs.getString("OPERATION_CODE")); - operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); - OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); - operations.add(operation); } } catch (SQLException e) { throw new OperationManagementDAOException("SQL error occurred while retrieving the operation " + - "available for the device'" + enrolmentId, e); - } finally { - OperationManagementDAOUtil.cleanupResources(stmt, rs); + "available for the device'" + enrolmentId, e); } return operations; } 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/operation/SQLServerOperationDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java index a3520084f6b..164df0b452b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/dao/impl/operation/SQLServerOperationDAOImpl.java @@ -56,12 +56,13 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; - +import java.util.ArrayList; +import java.util.LinkedList; /** * This class holds the implementation of OperationDAO which can be used to support SQLServer db syntax. */ @@ -72,44 +73,142 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl { @Override public List getOperationsForDevice(int enrolmentId, PaginationRequest request) throws OperationManagementDAOException { - PreparedStatement stmt = null; - ResultSet rs = null; Operation operation; List operations = new ArrayList(); + String createdTo = null; + String createdFrom = null; + DateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + boolean isCreatedDayProvided = false; + boolean isUpdatedDayProvided = false; //updated day = received day + boolean isOperationCodeProvided = false; + boolean isStatusProvided = false; + if (request.getOperationLogFilters().getCreatedDayFrom() != null) { + createdFrom = simple.format(request.getOperationLogFilters().getCreatedDayFrom()); + } + if (request.getOperationLogFilters().getCreatedDayTo() != null) { + createdTo = simple.format(request.getOperationLogFilters().getCreatedDayTo()); + } + Long updatedFrom = request.getOperationLogFilters().getUpdatedDayFrom(); + Long updatedTo = request.getOperationLogFilters().getUpdatedDayTo(); + List operationCode = request.getOperationLogFilters().getOperationCode(); + List status = request.getOperationLogFilters().getStatus(); + String sql = "SELECT " + + "o.ID, " + + "TYPE, " + + "o.CREATED_TIMESTAMP, " + + "o.RECEIVED_TIMESTAMP, " + + "o.OPERATION_CODE, " + + "om.STATUS, " + + "om.ID AS OM_MAPPING_ID, " + + "om.UPDATED_TIMESTAMP " + + "FROM " + + "DM_OPERATION o " + + "INNER JOIN " + + "(SELECT " + + "dm.OPERATION_ID, " + + "dm.ID, " + + "dm.STATUS, " + + "dm.UPDATED_TIMESTAMP " + + "FROM " + + "DM_ENROLMENT_OP_MAPPING dm " + + "WHERE " + + "dm.ENROLMENT_ID = ?"; + + if (updatedFrom != null && updatedFrom != 0 && updatedTo != null && updatedTo != 0) { + sql = sql + " AND dm.UPDATED_TIMESTAMP BETWEEN ? AND ?"; + isUpdatedDayProvided = true; + } + sql = sql + ") om ON o.ID = om.OPERATION_ID "; + if (createdFrom != null && !createdFrom.isEmpty() && createdTo != null && !createdTo.isEmpty()) { + sql = sql + " WHERE o.CREATED_TIMESTAMP BETWEEN ? AND ?"; + isCreatedDayProvided = true; + } + if ((isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " AND (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } else if ((!isCreatedDayProvided) && (status != null && !status.isEmpty())) { + int size = status.size(); + sql = sql + " WHERE (om.STATUS = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR om.STATUS = ?"; + } + sql = sql + ")"; + isStatusProvided = true; + } + if ((isCreatedDayProvided || isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + // sql = sql + " AND o.OPERATION_CODE = ? "; + int size = operationCode.size(); + sql = sql + " AND (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } else if ((!isCreatedDayProvided && !isStatusProvided) && (operationCode != null && !operationCode.isEmpty())) { + //sql = sql + " WHERE o.OPERATION_CODE = ? "; + int size = operationCode.size(); + sql = sql + " WHERE (o.OPERATION_CODE = ? "; + for (int i = 0; i < size - 1; i++) { + sql = sql + " OR o.OPERATION_CODE = ?"; + } + sql = sql + ")"; + isOperationCodeProvided = true; + } + sql = sql + " ORDER BY o.CREATED_TIMESTAMP DESC OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + int paramIndex = 1; try { Connection conn = OperationManagementDAOFactory.getConnection(); - String sql = "SELECT o.ID, TYPE, o.CREATED_TIMESTAMP, o.RECEIVED_TIMESTAMP, " + - "o.OPERATION_CODE, om.STATUS, om.ID AS OM_MAPPING_ID, om.UPDATED_TIMESTAMP FROM DM_OPERATION o " + - "INNER JOIN (SELECT dm.OPERATION_ID, dm.ID, dm.STATUS, dm.UPDATED_TIMESTAMP FROM DM_ENROLMENT_OP_MAPPING dm " + - "WHERE dm.ENROLMENT_ID = ?) om ON o.ID = om.OPERATION_ID ORDER BY o.CREATED_TIMESTAMP DESC " + - "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; - stmt = conn.prepareStatement(sql); - stmt.setInt(1, enrolmentId); - stmt.setInt(2, request.getStartIndex()); - stmt.setInt(3, request.getRowCount()); - rs = stmt.executeQuery(); - - while (rs.next()) { - operation = new Operation(); - operation.setId(rs.getInt("ID")); - operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); - operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); - if (rs.getLong("UPDATED_TIMESTAMP") == 0) { - operation.setReceivedTimeStamp(""); - } else { - operation.setReceivedTimeStamp( - new java.sql.Timestamp((rs.getLong("UPDATED_TIMESTAMP") * 1000)).toString()); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(paramIndex++, enrolmentId); + if (isUpdatedDayProvided) { + stmt.setLong(paramIndex++, updatedFrom); + stmt.setLong(paramIndex++, updatedTo); + } + if (isCreatedDayProvided) { + stmt.setString(paramIndex++, createdFrom); + stmt.setString(paramIndex++, createdTo); + } + if (isStatusProvided) { + int size = status.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, status.get(i)); + } + } + if (isOperationCodeProvided) { + int size = operationCode.size(); + for (int i = 0; i < size; i++) { + stmt.setString(paramIndex++, operationCode.get(i)); + } + } + stmt.setInt(paramIndex++, request.getStartIndex()); + stmt.setInt(paramIndex, request.getRowCount()); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + operation = new Operation(); + operation.setId(rs.getInt("ID")); + operation.setType(Operation.Type.valueOf(rs.getString("TYPE"))); + operation.setCreatedTimeStamp(rs.getTimestamp("CREATED_TIMESTAMP").toString()); + if (rs.getLong("UPDATED_TIMESTAMP") == 0) { + operation.setReceivedTimeStamp(""); + } else { + operation.setReceivedTimeStamp( + new java.sql.Timestamp((rs.getLong("UPDATED_TIMESTAMP") * 1000)).toString()); + } + operation.setCode(rs.getString("OPERATION_CODE")); + operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); + OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); + operations.add(operation); + } } - operation.setCode(rs.getString("OPERATION_CODE")); - operation.setStatus(Operation.Status.valueOf(rs.getString("STATUS"))); - OperationDAOUtil.setActivityId(operation, rs.getInt("ID")); - operations.add(operation); } } catch (SQLException e) { throw new OperationManagementDAOException("SQL error occurred while retrieving the operations " + - "available for the device '" + enrolmentId + "'", e); - } finally { - OperationManagementDAOUtil.cleanupResources(stmt, rs); + "available for the device '" + enrolmentId + "'", e); } return operations; }